文本文件  |  38366行  |  1.64 MB

      Trusted Platform Module Library
      Part 4: Supporting Routines

      Family "2.0"

      Level 00 Revision 01.16

      October 30, 2014

      Published




      Contact: admin@trustedcomputinggroup.org




      TCG Published
      Copyright © TCG 2006-2014




TCG
Trusted Platform Module Library                                                Part 4: Supporting Routines


Licenses and Notices

1. Copyright Licenses:
     Trusted Computing Group (TCG) grants to the user of the source code in this specification (the
      “Source Code”) a worldwide, irrevocable, nonexclusive, royalty free, copyright license to
      reproduce, create derivative works, distribute, display and perform the Source Code and
      derivative works thereof, and to grant others the rights granted herein.
     The TCG grants to the user of the other parts of the specification (other than the Source Code)
      the rights to reproduce, distribute, display, and perform the specification solely for the purpose
      of developing products based on such documents.
2. Source Code Distribution Conditions:
     Redistributions of Source Code must retain the above copyright licenses, this list of conditions
      and the following disclaimers.
     Redistributions in binary form must reproduce the above copyright licenses, this list of
      conditions and the following disclaimers in the documentation and/or other materials provided
      with the distribution.
3. Disclaimers:
     THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF LICENSE OR
      WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH RESPECT TO PATENT RIGHTS
      HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) THAT MAY BE NECESSARY TO IMPLEMENT
      THIS SPECIFICATION OR OTHERWISE. Contact TCG Administration
      (admin@trustedcomputinggroup.org) for information on specification licensing rights available
      through TCG membership agreements.
     THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES
      WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
      PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF INTELLECTUAL
      PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF ANY PROPOSAL,
      SPECIFICATION OR SAMPLE.
     Without limitation, TCG and its members and licensors disclaim all liability, including liability for
      infringement of any proprietary rights, relating to use of information in this specification and to
      the implementation of this specification, and TCG disclaims all liability for cost of procurement
      of substitute goods or services, lost profits, loss of use, loss of data or any incidental,
      consequential, direct, indirect, or special damages, whether under contract, tort, warranty or
      otherwise, arising in any way out of use or reliance upon this specification or any information
      herein.
Any marks and brands contained herein are the property of their respective owner.




Page ii                                      TCG Published                                    Family "2.0"
October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
Part 4: Supporting Routines                                                                       Trusted Platform Module Library


                                                           CONTENTS
1   Scope ................................................................................................................................... 1
2   Terms and definitions ........................................................................................................... 1
3   Symbols and abbreviated terms ............................................................................................ 1
4   Automation ........................................................................................................................... 1
    4.1 Configuration Parser ................................................................................................... 1
    4.2 Structure Parser .......................................................................................................... 2
       4.2.1       Introduction .......................................................................................................... 2
       4.2.2       Unmarshaling Code Prototype .............................................................................. 2
          4.2.2.1        Simple Types and Structures .......................................................................... 2
          4.2.2.2        Union Types ................................................................................................... 3
          4.2.2.3        Null Types ...................................................................................................... 3
          4.2.2.4        Arrays ............................................................................................................. 3
       4.2.3       Marshaling Code Function Prototypes .................................................................. 4
          4.2.3.1        Simple Types and Structures .......................................................................... 4
          4.2.3.2        Union Types ................................................................................................... 4
          4.2.3.3        Arrays ............................................................................................................. 4
    4.3     Command Parser ........................................................................................................ 5
    4.4     Portability .................................................................................................................... 5
5   Header Files ......................................................................................................................... 6
    5.1 Introduction ................................................................................................................. 6
    5.2 BaseTypes.h ............................................................................................................... 6
    5.3 bits.h ........................................................................................................................... 7
    5.4 bool.h .......................................................................................................................... 8
    5.5 Capabilities.h .............................................................................................................. 8
    5.6 TPMB.h ....................................................................................................................... 8
    5.7 TpmError.h .................................................................................................................. 9
    5.8 Global.h ...................................................................................................................... 9
       5.8.1       Description ........................................................................................................... 9
       5.8.2       Includes ............................................................................................................... 9
       5.8.3       Defines and Types ............................................................................................. 10
          5.8.3.1        Unreferenced Parameter .............................................................................. 10
          5.8.3.2        Crypto Self-Test Values ................................................................................ 10
          5.8.3.3        Hash and HMAC State Structures ................................................................. 10
          5.8.3.4        Other Types .................................................................................................. 11
       5.8.4       Loaded Object Structures ................................................................................... 11
          5.8.4.1        Description ................................................................................................... 11
          5.8.4.2        OBJECT_ATTRIBUTES ................................................................................ 11
          5.8.4.3        OBJECT Structure ........................................................................................ 12
          5.8.4.4        HASH_OBJECT Structure ............................................................................. 12
          5.8.4.5        ANY_OBJECT .............................................................................................. 13
       5.8.5       AUTH_DUP Types .............................................................................................. 13
       5.8.6       Active Session Context ....................................................................................... 13
          5.8.6.1        Description ................................................................................................... 13
          5.8.6.2        SESSION_ATTRIBUTES .............................................................................. 13
          5.8.6.3        SESSION Structure ...................................................................................... 14
       5.8.7       PCR ................................................................................................................... 15
          5.8.7.1        PCR_SAVE Structure ................................................................................... 15

Family "2.0"                                              TCG Published                                                            Page iii
Level 00 Revision 01.16                         Copyright © TCG 2006-2014                                            October 30, 2014
Trusted Platform Module Library                                                                         Part 4: Supporting Routines

          5.8.7.2        PCR_POLICY ............................................................................................... 16
          5.8.7.3        PCR_AUTHVALUE ....................................................................................... 16
       5.8.8       Startup ............................................................................................................... 16
          5.8.8.1        SHUTDOWN_NONE ..................................................................................... 16
          5.8.8.2        STARTUP_TYPE .......................................................................................... 16
       5.8.9       NV ...................................................................................................................... 16
          5.8.9.1        NV_RESERVE .............................................................................................. 16
          5.8.9.2        NV_INDEX .................................................................................................... 18
       5.8.10 COMMIT_INDEX_MASK ..................................................................................... 18
       5.8.11 RAM Global Values ............................................................................................ 18
          5.8.11.1       Description ................................................................................................... 18
          5.8.11.2       g_rcIndex ..................................................................................................... 18
          5.8.11.3       g_exclusiveAuditSession .............................................................................. 18
          5.8.11.4       g_time .......................................................................................................... 18
          5.8.11.5       g_phEnable .................................................................................................. 18
          5.8.11.6       g_pceReConfig ............................................................................................. 19
          5.8.11.7       g_DRTMHandle ............................................................................................ 19
          5.8.11.8       g_DrtmPreStartup ......................................................................................... 19
          5.8.11.9       g_StartupLocality3 ........................................................................................ 19
          5.8.11.10      g_updateNV ................................................................................................. 19
          5.8.11.11      g_clearOrderly .............................................................................................. 19
          5.8.11.12      g_prevOrderlyState ...................................................................................... 20
          5.8.11.13      g_nvOk ......................................................................................................... 20
          5.8.11.14      g_platformUnique ......................................................................................... 20
       5.8.12 Persistent Global Values .................................................................................... 20
          5.8.12.1       Description ................................................................................................... 20
          5.8.12.2       PERSISTENT_DATA .................................................................................... 20
          5.8.12.3       ORDERLY_DATA ......................................................................................... 22
          5.8.12.4       STATE_CLEAR_DATA ................................................................................. 23
          5.8.12.5       State Reset Data .......................................................................................... 24
       5.8.13 Global Macro Definitions .................................................................................... 25
       5.8.14 Private data ........................................................................................................ 25
    5.9     Tpm.h ........................................................................................................................ 29
    5.10    swap.h ...................................................................................................................... 30
    5.11    InternalRoutines.h ..................................................................................................... 31
    5.12    TpmBuildSwitches.h .................................................................................................. 32
    5.13    VendorString.h .......................................................................................................... 33
6   Main ................................................................................................................................... 35
    6.1 CommandDispatcher() ............................................................................................... 35
    6.2 ExecCommand.c ....................................................................................................... 35
       6.2.1       Introduction ........................................................................................................ 35
       6.2.2       Includes ............................................................................................................. 35
       6.2.3       ExecuteCommand() ............................................................................................ 35
    6.3     ParseHandleBuffer() .................................................................................................. 41
    6.4     SessionProcess.c ...................................................................................................... 42
       6.4.1       Introduction ........................................................................................................ 42
       6.4.2       Includes and Data Definitions ............................................................................. 42
       6.4.3       Authorization Support Functions ......................................................................... 42
          6.4.3.1        IsDAExempted() ........................................................................................... 42
          6.4.3.2        IncrementLockout() ....................................................................................... 43

Page iv                                                   TCG Published                                                      Family "2.0"
October 30, 2014                                Copyright © TCG 2006-2014                                  Level 00 Revision 01.16
Part 4: Supporting Routines                                                                     Trusted Platform Module Library

          6.4.3.3       IsSessionBindEntity() ................................................................................... 44
          6.4.3.4       IsPolicySessionRequired() ............................................................................ 45
          6.4.3.5       IsAuthValueAvailable() ................................................................................. 46
          6.4.3.6       IsAuthPolicyAvailable() ................................................................................. 48
       6.4.4      Session Parsing Functions ................................................................................. 49
          6.4.4.1       ComputeCpHash() ........................................................................................ 49
          6.4.4.2       CheckPWAuthSession() ................................................................................ 50
          6.4.4.3       ComputeCommandHMAC() ........................................................................... 51
          6.4.4.4       CheckSessionHMAC() .................................................................................. 53
          6.4.4.5       CheckPolicyAuthSession() ............................................................................ 53
          6.4.4.6       RetrieveSessionData() .................................................................................. 56
          6.4.4.7       CheckLockedOut() ........................................................................................ 59
          6.4.4.8       CheckAuthSession() ..................................................................................... 60
          6.4.4.9       CheckCommandAudit() ................................................................................. 62
          6.4.4.10      ParseSessionBuffer() .................................................................................... 63
          6.4.4.11      CheckAuthNoSession() ................................................................................. 65
       6.4.5      Response Session Processing ........................................................................... 66
          6.4.5.1       Introduction .................................................................................................. 66
          6.4.5.2       ComputeRpHash() ........................................................................................ 66
          6.4.5.3       InitAuditSession() ......................................................................................... 67
          6.4.5.4       Audit() .......................................................................................................... 67
          6.4.5.5       CommandAudit() ........................................................................................... 68
          6.4.5.6       UpdateAuditSessionStatus() ......................................................................... 69
          6.4.5.7       ComputeResponseHMAC() ........................................................................... 70
          6.4.5.8       BuildSingleResponseAuth() .......................................................................... 71
          6.4.5.9       UpdateTPMNonce() ...................................................................................... 72
          6.4.5.10      UpdateInternalSession() ............................................................................... 72
          6.4.5.11      BuildResponseSession() ............................................................................... 73
7   Command Support Functions .............................................................................................. 76
    7.1 Introduction ............................................................................................................... 76
    7.2 Attestation Command Support (Attest_spt.c) ............................................................. 76
       7.2.1      Includes ............................................................................................................. 76
       7.2.2      Functions ........................................................................................................... 76
          7.2.2.1       FillInAttestInfo() ............................................................................................ 76
          7.2.2.2       SignAttestInfo() ............................................................................................ 77
    7.3     Context Management Command Support (Context_spt.c) .......................................... 79
       7.3.1      Includes ............................................................................................................. 79
       7.3.2      Functions ........................................................................................................... 79
          7.3.2.1       ComputeContextProtectionKey() ................................................................... 79
          7.3.2.2       ComputeContextIntegrity() ............................................................................ 80
          7.3.2.3       SequenceDataImportExport() ........................................................................ 81
    7.4     Policy Command Support (Policy_spt.c) .................................................................... 81
       7.4.1      PolicyParameterChecks() ................................................................................... 81
       7.4.2      PolicyContextUpdate() ........................................................................................ 82
    7.5     NV Command Support (NV_spt.c) ............................................................................. 83
       7.5.1      Includes ............................................................................................................. 83
       7.5.2      Fuctions ............................................................................................................. 83
          7.5.2.1       NvReadAccessChecks() ............................................................................... 83
          7.5.2.2       NvWriteAccessChecks() ............................................................................... 84
    7.6     Object Command Support (Object_spt.c) ................................................................... 85

Family "2.0"                                            TCG Published                                                             Page v
Level 00 Revision 01.16                       Copyright © TCG 2006-2014                                            October 30, 2014
Trusted Platform Module Library                                                                        Part 4: Supporting Routines

       7.6.1       Includes ............................................................................................................. 85
       7.6.2       Local Functions .................................................................................................. 86
          7.6.2.1       EqualCryptSet() ............................................................................................ 86
          7.6.2.2       GetIV2BSize() .............................................................................................. 86
          7.6.2.3       ComputeProtectionKeyParms() ..................................................................... 87
          7.6.2.4       ComputeOuterIntegrity() ............................................................................... 88
          7.6.2.5       ComputeInnerIntegrity() ................................................................................ 89
          7.6.2.6       ProduceInnerIntegrity() ................................................................................. 89
          7.6.2.7       CheckInnerIntegrity() .................................................................................... 90
       7.6.3       Public Functions ................................................................................................. 90
          7.6.3.1       AreAttributesForParent() ............................................................................... 90
          7.6.3.2       SchemeChecks() .......................................................................................... 91
          7.6.3.3       PublicAttributesValidation()........................................................................... 94
          7.6.3.4       FillInCreationData() ...................................................................................... 95
          7.6.3.5       GetSeedForKDF() ......................................................................................... 97
          7.6.3.6       ProduceOuterWrap() ..................................................................................... 97
          7.6.3.7       UnwrapOuter() .............................................................................................. 99
          7.6.3.8       SensitiveToPrivate() ................................................................................... 100
          7.6.3.9       PrivateToSensitive() ................................................................................... 101
          7.6.3.10      SensitiveToDuplicate()................................................................................ 103
          7.6.3.11      DuplicateToSensitive()................................................................................ 105
          7.6.3.12      SecretToCredential() .................................................................................. 107
          7.6.3.13      CredentialToSecret() .................................................................................. 108
8   Subsystem........................................................................................................................ 109
    8.1 CommandAudit.c ..................................................................................................... 109
       8.1.1       Introduction ...................................................................................................... 109
       8.1.2       Includes ........................................................................................................... 109
       8.1.3       Functions ......................................................................................................... 109
          8.1.3.1       CommandAuditPreInstall_Init() ................................................................... 109
          8.1.3.2       CommandAuditStartup() ............................................................................. 109
          8.1.3.3       CommandAuditSet() ................................................................................... 110
          8.1.3.4       CommandAuditClear() ................................................................................ 110
          8.1.3.5       CommandAuditIsRequired() ........................................................................ 111
          8.1.3.6       CommandAuditCapGetCCList() .................................................................. 111
          8.1.3.7       CommandAuditGetDigest ............................................................................ 112
    8.2     DA.c ........................................................................................................................ 113
       8.2.1       Introduction ...................................................................................................... 113
       8.2.2       Includes and Data Definitions ........................................................................... 113
       8.2.3       Functions ......................................................................................................... 113
          8.2.3.1       DAPreInstall_Init() ...................................................................................... 113
          8.2.3.2       DAStartup() ................................................................................................ 114
          8.2.3.3       DARegisterFailure() .................................................................................... 114
          8.2.3.4       DASelfHeal() .............................................................................................. 115
    8.3     Hierarchy.c .............................................................................................................. 116
       8.3.1       Introduction ...................................................................................................... 116
       8.3.2       Includes ........................................................................................................... 116
       8.3.3       Functions ......................................................................................................... 116
          8.3.3.1       HierarchyPreInstall() ................................................................................... 116
          8.3.3.2       HierarchyStartup() ...................................................................................... 117
          8.3.3.3       HierarchyGetProof() ................................................................................... 118
          8.3.3.4       HierarchyGetPrimarySeed() ........................................................................ 118
          8.3.3.5       HierarchyIsEnabled() .................................................................................. 119

Page vi                                                 TCG Published                                                      Family "2.0"
October 30, 2014                               Copyright © TCG 2006-2014                                 Level 00 Revision 01.16
Part 4: Supporting Routines                                                                     Trusted Platform Module Library

    8.4     NV.c ........................................................................................................................ 119
       8.4.1      Introduction ...................................................................................................... 119
       8.4.2      Includes, Defines and Data Definitions ............................................................. 119
       8.4.3      NV Utility Functions .......................................................................................... 120
          8.4.3.1       NvCheckState() .......................................................................................... 120
          8.4.3.2       NvIsAvailable() ........................................................................................... 120
          8.4.3.3       NvCommit ................................................................................................... 120
          8.4.3.4       NvReadMaxCount() .................................................................................... 121
          8.4.3.5       NvWriteMaxCount() .................................................................................... 121
       8.4.4      NV Index and Persistent Object Access Functions ............................................ 121
          8.4.4.1       Introduction ................................................................................................ 121
          8.4.4.2       NvNext() ..................................................................................................... 121
          8.4.4.3       NvGetEnd() ................................................................................................ 122
          8.4.4.4       NvGetFreeByte ........................................................................................... 122
          8.4.4.5       NvGetEvictObjectSize................................................................................. 123
          8.4.4.6       NvGetCounterSize ...................................................................................... 123
          8.4.4.7       NvTestSpace() ............................................................................................ 123
          8.4.4.8       NvAdd() ...................................................................................................... 124
          8.4.4.9       NvDelete() .................................................................................................. 124
       8.4.5      RAM-based NV Index Data Access Functions ................................................... 125
          8.4.5.1       Introduction ................................................................................................ 125
          8.4.5.2       NvTestRAMSpace() .................................................................................... 125
          8.4.5.3       NvGetRamIndexOffset ................................................................................ 126
          8.4.5.4       NvAddRAM() .............................................................................................. 126
          8.4.5.5       NvDeleteRAM() .......................................................................................... 127
       8.4.6      Utility Functions ................................................................................................ 128
          8.4.6.1       NvInitStatic() .............................................................................................. 128
          8.4.6.2       NvInit() ....................................................................................................... 129
          8.4.6.3       NvReadReserved() ..................................................................................... 129
          8.4.6.4       NvWriteReserved() ..................................................................................... 130
          8.4.6.5       NvReadPersistent() .................................................................................... 130
          8.4.6.6       NvIsPlatformPersistentHandle() .................................................................. 131
          8.4.6.7       NvIsOwnerPersistentHandle() ..................................................................... 131
          8.4.6.8       NvNextIndex() ............................................................................................ 131
          8.4.6.9       NvNextEvict() ............................................................................................. 132
          8.4.6.10      NvFindHandle() .......................................................................................... 132
          8.4.6.11      NvPowerOn() .............................................................................................. 133
          8.4.6.12      NvStateSave() ............................................................................................ 133
          8.4.6.13      NvEntityStartup() ........................................................................................ 134
       8.4.7      NV Access Functions ....................................................................................... 135
          8.4.7.1       Introduction ................................................................................................ 135
          8.4.7.2       NvIsUndefinedIndex() ................................................................................. 135
          8.4.7.3       NvIndexIsAccessible() ................................................................................ 136
          8.4.7.4       NvIsUndefinedEvictHandle() ....................................................................... 137
          8.4.7.5       NvGetEvictObject() ..................................................................................... 138
          8.4.7.6       NvGetIndexInfo() ........................................................................................ 138
          8.4.7.7       NvInitialCounter() ....................................................................................... 139
          8.4.7.8       NvGetIndexData() ....................................................................................... 139
          8.4.7.9       NvGetIntIndexData() ................................................................................... 140
          8.4.7.10      NvWriteIndexInfo() ...................................................................................... 141
          8.4.7.11      NvWriteIndexData() .................................................................................... 142
          8.4.7.12      NvGetName() ............................................................................................. 143
          8.4.7.13      NvDefineIndex().......................................................................................... 143

Family "2.0"                                            TCG Published                                                            Page vii
Level 00 Revision 01.16                       Copyright © TCG 2006-2014                                            October 30, 2014
Trusted Platform Module Library                                                                      Part 4: Supporting Routines

          8.4.7.14      NvAddEvictObject() .................................................................................... 144
          8.4.7.15      NvDeleteEntity() ......................................................................................... 145
          8.4.7.16      NvFlushHierarchy() ..................................................................................... 146
          8.4.7.17      NvSetGlobalLock()...................................................................................... 147
          8.4.7.18      InsertSort() ................................................................................................. 148
          8.4.7.19      NvCapGetPersistent() ................................................................................. 149
          8.4.7.20      NvCapGetIndex() ........................................................................................ 150
          8.4.7.21      NvCapGetIndexNumber() ............................................................................ 151
          8.4.7.22      NvCapGetPersistentNumber() .................................................................... 151
          8.4.7.23      NvCapGetPersistentAvail() ......................................................................... 151
          8.4.7.24      NvCapGetCounterNumber() ........................................................................ 151
          8.4.7.25      NvCapGetCounterAvail() ............................................................................ 152
    8.5     Object.c................................................................................................................... 153
       8.5.1      Introduction ...................................................................................................... 153
       8.5.2      Includes and Data Definitions ........................................................................... 153
       8.5.3      Functions ......................................................................................................... 153
          8.5.3.1       ObjectStartup() ........................................................................................... 153
          8.5.3.2       ObjectCleanupEvict() .................................................................................. 153
          8.5.3.3       ObjectIsPresent() ....................................................................................... 154
          8.5.3.4       ObjectIsSequence() .................................................................................... 154
          8.5.3.5       ObjectGet() ................................................................................................. 155
          8.5.3.6       ObjectGetName() ........................................................................................ 155
          8.5.3.7       ObjectGetNameAlg() ................................................................................... 155
          8.5.3.8       ObjectGetQualifiedName() .......................................................................... 156
          8.5.3.9       ObjectDataGetHierarchy() .......................................................................... 156
          8.5.3.10      ObjectGetHierarchy() .................................................................................. 156
          8.5.3.11      ObjectAllocateSlot() .................................................................................... 157
          8.5.3.12      ObjectLoad()............................................................................................... 157
          8.5.3.13      AllocateSequenceSlot() .............................................................................. 160
          8.5.3.14      ObjectCreateHMACSequence() .................................................................. 160
          8.5.3.15      ObjectCreateHashSequence() .................................................................... 161
          8.5.3.16      ObjectCreateEventSequence() ................................................................... 161
          8.5.3.17      ObjectTerminateEvent() .............................................................................. 162
          8.5.3.18      ObjectContextLoad() ................................................................................... 163
          8.5.3.19      ObjectFlush() .............................................................................................. 163
          8.5.3.20      ObjectFlushHierarchy() ............................................................................... 163
          8.5.3.21      ObjectLoadEvict() ....................................................................................... 164
          8.5.3.22      ObjectComputeName() ............................................................................... 165
          8.5.3.23      ObjectComputeQualifiedName() ................................................................. 166
          8.5.3.24      ObjectDataIsStorage() ................................................................................ 166
          8.5.3.25      ObjectIsStorage() ....................................................................................... 167
          8.5.3.26      ObjectCapGetLoaded() ............................................................................... 167
          8.5.3.27      ObjectCapGetTransientAvail() .................................................................... 168
    8.6     PCR.c ..................................................................................................................... 168
       8.6.1      Introduction ...................................................................................................... 168
       8.6.2      Includes, Defines, and Data Definitions ............................................................ 168
       8.6.3      Functions ......................................................................................................... 169
          8.6.3.1       PCRBelongsAuthGroup() ............................................................................ 169
          8.6.3.2       PCRBelongsPolicyGroup() .......................................................................... 169
          8.6.3.3       PCRBelongsTCBGroup() ............................................................................ 170
          8.6.3.4       PCRPolicyIsAvailable() ............................................................................... 170
          8.6.3.5       PCRGetAuthValue() .................................................................................... 171
          8.6.3.6       PCRGetAuthPolicy() ................................................................................... 171
          8.6.3.7       PCRSimStart() ............................................................................................ 172
          8.6.3.8       GetSavedPcrPointer() ................................................................................. 172

Page viii                                               TCG Published                                                    Family "2.0"
October 30, 2014                               Copyright © TCG 2006-2014                               Level 00 Revision 01.16
Part 4: Supporting Routines                                                                     Trusted Platform Module Library

          8.6.3.9       PcrIsAllocated() .......................................................................................... 173
          8.6.3.10      GetPcrPointer() .......................................................................................... 174
          8.6.3.11      IsPcrSelected() ........................................................................................... 175
          8.6.3.12      FilterPcr() ................................................................................................... 175
          8.6.3.13      PcrDrtm() .................................................................................................... 176
          8.6.3.14      PCRStartup() .............................................................................................. 176
          8.6.3.15      PCRStateSave() ......................................................................................... 177
          8.6.3.16      PCRIsStateSaved() .................................................................................... 178
          8.6.3.17      PCRIsResetAllowed() ................................................................................. 179
          8.6.3.18      PCRChanged() ........................................................................................... 179
          8.6.3.19      PCRIsExtendAllowed() ............................................................................... 179
          8.6.3.20      PCRExtend() .............................................................................................. 180
          8.6.3.21      PCRComputeCurrentDigest() ...................................................................... 181
          8.6.3.22      PCRRead() ................................................................................................. 181
          8.6.3.23      PcrWrite() ................................................................................................... 183
          8.6.3.24      PCRAllocate() ............................................................................................. 183
          8.6.3.25      PCRSetValue() ........................................................................................... 185
          8.6.3.26      PCRResetDynamics ................................................................................... 185
          8.6.3.27      PCRCapGetAllocation() .............................................................................. 186
          8.6.3.28      PCRSetSelectBit() ...................................................................................... 186
          8.6.3.29      PCRGetProperty() ...................................................................................... 187
          8.6.3.30      PCRCapGetProperties() ............................................................................. 188
          8.6.3.31      PCRCapGetHandles() ................................................................................. 189
    8.7     PP.c ........................................................................................................................ 190
       8.7.1      Introduction ...................................................................................................... 190
       8.7.2      Includes ........................................................................................................... 190
       8.7.3      Functions ......................................................................................................... 190
          8.7.3.1       PhysicalPresencePreInstall_Init() ............................................................... 190
          8.7.3.2       PhysicalPresenceCommandSet() ................................................................ 191
          8.7.3.3       PhysicalPresenceCommandClear() ............................................................. 191
          8.7.3.4       PhysicalPresenceIsRequired() .................................................................... 192
          8.7.3.5       PhysicalPresenceCapGetCCList() .............................................................. 192
    8.8     Session.c ................................................................................................................ 193
       8.8.1      Introduction ...................................................................................................... 193
       8.8.2      Includes, Defines, and Local Variables ............................................................. 194
       8.8.3      File Scope Function -- ContextIdSetOldest() ..................................................... 194
       8.8.4      Startup Function -- SessionStartup() ................................................................ 195
       8.8.5      Access Functions ............................................................................................. 196
          8.8.5.1       SessionIsLoaded() ...................................................................................... 196
          8.8.5.2       SessionIsSaved() ....................................................................................... 196
          8.8.5.3       SessionPCRValueIsCurrent() ...................................................................... 197
          8.8.5.4       SessionGet() .............................................................................................. 197
       8.8.6      Utility Functions ................................................................................................ 198
          8.8.6.1       ContextIdSessionCreate() ........................................................................... 198
          8.8.6.2       SessionCreate().......................................................................................... 199
          8.8.6.3       SessionContextSave() ................................................................................ 201
          8.8.6.4       SessionContextLoad() ................................................................................ 202
          8.8.6.5       SessionFlush() ........................................................................................... 204
          8.8.6.6       SessionComputeBoundEntity() ................................................................... 204
          8.8.6.7       SessionInitPolicyData()............................................................................... 205
          8.8.6.8       SessionResetPolicyData() .......................................................................... 206
          8.8.6.9       SessionCapGetLoaded() ............................................................................. 206
          8.8.6.10      SessionCapGetSaved() .............................................................................. 207
          8.8.6.11      SessionCapGetLoadedNumber() ................................................................ 208

Family "2.0"                                            TCG Published                                                            Page ix
Level 00 Revision 01.16                       Copyright © TCG 2006-2014                                            October 30, 2014
Trusted Platform Module Library                                                                        Part 4: Supporting Routines

          8.8.6.12      SessionCapGetLoadedAvail() ..................................................................... 208
          8.8.6.13      SessionCapGetActiveNumber() .................................................................. 209
          8.8.6.14      SessionCapGetActiveAvail() ....................................................................... 209
    8.9     Time.c ..................................................................................................................... 209
       8.9.1       Introduction ...................................................................................................... 209
       8.9.2       Includes ........................................................................................................... 209
       8.9.3       Functions ......................................................................................................... 210
          8.9.3.1       TimePowerOn() .......................................................................................... 210
          8.9.3.2       TimeStartup() ............................................................................................. 210
          8.9.3.3       TimeUpdateToCurrent() .............................................................................. 211
          8.9.3.4       TimeSetAdjustRate() .................................................................................. 212
          8.9.3.5       TimeGetRange() ......................................................................................... 212
          8.9.3.6       TimeFillInfo ................................................................................................ 213
9   Support ............................................................................................................................ 214
    9.1 AlgorithmCap.c ........................................................................................................ 214
       9.1.1       Description ....................................................................................................... 214
       9.1.2       Includes and Defines ........................................................................................ 214
       9.1.3       AlgorithmCapGetImplemented() ........................................................................ 215
    9.2     Bits.c ....................................................................................................................... 217
       9.2.1       Introduction ...................................................................................................... 217
       9.2.2       Includes ........................................................................................................... 217
       9.2.3       Functions ......................................................................................................... 217
          9.2.3.1       BitIsSet() .................................................................................................... 217
          9.2.3.2       BitSet() ....................................................................................................... 217
          9.2.3.3       BitClear() .................................................................................................... 218
    9.3     CommandAttributeData.c ........................................................................................ 218
    9.4     CommandCodeAttributes.c ...................................................................................... 224
       9.4.1       Introduction ...................................................................................................... 224
       9.4.2       Includes and Defines ........................................................................................ 224
       9.4.3       Command Attribute Functions .......................................................................... 224
          9.4.3.1       CommandAuthRole() .................................................................................. 224
          9.4.3.2       CommandIsImplemented() .......................................................................... 224
          9.4.3.3       CommandGetAttribute() .............................................................................. 225
          9.4.3.4       EncryptSize() .............................................................................................. 225
          9.4.3.5       DecryptSize().............................................................................................. 226
          9.4.3.6       IsSessionAllowed() ..................................................................................... 226
          9.4.3.7       IsHandleInResponse() ................................................................................ 226
          9.4.3.8       IsWriteOperation() ...................................................................................... 227
          9.4.3.9       IsReadOperation() ...................................................................................... 227
          9.4.3.10      CommandCapGetCCList() .......................................................................... 227
    9.5     DRTM.c ................................................................................................................... 228
       9.5.1       Description ....................................................................................................... 228
       9.5.2       Includes ........................................................................................................... 228
       9.5.3       Functions ......................................................................................................... 229
          9.5.3.1       Signal_Hash_Start() ................................................................................... 229
          9.5.3.2       Signal_Hash_Data() ................................................................................... 229
          9.5.3.3       Signal_Hash_End() ..................................................................................... 229
    9.6     Entity.c .................................................................................................................... 229
       9.6.1       Description ....................................................................................................... 229
       9.6.2       Includes ........................................................................................................... 229

Page x                                                   TCG Published                                                      Family "2.0"
October 30, 2014                               Copyright © TCG 2006-2014                                  Level 00 Revision 01.16
Part 4: Supporting Routines                                                                     Trusted Platform Module Library

       9.6.3      Functions ......................................................................................................... 230
          9.6.3.1       EntityGetLoadStatus() ................................................................................ 230
          9.6.3.2       EntityGetAuthValue() .................................................................................. 232
          9.6.3.3       EntityGetAuthPolicy() ................................................................................. 233
          9.6.3.4       EntityGetName() ......................................................................................... 234
          9.6.3.5       EntityGetHierarchy() ................................................................................... 235
    9.7     Global.c................................................................................................................... 236
       9.7.1      Description ....................................................................................................... 236
       9.7.2      Includes and Defines ........................................................................................ 236
       9.7.3      Global Data Values .......................................................................................... 236
       9.7.4      Private Values .................................................................................................. 237
          9.7.4.1       SessionProcess.c ....................................................................................... 237
          9.7.4.2       DA.c ........................................................................................................... 237
          9.7.4.3       NV.c ........................................................................................................... 237
          9.7.4.4       Object.c ...................................................................................................... 238
          9.7.4.5       PCR.c ......................................................................................................... 238
          9.7.4.6       Session.c .................................................................................................... 238
          9.7.4.7       Manufacture.c ............................................................................................. 238
          9.7.4.8       Power.c ...................................................................................................... 238
          9.7.4.9       MemoryLib.c ............................................................................................... 238
          9.7.4.10      SelfTest.c ................................................................................................... 238
          9.7.4.11      TpmFail.c ................................................................................................... 238
    9.8     Handle.c .................................................................................................................. 239
       9.8.1      Description ....................................................................................................... 239
       9.8.2      Includes ........................................................................................................... 239
       9.8.3      Functions ......................................................................................................... 239
          9.8.3.1       HandleGetType() ........................................................................................ 239
          9.8.3.2       NextPermanentHandle() ............................................................................. 239
          9.8.3.3       PermanentCapGetHandles() ....................................................................... 240
    9.9     Locality.c ................................................................................................................. 241
       9.9.1      Includes ........................................................................................................... 241
       9.9.2      LocalityGetAttributes() ...................................................................................... 241
    9.10 Manufacture.c ......................................................................................................... 241
       9.10.1 Description ....................................................................................................... 241
       9.10.2 Includes and Data Definitions ........................................................................... 241
       9.10.3 Functions ......................................................................................................... 242
          9.10.3.1      TPM_Manufacture() .................................................................................... 242
          9.10.3.2      TPM_TearDown() ....................................................................................... 243
    9.11 Marshal.c ................................................................................................................ 244
       9.11.1     Introduction ...................................................................................................... 244
       9.11.2     Unmarshal and Marshal a Value ....................................................................... 244
       9.11.3     Unmarshal and Marshal a Union ....................................................................... 245
       9.11.4     Unmarshal and Marshal a Structure .................................................................. 247
       9.11.5     Unmarshal and Marshal an Array ..................................................................... 249
       9.11.6     TPM2B Handling .............................................................................................. 251
    9.12 MemoryLib.c............................................................................................................ 252
       9.12.1 Description ....................................................................................................... 252
       9.12.2 Includes and Data Definitions ........................................................................... 252
       9.12.3 Functions on BYTE Arrays................................................................................ 252


Family "2.0"                                            TCG Published                                                            Page xi
Level 00 Revision 01.16                       Copyright © TCG 2006-2014                                           October 30, 2014
Trusted Platform Module Library                                                                       Part 4: Supporting Routines

           9.12.3.1      MemoryMove()............................................................................................ 252
           9.12.3.2      MemoryCopy() ............................................................................................ 253
           9.12.3.3      MemoryEqual() ........................................................................................... 253
           9.12.3.4      MemoryCopy2B() ........................................................................................ 253
           9.12.3.5      MemoryConcat2B() ..................................................................................... 254
           9.12.3.6      Memory2BEqual() ....................................................................................... 254
           9.12.3.7      MemorySet() ............................................................................................... 255
           9.12.3.8      MemoryGetActionInputBuffer().................................................................... 255
           9.12.3.9      MemoryGetActionOutputBuffer() ................................................................. 255
           9.12.3.10     MemoryGetResponseBuffer() ...................................................................... 256
           9.12.3.11     MemoryRemoveTrailingZeros() ................................................................... 256
     9.13 Power.c ................................................................................................................... 256
        9.13.1 Description ....................................................................................................... 256
        9.13.2 Includes and Data Definitions ........................................................................... 256
        9.13.3 Functions ......................................................................................................... 257
           9.13.3.1      TPMInit() .................................................................................................... 257
           9.13.3.2      TPMRegisterStartup() ................................................................................. 257
           9.13.3.3      TPMIsStarted() ........................................................................................... 257
     9.14 PropertyCap.c ......................................................................................................... 257
        9.14.1 Description ....................................................................................................... 257
        9.14.2 Includes ........................................................................................................... 258
        9.14.3 Functions ......................................................................................................... 258
           9.14.3.1      PCRGetProperty() ...................................................................................... 258
           9.14.3.2      TPMCapGetProperties() ............................................................................. 264
     9.15 TpmFail.c ................................................................................................................ 265
        9.15.1 Includes, Defines, and Types ........................................................................... 265
        9.15.2 Typedefs .......................................................................................................... 265
        9.15.3 Local Functions ................................................................................................ 266
           9.15.3.1      MarshalUint16() .......................................................................................... 266
           9.15.3.2      MarshalUint32() .......................................................................................... 266
           9.15.3.3      UnmarshalHeader() .................................................................................... 267
        9.15.4 Public Functions ............................................................................................... 267
           9.15.4.1      SetForceFailureMode() ............................................................................... 267
           9.15.4.2      TpmFail() .................................................................................................... 267
        9.15.5 TpmFailureMode .............................................................................................. 268
10   Cryptographic Functions ................................................................................................... 272
     10.1 Introduction ............................................................................................................. 272
     10.2 CryptUtil.c ............................................................................................................... 272
        10.2.1 Includes ........................................................................................................... 272
        10.2.2 TranslateCryptErrors() ...................................................................................... 272
        10.2.3 Random Number Generation Functions ............................................................ 273
           10.2.3.1      CryptDrbgGetPutState() .............................................................................. 273
           10.2.3.2      CryptStirRandom() ...................................................................................... 273
           10.2.3.3      CryptGenerateRandom() ............................................................................. 273
        10.2.4 Hash/HMAC Functions ..................................................................................... 274
           10.2.4.1      CryptGetContextAlg() ................................................................................. 274
           10.2.4.2      CryptStartHash()......................................................................................... 274
           10.2.4.3      CryptStartHashSequence() ......................................................................... 275
           10.2.4.4      CryptStartHMAC() ....................................................................................... 275

Page xii                                                TCG Published                                                    Family "2.0"
October 30, 2014                               Copyright © TCG 2006-2014                                Level 00 Revision 01.16
Part 4: Supporting Routines                                                                   Trusted Platform Module Library

         10.2.4.5      CryptStartHMACSequence() ....................................................................... 276
         10.2.4.6      CryptStartHMAC2B() .................................................................................. 276
         10.2.4.7      CryptStartHMACSequence2B() ................................................................... 277
         10.2.4.8      CryptUpdateDigest() ................................................................................... 277
         10.2.4.9      CryptUpdateDigest2B() ............................................................................... 278
         10.2.4.10     CryptUpdateDigestInt() ............................................................................... 278
         10.2.4.11     CryptCompleteHash() ................................................................................. 279
         10.2.4.12     CryptCompleteHash2B() ............................................................................. 279
         10.2.4.13     CryptHashBlock() ....................................................................................... 280
         10.2.4.14     CryptCompleteHMAC() ............................................................................... 280
         10.2.4.15     CryptCompleteHMAC2B() ........................................................................... 281
         10.2.4.16     CryptHashStateImportExport() .................................................................... 281
         10.2.4.17     CryptGetHashDigestSize() .......................................................................... 281
         10.2.4.18     CryptGetHashBlockSize() ........................................................................... 282
         10.2.4.19     CryptGetHashAlgByIndex() ......................................................................... 282
         10.2.4.20     CryptSignHMAC() ....................................................................................... 282
         10.2.4.21     CryptHMACVerifySignature() ...................................................................... 283
         10.2.4.22     CryptGenerateKeyedHash() ........................................................................ 283
         10.2.4.23     CryptKDFa() ............................................................................................... 285
         10.2.4.24     CryptKDFaOnce() ....................................................................................... 285
         10.2.4.25     KDFa() ....................................................................................................... 285
         10.2.4.26     CryptKDFe() ............................................................................................... 286
       10.2.5 RSA Functions ................................................................................................. 286
         10.2.5.1      BuildRSA() ................................................................................................. 286
         10.2.5.2      CryptTestKeyRSA() .................................................................................... 286
         10.2.5.3      CryptGenerateKeyRSA() ............................................................................. 287
         10.2.5.4      CryptLoadPrivateRSA() .............................................................................. 288
         10.2.5.5      CryptSelectRSAScheme() ........................................................................... 288
         10.2.5.6      CryptDecryptRSA() ..................................................................................... 289
         10.2.5.7      CryptEncryptRSA() ..................................................................................... 291
         10.2.5.8      CryptSignRSA() .......................................................................................... 292
         10.2.5.9      CryptRSAVerifySignature() ......................................................................... 293
       10.2.6 ECC Functions ................................................................................................. 294
         10.2.6.1      CryptEccGetCurveDataPointer() ................................................................. 294
         10.2.6.2      CryptEccGetKeySizeInBits() ....................................................................... 294
         10.2.6.3      CryptEccGetKeySizeBytes() ....................................................................... 294
         10.2.6.4      CryptEccGetParameter()............................................................................. 294
         10.2.6.5      CryptGetCurveSignScheme() ...................................................................... 295
         10.2.6.6      CryptEccIsPointOnCurve() .......................................................................... 295
         10.2.6.7      CryptNewEccKey() ..................................................................................... 296
         10.2.6.8      CryptEccPointMultiply() .............................................................................. 296
         10.2.6.9      CryptGenerateKeyECC() ............................................................................ 297
         10.2.6.10     CryptSignECC() .......................................................................................... 297
         10.2.6.11     CryptECCVerifySignature() ......................................................................... 298
         10.2.6.12     CryptGenerateR() ....................................................................................... 299
         10.2.6.13     CryptCommit() ............................................................................................ 301
         10.2.6.14     CryptEndCommit() ...................................................................................... 301
         10.2.6.15     CryptCommitCompute() .............................................................................. 301
         10.2.6.16     CryptEccGetParameters() ........................................................................... 302
         10.2.6.17     CryptIsSchemeAnonymous() ....................................................................... 303
       10.2.7 Symmetric Functions ........................................................................................ 303
         10.2.7.1      ParmDecryptSym() ..................................................................................... 303
         10.2.7.2      ParmEncryptSym() ..................................................................................... 304
         10.2.7.3      CryptGenerateNewSymmetric() .................................................................. 305
         10.2.7.4      CryptGenerateKeySymmetric() ................................................................... 306

Family "2.0"                                          TCG Published                                                         Page xiii
Level 00 Revision 01.16                      Copyright © TCG 2006-2014                                         October 30, 2014
Trusted Platform Module Library                                                                     Part 4: Supporting Routines

         10.2.7.5       CryptXORObfuscation() .............................................................................. 307
       10.2.8 Initialization and shut down .............................................................................. 307
         10.2.8.1       CryptInitUnits() ........................................................................................... 307
         10.2.8.2       CryptStopUnits() ......................................................................................... 308
         10.2.8.3       CryptUtilStartup()........................................................................................ 308
       10.2.9 Algorithm-Independent Functions ..................................................................... 309
         10.2.9.1       Introduction ................................................................................................ 309
         10.2.9.2       CryptIsAsymAlgorithm() .............................................................................. 309
         10.2.9.3       CryptGetSymmetricBlockSize() ................................................................... 309
         10.2.9.4       CryptSymmetricEncrypt() ............................................................................ 310
         10.2.9.5       CryptSymmetricDecrypt() ............................................................................ 311
         10.2.9.6       CryptSecretEncrypt() .................................................................................. 313
         10.2.9.7       CryptSecretDecrypt() .................................................................................. 315
         10.2.9.8       CryptParameterEncryption() ....................................................................... 318
         10.2.9.9       CryptParameterDecryption() ....................................................................... 319
         10.2.9.10      CryptComputeSymmetricUnique() ............................................................... 320
         10.2.9.11      CryptComputeSymValue() .......................................................................... 321
         10.2.9.12      CryptCreateObject() ................................................................................... 321
         10.2.9.13      CryptObjectIsPublicConsistent() ................................................................. 324
         10.2.9.14      CryptObjectPublicPrivateMatch() ................................................................ 325
         10.2.9.15      CryptGetSignHashAlg() .............................................................................. 326
         10.2.9.16      CryptIsSplitSign() ....................................................................................... 327
         10.2.9.17      CryptIsSignScheme() .................................................................................. 327
         10.2.9.18      CryptIsDecryptScheme() ............................................................................. 328
         10.2.9.19      CryptSelectSignScheme() ........................................................................... 328
         10.2.9.20      CryptSign() ................................................................................................. 330
         10.2.9.21      CryptVerifySignature() ................................................................................ 331
       10.2.10 Math functions .................................................................................................. 332
         10.2.10.1      CryptDivide() .............................................................................................. 332
         10.2.10.2      CryptCompare() .......................................................................................... 333
         10.2.10.3      CryptCompareSigned() ............................................................................... 333
         10.2.10.4      CryptGetTestResult .................................................................................... 333
       10.2.11 Capability Support ............................................................................................ 334
         10.2.11.1      CryptCapGetECCCurve() ............................................................................ 334
         10.2.11.2      CryptCapGetEccCurveNumber() ................................................................. 335
         10.2.11.3      CryptAreKeySizesConsistent() .................................................................... 335
         10.2.11.4      CryptAlgSetImplemented() .......................................................................... 336
    10.3 Ticket.c ................................................................................................................... 336
       10.3.1 Introduction ...................................................................................................... 336
       10.3.2 Includes ........................................................................................................... 336
       10.3.3 Functions ......................................................................................................... 336
         10.3.3.1       TicketIsSafe() ............................................................................................. 336
         10.3.3.2       TicketComputeVerified() ............................................................................. 337
         10.3.3.3       TicketComputeAuth() .................................................................................. 337
         10.3.3.4       TicketComputeHashCheck() ....................................................................... 338
         10.3.3.5       TicketComputeCreation() ............................................................................ 339
    10.4 CryptSelfTest.c ....................................................................................................... 339
       10.4.1 Introduction ...................................................................................................... 339
       10.4.2 Functions ......................................................................................................... 340
         10.4.2.1       RunSelfTest() ............................................................................................. 340
         10.4.2.2       CryptSelfTest() ........................................................................................... 340

Page xiv                                               TCG Published                                                   Family "2.0"
October 30, 2014                              Copyright © TCG 2006-2014                               Level 00 Revision 01.16
Part 4: Supporting Routines                                                                      Trusted Platform Module Library

            10.4.2.3     CryptIncrementalSelfTest() ......................................................................... 341
            10.4.2.4     CryptInitializeToTest() ................................................................................ 342
            10.4.2.5     CryptTestAlgorithm() .................................................................................. 342
Annex A (informative) Implementation Dependent .................................................................. 344
   A.1 Introduction ............................................................................................................. 344
   A.2 Implementation.h ..................................................................................................... 344
Annex B (informative) Cryptographic Library Interface ............................................................ 359
   B.1 Introduction ............................................................................................................. 359
   B.2 Integer Format ........................................................................................................ 359
   B.3 CryptoEngine.h ....................................................................................................... 359
         B.3.1.     Introduction ...................................................................................................... 359
         B.3.2.     General Purpose Macros .................................................................................. 360
         B.3.3.     Self-test ........................................................................................................... 360
         B.3.4.     Hash-related Structures .................................................................................... 360
         B.3.5.     Asymmetric Structures and Values ................................................................... 362
            B.3.5.1.     ECC-related Structures ............................................................................... 362
            B.3.5.2.     RSA-related Structures ............................................................................... 362
         B.3.6.     Miscelaneous ................................................................................................... 362
      B.4     OsslCryptoEngine.h ................................................................................................ 364
         B.4.1.     Introduction ...................................................................................................... 364
         B.4.2.     Defines ............................................................................................................. 364
      B.5     MathFunctions.c ...................................................................................................... 365
         B.5.1.     Introduction ...................................................................................................... 365
         B.5.2.     Externally Accessible Functions ....................................................................... 365
            B.5.2.1.     _math__Normalize2B() ............................................................................... 365
            B.5.2.2.     _math__Denormalize2B() ........................................................................... 366
            B.5.2.3.     _math__sub() ............................................................................................. 366
            B.5.2.4.     _math__Inc() .............................................................................................. 367
            B.5.2.5.     _math__Dec() ............................................................................................. 368
            B.5.2.6.     _math__Mul() ............................................................................................. 368
            B.5.2.7.     _math__Div() .............................................................................................. 369
            B.5.2.8.     _math__uComp() ........................................................................................ 370
            B.5.2.9.     _math__Comp() .......................................................................................... 371
            B.5.2.10.    _math__ModExp ......................................................................................... 372
            B.5.2.11.    _math__IsPrime() ....................................................................................... 373
      B.6     CpriCryptPri.c .......................................................................................................... 375
         B.6.1.     Introduction ...................................................................................................... 375
         B.6.2.     Includes and Locals .......................................................................................... 375
         B.6.3.     Functions ......................................................................................................... 375
            B.6.3.1.     TpmFail() .................................................................................................... 375
            B.6.3.2.     FAILURE_TRAP() ....................................................................................... 375
            B.6.3.3.     _cpri__InitCryptoUnits() .............................................................................. 375
            B.6.3.4.     _cpri__StopCryptoUnits()............................................................................ 376
            B.6.3.5.     _cpri__Startup() .......................................................................................... 376
      B.7     CpriRNG.c ............................................................................................................... 377
         B.7.1.     Introduction ...................................................................................................... 377
         B.7.2.     Includes ........................................................................................................... 377
         B.7.3.     Functions ......................................................................................................... 377
            B.7.3.1.     _cpri__RngStartup() ................................................................................... 377

Family "2.0"                                             TCG Published                                                           Page xv
Level 00 Revision 01.16                        Copyright © TCG 2006-2014                                           October 30, 2014
Trusted Platform Module Library                                                                      Part 4: Supporting Routines

          B.7.3.2.      _cpri__DrbgGetPutState() .......................................................................... 377
          B.7.3.3.      _cpri__StirRandom() ................................................................................... 378
          B.7.3.4.      _cpri__GenerateRandom().......................................................................... 378
          B.7.3.4.1. _cpri__GenerateSeededRandom() .............................................................. 379
    B.8      CpriHash.c .............................................................................................................. 380
       B.8.1.      Description ....................................................................................................... 380
       B.8.2.      Includes, Defines, and Types ........................................................................... 380
       B.8.3.      Static Functions................................................................................................ 380
          B.8.3.1.      GetHashServer() ........................................................................................ 380
          B.8.3.2.      MarshalHashState() .................................................................................... 381
          B.8.3.3.      GetHashState()........................................................................................... 381
          B.8.3.4.      GetHashInfoPointer() .................................................................................. 382
       B.8.4.      Hash Functions ................................................................................................ 382
          B.8.4.1.      _cpri__HashStartup() .................................................................................. 382
          B.8.4.2.      _cpri__GetHashAlgByIndex() ...................................................................... 382
          B.8.4.3.      _cpri__GetHashBlockSize() ........................................................................ 383
          B.8.4.4.      _cpri__GetHashDER .................................................................................. 383
          B.8.4.5.      _cpri__GetDigestSize() ............................................................................... 383
          B.8.4.6.      _cpri__GetContextAlg() .............................................................................. 384
          B.8.4.7.      _cpri__CopyHashState ............................................................................... 384
          B.8.4.8.      _cpri__StartHash() ..................................................................................... 384
          B.8.4.9.      _cpri__UpdateHash() .................................................................................. 385
          B.8.4.10.     _cpri__CompleteHash() .............................................................................. 386
          B.8.4.11.     _cpri__ImportExportHashState() ................................................................. 387
          B.8.4.12.     _cpri__HashBlock() .................................................................................... 388
       B.8.5.      HMAC Functions .............................................................................................. 389
          B.8.5.1.      _cpri__StartHMAC ...................................................................................... 389
          B.8.5.2.      _cpri_CompleteHMAC() .............................................................................. 390
       B.8.6.      Mask and Key Generation Functions ................................................................ 390
          B.8.6.1.      _crypi_MGF1() ............................................................................................ 390
          B.8.6.2.      _cpri_KDFa() .............................................................................................. 392
          B.8.6.3.      _cpri__KDFe() ............................................................................................ 394
    B.9 CpriHashData.c ....................................................................................................... 396
    B.10 CpriMisc.c ............................................................................................................... 397
       B.10.1. Includes ........................................................................................................... 397
       B.10.2. Functions ......................................................................................................... 397
          B.10.2.1. BnTo2B() .................................................................................................... 397
          B.10.2.2. Copy2B() .................................................................................................... 397
          B.10.2.3. BnFrom2B() ................................................................................................ 398
    B.11 CpriSym.c ............................................................................................................... 399
       B.11.1. Introduction ...................................................................................................... 399
       B.11.2. Includes, Defines, and Typedefs ....................................................................... 399
       B.11.3. Utility Functions ................................................................................................ 399
          B.11.3.1. _cpri_SymStartup() ..................................................................................... 399
          B.11.3.2. _cpri__GetSymmetricBlockSize() ................................................................ 399
       B.11.4. AES Encryption ................................................................................................ 400
          B.11.4.1. _cpri__AESEncryptCBC() ........................................................................... 400
          B.11.4.2. _cpri__AESDecryptCBC() ........................................................................... 401
          B.11.4.3. _cpri__AESEncryptCFB() ........................................................................... 402

Page xvi                                                TCG Published                                                   Family "2.0"
October 30, 2014                               Copyright © TCG 2006-2014                               Level 00 Revision 01.16
Part 4: Supporting Routines                                                                  Trusted Platform Module Library

         B.11.4.4. _cpri__AESDecryptCFB() ........................................................................... 403
         B.11.4.5. _cpri__AESEncryptCTR() ........................................................................... 404
         B.11.4.6. _cpri__AESDecryptCTR() ........................................................................... 405
         B.11.4.7. _cpri__AESEncryptECB() ........................................................................... 405
         B.11.4.8. _cpri__AESDecryptECB() ........................................................................... 406
         B.11.4.9. _cpri__AESEncryptOFB() ........................................................................... 406
         B.11.4.10. _cpri__AESDecryptOFB() ........................................................................... 407
       B.11.5. SM4 Encryption ................................................................................................ 408
         B.11.5.1. _cpri__SM4EncryptCBC() ........................................................................... 408
         B.11.5.2. _cpri__SM4DecryptCBC() ........................................................................... 409
         B.11.5.3. _cpri__SM4EncryptCFB() ........................................................................... 410
         B.11.5.4. _cpri__SM4DecryptCFB() ........................................................................... 410
         B.11.5.5. _cpri__SM4EncryptCTR() ........................................................................... 411
         B.11.5.6. _cpri__SM4DecryptCTR() ........................................................................... 412
         B.11.5.7. _cpri__SM4EncryptECB() ........................................................................... 413
         B.11.5.8. _cpri__SM4DecryptECB() ........................................................................... 413
         B.11.5.9. _cpri__SM4EncryptOFB() ........................................................................... 414
         B.11.5.10. _cpri__SM4DecryptOFB() ........................................................................... 415
    B.12 RSA Files ................................................................................................................ 416
       B.12.1. CpriRSA.c ........................................................................................................ 416
         B.12.1.1. Introduction ................................................................................................ 416
         B.12.1.2. Includes ...................................................................................................... 416
         B.12.1.3. Local Functions .......................................................................................... 416
         B.12.1.3.1.        RsaPrivateExponent() ............................................................................ 416
         B.12.1.3.2.        _cpri__TestKeyRSA() ............................................................................. 418
         B.12.1.3.3.        RSAEP() ................................................................................................ 420
         B.12.1.3.4.        RSADP() ................................................................................................ 420
         B.12.1.3.5.        OaepEncode() ........................................................................................ 421
         B.12.1.3.6.        OaepDecode() ........................................................................................ 423
         B.12.1.3.7.        PKSC1v1_5Encode() .............................................................................. 425
         B.12.1.3.8.        RSAES_Decode() ................................................................................... 425
         B.12.1.3.9.        PssEncode() ........................................................................................... 426
         B.12.1.3.10.        PssDecode() ........................................................................................ 427
         B.12.1.3.11.        PKSC1v1_5SignEncode() ..................................................................... 429
         B.12.1.3.12.        RSASSA_Decode()............................................................................... 430
         B.12.1.4. Externally Accessible Functions .................................................................. 431
         B.12.1.4.1.        _cpri__RsaStartup() ............................................................................... 431
         B.12.1.4.2.        _cpri__EncryptRSA() .............................................................................. 431
         B.12.1.4.3.        _cpri__DecryptRSA() .............................................................................. 433
         B.12.1.4.4.        _cpri__SignRSA() ................................................................................... 434
         B.12.1.4.5.        _cpri__ValidateSignatureRSA() .............................................................. 435
         B.12.1.4.6.        _cpri__GenerateKeyRSA() ..................................................................... 435
       B.12.2. Alternative RSA Key Generation ....................................................................... 440
         B.12.2.1. Introduction ................................................................................................ 440
         B.12.2.2. RSAKeySieve.h .......................................................................................... 440
         B.12.2.3. RSAKeySieve.c .......................................................................................... 443
         B.12.2.3.1.        Includes and defines .............................................................................. 443
         B.12.2.3.2.        Bit Manipulation Functions ..................................................................... 443
         B.12.2.3.3.        Miscellaneous Functions ........................................................................ 445
         B.12.2.3.4.        Public Function ...................................................................................... 455
         B.12.2.4. RSAData.c .................................................................................................. 459
    B.13 Elliptic Curve Files .................................................................................................. 471
Family "2.0"                                           TCG Published                                                       Page xvii
Level 00 Revision 01.16                      Copyright © TCG 2006-2014                                         October 30, 2014
Trusted Platform Module Library                                                                          Part 4: Supporting Routines

         B.13.1. CpriDataEcc.h .................................................................................................. 471
         B.13.2. CpriDataEcc.c .................................................................................................. 472
         B.13.3. CpriECC.c ........................................................................................................ 479
            B.13.3.1. Includes and Defines .................................................................................. 479
            B.13.3.2. Functions .................................................................................................... 479
            B.13.3.2.1.        _cpri__EccStartup() ................................................................................ 479
            B.13.3.2.2.        _cpri__GetCurveIdByIndex() .................................................................. 479
            B.13.3.2.3.        _cpri__EccGetParametersByCurveId() ................................................... 479
            B.13.3.2.4.        Point2B() ................................................................................................ 480
            B.13.3.2.5.        EccCurveInit() ........................................................................................ 481
            B.13.3.2.6.        PointFrom2B() ........................................................................................ 482
            B.13.3.2.7.        EccInitPoint2B() ..................................................................................... 482
            B.13.3.2.8.        PointMul() .............................................................................................. 483
            B.13.3.2.9.        GetRandomPrivate() ............................................................................... 483
            B.13.3.2.10.        Mod2B() ............................................................................................... 484
            B.13.3.2.11.        _cpri__EccPointMultiply ....................................................................... 484
            B.13.3.2.12.        ClearPoint2B() ...................................................................................... 486
            B.13.3.2.13.        _cpri__EccCommitCompute() ............................................................... 486
            B.13.3.2.14.        _cpri__EccIsPointOnCurve() ................................................................ 489
            B.13.3.2.15.        _cpri__GenerateKeyEcc() ..................................................................... 490
            B.13.3.2.16.        _cpri__GetEphemeralEcc() ................................................................... 492
            B.13.3.2.17.        SignEcdsa().......................................................................................... 492
            B.13.3.2.18.        EcDaa() ................................................................................................ 495
            B.13.3.2.19.        SchnorrEcc() ........................................................................................ 496
            B.13.3.2.20.        SignSM2() ............................................................................................ 499
            B.13.3.2.21.        _cpri__SignEcc() .................................................................................. 502
            B.13.3.2.22.        ValidateSignatureEcdsa() ..................................................................... 502
            B.13.3.2.23.        ValidateSignatureEcSchnorr() .............................................................. 505
            B.13.3.2.24.        ValidateSignatueSM2Dsa() ................................................................... 506
            B.13.3.2.25.        _cpri__ValidateSignatureEcc() ............................................................. 508
            B.13.3.2.26.        avf1() ................................................................................................... 509
            B.13.3.2.27.        C_2_2_MQV() ...................................................................................... 509
            B.13.3.2.28.        avfSm2() .............................................................................................. 512
            B.13.3.2.29.        C_2_2_ECDH() .................................................................................... 514
            B.13.3.2.30.        _cpri__C_2_2_KeyExchange() ............................................................. 515
Annex C (informative) Simulation Environment ....................................................................... 517
   C.1 Introduction ............................................................................................................. 517
   C.2 Cancel.c .................................................................................................................. 517
         C.2.1.      Introduction ...................................................................................................... 517
         C.2.2.      Includes, Typedefs, Structures, and Defines ..................................................... 517
         C.2.3.      Functions ......................................................................................................... 517
            C.2.3.1.       _plat__IsCanceled() ................................................................................... 517
            C.2.3.2.       _plat__SetCancel() ..................................................................................... 517
            C.2.3.3.       _plat__ClearCancel() .................................................................................. 518
      C.3      Clock.c .................................................................................................................... 519
         C.3.1.      Introduction ...................................................................................................... 519
         C.3.2.      Includes and Data Definitions ........................................................................... 519
         C.3.3.      Functions ......................................................................................................... 519
            C.3.3.1.       _plat__ClockReset() ................................................................................... 519
            C.3.3.2.       _plat__ClockTimeFromStart() ..................................................................... 519
            C.3.3.3.       _plat__ClockTimeElapsed() ........................................................................ 519
            C.3.3.4.       _plat__ClockAdjustRate() ........................................................................... 520
      C.4      Entropy.c ................................................................................................................. 521

Page xviii                                                 TCG Published                                                     Family "2.0"
October 30, 2014                                  Copyright © TCG 2006-2014                                Level 00 Revision 01.16
Part 4: Supporting Routines                                                                    Trusted Platform Module Library

       C.4.1.     Includes ........................................................................................................... 521
       C.4.2.     Local values ..................................................................................................... 521
       C.4.3.     _plat__GetEntropy() ......................................................................................... 521
    C.5     LocalityPlat.c ........................................................................................................... 523
       C.5.1.     Includes ........................................................................................................... 523
       C.5.2.     Functions ......................................................................................................... 523
          C.5.2.1.     _plat__LocalityGet() ................................................................................... 523
          C.5.2.2.     _plat__LocalitySet() .................................................................................... 523
          C.5.2.3.     _plat__IsRsaKeyCacheEnabled() ............................................................... 523
    C.6     NVMem.c ................................................................................................................ 524
       C.6.1.     Introduction ...................................................................................................... 524
       C.6.2.     Includes ........................................................................................................... 524
       C.6.3.     Functions ......................................................................................................... 524
          C.6.3.1.     _plat__NvErrors() ....................................................................................... 524
          C.6.3.2.     _plat__NVEnable() ..................................................................................... 524
          C.6.3.3.     _plat__NVDisable() .................................................................................... 525
          C.6.3.4.     _plat__IsNvAvailable() ................................................................................ 526
          C.6.3.5.     _plat__NvMemoryRead() ............................................................................ 526
          C.6.3.6.     _plat__NvIsDifferent() ................................................................................. 526
          C.6.3.7.     _plat__NvMemoryWrite() ............................................................................ 527
          C.6.3.8.     _plat__NvMemoryMove() ............................................................................ 527
          C.6.3.9.     _plat__NvCommit() ..................................................................................... 527
          C.6.3.10.    _plat__SetNvAvail() .................................................................................... 528
          C.6.3.11.    _plat__ClearNvAvail() ................................................................................. 528
    C.7     PowerPlat.c ............................................................................................................. 529
       C.7.1.     Includes and Function Prototypes ..................................................................... 529
       C.7.2.     Functions ......................................................................................................... 529
          C.7.2.1.     _plat__Signal_PowerOn() ........................................................................... 529
          C.7.2.2.     _plat__WasPowerLost() .............................................................................. 529
          C.7.2.3.     _plat_Signal_Reset() .................................................................................. 529
          C.7.2.4.     _plat__Signal_PowerOff() ........................................................................... 530
    C.8     Platform.h ............................................................................................................... 531
       C.8.1.     Includes and Defines ........................................................................................ 531
       C.8.2.     Power Functions ............................................................................................... 531
          C.8.2.1.     _plat__Signal_PowerOn ............................................................................. 531
          C.8.2.2.     _plat__Signal_Reset ................................................................................... 531
          C.8.2.3.     _plat__WasPowerLost() .............................................................................. 531
          C.8.2.4.     _plat__Signal_PowerOff() ........................................................................... 531
       C.8.3.     Physical Presence Functions ............................................................................ 531
          C.8.3.1.     _plat__PhysicalPresenceAsserted() ............................................................ 531
          C.8.3.2.     _plat__Signal_PhysicalPresenceOn............................................................ 532
          C.8.3.3.     _plat__Signal_PhysicalPresenceOff() ......................................................... 532
       C.8.4.     Command Canceling Functions ........................................................................ 532
          C.8.4.1.     _plat__IsCanceled() ................................................................................... 532
          C.8.4.2.     _plat__SetCancel() ..................................................................................... 532
          C.8.4.3.     _plat__ClearCancel() .................................................................................. 532
       C.8.5.     NV memory functions ....................................................................................... 533
          C.8.5.1.     _plat__NvErrors() ....................................................................................... 533
          C.8.5.2.     _plat__NVEnable() ..................................................................................... 533

Family "2.0"                                           TCG Published                                                         Page xix
Level 00 Revision 01.16                       Copyright © TCG 2006-2014                                         October 30, 2014
Trusted Platform Module Library                                                                       Part 4: Supporting Routines

            C.8.5.3.      _plat__NVDisable() .................................................................................... 533
            C.8.5.4.      _plat__IsNvAvailable() ................................................................................ 533
            C.8.5.5.      _plat__NvCommit() ..................................................................................... 533
            C.8.5.6.      _plat__NvMemoryRead() ............................................................................ 534
            C.8.5.7.      _plat__NvIsDifferent() ................................................................................. 534
            C.8.5.8.      _plat__NvMemoryWrite() ............................................................................ 534
            C.8.5.9.      _plat__NvMemoryMove() ............................................................................ 534
            C.8.5.10.     _plat__SetNvAvail() .................................................................................... 535
            C.8.5.11.     _plat__ClearNvAvail() ................................................................................. 535
         C.8.6.     Locality Functions ............................................................................................ 535
            C.8.6.1.      _plat__LocalityGet() ................................................................................... 535
            C.8.6.2.      _plat__LocalitySet() .................................................................................... 535
            C.8.6.3.      _plat__IsRsaKeyCacheEnabled() ............................................................... 535
         C.8.7.     Clock Constants and Functions ........................................................................ 535
            C.8.7.1.      _plat__ClockReset() ................................................................................... 536
            C.8.7.2.      _plat__ClockTimeFromStart() ..................................................................... 536
            C.8.7.3.      _plat__ClockTimeElapsed() ........................................................................ 536
            C.8.7.4.      _plat__ClockAdjustRate() ........................................................................... 536
         C.8.8.     Single Function Files ........................................................................................ 537
            C.8.8.1.      _plat__GetEntropy() ................................................................................... 537
      C.9 PlatformData.h ........................................................................................................ 538
      C.10 PlatformData.c ........................................................................................................ 539
         C.10.1. Description ....................................................................................................... 539
         C.10.2. Includes ........................................................................................................... 539
      C.11 PPPlat.c .................................................................................................................. 540
         C.11.1. Description ....................................................................................................... 540
         C.11.2. Includes ........................................................................................................... 540
         C.11.3. Functions ......................................................................................................... 540
            C.11.3.1. _plat__PhysicalPresenceAsserted() ............................................................ 540
            C.11.3.2. _plat__Signal_PhysicalPresenceOn() ......................................................... 540
            C.11.3.3. _plat__Signal_PhysicalPresenceOff() ......................................................... 540
      C.12 Unique.c .................................................................................................................. 541
         C.12.1. Introduction ...................................................................................................... 541
         C.12.2. Includes ........................................................................................................... 541
         C.12.3. _plat__GetUnique() .......................................................................................... 541
Annex D (informative) Remote Procedure Interface ................................................................ 542
   D.1 Introduction ............................................................................................................. 542
   D.2 TpmTcpProtocol.h ................................................................................................... 543
         D.2.1.     Introduction ...................................................................................................... 543
         D.2.2.     Typedefs and Defines ....................................................................................... 543
      D.3     TcpServer.c ............................................................................................................. 545
         D.3.1.     Description ....................................................................................................... 545
         D.3.2.     Includes, Locals, Defines and Function Prototypes ........................................... 545
         D.3.3.     Functions ......................................................................................................... 545
            D.3.3.1.      CreateSocket() ........................................................................................... 545
            D.3.3.2.      PlatformServer() ......................................................................................... 546
            D.3.3.3.      PlatformSvcRoutine() .................................................................................. 547
            D.3.3.4.      PlatformSignalService() .............................................................................. 548
            D.3.3.5.      RegularCommandService() ......................................................................... 549

Page xx                                                  TCG Published                                                   Family "2.0"
October 30, 2014                                Copyright © TCG 2006-2014                               Level 00 Revision 01.16
Part 4: Supporting Routines                                                                    Trusted Platform Module Library

          D.3.3.6.     StartTcpServer() ......................................................................................... 549
          D.3.3.7.     ReadBytes() ............................................................................................... 550
          D.3.3.8.     WriteBytes() ............................................................................................... 550
          D.3.3.9.     WriteUINT32() ............................................................................................ 551
          D.3.3.10.    ReadVarBytes() .......................................................................................... 551
          D.3.3.11.    WriteVarBytes() .......................................................................................... 552
          D.3.3.12.    TpmServer() ............................................................................................... 552
    D.4     TPMCmdp.c ............................................................................................................ 555
       D.4.1.     Description ....................................................................................................... 555
       D.4.2.     Includes and Data Definitions ........................................................................... 555
       D.4.3.     Functions ......................................................................................................... 555
          D.4.3.1.     Signal_PowerOn() ...................................................................................... 555
          D.4.3.2.     Signal_PowerOff() ...................................................................................... 556
          D.4.3.3.     _rpc__ForceFailureMode() .......................................................................... 556
          D.4.3.4.     _rpc__Signal_PhysicalPresenceOn() .......................................................... 556
          D.4.3.5.     _rpc__Signal_PhysicalPresenceOff() .......................................................... 556
          D.4.3.6.     _rpc__Signal_Hash_Start() ......................................................................... 557
          D.4.3.7.     _rpc__Signal_Hash_Data() ......................................................................... 557
          D.4.3.8.     _rpc__Signal_HashEnd() ............................................................................ 557
          D.4.3.9.     _rpc__Signal_CancelOn() ........................................................................... 558
          D.4.3.10.    _rpc__Signal_CancelOff() ........................................................................... 558
          D.4.3.11.    _rpc__Signal_NvOn() ................................................................................. 559
          D.4.3.12.    _rpc__Signal_NvOff() ................................................................................. 559
          D.4.3.13.    _rpc__Shutdown() ...................................................................................... 559
    D.5     TPMCmds.c............................................................................................................. 560
       D.5.1.     Description ....................................................................................................... 560
       D.5.2.     Includes, Defines, Data Definitions, and Function Prototypes ........................... 560
       D.5.3.     Functions ......................................................................................................... 560
          D.5.3.1.     Usage() ...................................................................................................... 560
          D.5.3.2.     main() ......................................................................................................... 560




Family "2.0"                                           TCG Published                                                          Page xxi
Level 00 Revision 01.16                      Copyright © TCG 2006-2014                                           October 30, 2014
Part 4: Supporting Routines                                              Trusted Platform Module Library


                              Trusted Platform Module Library
                                Part 4: Supporting Routines

1     Scope

This part contains C code that describes the algorithms and methods used by the command code in TPM
2.0 Part 3. The code in this document augments TPM 2.0 Part 2 and TPM 2.0 Part 3 to provide a
complete description of a TPM, including the supporting framework for the code that performs the
command actions.
Any TPM 2.0 Part 4 code may be replaced by code that provides similar results when interfacing to the
action code in TPM 2.0 Part 3. The behavior of code in this document that is not included in an annex is
normative, as observed at the interfaces with TPM 2.0 Part 3 code. Code in an annex is provided for
completeness, that is, to allow a full implementation of the specification from the provided code.
The code in parts 3 and 4 is written to define the behavior of a compliant TPM. In some cases (e.g.,
firmware update), it is not possible to provide a compliant implementation. In those cases, any
implementation provided by the vendor that meets the general description of the function provided in TPM
2.0 Part 3 would be compliant.
The code in parts 3 and 4 is not written to meet any particular level of conformance nor does this
specification require that a TPM meet any particular level of conformance.


2     Terms and definitions

For the purposes of this document, the terms and definitions given in TPM 2.0 Part 1 apply.


3     Symbols and abbreviated terms

For the purposes of this document, the symbols and abbreviated terms given in TPM 2.0 Part 1 apply.


4     Automation

TPM 2.0 Part 2 and 3 are constructed so that they can be processed by an automated parser. For
example, TPM 2.0 Part 2 can be processed to generate header file contents such as structures, typedefs,
and enums. TPM 2.0 Part 3 can be processed to generate command and response marshaling and
unmarshaling code.
The automated processor is not provided to the TCG. It was used to generate the Microsoft Visual Studio
TPM simulator files. These files are not specification reference code, but rather design examples.

4.1     Configuration Parser

The tables in the TPM 2.0 Part 2 Annexes are constructed so that they can be processed by a program.
The program that processes these tables in the TPM 2.0 Part 2 Annexes is called "The TPM 2.0 Part 2
Configuration Parser."
The tables in the TPM 2.0 Part 2 Annexes determine the configuration of a TPM implementation. These
tables may be modified by an implementer to describe the algorithms and commands to be executed in
by a specific implementation as well as to set implementation limits such as the number of PCR, sizes of
buffers, etc.
The TPM 2.0 Part 2 Configuration Parser produces a set of structures and definitions that are used by the
TPM 2.0 Part 2 Structure Parser.



Family "2.0"                                TCG Published                                        Page 1
Level 00 Revision 01.16             Copyright © TCG 2006-2014                         October 30, 2014
Trusted Platform Module Library                                                              Part 4: Supporting Routines

4.2      Structure Parser

4.2.1        Introduction

The program that processes the tables in TPM 2.0 Part 2 (other than the table in the annexes) is called
"The TPM 2.0 Part 2 Structure Parser."

NOTE              A Perl script was used to parse the tables in TPM 2.0 Part 2 to produce the header files and unmarshaling code
                  in for the reference implementation.

The TPM 2.0 Part 2 Structure Parser takes as input the files produced by the TPM 2.0 Part 2
Configuration Parser and the same TPM 2.0 Part 2 specification that was used as input to the TPM 2.0
Part 2 Configuration Parser. The TPM 2.0 Part 2 Structure Parser will generate all of the C structure
constant definitions that are required by the TPM interface. Additionally, the parser will generate
unmarshaling code for all structures passed to the TPM, and marshaling code for structures passed from
the TPM.
The unmarshaling code produced by the parser uses the prototypes defined below. The unmarshaling
code will perform validations of the data to ensure that it is compliant with the limitations on the data
imposed by the structure definition and use the response code provided in the table if not.

EXAMPLE:          The definition for a TPMI_RH_PROVISION indicates that the primitive data type is a TPM_HANDLE and the
                  only allowed values are TPM_RH_OWNER and TPM_RH_PLATFORM. The definition also indicates that the
                  TPM shall indicate TPM_RC_HANDLE if the input value is not none of these values. The unmarshaling code
                  will validate that the input value has one of those allowed values and return TPM_RC_HANDLE if not.

The sections below describe the function prototypes for the marshaling and unmarshaling code that is
automatically generated by the TPM 2.0 Part 2 Structure Parser. These prototypes are described here as
the unmarshaling and marshaling of various types occurs in places other than when the command is
being parsed or the response is being built. The prototypes and the description of the interface are
intended to aid in the comprehension of the code that uses these auto-generated routines.

4.2.2        Unmarshaling Code Prototype

4.2.2.1        Simple Types and Structures

The general form for the unmarshaling code for a simple type or a structure is:

                TPM_RC TYPE_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size);

Where:
      TYPE                           name of the data type or structure
      *target                        location in the TPM memory into which the data from **buffer is placed
      **buffer                       location in input buffer containing the most significant octet (MSO) of
                                     *target
      *size                          number of octets remaining in **buffer
When the data is successfully unmarshaled, the called routine will return TPM_RC_SUCCESS.
Otherwise, it will return a Format-One response code (see TPM 2.0 Part 2).
If the data is successfully unmarshaled, *buffer is advanced point to the first octet of the next parameter
in the input buffer and size is reduced by the number of octets removed from the buffer.
When the data type is a simple type, the parser will generate code that will unmarshal the underlying type
and then perform checks on the type as indicated by the type definition.


Page 2                                              TCG Published                                              Family "2.0"
October 30, 2014                           Copyright © TCG 2006-2014                           Level 00 Revision 01.16
Part 4: Supporting Routines                                               Trusted Platform Module Library


When the data type is a structure, the parser will generate code that unmarshals each of the structure
elements in turn and performs any additional parameter checks as indicated by the data type.

4.2.2.2      Union Types

When a union is defined, an extra parameter is defined for the unmarshaling code. This parameter is the
selector for the type. The unmarshaling code for the union will unmarshal the type indicated by the
selector.
The function prototype for a union has the form:

   TPM_RC TYPE_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size, UINT32 selector);

where:
    TYPE                        name of the union type or structure
    *target                     location in the TPM memory into which the data from **buffer is placed
    **buffer                    location in input buffer containing the most significant octet (MSO) of
                                *target
    *size                       number of octets remaining in **buffer
    selector                    union selector that determines what will be unmarshaled into *target


4.2.2.3      Null Types

In some cases, the structure definition allows an optional “null” value. The “null” value allows the use of
the same C type for the entity even though it does not always have the same members.
For example, the TPMI_ALG_HASH data type is used in many places. In some cases, TPM_ALG_NULL
is permitted and in some cases it is not. If two different data types had to be defined, the interfaces and
code would become more complex because of the number of cast operations that would be necessary.
Rather than encumber the code, the “null” value is defined and the unmarshaling code is given a flag to
indicate if this instance of the type accepts the “null” parameter or not. When the data type has a “null”
value, the function prototype is

         TPM_RC TYPE_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size, bool flag);

The parser detects when the type allows a “null” value and will always include flag in any call to
unmarshal that type.

4.2.2.4      Arrays

Any data type may be included in an array. The function prototype use to unmarshal an array for a TYPE is

  TPM_RC TYPE_Array_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size,INT32 count);

The generated code for an array uses a count-limited loop within which it calls the unmarshaling code for
TYPE.




Family "2.0"                                TCG Published                                          Page 3
Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
Trusted Platform Module Library                                                   Part 4: Supporting Routines

4.2.3      Marshaling Code Function Prototypes

4.2.3.1     Simple Types and Structures

The general form for the unmarshaling code for a simple type or a structure is:

                 UINT16 TYPE_Marshal(TYPE *source, BYTE **buffer, INT32 *size);

Where:
    TYPE                          name of the data type or structure
    *source                       location in the TPM memory containing the value that is to be marshaled
                                  in to the designated buffer
    **buffer                      location in the output buffer where the first octet of the TYPE is to be
                                  placed
    *size                         number of octets remaining in **buffer. If size is a NULL pointer, then
                                  no data is marshaled and the routine will compute the size of the
                                  memory required to marshal the indicated type
When the data is successfully marshaled, the called routine will return the number of octets marshaled
into **buffer.
If the data is successfully marshaled, *buffer is advanced point to the first octet of the next location in
the output buffer and *size is reduced by the number of octets placed in the buffer.
When the data type is a simple type, the parser will generate code that will marshal the underlying type.
The presumption is that the TPM internal structures are consistent and correct so the marshaling code
does not validate that the data placed in the buffer has a permissible value.
When the data type is a structure, the parser will generate code that marshals each of the structure
elements in turn.

4.2.3.2     Union Types

An extra parameter is defined for the marshaling function of a union. This parameter is the selector for the
type. The marshaling code for the union will marshal the type indicated by the selector.
The function prototype for a union has the form:

    UINT16 TYPE_Marshal(TYPE *target, BYTE **buffer, INT32 *size, UINT32 selector);

The parameters have a similar meaning as those in 5.2.2.2 but the data movement is from source to
buffer.


4.2.3.3     Arrays

Any type may be included in an array. The function prototype use to unmarshal an array is:

   UINT16 TYPE_Array_Marshal(TYPE *source, BYTE **buffer, INT32 *size, INT32 count);

The generated code for an array uses a count-limited loop within which it calls the marshaling code for
TYPE.




Page 4                                        TCG Published                                     Family "2.0"
October 30, 2014                      Copyright © TCG 2006-2014                    Level 00 Revision 01.16
Part 4: Supporting Routines                                                Trusted Platform Module Library

4.3    Command Parser

The program that processes the tables in TPM 2.0 Part 3 is called "The TPM 2.0 Part 3 Command
Parser."
The TPM 2.0 Part 3 Command Parser takes as input a TPM 2.0 Part 3 of the TPM specification and some
configuration files produced by the TPM 2.0 Part 2 Configuration Parser. This parser uses the contents of
the command and response tables in TPM 2.0 Part 3 to produce unmarshaling code for the command
and the marshaling code for the response. Additionally, this parser produces support routines that are
used to check that the proper number of authorization values of the proper type have been provided.
These support routines are called by the functions in this TPM 2.0 Part 4.

4.4    Portability

Where reasonable, the code is written to be portable. There are a few known cases where the code is not
portable. Specifically, the handling of bit fields will not always be portable. The bit fields are marshaled
and unmarshaled as a simple element of the underlying type. For example, a TPMA_SESSION is defined
as a bit field in an octet (BYTE). When sent on the interface a TPMA_SESSION will occupy one octet.
When unmarshaled, it is unmarshaled as a UINT8. The ramifications of this are that a TPMA_SESSION
                  th
will occupy the 0 octet of the structure in which it is placed regardless of the size of the structure.
Many compilers will pad a bit field to some "natural" size for the processor, often 4 octets, meaning that
sizeof(TPMA_SESSION) would return 4 rather than 1 (the canonical size of a TPMA_SESSION).
                                                                                             th
For a little endian machine, padding of bit fields should have little consequence since the 0 octet always
                th
contains the 0 bit of the structure no matter how large the structure. However, for a big endian machine,
     th
the 0 bit will be in the highest numbered octet. When unmarshaling a TPMA_SESSION, the current
                                                         th                                               th
unmarshaling code will place the input octet at the 0 octet of the TPMA_SESSION. Since the 0 octet is
most significant octet, this has the effect of shifting all the session attribute bits left by 24 places.
As a consequence, someone implementing on a big endian machine should do one of two things:
a) allocate all structures as packed to a byte boundary (this may not be possible if the processor does
   not handle unaligned accesses); or
b) modify the code that manipulates bit fields that are not defined as being the alignment size of the
   system.
For many RISC processors, option #2 would be the only choice. This is may not be a terribly daunting
task since only two attribute structures are not 32-bits (TPMA_SESSION and TPMA_LOCALITY).




Family "2.0"                                 TCG Published                                          Page 5
Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                Part 4: Supporting Routines



     5     Header Files

     5.1    Introduction

     The files in this section are used to define values that are used in multiple parts of the specification and
     are not confined to a single module.

     5.2    BaseTypes.h

 1   #ifndef _BASETYPES_H
 2   #define _BASETYPES_H
 3   #include "stdint.h"

     NULL definition

 4   #ifndef          NULL
 5   #define          NULL        (0)
 6   #endif
 7   typedef uint8_t              UINT8;
 8   typedef uint8_t              BYTE;
 9   typedef int8_t               INT8;
10   typedef int                   BOOL;
11   typedef uint16_t             UINT16;
12   typedef int16_t              INT16;
13   typedef uint32_t             UINT32;
14   typedef int32_t              INT32;
15   typedef uint64_t             UINT64;
16   typedef int64_t              INT64;
17   typedef struct {
18       UINT16         size;
19       BYTE           buffer[1];
20   } TPM2B;
21   #endif




     Page 6                                       TCG Published                                    Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
    Part 4: Supporting Routines                                   Trusted Platform Module Library

    5.3    bits.h

1   #ifndef     _BITS_H
2   #define     _BITS_H
3   #define CLEAR_BIT(bit, vector)    BitClear((bit), (BYTE *)&(vector), sizeof(vector))
4   #define SET_BIT(bit, vector)      BitSet((bit), (BYTE *)&(vector), sizeof(vector))
5   #define TEST_BIT(bit, vector)     BitIsSet((bit), (BYTE *)&(vector), sizeof(vector))
6   #endif




    Family "2.0"                          TCG Published                                  Page 7
    Level 00 Revision 01.16          Copyright © TCG 2006-2014                October 30, 2014
     Trusted Platform Module Library                                                     Part 4: Supporting Routines

     5.4    bool.h

 1   #ifndef      _BOOL_H
 2   #define      _BOOL_H
 3   #if defined(TRUE)
 4   #undef TRUE
 5   #endif
 6   #if defined FALSE
 7   #undef FALSE
 8   #endif
 9   typedef int BOOL;
10   #define FALSE    ((BOOL)0)
11   #define TRUE     ((BOOL)1)
12   #endif


     5.5    Capabilities.h

     This file contains defines for the number of capability values that will fit into the largest data buffer.
     These defines are used in various function in the "support" and the "subsystem" code groups. A module
     that supports a type that is returned by a capability will have a function that returns the capabilities of the
     type.

     EXAMPLE          PCR.c contains PCRCapGetHandles() and PCRCapGetProperties().

 1   #ifndef        _CAPABILITIES_H
 2   #define        _CAPABILITIES_H
 3   #define       MAX_CAP_DATA                (MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32))
 4   #define       MAX_CAP_ALGS                (ALG_LAST_VALUE - ALG_FIRST_VALUE + 1)
 5   #define       MAX_CAP_HANDLES             (MAX_CAP_DATA/sizeof(TPM_HANDLE))
 6   #define       MAX_CAP_CC                  ((TPM_CC_LAST - TPM_CC_FIRST) + 1)
 7   #define       MAX_TPM_PROPERTIES          (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))
 8   #define       MAX_PCR_PROPERTIES          (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT))
 9   #define       MAX_ECC_CURVES              (MAX_CAP_DATA/sizeof(TPM_ECC_CURVE))
10   #endif


     5.6    TPMB.h

     This file contains extra TPM2B structures

 1   #ifndef _TPMB_H
 2   #define _TPMB_H

     This macro helps avoid having to type in the structure in order to create a new TPM2B type that is used in
     a function.

 3   #define TPM2B_TYPE(name, bytes)                           \
 4       typedef union {                                       \
 5           struct {                                          \
 6                UINT16 size;                                 \
 7                BYTE    buffer[(bytes)];                     \
 8           } t;                                              \
 9           TPM2B     b;                                      \
10       } TPM2B_##name

     Macro to instance and initialize a TPM2B value

11   #define TPM2B_INIT(TYPE, name) \
12       TPM2B_##TYPE    name = {sizeof(name.t.buffer), {0}}
13   #define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes)
14   #endif


     Page 8                                          TCG Published                                       Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014                     Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library

     5.7     TpmError.h

 1   #ifndef _TPM_ERROR_H
 2   #define _TPM_ERROR_H
 3   #include "TpmBuildSwitches.h"
 4   #define     FATAL_ERROR_ALLOCATION                         (1)
 5   #define     FATAL_ERROR_DIVIDE_ZERO                        (2)
 6   #define     FATAL_ERROR_INTERNAL                           (3)
 7   #define     FATAL_ERROR_PARAMETER                          (4)
 8   #define     FATAL_ERROR_ENTROPY                            (5)
 9   #define     FATAL_ERROR_SELF_TEST                          (6)
10   #define     FATAL_ERROR_CRYPTO                             (7)
11   #define     FATAL_ERROR_NV_UNRECOVERABLE                   (8)
12   #define     FATAL_ERROR_REMANUFACTURED                     (9) // indicates that the TPM has
13                                                                   // been re-manufactured after an
14                                                                   // unrecoverable NV error
15   #define        FATAL_ERROR_DRBG                            (10)
16   #define        FATAL_ERROR_FORCED                          (666)

     These are the crypto assertion routines. When a function returns an unexpected and unrecoverable
     result, the assertion fails and the TpmFail() is called

17   void
18   TpmFail(const char *function, int line, int code);
19   typedef void    (*FAIL_FUNCTION)(const char *, int, int);
20   #define FAIL(a) (TpmFail(__FUNCTION__, __LINE__, a))
21   #if defined(EMPTY_ASSERT)
22   #   define pAssert(a) ((void)0)
23   #else
24   #   define pAssert(a) (!!(a) ? 1 : (FAIL(FATAL_ERROR_PARAMETER), 0))
25   #endif
26   #endif // _TPM_ERROR_H


     5.8     Global.h

     5.8.1     Description

     This file contains internal global type definitions and data declarations that are need between
     subsystems. The instantiation of global data is in Global.c. The initialization of global data is in the
     subsystem that is the primary owner of the data.
     The first part of this file has the typedefs for structures and other defines used in many portions of the
     code. After the typedef section, is a section that defines global values that are only present in RAM. The
     next three sections define the structures for the NV data areas: persistent, orderly, and state save.
     Additional sections define the data that is used in specific modules. That data is private to the module but
     is collected here to simplify the management of the instance data. All the data is instanced in Global.c.

     5.8.2     Includes

 1   #ifndef         GLOBAL_H
 2   #define         GLOBAL_H
 3   //#define SELF_TEST
 4   #include        "TpmBuildSwitches.h"
 5   #include        "Tpm.h"
 6   #include        "TPMB.h"
 7   #include        "CryptoEngine.h"
 8   #include        <setjmp.h>




     Family "2.0"                                 TCG Published                                          Page 9
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                               Part 4: Supporting Routines

     5.8.3     Defines and Types

     5.8.3.1     Unreferenced Parameter

     This define is used to eliminate the compiler warning about an unreferenced parameter. Basically, it tells
     the compiler that it is not an accident that the parameter is unreferenced.

 9   #ifndef UNREFERENCED_PARAMETER
10   #   define UNREFERENCED_PARAMETER(a)            (a)
11   #endif
12   #include    "bits.h"


     5.8.3.2     Crypto Self-Test Values

     Define these values here if the AlgorithmTests() project is not used

13   #ifndef SELF_TEST
14   extern ALGORITHM_VECTOR     g_implementedAlgorithms;
15   extern ALGORITHM_VECTOR     g_toTest;
16   #else
17   LIB_IMPORT extern ALGORITHM_VECTOR     g_implementedAlgorithms;
18   LIB_IMPORT extern ALGORITHM_VECTOR     g_toTest;
19   #endif

     These macros are used in CryptUtil() to invoke the incremental self test.

20   #define       TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL)

     Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting to test a hash with
     that value, don't do it.

21   #define       TEST_HASH(alg)                                                                     \
22                 if(     TEST_BIT(alg, g_toTest)                                                    \
23                     && (alg != ALG_NULL_VALUE))                                                    \
24                     CryptTestAlgorithm(alg, NULL)


     5.8.3.3     Hash and HMAC State Structures

     These definitions are for the types that can be in a hash state structure. These types are used in the
     crypto utilities

25   typedef   BYTE    HASH_STATE_TYPE;
26   #define   HASH_STATE_EMPTY         ((HASH_STATE_TYPE) 0)
27   #define   HASH_STATE_HASH          ((HASH_STATE_TYPE) 1)
28   #define   HASH_STATE_HMAC          ((HASH_STATE_TYPE) 2)

     A HASH_STATE structure contains an opaque hash stack state. A caller would use this structure when
     performing incremental hash operations. The state is updated on each call. If type is an HMAC_STATE,
     or HMAC_STATE_SEQUENCE then state is followed by the HMAC key in oPad format.

29   typedef struct
30   {
31       CPRI_HASH_STATE          state;                   // hash state
32       HASH_STATE_TYPE          type;                    // type of the context
33   } HASH_STATE;




     Page 10                                      TCG Published                                  Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library


     An HMAC_STATE structure contains an opaque HMAC stack state. A caller would use this structure
     when performing incremental HMAC operations. This structure contains a hash state and an HMAC key
     and allows slightly better stack optimization than adding an HMAC key to each hash state.

34   typedef struct
35   {
36       HASH_STATE                hashState;               // the hash state
37       TPM2B_HASH_BLOCK          hmacKey;                 // the HMAC key
38   } HMAC_STATE;


     5.8.3.4     Other Types

     An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA)

39   typedef BYTE        AUTH_VALUE[sizeof(TPMU_HA)];

     A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO

40   typedef BYTE        TIME_INFO[sizeof(TPMS_TIME_INFO)];

     A NAME is a BYTE array that can contain a TPMU_NAME

41   typedef BYTE        NAME[sizeof(TPMU_NAME)];


     5.8.4     Loaded Object Structures

     5.8.4.1     Description

     The structures in this section define the object layout as it exists in TPM memory.
     Two types of objects are defined: an ordinary object such as a key, and a sequence object that may be a
     hash, HMAC, or event.

     5.8.4.2     OBJECT_ATTRIBUTES

     An OBJECT_ATTRIBUTES structure contains the variable attributes of an object. These properties are
     not part of the public properties but are used by the TPM in managing the object. An
     OBJECT_ATTRIBUTES is used in the definition of the OBJECT data type.

42   typedef struct
43   {
44       unsigned                  publicOnly      : 1;     //0)   SET if only the public portion of
45                                                          //     an object is loaded
46        unsigned                 epsHierarchy : 1;        //1)   SET if the object belongs to EPS
47                                                          //     Hierarchy
48        unsigned                 ppsHierarchy : 1;        //2)   SET if the object belongs to PPS
49                                                          //     Hierarchy
50        unsigned                 spsHierarchy : 1;        //3)   SET f the object belongs to SPS
51                                                          //     Hierarchy
52        unsigned                 evict           : 1;     //4)   SET if the object is a platform or
53                                                          //     owner evict object. Platform-
54                                                          //     evict object belongs to PPS
55                                                          //     hierarchy, owner-evict object
56                                                          //     belongs to SPS or EPS hierarchy.
57                                                          //     This bit is also used to mark a
58                                                          //     completed sequence object so it
59                                                          //     will be flush when the
60                                                          //     SequenceComplete command succeeds.
61        unsigned                 primary        : 1;      //5)   SET for a primary object

     Family "2.0"                                 TCG Published                                       Page 11
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                        October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

 62       unsigned                 temporary      :   1;
                                                    //6) SET for a temporary object
 63       unsigned                 stClear        :   1;
                                                    //7) SET for an stClear object
 64       unsigned                 hmacSeq        :   1;
                                                    //8) SET for an HMAC sequence object
 65       unsigned                 hashSeq        :   1;
                                                    //9) SET for a hash sequence object
 66       unsigned                 eventSeq       :   1;
                                                    //10) SET for an event sequence object
 67       unsigned                 ticketSafe     :   1;
                                                    //11) SET if a ticket is safe to create
 68                                                 //    for hash sequence object
 69       unsigned            firstBlock : 1;       //12) SET if the first block of hash
 70                                                 //    data has been received. It
 71                                                 //    works with ticketSafe bit
 72       unsigned            isParent     : 1;     //13) SET if the key has the proper
 73                                                 //    attributes to be a parent key
 74       unsigned            privateExp : 1;       //14) SET when the private exponent
 75                                                 //    of an RSA key has been validated.
 76       unsigned        reserved    : 1;      //15) reserved bits. unused.
 77   } OBJECT_ATTRIBUTES;


      5.8.4.3     OBJECT Structure

      An OBJECT structure holds the object public, sensitive, and meta-data associated. This structure is
      implementation dependent. For this implementation, the structure is not optimized for space but rather for
      clarity of the reference implementation. Other implementations may choose to overlap portions of the
      structure that are not used simultaneously. These changes would necessitate changes to the source code
      but those changes would be compatible with the reference implementation.

 78   typedef struct
 79   {
 80       // The attributes field is required to be first followed by the publicArea.
 81       // This allows the overlay of the object structure and a sequence structure
 82       OBJECT_ATTRIBUTES   attributes;         // object attributes
 83       TPMT_PUBLIC         publicArea;         // public area of an object
 84       TPMT_SENSITIVE      sensitive;          // sensitive area of an object
 85
 86   #ifdef TPM_ALG_RSA
 87       TPM2B_PUBLIC_KEY_RSA privateExponent;             // Additional field for the private
 88                                                         // exponent of an RSA key.
 89   #endif
 90       TPM2B_NAME               qualifiedName;           //   object qualified name
 91       TPMI_DH_OBJECT           evictHandle;             //   if the object is an evict object,
 92                                                         //   the original handle is kept here.
 93                                                         //   The 'working' handle will be the
 94                                                         //   handle of an object slot.
 95
 96       TPM2B_NAME               name;                    // Name of the object name. Kept here
 97                                                         // to avoid repeatedly computing it.
 98   } OBJECT;


      5.8.4.4     HASH_OBJECT Structure

      This structure holds a hash sequence object or an event sequence object.
      The first four components of this structure are manually set to be the same as the first four components of
      the object structure. This prevents the object from being inadvertently misused as sequence objects
      occupy the same memory as a regular object. A debug check is present to make sure that the offsets are
      what they are supposed to be.

 99   typedef struct
100   {
101       OBJECT_ATTRIBUTES        attributes;              //   The attributes of the HASH object
102       TPMI_ALG_PUBLIC          type;                    //   algorithm
103       TPMI_ALG_HASH            nameAlg;                 //   name algorithm
104       TPMA_OBJECT              objectAttributes;        //   object attributes

      Page 12                                      TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

105
106       // The data below is unique to a sequence object
107       TPM2B_AUTH          auth;               // auth for use of sequence
108       union
109       {
110           HASH_STATE      hashState[HASH_COUNT];
111           HMAC_STATE      hmacState;
112       }                   state;
113   } HASH_OBJECT;


      5.8.4.5     ANY_OBJECT

      This is the union for holding either a sequence object or a regular object.

114   typedef union
115   {
116       OBJECT                    entity;
117       HASH_OBJECT               hash;
118   } ANY_OBJECT;


      5.8.5     AUTH_DUP Types

      These values are used in the authorization processing.

119   typedef   UINT32              AUTH_ROLE;
120   #define   AUTH_NONE           ((AUTH_ROLE)(0))
121   #define   AUTH_USER           ((AUTH_ROLE)(1))
122   #define   AUTH_ADMIN          ((AUTH_ROLE)(2))
123   #define   AUTH_DUP            ((AUTH_ROLE)(3))


      5.8.6     Active Session Context

      5.8.6.1     Description

      The structures in this section define the internal structure of a session context.

      5.8.6.2     SESSION_ATTRIBUTES

      The attributes in the SESSION_ATTRIBUTES structure track the various properties of the session. It
      maintains most of the tracking state information for the policy session. It is used within the SESSION
      structure.

124   typedef struct
125   {
126       unsigned                  isPolicy : 1;       //1)        SET if the session may only
127                                                     //          be used for policy
128        unsigned                 isAudit : 1;        //2)        SET if the session is used
129                                                     //          for audit
130        unsigned                 isBound : 1;        //3)        SET if the session is bound to
131                                                     //          with an entity.
132                                                     //          This attribute will be CLEAR if
133                                                     //          either isPolicy or isAudit is SET.
134        unsigned                 iscpHashDefined : 1;//4)        SET if the cpHash has been defined
135                                                     //          This attribute is not SET unless
136                                                     //          'isPolicy' is SET.
137        unsigned                 isAuthValueNeeded : 1;
138                                                     //5)        SET if the authValue is required
139                                                     //          for computing the session HMAC.
140                                                     //          This attribute is not SET unless

      Family "2.0"                                  TCG Published                                         Page 13
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                              Part 4: Supporting Routines

141                                                       //   isPolicy is SET.
142       unsigned                    isPasswordNeeded : 1;
143                                                       //6) SET if a password authValue is
144                                                       //   required for authorization
145                                                       //   This attribute is not SET unless
146                                                       //   isPolicy is SET.
147       unsigned                    isPPRequired : 1;   //7) SET if physical presence is
148                                                       //   required to be asserted when the
149                                                       //   authorization is checked.
150                                                       //   This attribute is not SET unless
151                                                       //   isPolicy is SET.
152       unsigned                    isTrialPolicy : 1; //8) SET if the policy session is
153                                                       //   created for trial of the policy's
154                                                       //   policyHash generation.
155                                                       //   This attribute is not SET unless
156                                                       //   isPolicy is SET.
157       unsigned                    isDaBound : 1;      //9) SET if the bind entity had noDA
158                                                       //   CLEAR. If this is SET, then an
159                                                       //   auth failure using this session
160                                                       //   will count against lockout even
161                                                       //   if the object being authorized is
162                                                       //   exempt from DA.
163       unsigned                    isLockoutBound : 1; //10)SET if the session is bound to
164                                                       //   lockoutAuth.
165       unsigned                    requestWasBound : 1;//11) SET if the session is being used
166                                                       //    with the bind entity. If SET
167                                                       //    the authValue will not be use
168                                                       //    in the response HMAC computation.
169       unsigned                    checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN
170                                                       //    attribute needs to be checked
171                                                       //    when the policy is used for
172                                                       //    authorization for NV access.
173                                                       //    If this is SET for any other
174                                                       //    type, the policy will fail.
175       unsigned                    nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is
176                                                       //    required to be SET.
177   } SESSION_ATTRIBUTES;


      5.8.6.3     SESSION Structure

      The SESSION structure contains all the context of a session except for the associated contextID.

      NOTE:           The contextID of a session is only relevant when the session context is stored off the TPM.

178   typedef struct
179   {
180       TPM_ALG_ID                  authHashAlg;                   // session hash algorithm
181       TPM2B_NONCE                 nonceTPM;                      // last TPM-generated nonce for
182                                                                  // this session
183
184       TPMT_SYM_DEF                symmetric;                     // session symmetric algorithm (if any)
185       TPM2B_AUTH                  sessionKey;                    // session secret value used for
186                                                                  // generating HMAC and encryption keys
187
188       SESSION_ATTRIBUTES          attributes;                    //   session attributes
189       TPM_CC                      commandCode;                   //   command code (policy session)
190       TPMA_LOCALITY               commandLocality;               //   command locality (policy session)
191       UINT32                      pcrCounter;                    //   PCR counter value when PCR is
192                                                                  //   included (policy session)
193                                                                  //   If no PCR is included, this
194                                                                  //   value is 0.
195
196       UINT64                      startTime;                     // value of TPMS_CLOCK_INFO.clock when
197                                                                  // the session was started (policy


      Page 14                                            TCG Published                                              Family "2.0"
      October 30, 2014                          Copyright © TCG 2006-2014                            Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

198                                                        // session)
199
200       UINT64                    timeOut;               //   timeout relative to
201                                                        //   TPMS_CLOCK_INFO.clock
202                                                        //   There is no timeout if this value
203                                                        //   is 0.
204       union
205       {
206           TPM2B_NAME            boundEntity;            // value used to track the entity to
207                                                         // which the session is bound
208
209             TPM2B_DIGEST        cpHash;                 // the required cpHash value for the
210                                                         // command being authorized
211
212       } u1;                                             // 'boundEntity' and 'cpHash' may
213                                                         // share the same space to save memory
214
215       union
216       {
217           TPM2B_DIGEST          auditDigest;           // audit session digest
218           TPM2B_DIGEST          policyDigest;            // policyHash
219
220       } u2;                                            // audit log and policyHash may
221                                                        // share space to save memory
222   } SESSION;


      5.8.7     PCR

      5.8.7.1     PCR_SAVE Structure

      The PCR_SAVE structure type contains the PCR data that are saved across power cycles. Only the static
      PCR are required to be saved across power cycles. The DRTM and resettable PCR are not saved. The
      number of static and resettable PCR is determined by the platform-specific specification to which the TPM
      is built.

223   typedef struct
224   {
225   #ifdef TPM_ALG_SHA1
226       BYTE                      sha1[NUM_STATIC_PCR][SHA1_DIGEST_SIZE];
227   #endif
228   #ifdef TPM_ALG_SHA256
229       BYTE                      sha256[NUM_STATIC_PCR][SHA256_DIGEST_SIZE];
230   #endif
231   #ifdef TPM_ALG_SHA384
232       BYTE                      sha384[NUM_STATIC_PCR][SHA384_DIGEST_SIZE];
233   #endif
234   #ifdef TPM_ALG_SHA512
235       BYTE                      sha512[NUM_STATIC_PCR][SHA512_DIGEST_SIZE];
236   #endif
237   #ifdef TPM_ALG_SM3_256
238       BYTE                      sm3_256[NUM_STATIC_PCR][SM3_256_DIGEST_SIZE];
239   #endif
240
241       // This counter increments whenever the PCR are updated.
242       // NOTE: A platform-specific specification may designate
243       //       certain PCR changes as not causing this counter
244       //       to increment.
245       UINT32              pcrCounter;
246
247   } PCR_SAVE;




      Family "2.0"                                 TCG Published                                      Page 15
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

      5.8.7.2     PCR_POLICY

      This structure holds the PCR policies, one for each group of PCR controlled by policy.

248   typedef struct
249   {
250       TPMI_ALG_HASH               hashAlg[NUM_POLICY_PCR_GROUP];
251       TPM2B_DIGEST                a;
252       TPM2B_DIGEST                policy[NUM_POLICY_PCR_GROUP];
253   } PCR_POLICY;


      5.8.7.3     PCR_AUTHVALUE

      This structure holds the PCR policies, one for each group of PCR controlled by policy.

254   typedef struct
255   {
256       TPM2B_DIGEST                auth[NUM_AUTHVALUE_PCR_GROUP];
257   } PCR_AUTHVALUE;


      5.8.8     Startup

      5.8.8.1     SHUTDOWN_NONE

      Part 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() and
      TPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was received.

      NOTE:           This is a reserved value.

258   #define SHUTDOWN_NONE           (TPM_SU)(0xFFFF)


      5.8.8.2     STARTUP_TYPE

      This enumeration is the possible startup types. The type is determined by the combination of
      TPM2_ShutDown() and TPM2_Startup().

259   typedef enum
260   {
261       SU_RESET,
262       SU_RESTART,
263       SU_RESUME
264   } STARTUP_TYPE;


      5.8.9     NV

      5.8.9.1     NV_RESERVE

      This enumeration defines the master list of the elements of a reserved portion of NV. This list includes all
      the pre-defined data that takes space in NV, either as persistent data or as state save data. The
      enumerations are used as indexes into an array of offset values. The offset values then are used to index
      into NV. This is method provides an imperfect analog to an actual NV implementation.

265   typedef enum
266   {
267   // Entries below mirror the PERSISTENT_DATA structure. These values are written
268   // to NV as individual items.
269       // hierarchy

      Page 16                                          TCG Published                                Family "2.0"
      October 30, 2014                            Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

270       NV_DISABLE_CLEAR,
271       NV_OWNER_ALG,
272       NV_ENDORSEMENT_ALG,
273       NV_LOCKOUT_ALG,
274       NV_OWNER_POLICY,
275       NV_ENDORSEMENT_POLICY,
276       NV_LOCKOUT_POLICY,
277       NV_OWNER_AUTH,
278       NV_ENDORSEMENT_AUTH,
279       NV_LOCKOUT_AUTH,
280
281       NV_EP_SEED,
282       NV_SP_SEED,
283       NV_PP_SEED,
284
285       NV_PH_PROOF,
286       NV_SH_PROOF,
287       NV_EH_PROOF,
288
289       // Time
290       NV_TOTAL_RESET_COUNT,
291       NV_RESET_COUNT,
292
293       // PCR
294       NV_PCR_POLICIES,
295       NV_PCR_ALLOCATED,
296
297       // Physical Presence
298       NV_PP_LIST,
299
300       // Dictionary Attack
301       NV_FAILED_TRIES,
302       NV_MAX_TRIES,
303       NV_RECOVERY_TIME,
304       NV_LOCKOUT_RECOVERY,
305       NV_LOCKOUT_AUTH_ENABLED,
306
307       // Orderly State flag
308       NV_ORDERLY,
309
310       // Command Audit
311       NV_AUDIT_COMMANDS,
312       NV_AUDIT_HASH_ALG,
313       NV_AUDIT_COUNTER,
314
315       // Algorithm Set
316       NV_ALGORITHM_SET,
317
318       NV_FIRMWARE_V1,
319       NV_FIRMWARE_V2,
320
321   // The entries above are in PERSISTENT_DATA. The entries below represent
322   // structures that are read and written as a unit.
323
324   // ORDERLY_DATA data structure written on each orderly shutdown
325       NV_ORDERLY_DATA,
326
327   // STATE_CLEAR_DATA structure written on each Shutdown(STATE)
328       NV_STATE_CLEAR,
329
330   // STATE_RESET_DATA structure written on each Shutdown(STATE)
331       NV_STATE_RESET,
332
333       NV_RESERVE_LAST             // end of NV reserved data list
334   } NV_RESERVE;


      Family "2.0"                        TCG Published                                 Page 17
      Level 00 Revision 01.16        Copyright © TCG 2006-2014                October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

      5.8.9.2     NV_INDEX

      The NV_INDEX structure defines the internal format for an NV index. The indexData size varies
      according to the type of the index. In this implementation, all of the index is manipulated as a unit.

335   typedef struct
336   {
337       TPMS_NV_PUBLIC           publicArea;
338       TPM2B_AUTH               authValue;
339   } NV_INDEX;


      5.8.10     COMMIT_INDEX_MASK

      This is the define for the mask value that is used when manipulating the bits in the commit bit array. The
      commit counter is a 64-bit value and the low order bits are used to index the commitArray. This mask
      value is applied to the commit counter to extract the bit number in the array.

340   #ifdef TPM_ALG_ECC
341   #define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1))
342   #endif


      5.8.11     RAM Global Values

      5.8.11.1    Description

      The values in this section are only extant in RAM. They are defined here and instanced in Global.c.

      5.8.11.2    g_rcIndex

      This array is used to contain the array of values that are added to a return code when it is a parameter-,
      handle-, or session-related error. This is an implementation choice and the same result can be achieved
      by using a macro.

343   extern const UINT16          g_rcIndex[15];


      5.8.11.3    g_exclusiveAuditSession

      This location holds the session handle for the current exclusive audit session. If there is no exclusive
      audit session, the location is set to TPM_RH_UNASSIGNED.

344   extern TPM_HANDLE            g_exclusiveAuditSession;


      5.8.11.4    g_time

      This value is the count of milliseconds since the TPM was powered up. This value is initialized at
      _TPM_Init().

345   extern     UINT64            g_time;


      5.8.11.5    g_phEnable

      This is the platform hierarchy control and determines if the platform hierarchy is available. This value is
      SET on each TPM2_Startup(). The default value is SET.

346   extern BOOL                  g_phEnable;

      Page 18                                      TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      5.8.11.6    g_pceReConfig

      This value is SET if a TPM2_PCR_Allocate() command successfully executed since the last
      TPM2_Startup(). If so, then the next shutdown is required to be Shutdown(CLEAR).

347   extern BOOL                   g_pcrReConfig;


      5.8.11.7    g_DRTMHandle

      This location indicates the sequence object handle that holds the DRTM sequence data. When not used,
      it is set to TPM_RH_UNASSIGNED. A sequence DRTM sequence is started on either _TPM_Init() or
      _TPM_Hash_Start().

348   extern TPMI_DH_OBJECT         g_DRTMHandle;


      5.8.11.8    g_DrtmPreStartup

      This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The define
      for PRE_STARTUP_FLAG is used to add the g_DrtmPreStartup value to gp_orderlyState at shutdown.
      This hack is to avoid adding another NV variable.

349   extern BOOL              g_DrtmPreStartup;
350   #define PRE_STARTUP_FLAG     0x8000


      5.8.11.9    g_StartupLocality3

      This value indicates that a TPM2_Startup() occured at locality 3. Otherwise, it at locality 0. The define for
      STARTUP_LOCALITY_3 is to indicate that the startup was not at locality 0. This hack is to avoid adding
      another NV variable.

351   extern BOOL             g_StartupLocality3;
352   #define STARTUP_LOCALITY_3       0x4000


      5.8.11.10 g_updateNV

      This flag indicates if NV should be updated at the end of a command. This flag is set to FALSE at the
      beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand() after the
      detailed actions of a command complete. If the command execution was successful and this flag is SET,
      any pending NV writes will be committed to NV.

353   extern BOOL                   g_updateNV;


      5.8.11.11 g_clearOrderly

      This flag indicates if the execution of a command should cause the orderly state to be cleared. This flag
      is set to FALSE at the beginning of each command in ExecuteCommand() and is checked in
      ExecuteCommand() after the detailed actions of a command complete but before the check of
      g_updateNV. If this flag is TRUE, and the orderly state is not SHUTDOWN_NONE, then the orderly state
      in NV memory will be changed to SHUTDOWN_NONE.

354   extern BOOL                   g_clearOrderly;




      Family "2.0"                                 TCG Published                                         Page 19
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

      5.8.11.12 g_prevOrderlyState

      This location indicates how the TPM was shut down before the most recent TPM2_Startup(). This value,
      along with the startup type, determines if the TPM should do a TPM Reset, TPM Restart, or TPM
      Resume.

355   extern TPM_SU                 g_prevOrderlyState;


      5.8.11.13 g_nvOk

      This value indicates if the NV integrity check was successful or not. If not and the failure was severe, then
      the TPM would have been put into failure mode after it had been re-manufactured. If the NV failure was in
      the area where the state-save data is kept, then this variable will have a value of FALSE indicating that a
      TPM2_Startup(CLEAR) is required.

356   extern BOOL                   g_nvOk;


      5.8.11.14 g_platformUnique

      This location contains the unique value(s) used to identify the TPM. It is loaded on every
      _TPM2_Startup() The first value is used to seed the RNG. The second value is used as a vendor
      authValue. The value used by the RNG would be the value derived from the chip unique value (such as
      fused) with a dependency on the authorities of the code in the TPM boot path. The second would be
      derived from the chip unique value with a dependency on the details of the code in the boot path. That is,
      the first value depends on the various signers of the code and the second depends on what was signed.
      The TPM vendor should not be able to know the first value but they are expected to know the second.

357   extern TPM2B_AUTH             g_platformUniqueAuthorities; // Reserved for RNG
358   extern TPM2B_AUTH             g_platformUniqueDetails;   // referenced by VENDOR_PERMANENT


      5.8.12     Persistent Global Values

      5.8.12.1     Description

      The values in this section are global values that are persistent across power events. The lifetime of the
      values determines the structure in which the value is placed.

      5.8.12.2     PERSISTENT_DATA

      This structure holds the persistent values that only change as a consequence of a specific Protected
      Capability and are not affected by TPM power events (TPM2_Startup() or TPM2_Shutdown().

359   typedef struct
360   {
361   //*********************************************************************************
362   //          Hierarchy
363   //*********************************************************************************
364   // The values in this section are related to the hierarchies.
365
366        BOOL                     disableClear;            // TRUE if TPM2_Clear() using
367                                                          // lockoutAuth is disabled
368
369        // Hierarchy authPolicies
370        TPMI_ALG_HASH       ownerAlg;
371        TPMI_ALG_HASH       endorsementAlg;
372        TPMI_ALG_HASH       lockoutAlg;
373        TPM2B_DIGEST        ownerPolicy;

      Page 20                                       TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                        Trusted Platform Module Library

374        TPM2B_DIGEST             endorsementPolicy;
375        TPM2B_DIGEST             lockoutPolicy;
376
377        // Hierarchy authValues
378        TPM2B_AUTH          ownerAuth;
379        TPM2B_AUTH          endorsementAuth;
380        TPM2B_AUTH          lockoutAuth;
381
382        // Primary Seeds
383        TPM2B_SEED          EPSeed;
384        TPM2B_SEED          SPSeed;
385        TPM2B_SEED          PPSeed;
386        // Note there is a nullSeed in the state_reset memory.
387
388        // Hierarchy proofs
389        TPM2B_AUTH          phProof;
390        TPM2B_AUTH          shProof;
391        TPM2B_AUTH          ehProof;
392        // Note there is a nullProof in the state_reset memory.
393
394   //*********************************************************************************
395   //          Reset Events
396   //*********************************************************************************
397   // A count that increments at each TPM reset and never get reset during the life
398   // time of TPM. The value of this counter is initialized to 1 during TPM
399   // manufacture process.
400       UINT64               totalResetCount;
401
402   // This counter increments on each TPM Reset. The counter is reset by
403   // TPM2_Clear().
404       UINT32              resetCount;
405
406   //*********************************************************************************
407   //           PCR
408   //*********************************************************************************
409   // This structure hold the policies for those PCR that have an update policy.
410   // This implementation only supports a single group of PCR controlled by
411   // policy. If more are required, then this structure would be changed to
412   // an array.
413       PCR_POLICY          pcrPolicies;
414
415   //   This structure indicates the allocation of PCR. The structure contains a
416   //   list of PCR allocations for each implemented algorithm. If no PCR are
417   //   allocated for an algorithm, a list entry still exists but the bit map
418   //   will contain no SET bits.
419         TPML_PCR_SELECTION pcrAllocated;
420
421   //*********************************************************************************
422   //          Physical Presence
423   //*********************************************************************************
424   // The PP_LIST type contains a bit map of the commands that require physical
425   // to be asserted when the authorization is evaluated. Physical presence will be
426   // checked if the corresponding bit in the array is SET and if the authorization
427   // handle is TPM_RH_PLATFORM.
428   //
429   // These bits may be changed with TPM2_PP_Commands().
430       BYTE                ppList[((TPM_CC_PP_LAST - TPM_CC_PP_FIRST + 1) + 7)/8];
431
432   //*********************************************************************************
433   //          Dictionary attack values
434   //*********************************************************************************
435   // These values are used for dictionary attack tracking and control.
436       UINT32              failedTries;        // the current count of unexpired
437                                               // authorization failures
438
439        UINT32                   maxTries;            // number of unexpired authorization

      Family "2.0"                              TCG Published                                  Page 21
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

440                                                      // failures before the TPM is in
441                                                      // lockout
442
443       UINT32                  recoveryTime;          // time between authorization failures
444                                                      // before failedTries is decremented
445
446       UINT32                  lockoutRecovery;       // time that must expire between
447                                                      // authorization failures associated
448                                                      // with lockoutAuth
449
450       BOOL                    lockOutAuthEnabled; // TRUE if use of lockoutAuth is
451                                                   // allowed
452
453   //*****************************************************************************
454   //            Orderly State
455   //*****************************************************************************
456   // The orderly state for current cycle
457       TPM_SU              orderlyState;
458
459   //*****************************************************************************
460   //           Command audit values.
461   //*****************************************************************************
462       BYTE                auditComands[((TPM_CC_LAST - TPM_CC_FIRST + 1) + 7) / 8];
463       TPMI_ALG_HASH       auditHashAlg;
464       UINT64              auditCounter;
465
466   //*****************************************************************************
467   //           Algorithm selection
468   //*****************************************************************************
469   //
470   // The 'algorithmSet' value indicates the collection of algorithms that are
471   // currently in used on the TPM. The interpretation of value is vendor dependent.
472       UINT32              algorithmSet;
473
474   //*****************************************************************************
475   //           Firmware version
476   //*****************************************************************************
477   // The firmwareV1 and firmwareV2 values are instanced in TimeStamp.c. This is
478   // a scheme used in development to allow determination of the linker build time
479   // of the TPM. An actual implementation would implement these values in a way that
480   // is consistent with vendor needs. The values are maintained in RAM for simplified
481   // access with a master version in NV. These values are modified in a
482   // vendor-specific way.
483
484   // g_firmwareV1 contains the more significant 32-bits of the vendor version number.
485   // In the reference implementation, if this value is printed as a hex
486   // value, it will have the format of yyyymmdd
487       UINT32              firmwareV1;
488
489   // g_firmwareV1 contains the less significant 32-bits of the vendor version number.
490   // In the reference implementation, if this value is printed as a hex
491   // value, it will have the format of 00 hh mm ss
492       UINT32              firmwareV2;
493
494   } PERSISTENT_DATA;
495   extern PERSISTENT_DATA      gp;


      5.8.12.3   ORDERLY_DATA

      The data in this structure is saved to NV on each TPM2_Shutdown().

496   typedef struct orderly_data
497   {
498


      Page 22                                   TCG Published                             Family "2.0"
      October 30, 2014                   Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

499   //*****************************************************************************
500   //           TIME
501   //*****************************************************************************
502
503   //   Clock has two parts. One is the state save part and one is the NV part. The
504   //   state save version is updated on each command. When the clock rolls over, the
505   //   NV version is updated. When the TPM starts up, if the TPM was shutdown in and
506   //   orderly way, then the sClock value is used to initialize the clock. If the
507   //   TPM shutdown was not orderly, then the persistent value is used and the safe
508   //   attribute is clear.
509
510        UINT64                   clock;        // The orderly version of clock
511        TPMI_YES_NO              clockSafe;    // Indicates if the clock value is
512                                               // safe.
513   //*********************************************************************************
514   //          DRBG
515   //*********************************************************************************
516   #ifdef _DRBG_STATE_SAVE
517       // This is DRBG state data. This is saved each time the value of clock is
518       // updated.
519       DRBG_STATE          drbgState;
520   #endif
521
522   } ORDERLY_DATA;
523   extern ORDERLY_DATA           go;


      5.8.12.4    STATE_CLEAR_DATA

      This structure contains the data that is saved on Shutdown(STATE). and restored on Startup(STATE).
      The values are set to their default settings on any Startup(Clear). In other words the data is only
      persistent across TPM Resume.
      If the comments associated with a parameter indicate a default reset value, the value is applied on each
      Startup(CLEAR).

524   typedef struct state_clear_data
525   {
526   //*****************************************************************************
527   //           Hierarchy Control
528   //*****************************************************************************
529       BOOL                shEnable;           // default reset is SET
530       BOOL                ehEnable;           // default reset is SET
531       BOOL                phEnableNV;         // default reset is SET
532       TPMI_ALG_HASH       platformAlg;        // default reset is TPM_ALG_NULL
533       TPM2B_DIGEST        platformPolicy;     // default reset is an Empty Buffer
534       TPM2B_AUTH          platformAuth;       // default reset is an Empty Buffer
535
536   //*****************************************************************************
537   //           PCR
538   //*****************************************************************************
539   // The set of PCR to be saved on Shutdown(STATE)
540       PCR_SAVE            pcrSave;            // default reset is 0...0
541
542   //   This structure hold the authorization values for those PCR that have an
543   //   update authorization.
544   //   This implementation only supports a single group of PCR controlled by
545   //   authorization. If more are required, then this structure would be changed to
546   //   an array.
547         PCR_AUTHVALUE        pcrAuthValues;
548
549   } STATE_CLEAR_DATA;
550   extern STATE_CLEAR_DATA gc;




      Family "2.0"                               TCG Published                                       Page 23
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                        October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

      5.8.12.5    State Reset Data

      This structure contains data is that is saved on Shutdown(STATE) and restored on the subsequent
      Startup(ANY). That is, the data is preserved across TPM Resume and TPM Restart.
      If a default value is specified in the comments this value is applied on TPM Reset.

551   typedef struct state_reset_data
552   {
553   //*****************************************************************************
554   //          Hierarchy Control
555   //*****************************************************************************
556       TPM2B_AUTH          nullProof;          // The proof value associated with
557                                               // the TPM_RH_NULL hierarchy. The
558                                               // default reset value is from the RNG.
559
560       TPM2B_SEED               nullSeed;                // The seed value for the TPM_RN_NULL
561                                                         // hierarchy. The default reset value
562                                                         // is from the RNG.
563
564   //*****************************************************************************
565   //           Context
566   //*****************************************************************************
567   // The 'clearCount' counter is incremented each time the TPM successfully executes
568   // a TPM Resume. The counter is included in each saved context that has 'stClear'
569   // SET (including descendants of keys that have 'stClear' SET). This prevents these
570   // objects from being loaded after a TPM Resume.
571   // If 'clearCount' at its maximum value when the TPM receives a Shutdown(STATE),
572   // the TPM will return TPM_RC_RANGE and the TPM will only accept Shutdown(CLEAR).
573       UINT32              clearCount;         // The default reset value is 0.
574
575       UINT64                   objectContextID;         // This is the context ID for a saved
576                                                         // object context. The default reset
577                                                         // value is 0.
578
579       CONTEXT_SLOT             contextArray[MAX_ACTIVE_SESSIONS];
580                                                    // This is the value from which the
581                                                    // 'contextID' is derived. The
582                                                    // default reset value is {0}.
583
584       CONTEXT_COUNTER          contextCounter;          //   This array contains contains the
585                                                         //   values used to track the version
586                                                         //   numbers of saved contexts (see
587                                                         //   Session.c in for details). The
588                                                         //   default reset value is 0.
589
590   //*****************************************************************************
591   //           Command Audit
592   //*****************************************************************************
593   // When an audited command completes, ExecuteCommand() checks the return
594   // value. If it is TPM_RC_SUCCESS, and the command is an audited command, the
595   // TPM will extend the cpHash and rpHash for the command to this value. If this
596   // digest was the Zero Digest before the cpHash was extended, the audit counter
597   // is incremented.
598
599       TPM2B_DIGEST             commandAuditDigest; // This value is set to an Empty Digest
600                                                    // by TPM2_GetCommandAuditDigest() or a
601                                                    // TPM Reset.
602
603   //*****************************************************************************
604   //           Boot counter
605   //*****************************************************************************
606
607       UINT32                   restartCount;            // This counter counts TPM Restarts.
608                                                         // The default reset value is 0.


      Page 24                                      TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

609
610   //*********************************************************************************
611   //            PCR
612   //*********************************************************************************
613   // This counter increments whenever the PCR are updated. This counter is preserved
614   // across TPM Resume even though the PCR are not preserved. This is because
615   // sessions remain active across TPM Restart and the count value in the session
616   // is compared to this counter so this counter must have values that are unique
617   // as long as the sessions are active.
618   // NOTE: A platform-specific specification may designate that certain PCR changes
619   //       do not increment this counter to increment.
620       UINT32              pcrCounter;         // The default reset value is 0.
621
622   #ifdef TPM_ALG_ECC
623
624   //*****************************************************************************
625   //         ECDAA
626   //*****************************************************************************
627       UINT64              commitCounter;      // This counter increments each time
628                                               // TPM2_Commit() returns
629                                               // TPM_RC_SUCCESS. The default reset
630                                               // value is 0.
631
632       TPM2B_NONCE               commitNonce;            // This random value is used to compute
633                                                         // the commit values. The default reset
634                                                         // value is from the RNG.
635
636   // This implementation relies on the number of bits in g_commitArray being a
637   // power of 2 (8, 16, 32, 64, etc.) and no greater than 64K.
638       BYTE                 commitArray[16];   // The default reset value is {0}.
639
640   #endif //TPM_ALG_ECC
641
642   } STATE_RESET_DATA;
643   extern STATE_RESET_DATA gr;


      5.8.13   Global Macro Definitions

      This macro is used to ensure that a handle, session, or parameter number is only added if the response
      code is FMT1.

644   #define RcSafeAddToResult(r, v) \
645       ((r) + (((r) & RC_FMT1) ? (v) : 0))

      This macro is used when a parameter is not otherwise referenced in a function. This macro is normally
      not used by itself but is paired with a pAssert() within a #ifdef pAssert. If pAssert is not defined, then a
      parameter might not otherwise be referenced. This macro uses the parameter from the perspective of the
      compiler so it doesn't complain.

646   #define UNREFERENCED(a) ((void)(a))


      5.8.14   Private data

647   #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C

      From SessionProcess.c
      The following arrays are used to save command sessions information so that the command
      handle/session buffer does not have to be preserved for the duration of the command. These arrays are
      indexed by the session index in accordance with the order of sessions in the session area of the
      command.

      Family "2.0"                                 TCG Published                                        Page 25
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines


      Array of the authorization session handles

648   extern TPM_HANDLE             s_sessionHandles[MAX_SESSION_NUM];

      Array of authorization session attributes

649   extern TPMA_SESSION           s_attributes[MAX_SESSION_NUM];

      Array of handles authorized by the corresponding authorization sessions; and if none, then
      TPM_RH_UNASSIGNED value is used

650   extern TPM_HANDLE             s_associatedHandles[MAX_SESSION_NUM];

      Array of nonces provided by the caller for the corresponding sessions

651   extern TPM2B_NONCE            s_nonceCaller[MAX_SESSION_NUM];

      Array of authorization values (HMAC's or passwords) for the corresponding sessions

652   extern TPM2B_AUTH             s_inputAuthValues[MAX_SESSION_NUM];

      Special value to indicate an undefined session index

653   #define                  UNDEFINED_INDEX        (0xFFFF)

      Index of the session used for encryption of a response parameter

654   extern UINT32                 s_encryptSessionIndex;

      Index of the session used for decryption of a command parameter

655   extern UINT32                 s_decryptSessionIndex;

      Index of a session used for audit

656   extern UINT32                 s_auditSessionIndex;

      The cpHash for an audit session

657   extern TPM2B_DIGEST           s_cpHashForAudit;

      The cpHash for command audit

658   #ifdef TPM_CC_GetCommandAuditDigest
659   extern TPM2B_DIGEST   s_cpHashForCommandAudit;
660   #endif

      Number of authorization sessions present in the command

661   extern UINT32                 s_sessionNum;

      Flag indicating if NV update is pending for the lockOutAuthEnabled or failedTries DA parameter

662   extern BOOL             s_DAPendingOnNV;
663   #endif // SESSION_PROCESS_C
664   #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C

      From DA.c

      Page 26                                      TCG Published                                 Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library


      This variable holds the accumulated time since the last time that failedTries was decremented. This value
      is in millisecond.

665   extern UINT64            s_selfHealTimer;

      This variable holds the accumulated time that the lockoutAuth has been blocked.

666   extern UINT64       s_lockoutTimer;
667   #endif // DA_C
668   #if defined NV_C || defined GLOBAL_C

      From NV.c
      List of pre-defined address of reserved data

669   extern UINT32            s_reservedAddr[NV_RESERVE_LAST];

      List of pre-defined reserved data size in byte

670   extern UINT32            s_reservedSize[NV_RESERVE_LAST];

      Size of data in RAM index buffer

671   extern UINT32            s_ramIndexSize;

      Reserved RAM space for frequently updated NV Index. The data layout in ram buffer is {NV_handle(),
      size of data, data} for each NV index data stored in RAM

672   extern BYTE          s_ramIndex[RAM_INDEX_SPACE];

      Address of size of RAM index space in NV

673   extern UINT32       s_ramIndexSizeAddr;

      Address of NV copy of RAM index space

674   extern UINT32       s_ramIndexAddr;

      Address of maximum counter value; an auxiliary variable to implement NV counters

675   extern UINT32       s_maxCountAddr;

      Beginning of NV dynamic area; starts right after the s_maxCountAddr and s_evictHandleMapAddr
      variables

676   extern UINT32       s_evictNvStart;

      Beginning of NV dynamic area; also the beginning of the predefined reserved data area.

677   extern UINT32       s_evictNvEnd;

      NV availability is sampled as the start of each command and stored here so that its value remains
      consistent during the command execution

678   extern TPM_RC   s_NvStatus;
679   #endif
680   #if defined OBJECT_C || defined GLOBAL_C

      From Object.c

      Family "2.0"                                   TCG Published                                    Page 27
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines


      This type is the container for an object.

681   typedef struct
682   {
683       BOOL            occupied;
684       ANY_OBJECT          object;
685   } OBJECT_SLOT;

      This is the memory that holds the loaded objects.

686   extern OBJECT_SLOT     s_objects[MAX_LOADED_OBJECTS];
687   #endif // OBJECT_C
688   #if defined PCR_C || defined GLOBAL_C

      From PCR.c

689   typedef struct
690   {
691   #ifdef TPM_ALG_SHA1
692       // SHA1 PCR
693       BYTE    sha1Pcr[SHA1_DIGEST_SIZE];
694   #endif
695   #ifdef TPM_ALG_SHA256
696       // SHA256 PCR
697       BYTE    sha256Pcr[SHA256_DIGEST_SIZE];
698   #endif
699   #ifdef TPM_ALG_SHA384
700       // SHA384 PCR
701       BYTE    sha384Pcr[SHA384_DIGEST_SIZE];
702   #endif
703   #ifdef TPM_ALG_SHA512
704       // SHA512 PCR
705       BYTE    sha512Pcr[SHA512_DIGEST_SIZE];
706   #endif
707   #ifdef TPM_ALG_SM3_256
708       // SHA256 PCR
709       BYTE    sm3_256Pcr[SM3_256_DIGEST_SIZE];
710   #endif
711   } PCR;
712   typedef struct
713   {
714       unsigned int    stateSave : 1;                          //   if the PCR value should be
715                                                               //   saved in state save
716        unsigned int        resetLocality : 5;                 //   The locality that the PCR
717                                                               //   can be reset
718        unsigned int        extendLocality : 5;                //   The locality that the PCR
719                                                               //   can be extend
720   } PCR_Attributes;
721   extern PCR          s_pcrs[IMPLEMENTATION_PCR];
722   #endif // PCR_C
723   #if defined SESSION_C || defined GLOBAL_C

      From Session.c
      Container for HMAC or policy session tracking information

724   typedef struct
725   {
726       BOOL                      occupied;
727       SESSION                   session;          // session structure
728   } SESSION_SLOT;
729   extern SESSION_SLOT           s_sessions[MAX_LOADED_SESSIONS];




      Page 28                                     TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library


      The index in conextArray that has the value of the oldest saved session context. When no context is
      saved, this will have a value that is greater than or equal to MAX_ACTIVE_SESSIONS.

730   extern UINT32                  s_oldestSavedSession;

      The number of available session slot openings. When this is 1, a session can't be created or loaded if the
      GAP is maxed out. The exception is that the oldest saved session context can always be loaded
      (assuming that there is a space in memory to put it)

731   extern int                     s_freeSessionSlots;
732   #endif // SESSION_C

      From Manufacture.c

733   extern BOOL              g_manufactured;
734   #if defined POWER_C || defined GLOBAL_C

      From Power.c
      This value indicates if a TPM2_Startup() commands has been receive since the power on event. This
      flag is maintained in power simulation module because this is the only place that may reliably set this flag
      to FALSE.

735   extern BOOL              s_initialized;
736   #endif // POWER_C
737   #if defined MEMORY_LIB_C || defined GLOBAL_C

      The s_actionOutputBuffer should not be modifiable by the host system until the TPM has returned a
      response code. The s_actionOutputBuffer should not be accessible until response parameter encryption,
      if any, is complete.

738   extern   UINT32   s_actionInputBuffer[1024];          // action input buffer
739   extern   UINT32   s_actionOutputBuffer[1024];         // action output buffer
740   extern   BYTE     s_responseBuffer[MAX_RESPONSE_SIZE];// response buffer
741   #endif   // MEMORY_LIB_C

      From TPMFail.c
      This value holds the address of the string containing the name of the function in which the failure
      occurred. This address value isn't useful for anything other than helping the vendor to know in which file
      the failure occurred.

742   extern jmp_buf   g_jumpBuffer;          //           the jump buffer
743   extern BOOL      g_inFailureMode;       //           Indicates that the TPM is in failure mode
744   extern BOOL      g_forceFailureMode;    //           flag to force failure mode during test
745   #if defined TPM_FAIL_C || defined GLOBAL_C           || 1
746   extern UINT32    s_failFunction;
747   extern UINT32    s_failLine;            //           the line in the file at which
748                                           //           the error was signaled
749   extern UINT32    s_failCode;            //           the error code used
750   #endif // TPM_FAIL_C
751   #endif // GLOBAL_H


      5.9    Tpm.h

      Root header file for building any TPM.lib code

  1   #ifndef        _TPM_H_
  2   #define        _TPM_H_
  3   #include       "bool.h"


      Family "2.0"                                 TCG Published                                        Page 29
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                            Part 4: Supporting Routines

 4   #include    "Implementation.h"
 5   #include    "TPM_Types.h"
 6   #include    "swap.h"
 7   #endif // _TPM_H_


     5.10    swap.h

 1   #ifndef _SWAP_H
 2   #define _SWAP_H
 3   #include "Implementation.h"
 4   #if    NO_AUTO_ALIGN == YES || LITTLE_ENDIAN_TPM == YES

     The aggregation macros for machines that do not allow unaligned access or for little-endian machines.
     Aggregate bytes into an UINT

 5   #define BYTE_ARRAY_TO_UINT8(b)          (UINT8)((b)[0])
 6   #define BYTE_ARRAY_TO_UINT16(b)         (UINT16)( ((b)[0] << 8) \
 7                                                    + (b)[1])
 8   #define BYTE_ARRAY_TO_UINT32(b)         (UINT32)( ((b)[0] << 24) \
 9                                                    + ((b)[1] << 16) \
10                                                    + ((b)[2] << 8 ) \
11                                                    + (b)[3])
12   #define BYTE_ARRAY_TO_UINT64(b)         (UINT64)( ((UINT64)(b)[0] <<       56)   \
13                                                    + ((UINT64)(b)[1] <<      48)   \
14                                                    + ((UINT64)(b)[2] <<      40)   \
15                                                    + ((UINT64)(b)[3] <<      32)   \
16                                                    + ((UINT64)(b)[4] <<      24)   \
17                                                    + ((UINT64)(b)[5] <<      16)   \
18                                                    + ((UINT64)(b)[6] <<       8)   \
19                                                    + (UINT64)(b)[7])

     Disaggregate a UINT into a byte array

20   #define UINT8_TO_BYTE_ARRAY(i, b)           ((b)[0]   = (BYTE)(i), i)
21   #define UINT16_TO_BYTE_ARRAY(i, b)          ((b)[0]   = (BYTE)((i) >>     8), \
22                                                (b)[1]   = (BYTE) (i),           \
23                                                (i))
24   #define UINT32_TO_BYTE_ARRAY(i, b)          ((b)[0]   =   (BYTE)((i) >> 24), \
25                                                (b)[1]   =   (BYTE)((i) >> 16), \
26                                                (b)[2]   =   (BYTE)((i) >> 8), \
27                                                (b)[3]   =   (BYTE) (i),        \
28                                                (i))
29   #define UINT64_TO_BYTE_ARRAY(i, b)          ((b)[0]   =   (BYTE)((i) >>   56),   \
30                                                (b)[1]   =   (BYTE)((i) >>   48),   \
31                                                (b)[2]   =   (BYTE)((i) >>   40),   \
32                                                (b)[3]   =   (BYTE)((i) >>   32),   \
33                                                (b)[4]   =   (BYTE)((i) >>   24),   \
34                                                (b)[5]   =   (BYTE)((i) >>   16),   \
35                                                (b)[6]   =   (BYTE)((i) >>    8),   \
36                                                (b)[7]   =   (BYTE) (i),            \
37                                                (i))
38   #else

     the big-endian macros for machines that allow unaligned memory access Aggregate a byte array into a
     UINT

39   #define   BYTE_ARRAY_TO_UINT8(b)            *((UINT8      *)(b))
40   #define   BYTE_ARRAY_TO_UINT16(b)           *((UINT16     *)(b))
41   #define   BYTE_ARRAY_TO_UINT32(b)           *((UINT32     *)(b))
42   #define   BYTE_ARRAY_TO_UINT64(b)           *((UINT64     *)(b))

     Disaggregate a UINT into a byte array

     Page 30                                    TCG Published                                 Family "2.0"
     October 30, 2014                    Copyright © TCG 2006-2014                Level 00 Revision 01.16
     Part 4: Supporting Routines                                               Trusted Platform Module Library

43   #define   UINT8_TO_BYTE_ARRAY(i, b)      (*((UINT8    *)(b))   =   (i))
44   #define   UINT16_TO_BYTE_ARRAY(i, b)     (*((UINT16   *)(b))   =   (i))
45   #define   UINT32_TO_BYTE_ARRAY(i, b)     (*((UINT32   *)(b))   =   (i))
46   #define   UINT64_TO_BYTE_ARRAY(i, b)     (*((UINT64   *)(b))   =   (i))
47   #endif    // NO_AUTO_ALIGN == YES
48   #endif    // _SWAP_H


     5.11   InternalRoutines.h

 1   #ifndef        INTERNAL_ROUTINES_H
 2   #define        INTERNAL_ROUTINES_H

     NULL definition

 3   #ifndef              NULL
 4   #define              NULL        (0)
 5   #endif

     UNUSED_PARAMETER

 6   #ifndef              UNUSED_PARAMETER
 7   #define              UNUSED_PARAMETER(param)    (void)(param);
 8   #endif

     Internal data definition

 9   #include "Global.h"
10   #include "VendorString.h"

     Error Reporting

11   #include "TpmError.h"

     DRTM functions

12   #include "_TPM_Hash_Start_fp.h"
13   #include "_TPM_Hash_Data_fp.h"
14   #include "_TPM_Hash_End_fp.h"

     Internal subsystem functions

15   #include   "Object_fp.h"
16   #include   "Entity_fp.h"
17   #include   "Session_fp.h"
18   #include   "Hierarchy_fp.h"
19   #include   "NV_fp.h"
20   #include   "PCR_fp.h"
21   #include   "DA_fp.h"
22   #include   "TpmFail_fp.h"

     Internal support functions

23   #include   "CommandCodeAttributes_fp.h"
24   #include   "MemoryLib_fp.h"
25   #include   "marshal_fp.h"
26   #include   "Time_fp.h"
27   #include   "Locality_fp.h"
28   #include   "PP_fp.h"
29   #include   "CommandAudit_fp.h"
30   #include   "Manufacture_fp.h"
31   #include   "Power_fp.h"

     Family "2.0"                             TCG Published                                          Page 31
     Level 00 Revision 01.16            Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                      Part 4: Supporting Routines

32   #include   "Handle_fp.h"
33   #include   "Commands_fp.h"
34   #include   "AlgorithmCap_fp.h"
35   #include   "PropertyCap_fp.h"
36   #include   "Bits_fp.h"

     Internal crypto functions

37   #include "Ticket_fp.h"
38   #include "CryptUtil_fp.h"
39   #include "CryptSelfTest_fp.h"
40   #endif


     5.12    TpmBuildSwitches.h

     This file contains the build switches. This contains switches for multiple versions of the crypto-library so
     some may not apply to your environment.

 1   #ifndef   _TPM_BUILD_SWITCHES_H
 2   #define   _TPM_BUILD_SWITCHES_H
 3   #define   SIMULATION
 4   #define   FIPS_COMPLIANT

     Define the alignment macro appropriate for the build environment For MS C compiler

 5   #define ALIGN_TO(boundary)            __declspec(align(boundary))

     For ISO 9899:2011

 6   // #define ALIGN_TO(boundary)                 _Alignas(boundary)

     This switch enables the RNG state save and restore

 7   #undef _DRBG_STATE_SAVE
 8   #define _DRBG_STATE_SAVE                    // Comment this out if no state save is wanted

     Set the alignment size for the crypto. It would be nice to set this according to macros automatically
     defined by the build environment, but that doesn't seem possible because there isn't any simple set for
     that. So, this is just a plugged value. Your compiler should complain if this alignment isn't possible.

     NOTE:           this value can be set at the command line or just plugged in here.

 9   #ifdef CRYPTO_ALIGN_16
10   #   define CRYPTO_ALIGNMENT    16
11   #elif defined CRYPTO_ALIGN_8
12   #   define CRYPTO_ALIGNMENT    8
13   #eliF defined CRYPTO_ALIGN_2
14   #   define CRYPTO_ALIGNMENT    2
15   #elif defined CRTYPO_ALIGN_1
16   #   define CRYPTO_ALIGNMENT    1
17   #else
18   #   define CRYPTO_ALIGNMENT    4    // For 32-bit builds
19   #endif
20   #define CRYPTO_ALIGNED ALIGN_TO(CRYPTO_ALIGNMENT)

     This macro is used to handle LIB_EXPORT of function and variable names in lieu of a .def file

21   #define LIB_EXPORT __declspec(dllexport)
22   // #define LIB_EXPORT



     Page 32                                            TCG Published                                   Family "2.0"
     October 30, 2014                          Copyright © TCG 2006-2014                   Level 00 Revision 01.16
     Part 4: Supporting Routines                                                  Trusted Platform Module Library


     For import of a variable

23   #define LIB_IMPORT __declspec(dllimport)
24   //#define LIB_IMPORT

     This is defined to indicate a function that does not return. This is used in static code anlaysis.

25   #define _No_Return_ __declspec(noreturn)
26   //#define _No_Return_
27   #ifdef SELF_TEST
28   #pragma comment(lib, "algorithmtests.lib")
29   #endif

     The switches in this group can only be enabled when running a simulation

30   #ifdef SIMULATION
31   #   define RSA_KEY_CACHE
32   #   define TPM_RNG_FOR_DEBUG
33   #else
34   #   undef RSA_KEY_CACHE
35   #   undef TPM_RNG_FOR_DEBUG
36   #endif // SIMULATION
37   #define INLINE __inline
38   #endif // _TPM_BUILD_SWITCHES_H


     5.13   VendorString.h

 1   #ifndef         _VENDOR_STRING_H
 2   #define         _VENDOR_STRING_H

     Define up to 4-byte values for MANUFACTURER.         This value defines the response for
     TPM_PT_MANUFACTURER in TPM2_GetCapability(). The following line should be un-commented and a
     vendor specific string should be provided here.

 3   #define        MANUFACTURER       "MSFT"

     The following #if macro may be deleted after a proper MANUFACTURER is provided.

 4   #ifndef MANUFACTURER
 5   #error MANUFACTURER is not provided. \
 6   Please modify include\VendorString.h to provide a specific \
 7   manufacturer name.
 8   #endif

     Define up to 4, 4-byte values. The values must each be 4 bytes long and the last value used may contain
     trailing zeros. These values define the response for TPM_PT_VENDOR_STRING_(1-4) in
     TPM2_GetCapability(). The following line should be un-commented and a vendor specific string should
     be provided here. The vendor strings 2-4 may also be defined as appropriately.

 9   #define           VENDOR_STRING_1             "xCG "
10   #define           VENDOR_STRING_2             "fTPM"
11   // #define           VENDOR_STRING_3
12   // #define           VENDOR_STRING_4

     The following #if macro may be deleted after a proper VENDOR_STRING_1 is provided.

13   #ifndef VENDOR_STRING_1
14   #error VENDOR_STRING_1 is not provided. \
15   Please modify include\VendorString.h to provide a vednor specific \
16   string.


     Family "2.0"                                  TCG Published                                          Page 33
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
     Trusted Platform Module Library                                                  Part 4: Supporting Routines

17   #endif

     the more significant 32-bits of a vendor-specific value indicating the version of the firmware The following
     line should be un-commented and a vendor specific firmware V1 should be provided here. The
     FIRMWARE_V2 may also be defined as appropriate.

18   #define     FIRMWARE_V1               (0x20140504)

     the less significant 32-bits of a vendor-specific value indicating the version of the firmware

19   #define     FIRMWARE_V2               (0x00200136)

     The following #if macro may be deleted after a proper FIRMWARE_V1 is provided.

20   #ifndef FIRMWARE_V1
21   #error FIRMWARE_V1 is not provided. \
22   Please modify include\VendorString.h to provide a vendor specific firmware \
23   version
24   #endif
25   #endif




     Page 34                                       TCG Published                                      Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
     Part 4: Supporting Routines                                                   Trusted Platform Module Library


     6     Main

     6.1      CommandDispatcher.h

     In the reference implementation, a program that uses TPM 2.0 Part 3 as input automatically generates
     the command dispatch code. The function prototype header file (CommandDispatcher_fp.h) is shown
     here.
     CommandDispatcher() performs the following operations:
          unmarshals command parameters from the input buffer;
          invokes the function that performs the command actions;
          marshals the returned handles, if any; and
          marshals the returned parameters, if any, into the output buffer putting in the parameterSize field if
           authorization sessions are present.

 1   #ifndef        _COMMANDDISPATCHER_FP_H_
 2   #define        _COMMANDDISPATCHER_FP_H_
 3   TPM_RC
 4   CommandDispatcher(
 5       TPMI_ST_COMMAND_TAG      tag,   //             IN: Input command tag
 6       TPM_CC      commandCode,        //             IN: Command code
 7       INT32       *parmBufferSize,    //             IN: size of parameter buffer
 8       BYTE        *parmBufferStart,   //             IN: pointer to start of parameter buffer
 9       TPM_HANDLE handles[],           //             IN: handle array
10       UINT32      *responseHandleSize,//             OUT: size of handle buffer in response
11       UINT32      *respParmSize       //             OUT: size of parameter buffer in response
12       );
13   #endif // _COMMANDDISPATCHER_FP_H_


     6.2      ExecCommand.c

     6.2.1      Introduction

     This file contains the entry function ExecuteCommand() which provides the main control flow for TPM
     command execution.

     6.2.2      Includes

 1   #include     "InternalRoutines.h"
 2   #include     "HandleProcess_fp.h"
 3   #include     "SessionProcess_fp.h"
 4   #include     "CommandDispatcher_fp.h"

     Uncomment this next #include if doing static command/response buffer sizing

 5   // #include "CommandResponseSizes_fp.h"


     6.2.3      ExecuteCommand()

     The function performs the following steps.
     a) Parses the command header from input buffer.
     b) Calls ParseHandleBuffer() to parse the handle area of the command.
     c) Validates that each of the handles references a loaded entity.

     Family "2.0"                                   TCG Published                                          Page 35
     Level 00 Revision 01.16                 Copyright © TCG 2006-2014                           October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines


     d) Calls ParseSessionBuffer() () to:
          1) unmarshal and parse the session area;
          2) check the authorizations; and
          3) when necessary, decrypt a parameter.
     e) Calls CommandDispatcher() to:
          1) unmarshal the command parameters from the command buffer;
          2) call the routine that performs the command actions; and
          3) marshal the responses into the response buffer.
     f)   If any error occurs in any of the steps above create the error response and return.
     g) Calls BuildResponseSession() to:
          1) when necessary, encrypt a parameter
          2) build the response authorization sessions
          3) update the audit sessions and nonces
     h) Assembles handle, parameter and session buffers for response and return.

 6   LIB_EXPORT void
 7   ExecuteCommand(
 8        unsigned    int      requestSize,       //   IN: command buffer size
 9        unsigned    char    *request,           //   IN: command buffer
10        unsigned    int     *responseSize,      //   OUT: response buffer size
11        unsigned    char    **response          //   OUT: response buffer
12        )
13   {
14        // Command local variables
15        TPM_ST               tag;                         // these first three variables are the
16        UINT32               commandSize;
17        TPM_CC               commandCode = 0;
18
19        BYTE                     *parmBufferStart;        // pointer to the first byte of an
20                                                          // optional parameter buffer
21
22        UINT32                    parmBufferSize = 0;// number of bytes in parameter area
23
24        UINT32                    handleNum = 0;          // number of handles unmarshaled into
25                                                          // the handles array
26
27        TPM_HANDLE                handles[MAX_HANDLE_NUM];// array to hold handles in the
28                                                     // command. Only handles in the handle
29                                                     // area are stored here, not handles
30                                                     // passed as parameters.
31
32        // Response local variables
33        TPM_RC               result;                      // return code for the command
34
35        TPM_ST                    resTag;                 // tag for the response
36
37        UINT32                    resHandleSize = 0; //       size of the handle area in the
38                                                     //       response. This is needed so that the
39                                                     //       handle area can be skipped when
40                                                     //       generating the rpHash.
41
42        UINT32                    resParmSize = 0;        // the size of the response parameters
43                                                          // These values go in the rpHash.
44
45        UINT32                    resAuthSize = 0;        // size of authorization area in the


     Page 36                                       TCG Published                                   Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

 46                                                       // response
 47
 48       INT32                      size;                // remaining data to be unmarshaled
 49                                                       // or remaining space in the marshaling
 50                                                       // buffer
 51
 52       BYTE                      *buffer;              // pointer into the buffer being used
 53                                                       // for marshaling or unmarshaling
 54
 55       UINT32                     i;                    // local temp
 56
 57   // This next function call is used in development to size the command and response
 58   // buffers. The values printed are the sizes of the internal structures and
 59   // not the sizes of the canonical forms of the command response structures. Also,
 60   // the sizes do not include the tag, commandCode, requestSize, or the authorization
 61   // fields.
 62   //CommandResponseSizes();
 63
 64       // Set flags for NV access state. This should happen before any other
 65       // operation that may require a NV write. Note, that this needs to be done
 66       // even when in failure mode. Otherwise, g_updateNV would stay SET while in
 67       // Failure mode and the NB would be written on each call.
 68       g_updateNV = FALSE;
 69       g_clearOrderly = FALSE;
 70
 71       // As of Sept 25, 2013, the failure mode handling has been incorporated in the
 72       // reference code. This implementation requires that the system support
 73       // setjmp/longjmp. This code is put here because of the complexity being
 74       // added to the platform and simulator code to deal with all the variations
 75       // of errors.
 76       if(g_inFailureMode)
 77       {
 78           // Do failure mode processing
 79           TpmFailureMode (requestSize, request, responseSize, response);
 80           return;
 81       }
 82       if(setjmp(g_jumpBuffer) != 0)
 83       {
 84           // Get here if we got a longjump putting us into failure mode
 85           g_inFailureMode = TRUE;
 86           result = TPM_RC_FAILURE;
 87           goto Fail;
 88       }
 89
 90       // Assume that everything is going to work.
 91       result = TPM_RC_SUCCESS;
 92
 93       // Query platform to get the NV state. The result state is saved internally
 94       // and will be reported by NvIsAvailable(). The reference code requires that
 95       // accessibility of NV does not change during the execution of a command.
 96       // Specifically, if NV is available when the command execution starts and then
 97       // is not available later when it is necessary to write to NV, then the TPM
 98       // will go into failure mode.
 99       NvCheckState();
100
101       // Due to the limitations of the simulation, TPM clock must be explicitly
102       // synchronized with the system clock whenever a command is received.
103       // This function call is not necessary in a hardware TPM. However, taking
104       // a snapshot of the hardware timer at the beginning of the command allows
105       // the time value to be consistent for the duration of the command execution.
106       TimeUpdateToCurrent();
107
108       // Any command through this function will unceremoniously end the
109       // _TPM_Hash_Data/_TPM_Hash_End sequence.
110       if(g_DRTMHandle != TPM_RH_UNASSIGNED)
111           ObjectTerminateEvent();

      Family "2.0"                                TCG Published                                  Page 37
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                  Part 4: Supporting Routines

112
113         // Get command buffer size and command buffer.
114         size = requestSize;
115         buffer = request;
116
117         // Parse command header: tag, commandSize and commandCode.
118         // First parse the tag. The unmarshaling routine will validate
119         // that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS.
120         result = TPMI_ST_COMMAND_TAG_Unmarshal(&tag, &buffer, &size);
121         if(result != TPM_RC_SUCCESS)
122             goto Cleanup;
123
124         // Unmarshal the commandSize indicator.
125         result = UINT32_Unmarshal(&commandSize, &buffer, &size);
126         if(result != TPM_RC_SUCCESS)
127             goto Cleanup;
128
129         // On a TPM that receives bytes on a port, the number of bytes that were
130         // received on that port is requestSize it must be identical to commandSize.
131         // In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed
132         // by the implementation. The check against MAX_COMMAND_SIZE may be redundant
133         // as the input processing (the function that receives the command bytes and
134         // places them in the input buffer) would likely have the input truncated when
135         // it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize.
136         if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE)
137         {
138             result = TPM_RC_COMMAND_SIZE;
139             goto Cleanup;
140         }
141
142         // Unmarshal the command code.
143         result = TPM_CC_Unmarshal(&commandCode, &buffer, &size);
144         if(result != TPM_RC_SUCCESS)
145             goto Cleanup;
146
147         // Check to see if the command is implemented.
148         if(!CommandIsImplemented(commandCode))
149         {
150             result = TPM_RC_COMMAND_CODE;
151             goto Cleanup;
152         }
153
154   #if   FIELD_UPGRADE_IMPLEMENTED == YES
155       // If the TPM is in FUM, then the only allowed command is
156       // TPM_CC_FieldUpgradeData.
157       if(IsFieldUgradeMode() && (commandCode != TPM_CC_FieldUpgradeData))
158       {
159            result = TPM_RC_UPGRADE;
160            goto Cleanup;
161       }
162       else
163   #endif
164            // Excepting FUM, the TPM only accepts TPM2_Startup() after
165            // _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup()
166            // is no longer allowed.
167            if((    !TPMIsStarted() && commandCode != TPM_CC_Startup)
168                 || (TPMIsStarted() && commandCode == TPM_CC_Startup))
169            {
170                 result = TPM_RC_INITIALIZE;
171                 goto Cleanup;
172            }
173
174         // Start regular command process.
175         // Parse Handle buffer.
176         result = ParseHandleBuffer(commandCode, &buffer, &size, handles, &handleNum);
177         if(result != TPM_RC_SUCCESS)

      Page 38                                TCG Published                           Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014        Level 00 Revision 01.16
      Part 4: Supporting Routines                                     Trusted Platform Module Library

178            goto Cleanup;
179
180       // Number of handles retrieved from handle area should be less than
181       // MAX_HANDLE_NUM.
182       pAssert(handleNum <= MAX_HANDLE_NUM);
183
184       // All handles in the handle area are required to reference TPM-resident
185       // entities.
186       for(i = 0; i < handleNum; i++)
187       {
188           result = EntityGetLoadStatus(&handles[i], commandCode);
189           if(result != TPM_RC_SUCCESS)
190           {
191               if(result == TPM_RC_REFERENCE_H0)
192                   result = result + i;
193               else
194                   result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]);
195               goto Cleanup;
196           }
197       }
198
199       // Authorization session handling for the command.
200       if(tag == TPM_ST_SESSIONS)
201       {
202           BYTE        *sessionBufferStart;// address of the session area first byte
203                                           // in the input buffer
204
205            UINT32        authorizationSize;   // number of bytes in the session area
206
207            // Find out session buffer size.
208            result = UINT32_Unmarshal(&authorizationSize, &buffer, &size);
209            if(result != TPM_RC_SUCCESS)
210                goto Cleanup;
211
212            // Perform sanity check on the unmarshaled    value. If it is smaller than
213            // the smallest possible session or larger    than the remaining size of
214            // the command, then it is an error. NOTE:    This check could pass but the
215            // session size could still be wrong. That    will be determined after the
216            // sessions are unmarshaled.
217            if(    authorizationSize < 9
218                || authorizationSize > (UINT32) size)
219            {
220                 result = TPM_RC_SIZE;
221                 goto Cleanup;
222            }
223
224            // The sessions, if any, follows authorizationSize.
225            sessionBufferStart = buffer;
226
227            // The parameters follow the session area.
228            parmBufferStart = sessionBufferStart + authorizationSize;
229
230            // Any data left over after removing the authorization sessions is
231            // parameter data. If the command does not have parameters, then an
232            // error will be returned if the remaining size is not zero. This is
233            // checked later.
234            parmBufferSize = size - authorizationSize;
235
236            // The actions of ParseSessionBuffer() are described in the introduction.
237            result = ParseSessionBuffer(commandCode,
238                                        handleNum,
239                                        handles,
240                                        sessionBufferStart,
241                                        authorizationSize,
242                                        parmBufferStart,
243                                        parmBufferSize);

      Family "2.0"                           TCG Published                                  Page 39
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                   Part 4: Supporting Routines

244             if(result != TPM_RC_SUCCESS)
245                 goto Cleanup;
246       }
247       else
248       {
249           // Whatever remains in the input buffer is used for the parameters of the
250           // command.
251           parmBufferStart = buffer;
252           parmBufferSize = size;
253
254             // The command has no authorization sessions.
255             // If the command requires authorizations, then CheckAuthNoSession() will
256             // return an error.
257             result = CheckAuthNoSession(commandCode, handleNum, handles,
258                                          parmBufferStart, parmBufferSize);
259             if(result != TPM_RC_SUCCESS)
260                 goto Cleanup;
261       }
262
263       // CommandDispatcher returns a response handle buffer and a response parameter
264       // buffer if it succeeds. It will also set the parameterSize field in the
265       // buffer if the tag is TPM_RC_SESSIONS.
266       result = CommandDispatcher(tag,
267                                  commandCode,
268                                  (INT32 *) &parmBufferSize,
269                                  parmBufferStart,
270                                  handles,
271                                  &resHandleSize,
272                                  &resParmSize);
273       if(result != TPM_RC_SUCCESS)
274           goto Cleanup;
275
276       // Build the session area at the end of the parameter area.
277       BuildResponseSession(tag,
278                            commandCode,
279                            resHandleSize,
280                            resParmSize,
281                            &resAuthSize);
282
283   Cleanup:
284       // This implementation loads an "evict" object to a transient object slot in
285       // RAM whenever an "evict" object handle is used in a command so that the
286       // access to any object is the same. These temporary objects need to be
287       // cleared from RAM whether the command succeeds or fails.
288       ObjectCleanupEvict();
289
290   Fail:
291       // The response will contain at least a response header.
292       *responseSize = sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC);
293
294       // If the command completed successfully, then build the rest of the response.
295       if(result == TPM_RC_SUCCESS)
296       {
297           // Outgoing tag will be the same as the incoming tag.
298           resTag = tag;
299           // The overall response will include the handles, parameters,
300           // and authorizations.
301           *responseSize += resHandleSize + resParmSize + resAuthSize;
302
303             // Adding parameter size field.
304             if(tag == TPM_ST_SESSIONS)
305                 *responseSize += sizeof(UINT32);
306
307             if(      g_clearOrderly == TRUE
308                   && gp.orderlyState != SHUTDOWN_NONE)
309             {

      Page 40                                  TCG Published                          Family "2.0"
      October 30, 2014                   Copyright © TCG 2006-2014       Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

310                    gp.orderlyState = SHUTDOWN_NONE;
311                    NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
312                    g_updateNV = TRUE;
313             }
314         }
315         else
316         {
317             // The command failed.
318             // If this was a failure due to a bad command tag, then need to return
319             // a TPM 1.2 compatible response
320             if(result == TPM_RC_BAD_TAG)
321                  resTag = TPM_ST_RSP_COMMAND;
322             else
323                  // return 2.0 compatible response
324                  resTag = TPM_ST_NO_SESSIONS;
325         }
326         // Try to commit all the writes to NV if any NV write happened during this
327         // command execution. This check should be made for both succeeded and failed
328         // commands, because a failed one may trigger a NV write in DA logic as well.
329         // This is the only place in the command execution path that may call the NV
330         // commit. If the NV commit fails, the TPM should be put in failure mode.
331         if(g_updateNV && !g_inFailureMode)
332         {
333             g_updateNV = FALSE;
334             if(!NvCommit())
335                  FAIL(FATAL_ERROR_INTERNAL);
336         }
337
338         // Marshal the response header.
339         buffer = MemoryGetResponseBuffer(commandCode);
340         TPM_ST_Marshal(&resTag, &buffer, NULL);
341         UINT32_Marshal((UINT32 *)responseSize, &buffer, NULL);
342         pAssert(*responseSize <= MAX_RESPONSE_SIZE);
343         TPM_RC_Marshal(&result, &buffer, NULL);
344
345         *response = MemoryGetResponseBuffer(commandCode);
346
347         // Clear unused bit in response buffer.
348         MemorySet(*response + *responseSize, 0, MAX_RESPONSE_SIZE - *responseSize);
349
350         return;
351   }


      6.3    ParseHandleBuffer.h

      In the reference implementation, the routine for unmarshaling the command handles is automatically
      generated from TPM 2.0 Part 3 command tables. The prototype header file (HandleProcess_fp.h) is
      shown here.

  1   #ifndef         _HANDLEPROCESS_FP_H_
  2   #define         _HANDLEPROCESS_FP_H_
  3   TPM_RC
  4   ParseHandleBuffer(
  5         TPM_CC         commandCode,                  //   IN: Command being processed
  6         BYTE           **handleBufferStart,          //   IN/OUT: command buffer where handles
  7                                                      //     are located. Updated as handles
  8                                                      //     are unmarshaled
  9         INT32          *bufferRemainingSize,         //   IN/OUT: indicates the amount of data
 10                                                      //     left in the command buffer.
 11                                                      //     Updated as handles are unmarshaled
 12       TPM_HANDLE handles[],                          //   OUT: Array that receives the handles
 13       UINT32     *handleCount                        //   OUT: Receives the count of handles
 14       );
 15   #endif // _HANDLEPROCESS_FP_H_

      Family "2.0"                                TCG Published                                  Page 41
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                     October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines

     6.4     SessionProcess.c

     6.4.1     Introduction

     This file contains the subsystem that process the authorization sessions including implementation of the
     Dictionary Attack logic. ExecCommand() uses ParseSessionBuffer() to process the authorization session
     area of a command and BuildResponseSession() to create the authorization session area of a response.

     6.4.2     Includes and Data Definitions

 1   #define SESSION_PROCESS_C
 2   #include "InternalRoutines.h"
 3   #include "SessionProcess_fp.h"
 4   #include "Platform.h"


     6.4.3     Authorization Support Functions

     6.4.3.1      IsDAExempted()

     This function indicates if a handle is exempted from DA logic. A handle is exempted if it is
     a) a primary seed handle,
     b) an object with noDA bit SET,
     c) an NV Index with TPMA_NV_NO_DA bit SET, or
     d) a PCR handle.

     Return Value                      Meaning

     TRUE                              handle is exempted from DA logic
     FALSE                             handle is not exempted from DA logic

 5   BOOL
 6   IsDAExempted(
 7         TPM_HANDLE          handle              // IN: entity handle
 8         )
 9   {
10         BOOL          result = FALSE;
11
12         switch(HandleGetType(handle))
13         {
14             case TPM_HT_PERMANENT:
15                 // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from
16                 // DA protection.
17                 result = (handle != TPM_RH_LOCKOUT);
18                 break;
19
20             // When this function is called, a persistent object will have been loaded
21             // into an object slot and assigned a transient handle.
22             case TPM_HT_TRANSIENT:
23             {
24                 OBJECT      *object;
25                 object = ObjectGet(handle);
26                 result = (object->publicArea.objectAttributes.noDA == SET);
27                 break;
28             }
29             case TPM_HT_NV_INDEX:
30             {
31                 NV_INDEX        nvIndex;

     Page 42                                       TCG Published                                    Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                                 Trusted Platform Module Library

32                    NvGetIndexInfo(handle, &nvIndex);
33                    result = (nvIndex.publicArea.attributes.TPMA_NV_NO_DA == SET);
34                    break;
35             }
36             case TPM_HT_PCR:
37                 // PCRs are always exempted from DA.
38                 result = TRUE;
39                 break;
40             default:
41                 break;
42       }
43       return result;
44   }


     6.4.3.2     IncrementLockout()

     This function is called after an authorization failure that involves use of an authValue. If the entity
     referenced by the handle is not exempt from DA protection, then the failedTries counter will be
     incremented.

     Error Returns                  Meaning

     TPM_RC_AUTH_FAIL               authorization failure that caused DA lockout to increment
     TPM_RC_BAD_AUTH                authorization failure did not cause DA lockout to increment

45   static TPM_RC
46   IncrementLockout(
47       UINT32                sessionIndex
48       )
49   {
50       TPM_HANDLE            handle = s_associatedHandles[sessionIndex];
51       TPM_HANDLE            sessionHandle = s_sessionHandles[sessionIndex];
52       TPM_RC                result;
53       SESSION              *session = NULL;
54
55       // Don't increment lockout unless the handle associated with the session
56       // is DA protected or the session is bound to a DA protected entity.
57       if(sessionHandle == TPM_RS_PW)
58       {
59           if(IsDAExempted(handle))
60               return TPM_RC_BAD_AUTH;
61
62       }
63       else
64       {
65           session = SessionGet(sessionHandle);
66           // If the session is bound to lockout, then use that as the relevant
67           // handle. This means that an auth failure with a bound session
68           // bound to lockoutAuth will take precedence over any other
69           // lockout check
70           if(session->attributes.isLockoutBound == SET)
71               handle = TPM_RH_LOCKOUT;
72
73             if(      session->attributes.isDaBound == CLEAR
74                   && IsDAExempted(handle)
75               )
76                   // If the handle was changed to TPM_RH_LOCKOUT, this will not return
77                   // TPM_RC_BAD_AUTH
78                    return TPM_RC_BAD_AUTH;
79
80       }
81
82       if(handle == TPM_RH_LOCKOUT)

     Family "2.0"                                TCG Published                                            Page 43
     Level 00 Revision 01.16            Copyright © TCG 2006-2014                                 October 30, 2014
      Trusted Platform Module Library                                                       Part 4: Supporting Routines

 83        {
 84             pAssert(gp.lockOutAuthEnabled);
 85             gp.lockOutAuthEnabled = FALSE;
 86             // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since
 87             // the lockout auth will be reset at startup.
 88             if(gp.lockoutRecovery != 0)
 89             {
 90                 result = NvIsAvailable();
 91                 if(result != TPM_RC_SUCCESS)
 92                 {
 93                     // No NV access for now. Put the TPM in pending mode.
 94                     s_DAPendingOnNV = TRUE;
 95                 }
 96                 else
 97                 {
 98                     // Update NV.
 99                     NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
100                     g_updateNV = TRUE;
101                 }
102             }
103        }
104        else
105        {
106            if(gp.recoveryTime != 0)
107            {
108                gp.failedTries++;
109                result = NvIsAvailable();
110                if(result != TPM_RC_SUCCESS)
111                {
112                    // No NV access for now. Put the TPM in pending mode.
113                    s_DAPendingOnNV = TRUE;
114                }
115                else
116                {
117                    // Record changes to NV.
118                    NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
119                    g_updateNV = TRUE;
120                }
121            }
122        }
123
124        // Register a DA failure and reset the timers.
125        DARegisterFailure(handle);
126
127        return TPM_RC_AUTH_FAIL;
128   }


      6.4.3.3     IsSessionBindEntity()

      This function indicates if the entity associated with the handle is the entity, to which this session is bound.
      The binding would occur by making the bind parameter in TPM2_StartAuthSession() not equal to
      TPM_RH_NULL. The binding only occurs if the session is an HMAC session. The bind value is a
      combination of the Name and the authValue of the entity.

      Return Value                      Meaning

      TRUE                              handle points to the session start entity
      FALSE                             handle does not point to the session start entity

129   static BOOL
130   IsSessionBindEntity(
131        TPM_HANDLE           associatedHandle,         // IN: handle to be authorized
132        SESSION             *session                   // IN: associated session

      Page 44                                         TCG Published                                       Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

133        )
134   {
135        TPM2B_NAME        entity;                    // The bind value for the entity
136
137        // If the session is not bound, return FALSE.
138        if(!session->attributes.isBound)
139            return FALSE;
140
141        // Compute the bind value for the entity.
142        SessionComputeBoundEntity(associatedHandle, &entity);
143
144        // Compare to the bind value in the session.
145        session->attributes.requestWasBound =
146                Memory2BEqual(&entity.b, &session->u1.boundEntity.b);
147        return session->attributes.requestWasBound;
148   }


      6.4.3.4     IsPolicySessionRequired()

      Checks if a policy session is required for a command. If a command requires DUP or ADMIN role
      authorization, then the handle that requires that role is the first handle in the command. This simplifies
      this checking. If a new command is created that requires multiple ADMIN role authorizations, then it will
      have to be special-cased in this function. A policy session is required if:
      a) the command requires the DUP role,
      b) the command requires the ADMIN role and the authorized entity is an object and its adminWithPolicy
         bit is SET, or
      c) the command requires the ADMIN role and the authorized entity is a permanent handle or an NV
         Index.
      d) The authorized entity is a PCR belonging to a policy group, and has its policy initialized

      Return Value                     Meaning

      TRUE                             policy session is required
      FALSE                            policy session is not required

149   static BOOL
150   IsPolicySessionRequired(
151        TPM_CC               commandCode,        // IN: command code
152        UINT32               sessionIndex        // IN: session index
153        )
154   {
155        AUTH_ROLE           role = CommandAuthRole(commandCode, sessionIndex);
156        TPM_HT              type = HandleGetType(s_associatedHandles[sessionIndex]);
157
158        if(role == AUTH_DUP)
159            return TRUE;
160
161        if(role == AUTH_ADMIN)
162        {
163            if(type == TPM_HT_TRANSIENT)
164            {
165                OBJECT      *object = ObjectGet(s_associatedHandles[sessionIndex]);
166
167                  if(object->publicArea.objectAttributes.adminWithPolicy == CLEAR)
168                      return FALSE;
169             }
170             return TRUE;
171        }
172


      Family "2.0"                                  TCG Published                                      Page 45
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

173        if(type == TPM_HT_PCR)
174        {
175            if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex]))
176            {
177                TPM2B_DIGEST        policy;
178                TPMI_ALG_HASH       policyAlg;
179                policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex],
180                                              &policy);
181                if(policyAlg != TPM_ALG_NULL)
182                    return TRUE;
183            }
184        }
185        return FALSE;
186   }


      6.4.3.5     IsAuthValueAvailable()

      This function indicates if authValue is available and allowed for USER role authorization of an entity.
      This function is similar to IsAuthPolicyAvailable() except that it does not check the size of the authValue
      as IsAuthPolicyAvailable() does (a null authValue is a valid auth, but a null policy is not a valid policy).
      This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy.
      Those checks are assumed to have been performed during the handle unmarshaling.

      Return Value                      Meaning

      TRUE                              authValue is available
      FALSE                             authValue is not available

187   static BOOL
188   IsAuthValueAvailable(
189        TPM_HANDLE           handle,             // IN: handle of entity
190        TPM_CC               commandCode,        // IN: commandCode
191        UINT32               sessionIndex        // IN: session index
192        )
193   {
194        BOOL             result = FALSE;
195        // If a policy session is required, the entity can not be authorized by
196        // authValue. However, at this point, the policy session requirement should
197        // already have been checked.
198        pAssert(!IsPolicySessionRequired(commandCode, sessionIndex));
199
200       switch(HandleGetType(handle))
201       {
202           case TPM_HT_PERMANENT:
203               switch(handle)
204               {
205                       // At this point hierarchy availability has already been
206                       // checked so primary seed handles are always available here
207                   case TPM_RH_OWNER:
208                   case TPM_RH_ENDORSEMENT:
209                   case TPM_RH_PLATFORM:
210   #ifdef VENDOR_PERMANENT
211                       // This vendor defined handle associated with the
212                       // manufacturer's shared secret
213                   case VENDOR_PERMANENT:
214   #endif
215                       // NullAuth is always available.
216                   case TPM_RH_NULL:
217                        // At the point when authValue availability is checked, control
218                       // path has already passed the DA check so LockOut auth is
219                       // always available here
220                   case TPM_RH_LOCKOUT:

      Page 46                                        TCG Published                                   Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                       Trusted Platform Module Library

221
222                          result = TRUE;
223                          break;
224                      default:
225                          // Otherwise authValue is not available.
226                          break;
227                }
228                break;
229            case TPM_HT_TRANSIENT:
230                // A persistent object has already been loaded and the internal
231                // handle changed.
232                {
233                    OBJECT          *object;
234                    object = ObjectGet(handle);
235
236                      // authValue is always available for a sequence object.
237                      if(ObjectIsSequence(object))
238                      {
239                           result = TRUE;
240                           break;
241                      }
242                      // authValue is available for an object if it has its sensitive
243                      // portion loaded and
244                      // 1. userWithAuth bit is SET, or
245                      // 2. ADMIN role is required
246                      if(    object->attributes.publicOnly == CLEAR
247                          &&    (object->publicArea.objectAttributes.userWithAuth == SET
248                             || (CommandAuthRole(commandCode, sessionIndex) == AUTH_ADMIN
249                                && object->publicArea.objectAttributes.adminWithPolicy
250                                   == CLEAR)))
251                           result = TRUE;
252                }
253                break;
254            case TPM_HT_NV_INDEX:
255                // NV Index.
256                {
257                    NV_INDEX         nvIndex;
258                    NvGetIndexInfo(handle, &nvIndex);
259                    if(IsWriteOperation(commandCode))
260                    {
261                        if (nvIndex.publicArea.attributes.TPMA_NV_AUTHWRITE == SET)
262                             result = TRUE;
263
264                      }
265                      else
266                      {
267                          if (nvIndex.publicArea.attributes.TPMA_NV_AUTHREAD == SET)
268                              result = TRUE;
269                      }
270                }
271                break;
272            case TPM_HT_PCR:
273                // PCR handle.
274                // authValue is always allowed for PCR
275                result = TRUE;
276                break;
277            default:
278                // Otherwise, authValue is not available
279                break;
280       }
281       return result;
282   }




      Family "2.0"                           TCG Published                                    Page 47
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

      6.4.3.6     IsAuthPolicyAvailable()

      This function indicates if an authPolicy is available and allowed.
      This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy.
      Those checks are assumed to have been performed during the handle unmarshaling.

      Return Value                      Meaning

      TRUE                              authPolicy is available
      FALSE                             authPolicy is not available

283   static BOOL
284   IsAuthPolicyAvailable(
285        TPM_HANDLE           handle,              // IN: handle of entity
286        TPM_CC               commandCode,         // IN: commandCode
287        UINT32               sessionIndex         // IN: session index
288        )
289   {
290        BOOL            result = FALSE;
291        switch(HandleGetType(handle))
292        {
293            case TPM_HT_PERMANENT:
294                switch(handle)
295                {
296                    // At this point hierarchy availability has already been checked.
297                    case TPM_RH_OWNER:
298                        if (gp.ownerPolicy.t.size != 0)
299                            result = TRUE;
300                        break;
301
302                       case TPM_RH_ENDORSEMENT:
303                           if (gp.endorsementPolicy.t.size != 0)
304                               result = TRUE;
305                           break;
306
307                       case TPM_RH_PLATFORM:
308                           if (gc.platformPolicy.t.size != 0)
309                                result = TRUE;
310                           break;
311                       case TPM_RH_LOCKOUT:
312                           if(gp.lockoutPolicy.t.size != 0)
313                                result = TRUE;
314                           break;
315                       default:
316                           break;
317                 }
318                 break;
319             case TPM_HT_TRANSIENT:
320                 {
321                     // Object handle.
322                     // An evict object would already have been loaded and given a
323                     // transient object handle by this point.
324                     OBJECT *object = ObjectGet(handle);
325                     // Policy authorization is not available for an object with only
326                     // public portion loaded.
327                     if(object->attributes.publicOnly == CLEAR)
328                     {
329                         // Policy authorization is always available for an object but
330                         // is never available for a sequence.
331                         if(!ObjectIsSequence(object))
332                             result = TRUE;
333                     }
334                     break;

      Page 48                                        TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

335                 }
336             case TPM_HT_NV_INDEX:
337                 // An NV Index.
338                 {
339                      NV_INDEX          nvIndex;
340                      NvGetIndexInfo(handle, &nvIndex);
341                      // If the policy size is not zero, check if policy can be used.
342                      if(nvIndex.publicArea.authPolicy.t.size != 0)
343                      {
344                          // If policy session is required for this handle, always
345                          // uses policy regardless of the attributes bit setting
346                          if(IsPolicySessionRequired(commandCode, sessionIndex))
347                               result = TRUE;
348                          // Otherwise, the presence of the policy depends on the NV
349                          // attributes.
350                          else if(IsWriteOperation(commandCode))
351                          {
352                               if (   nvIndex.publicArea.attributes.TPMA_NV_POLICYWRITE
353                                   == SET)
354                                   result = TRUE;
355                          }
356                          else
357                          {
358                               if (    nvIndex.publicArea.attributes.TPMA_NV_POLICYREAD
359                                   == SET)
360                                   result = TRUE;
361                          }
362                      }
363                 }
364                 break;
365             case TPM_HT_PCR:
366                 // PCR handle.
367                 if(PCRPolicyIsAvailable(handle))
368                      result = TRUE;
369                 break;
370             default:
371                 break;
372       }
373       return result;
374   }


      6.4.4     Session Parsing Functions

      6.4.4.1     ComputeCpHash()

      This function computes the cpHash as defined in Part 2 and described in Part 1.

375   static void
376   ComputeCpHash(
377       TPMI_ALG_HASH        hashAlg,               //   IN: hash algorithm
378       TPM_CC               commandCode,           //   IN: command code
379       UINT32               handleNum,             //   IN: number of handle
380       TPM_HANDLE           handles[],             //   IN: array of handle
381       UINT32               parmBufferSize,        //   IN: size of input parameter area
382       BYTE                *parmBuffer,            //   IN: input parameter area
383       TPM2B_DIGEST        *cpHash,                //   OUT: cpHash
384       TPM2B_DIGEST        *nameHash               //   OUT: name hash of command
385       )
386   {
387       UINT32               i;
388       HASH_STATE           hashState;
389       TPM2B_NAME           name;
390


      Family "2.0"                               TCG Published                                      Page 49
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

391       // cpHash = hash(commandCode [ || authName1
392       //                           [ || authName2
393       //                           [ || authName 3 ]]]
394       //                           [ || parameters])
395       // A cpHash can contain just a commandCode only if the lone session is
396       // an audit session.
397
398       // Start cpHash.
399       cpHash->t.size = CryptStartHash(hashAlg, &hashState);
400
401       // Add commandCode.
402       CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
403
404       // Add authNames for each of the handles.
405       for(i = 0; i < handleNum; i++)
406       {
407           name.t.size = EntityGetName(handles[i], &name.t.name);
408           CryptUpdateDigest2B(&hashState, &name.b);
409       }
410
411       // Add the parameters.
412       CryptUpdateDigest(&hashState, parmBufferSize, parmBuffer);
413
414       // Complete the hash.
415       CryptCompleteHash2B(&hashState, &cpHash->b);
416
417       // If the nameHash is needed, compute it here.
418       if(nameHash != NULL)
419       {
420           // Start name hash. hashState may be reused.
421           nameHash->t.size = CryptStartHash(hashAlg, &hashState);
422
423             // Adding names.
424             for(i = 0; i < handleNum; i++)
425             {
426                 name.t.size = EntityGetName(handles[i], &name.t.name);
427                 CryptUpdateDigest2B(&hashState, &name.b);
428             }
429             // Complete hash.
430             CryptCompleteHash2B(&hashState, &nameHash->b);
431       }
432       return;
433   }


      6.4.4.2     CheckPWAuthSession()

      This function validates the authorization provided in a PWAP session. It compares the input value to
      authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the
      referenced entities from s_inputAuthValues[] and s_associatedHandles[].

      Error Returns                     Meaning

      TPM_RC_AUTH_FAIL                  auth fails and increments DA failure count
      TPM_RC_BAD_AUTH                   auth fails but DA does not apply

434   static TPM_RC
435   CheckPWAuthSession(
436       UINT32              sessionIndex          // IN: index of session to be processed
437       )
438   {
439       TPM2B_AUTH         authValue;
440       TPM_HANDLE         associatedHandle = s_associatedHandles[sessionIndex];
441

      Page 50                                        TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

442       // Strip trailing zeros from the password.
443       MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]);
444
445       // Get the auth value and size.
446       authValue.t.size = EntityGetAuthValue(associatedHandle, &authValue.t.buffer);
447
448       // Success if the digests are identical.
449       if(Memory2BEqual(&s_inputAuthValues[sessionIndex].b, &authValue.b))
450       {
451           return TPM_RC_SUCCESS;
452       }
453       else                    // if the digests are not identical
454       {
455           // Invoke DA protection if applicable.
456           return IncrementLockout(sessionIndex);
457       }
458   }


      6.4.4.3    ComputeCommandHMAC()

      This function computes the HMAC for an authorization session in a command.

459   static void
460   ComputeCommandHMAC(
461       UINT32              sessionIndex,    // IN: index of session to be processed
462       TPM2B_DIGEST       *cpHash,          // IN: cpHash
463       TPM2B_DIGEST       *hmac             // OUT: authorization HMAC
464       )
465   {
466       TPM2B_TYPE(KEY,    (sizeof(AUTH_VALUE) * 2));
467       TPM2B_KEY           key;
468       BYTE                marshalBuffer[sizeof(TPMA_SESSION)];
469       BYTE               *buffer;
470       UINT32              marshalSize;
471       HMAC_STATE          hmacState;
472       TPM2B_NONCE        *nonceDecrypt;
473       TPM2B_NONCE        *nonceEncrypt;
474       SESSION            *session;
475       TPM_HT              sessionHandleType =
476                                   HandleGetType(s_sessionHandles[sessionIndex]);
477
478       nonceDecrypt = NULL;
479       nonceEncrypt = NULL;
480
481       // Determine if extra nonceTPM values are going to be required.
482       // If this is the first session (sessionIndex = 0) and it is an authorization
483       // session that uses an HMAC, then check if additional session nonces are to be
484       // included.
485       if(   sessionIndex == 0
486          && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
487       {
488           // If there is a decrypt session and if this is not the decrypt session,
489           // then an extra nonce may be needed.
490           if(    s_decryptSessionIndex != UNDEFINED_INDEX
491               && s_decryptSessionIndex != sessionIndex)
492           {
493                // Will add the nonce for the decrypt session.
494                SESSION *decryptSession
495                            = SessionGet(s_sessionHandles[s_decryptSessionIndex]);
496                nonceDecrypt = &decryptSession->nonceTPM;
497           }
498           // Now repeat for the encrypt session.
499           if(    s_encryptSessionIndex != UNDEFINED_INDEX
500               && s_encryptSessionIndex != sessionIndex


      Family "2.0"                             TCG Published                                     Page 51
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                      October 30, 2014
      Trusted Platform Module Library                                    Part 4: Supporting Routines

501                 && s_encryptSessionIndex != s_decryptSessionIndex)
502             {
503                 // Have to have the nonce for the encrypt session.
504                 SESSION *encryptSession
505                             = SessionGet(s_sessionHandles[s_encryptSessionIndex]);
506                 nonceEncrypt = &encryptSession->nonceTPM;
507             }
508       }
509
510       // Continue with the HMAC processing.
511       session = SessionGet(s_sessionHandles[sessionIndex]);
512
513       // Generate HMAC key.
514       MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
515
516       //   Check if the session has an associated handle and if the associated entity
517       //   is the one to which the session is bound. If not, add the authValue of
518       //   this entity to the HMAC key.
519       //   If the session is bound to the object or the session is a policy session
520       //   with no authValue required, do not include the authValue in the HMAC key.
521       //   Note: For a policy session, its isBound attribute is CLEARED.
522
523       // If the session isn't used for authorization, then there is no auth value
524       // to add
525       if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
526       {
527           // used for auth so see if this is a policy session with authValue needed
528           // or an hmac session that is not bound
529           if(         sessionHandleType == TPM_HT_POLICY_SESSION
530                   && session->attributes.isAuthValueNeeded == SET
531               ||      sessionHandleType == TPM_HT_HMAC_SESSION
532                   && !IsSessionBindEntity(s_associatedHandles[sessionIndex], session)
533             )
534           {
535               // add the authValue to the HMAC key
536               pAssert((sizeof(AUTH_VALUE) + key.t.size) <= sizeof(key.t.buffer));
537               key.t.size =   key.t.size
538                            + EntityGetAuthValue(s_associatedHandles[sessionIndex],
539                                            (AUTH_VALUE *)&(key.t.buffer[key.t.size]));
540           }
541       }
542
543        // if the HMAC key size is 0, a NULL string HMAC is allowed
544        if(    key.t.size == 0
545            && s_inputAuthValues[sessionIndex].t.size == 0)
546        {
547            hmac->t.size = 0;
548            return;
549        }
550
551       // Start HMAC
552       hmac->t.size = CryptStartHMAC2B(session->authHashAlg, &key.b, &hmacState);
553
554       // Add cpHash
555       CryptUpdateDigest2B(&hmacState, &cpHash->b);
556
557       // Add nonceCaller
558       CryptUpdateDigest2B(&hmacState, &s_nonceCaller[sessionIndex].b);
559
560       // Add nonceTPM
561       CryptUpdateDigest2B(&hmacState, &session->nonceTPM.b);
562
563       // If needed, add nonceTPM for decrypt session
564       if(nonceDecrypt != NULL)
565           CryptUpdateDigest2B(&hmacState, &nonceDecrypt->b);
566

      Page 52                                TCG Published                             Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

567        // If needed, add nonceTPM for encrypt session
568        if(nonceEncrypt != NULL)
569            CryptUpdateDigest2B(&hmacState, &nonceEncrypt->b);
570
571        // Add sessionAttributes
572        buffer = marshalBuffer;
573        marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]),
574                                           &buffer, NULL);
575        CryptUpdateDigest(&hmacState, marshalSize, marshalBuffer);
576
577        // Complete the HMAC computation
578        CryptCompleteHMAC2B(&hmacState, &hmac->b);
579
580        return;
581   }


      6.4.4.4     CheckSessionHMAC()

      This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the
      expected HMAC value and then compares the result with the HMAC in the authorization session. The
      authorization is successful if they are the same.
      If the authorizations are not the same, IncrementLockout() is called. It will return TPM_RC_AUTH_FAIL if
      the failure caused the failureCount to increment. Otherwise, it will return TPM_RC_BAD_AUTH.

      Error Returns                    Meaning

      TPM_RC_AUTH_FAIL                 auth failure caused failureCount increment
      TPM_RC_BAD_AUTH                  auth failure did not cause failureCount increment

582   static TPM_RC
583   CheckSessionHMAC(
584        UINT32               sessionIndex,      // IN: index of session to be processed
585        TPM2B_DIGEST        *cpHash             // IN: cpHash of the command
586        )
587   {
588        TPM2B_DIGEST             hmac;                // authHMAC for comparing
589
590        // Compute authHMAC
591        ComputeCommandHMAC(sessionIndex, cpHash, &hmac);
592
593        // Compare the input HMAC with the authHMAC computed above.
594        if(!Memory2BEqual(&s_inputAuthValues[sessionIndex].b, &hmac.b))
595        {
596            // If an HMAC session has a failure, invoke the anti-hammering
597            // if it applies to the authorized entity or the session.
598            // Otherwise, just indicate that the authorization is bad.
599            return IncrementLockout(sessionIndex);
600        }
601        return TPM_RC_SUCCESS;
602   }


      6.4.4.5     CheckPolicyAuthSession()

      This function is used to validate the authorization in a policy session. This function performs the following
      comparisons to see if a policy authorization is properly provided. The check are:
      a) compare policyDigest in session with authPolicy associated with the entity to be authorized;
      b) compare timeout if applicable;
      c) compare commandCode if applicable;

      Family "2.0"                                  TCG Published                                         Page 53
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines


      d) compare cpHash if applicable; and
      e) see if PCR values have changed since computed.
      If all the above checks succeed, the handle is authorized. The order of these comparisons is not
      important because any failure will result in the same error code.

      Error Returns                     Meaning

      TPM_RC_PCR_CHANGED                PCR value is not current
      TPM_RC_POLICY_FAIL                policy session fails
      TPM_RC_LOCALITY                   command locality is not allowed
      TPM_RC_POLICY_CC                  CC doesn't match
      TPM_RC_EXPIRED                    policy session has expired
      TPM_RC_PP                         PP is required but not asserted
      TPM_RC_NV_UNAVAILABLE             NV is not available for write
      TPM_RC_NV_RATE                    NV is rate limiting

603   static TPM_RC
604   CheckPolicyAuthSession(
605       UINT32              sessionIndex,          //   IN: index of session to be processed
606       TPM_CC              commandCode,           //   IN: command code
607       TPM2B_DIGEST       *cpHash,                //   IN: cpHash using the algorithm of this
608                                                  //       session
609       TPM2B_DIGEST       *nameHash               //   IN: nameHash using the session algorithm
610       )
611   {
612       TPM_RC              result = TPM_RC_SUCCESS;
613       SESSION            *session;
614       TPM2B_DIGEST        authPolicy;
615       TPMI_ALG_HASH       policyAlg;
616       UINT8               locality;
617
618       // Initialize pointer to the auth session.
619       session = SessionGet(s_sessionHandles[sessionIndex]);
620
621       // If the command is TPM_RC_PolicySecret(), make sure that
622       // either password or authValue is required
623       if(     commandCode == TPM_CC_PolicySecret
624           && session->attributes.isPasswordNeeded == CLEAR
625           && session->attributes.isAuthValueNeeded == CLEAR)
626           return TPM_RC_MODE;
627
628       // See if the PCR counter for the session is still valid.
629       if( !SessionPCRValueIsCurrent(s_sessionHandles[sessionIndex]) )
630           return TPM_RC_PCR_CHANGED;
631
632       // Get authPolicy.
633       policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex],
634                                       &authPolicy);
635       // Compare authPolicy.
636       if(!Memory2BEqual(&session->u2.policyDigest.b, &authPolicy.b))
637           return TPM_RC_POLICY_FAIL;
638
639       // Policy is OK so check if the other factors are correct
640
641       // Compare policy hash algorithm.
642       if(policyAlg != session->authHashAlg)
643           return TPM_RC_POLICY_FAIL;
644
645       // Compare timeout.

      Page 54                                         TCG Published                             Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                  Trusted Platform Module Library

646       if(session->timeOut != 0)
647       {
648           // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE
649           // or TPM_RC_NV_RATE error may be returned here.
650           result = NvIsAvailable();
651           if(result != TPM_RC_SUCCESS)
652               return result;
653
654            if(session->timeOut < go.clock)
655                return TPM_RC_EXPIRED;
656       }
657
658       // If command code is provided it must match
659       if(session->commandCode != 0)
660       {
661           if(session->commandCode != commandCode)
662                return TPM_RC_POLICY_CC;
663       }
664       else
665       {
666           // If command requires a DUP or ADMIN authorization, the session must have
667           // command code set.
668           AUTH_ROLE    role = CommandAuthRole(commandCode, sessionIndex);
669           if(role == AUTH_ADMIN || role == AUTH_DUP)
670                return TPM_RC_POLICY_FAIL;
671       }
672       // Check command locality.
673       {
674           BYTE          sessionLocality[sizeof(TPMA_LOCALITY)];
675           BYTE         *buffer = sessionLocality;
676
677            // Get existing locality setting in canonical form
678            TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
679
680           // See if the locality has been set
681           if(sessionLocality[0] != 0)
682           {
683               // If so, get the current locality
684               locality = _plat__LocalityGet();
685               if (locality < 5)
686               {
687                   if(    ((sessionLocality[0] & (1 << locality)) == 0)
688                       || sessionLocality[0] > 31)
689                       return TPM_RC_LOCALITY;
690               }
691               else if (locality > 31)
692               {
693                   if(sessionLocality[0] != locality)
694                       return TPM_RC_LOCALITY;
695               }
696               else
697               {
698                   // Could throw an assert here but a locality error is just
699                   // as good. It just means that, whatever the locality is, it isn't
700                   // the locality requested so...
701                   return TPM_RC_LOCALITY;
702               }
703           }
704       } // end of locality check
705
706       // Check physical presence.
707       if(   session->attributes.isPPRequired == SET
708          && !_plat__PhysicalPresenceAsserted())
709           return TPM_RC_PP;
710
711       // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or

      Family "2.0"                         TCG Published                                 Page 55
      Level 00 Revision 01.16        Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

712       // DUP role for this handle.
713       if(session->u1.cpHash.b.size != 0)
714       {
715           if(session->attributes.iscpHashDefined)
716           {
717                // Compare cpHash.
718                if(!Memory2BEqual(&session->u1.cpHash.b, &cpHash->b))
719                    return TPM_RC_POLICY_FAIL;
720           }
721           else
722           {
723                // Compare nameHash.
724                // When cpHash is not defined, nameHash is placed in its space.
725                if(!Memory2BEqual(&session->u1.cpHash.b, &nameHash->b))
726                    return TPM_RC_POLICY_FAIL;
727           }
728       }
729       if(session->attributes.checkNvWritten)
730       {
731           NV_INDEX         nvIndex;
732
733             // If this is not an NV index, the policy makes no sense so fail it.
734             if(HandleGetType(s_associatedHandles[sessionIndex])!= TPM_HT_NV_INDEX)
735                 return TPM_RC_POLICY_FAIL;
736
737             // Get the index data
738             NvGetIndexInfo(s_associatedHandles[sessionIndex], &nvIndex);
739
740             // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state
741             if(    (nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
742                 != (session->attributes.nvWrittenState == SET))
743                 return TPM_RC_POLICY_FAIL;
744       }
745
746       return TPM_RC_SUCCESS;
747   }


      6.4.4.6     RetrieveSessionData()

      This function will unmarshal the sessions in the session area of a command. The values are placed in the
      arrays that are defined at the beginning of this file. The normal unmarshaling errors are possible.

      Error Returns                     Meaning

      TPM_RC_SUCCSS                     unmarshaled without error
      TPM_RC_SIZE                       the number of bytes unmarshaled is not the same as the value for
                                        authorizationSize in the command

748   static TPM_RC
749   RetrieveSessionData (
750       TPM_CC               commandCode,         //   IN: command   code
751       UINT32              *sessionCount,        //   OUT: number   of sessions found
752       BYTE                *sessionBuffer,       //   IN: pointer   to the session buffer
753       INT32                bufferSize           //   IN: size of   the session buffer
754       )
755   {
756       int             sessionIndex;
757       int             i;
758       TPM_RC          result;
759       SESSION        *session;
760       TPM_HT          sessionType;
761
762       s_decryptSessionIndex = UNDEFINED_INDEX;

      Page 56                                       TCG Published                                    Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                     Trusted Platform Module Library

763       s_encryptSessionIndex = UNDEFINED_INDEX;
764       s_auditSessionIndex = UNDEFINED_INDEX;
765
766       for(sessionIndex = 0; bufferSize > 0; sessionIndex++)
767       {
768           // If maximum allowed number of sessions has been parsed, return a size
769           // error with a session number that is larger than the number of allowed
770           // sessions
771           if(sessionIndex == MAX_SESSION_NUM)
772               return TPM_RC_SIZE + TPM_RC_S + g_rcIndex[sessionIndex+1];
773
774            // make sure that the associated handle for each session starts out
775            // unassigned
776            s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
777
778            // First parameter: Session handle.
779            result = TPMI_SH_AUTH_SESSION_Unmarshal(&s_sessionHandles[sessionIndex],
780                                                    &sessionBuffer, &bufferSize, TRUE);
781            if(result != TPM_RC_SUCCESS)
782                return result + TPM_RC_S + g_rcIndex[sessionIndex];
783
784            // Second parameter: Nonce.
785            result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex],
786                                           &sessionBuffer, &bufferSize);
787            if(result != TPM_RC_SUCCESS)
788                return result + TPM_RC_S + g_rcIndex[sessionIndex];
789
790            // Third parameter: sessionAttributes.
791            result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex],
792                                            &sessionBuffer, &bufferSize);
793            if(result != TPM_RC_SUCCESS)
794                return result + TPM_RC_S + g_rcIndex[sessionIndex];
795
796            // Fourth parameter: authValue (PW or HMAC).
797            result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex],
798                                          &sessionBuffer, &bufferSize);
799            if(result != TPM_RC_SUCCESS)
800                return result + TPM_RC_S + g_rcIndex[sessionIndex];
801
802            if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
803            {
804                // A PWAP session needs additional processing.
805                //      Can't have any attributes set other than continueSession bit
806                if(    s_attributes[sessionIndex].encrypt
807                    || s_attributes[sessionIndex].decrypt
808                    || s_attributes[sessionIndex].audit
809                    || s_attributes[sessionIndex].auditExclusive
810                    || s_attributes[sessionIndex].auditReset
811                  )
812                     return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
813
814                  //     The nonce size must be zero.
815                  if(s_nonceCaller[sessionIndex].t.size != 0)
816                      return TPM_RC_NONCE + TPM_RC_S + g_rcIndex[sessionIndex];
817
818                continue;
819            }
820            // For not password sessions...
821
822            // Find out if the session is loaded.
823            if(!SessionIsLoaded(s_sessionHandles[sessionIndex]))
824                return TPM_RC_REFERENCE_S0 + sessionIndex;
825
826            sessionType = HandleGetType(s_sessionHandles[sessionIndex]);
827            session = SessionGet(s_sessionHandles[sessionIndex]);
828            // Check if the session is an HMAC/policy session.

      Family "2.0"                           TCG Published                                  Page 57
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

829             if(        (   session->attributes.isPolicy == SET
830                         && sessionType == TPM_HT_HMAC_SESSION
831                        )
832                     || (    session->attributes.isPolicy == CLEAR
833                          && sessionType == TPM_HT_POLICY_SESSION
834                        )
835                 )
836                      return TPM_RC_HANDLE + TPM_RC_S + g_rcIndex[sessionIndex];
837
838             // Check that this handle has not previously been used.
839             for(i = 0; i < sessionIndex; i++)
840             {
841                 if(s_sessionHandles[i] == s_sessionHandles[sessionIndex])
842                     return TPM_RC_HANDLE + TPM_RC_S + g_rcIndex[sessionIndex];
843             }
844
845             // If the session is used for parameter encryption or audit as well, set
846             // the corresponding indices.
847
848             // First process decrypt.
849             if(s_attributes[sessionIndex].decrypt)
850             {
851                 // Check if the commandCode allows command parameter encryption.
852                 if(DecryptSize(commandCode) == 0)
853                     return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
854
855                      // Encrypt attribute can only appear in one session
856                      if(s_decryptSessionIndex != UNDEFINED_INDEX)
857                          return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
858
859                      // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL
860                      if(session->symmetric.algorithm == TPM_ALG_NULL)
861                          return TPM_RC_SYMMETRIC + TPM_RC_S + g_rcIndex[sessionIndex];
862
863                      // All checks passed, so set the index for the session used to decrypt
864                      // a command parameter.
865                      s_decryptSessionIndex = sessionIndex;
866             }
867
868             // Now process encrypt.
869             if(s_attributes[sessionIndex].encrypt)
870             {
871                 // Check if the commandCode allows response parameter encryption.
872                 if(EncryptSize(commandCode) == 0)
873                     return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
874
875                      // Encrypt attribute can only appear in one session.
876                      if(s_encryptSessionIndex != UNDEFINED_INDEX)
877                          return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
878
879                      // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL
880                      if(session->symmetric.algorithm == TPM_ALG_NULL)
881                          return TPM_RC_SYMMETRIC + TPM_RC_S + g_rcIndex[sessionIndex];
882
883                      // All checks passed, so set the index for the session used to encrypt
884                      // a response parameter.
885                      s_encryptSessionIndex = sessionIndex;
886             }
887
888             // At last process audit.
889             if(s_attributes[sessionIndex].audit)
890             {
891                 // Audit attribute can only appear in one session.
892                 if(s_auditSessionIndex != UNDEFINED_INDEX)
893                     return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
894

      Page 58                                     TCG Published                           Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

895                   // An audit session can not be policy session.
896                   if(    HandleGetType(s_sessionHandles[sessionIndex])
897                       == TPM_HT_POLICY_SESSION)
898                        return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
899
900                   // If this is a reset of the audit session, or the first use
901                   // of the session as an audit session, it doesn't matter what
902                   // the exclusive state is. The session will become exclusive.
903                   if(    s_attributes[sessionIndex].auditReset == CLEAR
904                       && session->attributes.isAudit == SET)
905                   {
906                        // Not first use or reset. If auditExlusive is SET, then this
907                        // session must be the current exclusive session.
908                        if(    s_attributes[sessionIndex].auditExclusive == SET
909                            && g_exclusiveAuditSession != s_sessionHandles[sessionIndex])
910                            return TPM_RC_EXCLUSIVE;
911                   }
912
913                   s_auditSessionIndex = sessionIndex;
914             }
915
916             // Initialize associated handle as undefined. This will be changed when
917             // the handles are processed.
918             s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
919
920        }
921
922        // Set the number of sessions found.
923        *sessionCount = sessionIndex;
924        return TPM_RC_SUCCESS;
925   }


      6.4.4.7       CheckLockedOut()

      This function checks to see if the TPM is in lockout. This function should only be called if the entity being
      checked is subject to DA protection. The TPM is in lockout if the NV is not available and a DA write is
      pending. Otherwise the TPM is locked out if checking for lockoutAuth (lockoutAuthCheck == TRUE) and
      use of lockoutAuth is disabled, or failedTries >= maxTries

      Error Returns                    Meaning

      TPM_RC_NV_RATE                   NV is rate limiting
      TPM_RC_NV_UNAVAILABLE            NV is not available at this time
      TPM_RC_LOCKOUT                   TPM is in lockout

926   static TPM_RC
927   CheckLockedOut(
928        BOOL                 lockoutAuthCheck             // IN: TRUE if checking is for lockoutAuth
929        )
930   {
931        TPM_RC         result;
932
933        // If NV is unavailable, and current cycle state recorded in NV is not
934        // SHUTDOWN_NONE, refuse to check any authorization because we would
935        // not be able to handle a DA failure.
936        result = NvIsAvailable();
937        if(result != TPM_RC_SUCCESS && gp.orderlyState != SHUTDOWN_NONE)
938            return result;
939
940        // Check if DA info needs to be updated in NV.
941        if(s_DAPendingOnNV)
942        {

      Family "2.0"                                  TCG Published                                        Page 59
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                     Part 4: Supporting Routines

943             // If NV is accessible, ...
944             if(result == TPM_RC_SUCCESS)
945             {
946                  // ... write the pending DA data and proceed.
947                  NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED,
948                                  &gp.lockOutAuthEnabled);
949                  NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
950                  g_updateNV = TRUE;
951                  s_DAPendingOnNV = FALSE;
952             }
953             else
954             {
955                  // Otherwise no authorization can be checked.
956                  return result;
957             }
958       }
959
960       // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth
961       // is disabled...
962       if(lockoutAuthCheck)
963       {
964           if(gp.lockOutAuthEnabled == FALSE)
965               return TPM_RC_LOCKOUT;
966       }
967       else
968       {
969           // ... or if the number of failed tries has been maxed out.
970           if(gp.failedTries >= gp.maxTries)
971               return TPM_RC_LOCKOUT;
972       }
973       return TPM_RC_SUCCESS;
974   }


      6.4.4.8     CheckAuthSession()

      This function checks that the authorization session properly authorizes the use of the associated handle.

      Error Returns                     Meaning

      TPM_RC_LOCKOUT                    entity is protected by DA and TPM is in lockout, or TPM is locked out
                                        on NV update pending on DA parameters
      TPM_RC_PP                         Physical Presence is required but not provided
      TPM_RC_AUTH_FAIL                  HMAC or PW authorization failed with DA side-effects (can be a
                                        policy session)
      TPM_RC_BAD_AUTH                   HMAC or PW authorization failed without DA side-effects (can be a
                                        policy session)
      TPM_RC_POLICY_FAIL                if policy session fails
      TPM_RC_POLICY_CC                  command code of policy was wrong
      TPM_RC_EXPIRED                    the policy session has expired
      TPM_RC_PCR                        ???
      TPM_RC_AUTH_UNAVAILABLE           authValue or authPolicy unavailable

975   static TPM_RC
976   CheckAuthSession(
977       TPM_CC               commandCode,           //   IN:    commandCode
978       UINT32               sessionIndex,          //   IN:    index of session to be processed
979       TPM2B_DIGEST        *cpHash,                //   IN:    cpHash
980       TPM2B_DIGEST        *nameHash               //   IN:    nameHash


      Page 60                                          TCG Published                                      Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014                    Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

 981       )
 982   {
 983       TPM_RC              result;
 984       SESSION            *session = NULL;
 985       TPM_HANDLE          sessionHandle = s_sessionHandles[sessionIndex];
 986       TPM_HANDLE          associatedHandle = s_associatedHandles[sessionIndex];
 987       TPM_HT              sessionHandleType = HandleGetType(sessionHandle);
 988
 989       pAssert(sessionHandle != TPM_RH_UNASSIGNED);
 990
 991       if(sessionHandle != TPM_RS_PW)
 992           session = SessionGet(sessionHandle);
 993
 994       pAssert(sessionHandleType != TPM_HT_POLICY_SESSION || session != NULL);
 995
 996       // If the authorization session is not a policy session, or if the policy
 997       // session requires authorization, then check lockout.
 998       if(    sessionHandleType != TPM_HT_POLICY_SESSION
 999          || session->attributes.isAuthValueNeeded
1000          || session->attributes.isPasswordNeeded)
1001       {
1002           // See if entity is subject to lockout.
1003           if(!IsDAExempted(associatedHandle))
1004           {
1005               // If NV is unavailable, and current cycle state recorded in NV is not
1006               // SHUTDOWN_NONE, refuse to check any authorization because we would
1007               // not be able to handle a DA failure.
1008               result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT);
1009               if(result != TPM_RC_SUCCESS)
1010                   return result;
1011           }
1012       }
1013
1014       if(associatedHandle == TPM_RH_PLATFORM)
1015       {
1016           // If the physical presence is required for this command, check for PP
1017           // assertion. If it isn't asserted, no point going any further.
1018           if(    PhysicalPresenceIsRequired(commandCode)
1019               && !_plat__PhysicalPresenceAsserted()
1020             )
1021                return TPM_RC_PP;
1022       }
1023       // If a policy session is required, make sure that it is being used.
1024       if(   IsPolicySessionRequired(commandCode, sessionIndex)
1025          && sessionHandleType != TPM_HT_POLICY_SESSION)
1026           return TPM_RC_AUTH_TYPE;
1027
1028       // If this is a PW authorization, check it and return.
1029       if(sessionHandle == TPM_RS_PW)
1030       {
1031           if(IsAuthValueAvailable(associatedHandle, commandCode, sessionIndex))
1032                return CheckPWAuthSession(sessionIndex);
1033           else
1034                return TPM_RC_AUTH_UNAVAILABLE;
1035       }
1036       // If this is a policy session, ...
1037       if(sessionHandleType == TPM_HT_POLICY_SESSION)
1038       {
1039           // ... see if the entity has a policy, ...
1040           if( !IsAuthPolicyAvailable(associatedHandle, commandCode, sessionIndex))
1041                return TPM_RC_AUTH_UNAVAILABLE;
1042           // ... and check the policy session.
1043           result = CheckPolicyAuthSession(sessionIndex, commandCode,
1044                                            cpHash, nameHash);
1045           if (result != TPM_RC_SUCCESS)
1046                return result;

       Family "2.0"                           TCG Published                                 Page 61
       Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
       Trusted Platform Module Library                                                    Part 4: Supporting Routines

1047       }
1048       else
1049       {
1050           // For non policy, the entity being accessed must allow authorization
1051           // with an auth value. This is required even if the auth value is not
1052           // going to be used in an HMAC because it is bound.
1053           if(!IsAuthValueAvailable(associatedHandle, commandCode, sessionIndex))
1054               return TPM_RC_AUTH_UNAVAILABLE;
1055       }
1056       // At this point, the session must be either a policy or an HMAC session.
1057       session = SessionGet(s_sessionHandles[sessionIndex]);
1058
1059       if(         sessionHandleType == TPM_HT_POLICY_SESSION
1060             &&    session->attributes.isPasswordNeeded == SET)
1061       {
1062             // For policy session that requires a password, check it as PWAP session.
1063             return CheckPWAuthSession(sessionIndex);
1064       }
1065       else
1066       {
1067           // For other policy or HMAC sessions, have its HMAC checked.
1068           return CheckSessionHMAC(sessionIndex, cpHash);
1069       }
1070   }
1071   #ifdef    TPM_CC_GetCommandAuditDigest


       6.4.4.9     CheckCommandAudit()

       This function checks if the current command may trigger command audit, and if it is safe to perform the
       action.

       Error Returns                     Meaning

       TPM_RC_NV_UNAVAILABLE             NV is not available for write
       TPM_RC_NV_RATE                    NV is rate limiting

1072   static TPM_RC
1073   CheckCommandAudit(
1074       TPM_CC               commandCode,                   //   IN:   Command code
1075       UINT32               handleNum,                     //   IN:   number of element in handle array
1076       TPM_HANDLE           handles[],                     //   IN:   array of handle
1077       BYTE                *parmBufferStart,               //   IN:   start of parameter buffer
1078       UINT32               parmBufferSize                 //   IN:   size of parameter buffer
1079       )
1080   {
1081       TPM_RC          result = TPM_RC_SUCCESS;
1082
1083       // If audit is implemented, need to check to see if auditing is being done
1084       // for this command.
1085       if(CommandAuditIsRequired(commandCode))
1086       {
1087           // If the audit digest is clear and command audit is required, NV must be
1088           // available so that TPM2_GetCommandAuditDigest() is able to increment
1089           // audit counter. If NV is not available, the function bails out to prevent
1090           // the TPM from attempting an operation that would fail anyway.
1091           if(     gr.commandAuditDigest.t.size == 0
1092               || commandCode == TPM_CC_GetCommandAuditDigest)
1093           {
1094                result = NvIsAvailable();
1095                if(result != TPM_RC_SUCCESS)
1096                    return result;
1097           }
1098           ComputeCpHash(gp.auditHashAlg, commandCode, handleNum,

       Page 62                                         TCG Published                                    Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
       Part 4: Supporting Routines                                                  Trusted Platform Module Library

1099                             handles, parmBufferSize, parmBufferStart,
1100                             &s_cpHashForCommandAudit, NULL);
1101        }
1102
1103       return TPM_RC_SUCCESS;
1104   }
1105   #endif


       6.4.4.10    ParseSessionBuffer()

       This function is the entry function for command session processing. It iterates sessions in session area
       and reports if the required authorization has been properly provided. It also processes audit session and
       passes the information of encryption sessions to parameter encryption module.

       Error Returns                   Meaning

       various                         parsing failure or authorization failure

1106   TPM_RC
1107   ParseSessionBuffer(
1108        TPM_CC              commandCode,                    //   IN:   Command code
1109        UINT32              handleNum,                      //   IN:   number of element in handle array
1110        TPM_HANDLE          handles[],                      //   IN:   array of handle
1111        BYTE               *sessionBufferStart,             //   IN:   start of session buffer
1112        UINT32              sessionBufferSize,              //   IN:   size of session buffer
1113        BYTE               *parmBufferStart,                //   IN:   start of parameter buffer
1114        UINT32              parmBufferSize                  //   IN:   size of parameter buffer
1115        )
1116   {
1117        TPM_RC              result;
1118        UINT32              i;
1119        INT32               size = 0;
1120        TPM2B_AUTH          extraKey;
1121        UINT32              sessionIndex;
1122        SESSION            *session;
1123        TPM2B_DIGEST        cpHash;
1124        TPM2B_DIGEST        nameHash;
1125        TPM_ALG_ID          cpHashAlg = TPM_ALG_NULL;             // algID for the last computed
1126                                                                  // cpHash
1127
1128        // Check if a command allows any session in its session area.
1129        if(!IsSessionAllowed(commandCode))
1130            return TPM_RC_AUTH_CONTEXT;
1131
1132        // Default-initialization.
1133        s_sessionNum = 0;
1134        cpHash.t.size = 0;
1135
1136        result = RetrieveSessionData(commandCode, &s_sessionNum,
1137                                     sessionBufferStart, sessionBufferSize);
1138        if(result != TPM_RC_SUCCESS)
1139            return result;
1140
1141        // There is no command in the TPM spec that has more handles than
1142        // MAX_SESSION_NUM.
1143        pAssert(handleNum <= MAX_SESSION_NUM);
1144
1145        // Associate the session with an authorization handle.
1146        for(i = 0; i < handleNum; i++)
1147        {
1148            if(CommandAuthRole(commandCode, i) != AUTH_NONE)
1149            {
1150                // If the received session number is less than the number of handle
1151                // that requires authorization, an error should be returned.

       Family "2.0"                                 TCG Published                                         Page 63
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
       Trusted Platform Module Library                                   Part 4: Supporting Routines

1152                 // Note: for all the TPM 2.0 commands, handles requiring
1153                 // authorization come first in a command input.
1154                 if(i > (s_sessionNum - 1))
1155                     return TPM_RC_AUTH_MISSING;
1156
1157                 // Record the handle associated with the authorization session
1158                 s_associatedHandles[i] = handles[i];
1159             }
1160       }
1161
1162       // Consistency checks are done first to avoid auth failure when the command
1163       // will not be executed anyway.
1164       for(sessionIndex = 0; sessionIndex < s_sessionNum; sessionIndex++)
1165       {
1166           // PW session must be an authorization session
1167           if(s_sessionHandles[sessionIndex] == TPM_RS_PW )
1168           {
1169                if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED)
1170                    return TPM_RC_HANDLE + g_rcIndex[sessionIndex];
1171           }
1172           else
1173           {
1174                session = SessionGet(s_sessionHandles[sessionIndex]);
1175
1176                 // A trial session can not appear in session area, because it cannot
1177                 // be used for authorization, audit or encrypt/decrypt.
1178                 if(session->attributes.isTrialPolicy == SET)
1179                     return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
1180
1181                 // See if the session is bound to a DA protected entity
1182                 // NOTE: Since a policy session is never bound, a policy is still
1183                 // usable even if the object is DA protected and the TPM is in
1184                 // lockout.
1185                 if(session->attributes.isDaBound == SET)
1186                 {
1187                     result = CheckLockedOut(session->attributes.isLockoutBound == SET);
1188                     if(result != TPM_RC_SUCCESS)
1189                         return result;
1190                 }
1191                 // If the current cpHash is the right one, don't re-compute.
1192                 if(cpHashAlg != session->authHashAlg)    // different so compute
1193                 {
1194                     cpHashAlg = session->authHashAlg;    // save this new algID
1195                     ComputeCpHash(session->authHashAlg, commandCode, handleNum,
1196                                   handles, parmBufferSize, parmBufferStart,
1197                                   &cpHash, &nameHash);
1198                 }
1199                 // If this session is for auditing, save the cpHash.
1200                 if(s_attributes[sessionIndex].audit)
1201                     s_cpHashForAudit = cpHash;
1202             }
1203
1204             // if the session has an associated handle, check the auth
1205             if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
1206             {
1207                  result = CheckAuthSession(commandCode, sessionIndex,
1208                                            &cpHash, &nameHash);
1209                  if(result != TPM_RC_SUCCESS)
1210                      return RcSafeAddToResult(result,
1211                                               TPM_RC_S + g_rcIndex[sessionIndex]);
1212             }
1213             else
1214             {
1215                  // a session that is not for authorization must either be encrypt,
1216                  // decrypt, or audit
1217                  if(     s_attributes[sessionIndex].audit == CLEAR

       Page 64                                TCG Published                            Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                          Trusted Platform Module Library

1218                       && s_attributes[sessionIndex].encrypt == CLEAR
1219                       && s_attributes[sessionIndex].decrypt == CLEAR)
1220                       return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex];
1221
1222                   // check HMAC for encrypt/decrypt/audit only sessions
1223                   result = CheckSessionHMAC(sessionIndex, &cpHash);
1224                   if(result != TPM_RC_SUCCESS)
1225                       return RcSafeAddToResult(result,
1226                                                TPM_RC_S + g_rcIndex[sessionIndex]);
1227              }
1228       }
1229
1230   #ifdef TPM_CC_GetCommandAuditDigest
1231       // Check if the command should be audited.
1232       result = CheckCommandAudit(commandCode, handleNum, handles,
1233                                  parmBufferStart, parmBufferSize);
1234       if(result != TPM_RC_SUCCESS)
1235           return result;              // No session number to reference
1236   #endif
1237
1238       // Decrypt the first parameter if applicable. This should be the last operation
1239       // in session processing.
1240       // If the encrypt session is associated with a handle and the handle's
1241       // authValue is available, then authValue is concatenated with sessionAuth to
1242       // generate encryption key, no matter if the handle is the session bound entity
1243       // or not.
1244       if(s_decryptSessionIndex != UNDEFINED_INDEX)
1245       {
1246           // Get size of the leading size field in decrypt parameter
1247           if(    s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED
1248               && IsAuthValueAvailable(s_associatedHandles[s_decryptSessionIndex],
1249                                       commandCode,
1250                                       s_decryptSessionIndex)
1251             )
1252           {
1253                extraKey.b.size=
1254                    EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex],
1255                                       &extraKey.t.buffer);
1256           }
1257           else
1258           {
1259                extraKey.b.size = 0;
1260           }
1261           size = DecryptSize(commandCode);
1262           result = CryptParameterDecryption(
1263                         s_sessionHandles[s_decryptSessionIndex],
1264                         &s_nonceCaller[s_decryptSessionIndex].b,
1265                         parmBufferSize, (UINT16)size,
1266                         &extraKey,
1267                         parmBufferStart);
1268           if(result != TPM_RC_SUCCESS)
1269                return RcSafeAddToResult(result,
1270                                         TPM_RC_S + g_rcIndex[s_decryptSessionIndex]);
1271       }
1272
1273       return TPM_RC_SUCCESS;
1274   }


       6.4.4.11       CheckAuthNoSession()

       Function to process a command with no session associated. The function makes sure all the handles in
       the command require no authorization.



       Family "2.0"                             TCG Published                                     Page 65
       Level 00 Revision 01.16           Copyright © TCG 2006-2014                       October 30, 2014
       Trusted Platform Module Library                                                Part 4: Supporting Routines


       Error Returns                     Meaning

       TPM_RC_AUTH_MISSING               failure - one or more handles require auth

1275   TPM_RC
1276   CheckAuthNoSession(
1277       TPM_CC               commandCode,               //   IN:   Command Code
1278       UINT32               handleNum,                 //   IN:   number of handles in command
1279       TPM_HANDLE           handles[],                 //   IN:   array of handle
1280       BYTE                *parmBufferStart,           //   IN:   start of parameter buffer
1281       UINT32               parmBufferSize             //   IN:   size of parameter buffer
1282       )
1283   {
1284       UINT32 i;
1285       TPM_RC                result = TPM_RC_SUCCESS;
1286
1287       // Check if the commandCode requires authorization
1288       for(i = 0; i < handleNum; i++)
1289       {
1290           if(CommandAuthRole(commandCode, i) != AUTH_NONE)
1291               return TPM_RC_AUTH_MISSING;
1292       }
1293
1294   #ifdef TPM_CC_GetCommandAuditDigest
1295       // Check if the command should be audited.
1296       result = CheckCommandAudit(commandCode, handleNum, handles,
1297                                  parmBufferStart, parmBufferSize);
1298       if(result != TPM_RC_SUCCESS) return result;
1299   #endif
1300
1301       // Initialize number of sessions to be 0
1302       s_sessionNum = 0;
1303
1304       return TPM_RC_SUCCESS;
1305   }


       6.4.5     Response Session Processing

       6.4.5.1     Introduction

       The following functions build the session area in a response, and handle the audit sessions (if present).

       6.4.5.2     ComputeRpHash()

       Function to compute rpHash (Response Parameter Hash). The rpHash is only computed if there is an
       HMAC authorization session and the return code is TPM_RC_SUCCESS.

1306   static void
1307   ComputeRpHash(
1308       TPM_ALG_ID           hashAlg,                   //   IN: hash algorithm to compute rpHash
1309       TPM_CC               commandCode,               //   IN: commandCode
1310       UINT32               resParmBufferSize,         //   IN: size of response parameter buffer
1311       BYTE                *resParmBuffer,             //   IN: response parameter buffer
1312       TPM2B_DIGEST        *rpHash                     //   OUT: rpHash
1313       )
1314   {
1315       // The command result in rpHash is always TPM_RC_SUCCESS.
1316       TPM_RC      responseCode = TPM_RC_SUCCESS;
1317       HASH_STATE hashState;
1318
1319       //     rpHash := hash(responseCode || commandCode || parameters)

       Page 66                                        TCG Published                                  Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
       Part 4: Supporting Routines                                                  Trusted Platform Module Library

1320
1321        // Initiate hash creation.
1322        rpHash->t.size = CryptStartHash(hashAlg, &hashState);
1323
1324        // Add hash constituents.
1325        CryptUpdateDigestInt(&hashState, sizeof(TPM_RC), &responseCode);
1326        CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
1327        CryptUpdateDigest(&hashState, resParmBufferSize, resParmBuffer);
1328
1329        // Complete hash computation.
1330        CryptCompleteHash2B(&hashState, &rpHash->b);
1331
1332        return;
1333   }


       6.4.5.3      InitAuditSession()

       This function initializes the audit data in an audit session.

1334   static void
1335   InitAuditSession(
1336        SESSION              *session             // session to be initialized
1337        )
1338   {
1339        // Mark session as an audit session.
1340        session->attributes.isAudit = SET;
1341
1342        // Audit session can not be bound.
1343        session->attributes.isBound = CLEAR;
1344
1345        // Size of the audit log is the size of session hash algorithm digest.
1346        session->u2.auditDigest.t.size = CryptGetHashDigestSize(session->authHashAlg);
1347
1348        // Set the original digest value to be 0.
1349        MemorySet(&session->u2.auditDigest.t.buffer,
1350                  0,
1351                  session->u2.auditDigest.t.size);
1352
1353        return;
1354   }


       6.4.5.4      Audit()

       This function updates the audit digest in an audit session.

1355   static void
1356   Audit(
1357        SESSION              *auditSession,            //   IN:    loaded audit session
1358        TPM_CC                commandCode,             //   IN:    commandCode
1359        UINT32                resParmBufferSize,       //   IN:    size of response parameter buffer
1360        BYTE                 *resParmBuffer            //   IN:    response parameter buffer
1361        )
1362   {
1363        TPM2B_DIGEST          rpHash;                  // rpHash for response
1364        HASH_STATE            hashState;
1365
1366        // Compute rpHash
1367        ComputeRpHash(auditSession->authHashAlg,
1368                      commandCode,
1369                      resParmBufferSize,
1370                      resParmBuffer,
1371                      &rpHash);
1372

       Family "2.0"                                   TCG Published                                       Page 67
       Level 00 Revision 01.16                Copyright © TCG 2006-2014                         October 30, 2014
       Trusted Platform Module Library                                    Part 4: Supporting Routines

1373       // auditDigestnew :=      hash (auditDigestold || cpHash || rpHash)
1374
1375       // Start hash computation.
1376       CryptStartHash(auditSession->authHashAlg, &hashState);
1377
1378       // Add old digest.
1379       CryptUpdateDigest2B(&hashState, &auditSession->u2.auditDigest.b);
1380
1381       // Add cpHash and rpHash.
1382       CryptUpdateDigest2B(&hashState, &s_cpHashForAudit.b);
1383       CryptUpdateDigest2B(&hashState, &rpHash.b);
1384
1385       // Finalize the hash.
1386       CryptCompleteHash2B(&hashState, &auditSession->u2.auditDigest.b);
1387
1388       return;
1389   }
1390   #ifdef TPM_CC_GetCommandAuditDigest


       6.4.5.5     CommandAudit()

       This function updates the command audit digest.

1391   static void
1392   CommandAudit(
1393       TPM_CC              commandCode,       // IN: commandCode
1394       UINT32              resParmBufferSize, // IN: size of response parameter buffer
1395       BYTE               *resParmBuffer      // IN: response parameter buffer
1396       )
1397   {
1398       if(CommandAuditIsRequired(commandCode))
1399       {
1400           TPM2B_DIGEST    rpHash;        // rpHash for response
1401           HASH_STATE      hashState;
1402
1403             // Compute rpHash.
1404             ComputeRpHash(gp.auditHashAlg, commandCode, resParmBufferSize,
1405                           resParmBuffer, &rpHash);
1406
1407             // If the digest.size is one, it indicates the special case of changing
1408             // the audit hash algorithm. For this case, no audit is done on exit.
1409             // NOTE: When the hash algorithm is changed, g_updateNV is set in order to
1410             // force an update to the NV on exit so that the change in digest will
1411             // be recorded. So, it is safe to exit here without setting any flags
1412             // because the digest change will be written to NV when this code exits.
1413             if(gr.commandAuditDigest.t.size == 1)
1414             {
1415                 gr.commandAuditDigest.t.size = 0;
1416                 return;
1417             }
1418
1419             // If the digest size is zero, need to start a new digest and increment
1420             // the audit counter.
1421             if(gr.commandAuditDigest.t.size == 0)
1422             {
1423                 gr.commandAuditDigest.t.size = CryptGetHashDigestSize(gp.auditHashAlg);
1424                 MemorySet(gr.commandAuditDigest.t.buffer,
1425                           0,
1426                           gr.commandAuditDigest.t.size);
1427
1428                 // Bump the counter and save its value to NV.
1429                 gp.auditCounter++;
1430                 NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
1431                 g_updateNV = TRUE;


       Page 68                                    TCG Published                         Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014        Level 00 Revision 01.16
       Part 4: Supporting Routines                                                     Trusted Platform Module Library

1432             }
1433
1434             // auditDigestnew :=         hash (auditDigestold || cpHash || rpHash)
1435
1436             // Start hash computation.
1437             CryptStartHash(gp.auditHashAlg, &hashState);
1438
1439             // Add old digest.
1440             CryptUpdateDigest2B(&hashState, &gr.commandAuditDigest.b);
1441
1442             // Add cpHash
1443             CryptUpdateDigest2B(&hashState, &s_cpHashForCommandAudit.b);
1444
1445             // Add rpHash
1446             CryptUpdateDigest2B(&hashState, &rpHash.b);
1447
1448             // Finalize the hash.
1449             CryptCompleteHash2B(&hashState, &gr.commandAuditDigest.b);
1450        }
1451        return;
1452   }
1453   #endif


       6.4.5.6       UpdateAuditSessionStatus()

       Function to update the internal audit related states of a session. It
       a) initializes the session as audit session and sets it to be exclusive if this is the first time it is used for
          audit or audit reset was requested;
       b) reports exclusive audit session;
       c) extends audit log; and
       d) clears exclusive audit session if no audit session found in the command.

1454   static void
1455   UpdateAuditSessionStatus(
1456        TPM_CC                commandCode,       // IN: commandCode
1457        UINT32                resParmBufferSize, // IN: size of response parameter buffer
1458        BYTE                 *resParmBuffer      // IN: response parameter buffer
1459        )
1460   {
1461        UINT32                i;
1462        TPM_HANDLE            auditSession = TPM_RH_UNASSIGNED;
1463
1464        // Iterate through sessions
1465        for (i = 0; i < s_sessionNum; i++)
1466        {
1467            SESSION     *session;
1468
1469             // PW session do not have a loaded session and can not be an audit
1470             // session either. Skip it.
1471             if(s_sessionHandles[i] == TPM_RS_PW) continue;
1472
1473             session = SessionGet(s_sessionHandles[i]);
1474
1475             // If a session is used for audit
1476             if(s_attributes[i].audit == SET)
1477             {
1478                 // An audit session has been found
1479                 auditSession = s_sessionHandles[i];
1480
1481                  // If the session has not been an audit session yet, or
1482                  // the auditSetting bits indicate a reset, initialize it and set

       Family "2.0"                                    TCG Published                                            Page 69
       Level 00 Revision 01.16                 Copyright © TCG 2006-2014                             October 30, 2014
       Trusted Platform Module Library                                        Part 4: Supporting Routines

1483                  // it to be the exclusive session
1484                  if(    session->attributes.isAudit == CLEAR
1485                      || s_attributes[i].auditReset == SET
1486                    )
1487                  {
1488                       InitAuditSession(session);
1489                       g_exclusiveAuditSession = auditSession;
1490                  }
1491                  else
1492                  {
1493                       // Check if the audit session is the current exclusive audit
1494                       // session and, if not, clear previous exclusive audit session.
1495                       if(g_exclusiveAuditSession != auditSession)
1496                           g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
1497                  }
1498
1499                  // Report audit session exclusivity.
1500                  if(g_exclusiveAuditSession == auditSession)
1501                  {
1502                      s_attributes[i].auditExclusive = SET;
1503                  }
1504                  else
1505                  {
1506                      s_attributes[i].auditExclusive = CLEAR;
1507                  }
1508
1509                  // Extend audit log.
1510                  Audit(session, commandCode, resParmBufferSize, resParmBuffer);
1511             }
1512       }
1513
1514       // If no audit session is found in the command, and the command allows
1515       // a session then, clear the current exclusive
1516       // audit session.
1517       if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(commandCode))
1518       {
1519           g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
1520       }
1521
1522       return;
1523   }


       6.4.5.7       ComputeResponseHMAC()

       Function to compute HMAC for authorization session in a response.

1524   static void
1525   ComputeResponseHMAC(
1526       UINT32              sessionIndex,         //   IN: session index to be processed
1527       SESSION            *session,              //   IN: loaded session
1528       TPM_CC              commandCode,          //   IN: commandCode
1529       TPM2B_NONCE        *nonceTPM,             //   IN: nonceTPM
1530       UINT32              resParmBufferSize,    //   IN: size of response parameter buffer
1531       BYTE               *resParmBuffer,        //   IN: response parameter buffer
1532       TPM2B_DIGEST       *hmac                  //   OUT: authHMAC
1533       )
1534   {
1535       TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));
1536       TPM2B_KEY        key;       // HMAC key
1537       BYTE             marshalBuffer[sizeof(TPMA_SESSION)];
1538       BYTE            *buffer;
1539       UINT32           marshalSize;
1540       HMAC_STATE       hmacState;
1541       TPM2B_DIGEST     rp_hash;


       Page 70                                   TCG Published                              Family "2.0"
       October 30, 2014                   Copyright © TCG 2006-2014             Level 00 Revision 01.16
       Part 4: Supporting Routines                                          Trusted Platform Module Library

1542
1543       // Compute rpHash.
1544       ComputeRpHash(session->authHashAlg, commandCode, resParmBufferSize,
1545                     resParmBuffer, &rp_hash);
1546
1547       // Generate HMAC key
1548       MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
1549
1550       // Check if the session has an associated handle and the associated entity is
1551       // the one that the session is bound to.
1552       // If not bound, add the authValue of this entity to the HMAC key.
1553       if(   s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED
1554          &&    !( HandleGetType(s_sessionHandles[sessionIndex])
1555                     == TPM_HT_POLICY_SESSION
1556             &&   session->attributes.isAuthValueNeeded == CLEAR)
1557          && !session->attributes.requestWasBound)
1558       {
1559           pAssert((sizeof(AUTH_VALUE) + key.t.size) <= sizeof(key.t.buffer));
1560           key.t.size = key.t.size +
1561                           EntityGetAuthValue(s_associatedHandles[sessionIndex],
1562                                              (AUTH_VALUE *)&key.t.buffer[key.t.size]);
1563       }
1564
1565       // if the HMAC key size for a policy session is 0, the response HMAC is
1566       // computed according to the input HMAC
1567       if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION
1568           && key.t.size == 0
1569           && s_inputAuthValues[sessionIndex].t.size == 0)
1570       {
1571           hmac->t.size = 0;
1572           return;
1573       }
1574
1575       // Start HMAC computation.
1576       hmac->t.size = CryptStartHMAC2B(session->authHashAlg, &key.b, &hmacState);
1577
1578       // Add hash components.
1579       CryptUpdateDigest2B(&hmacState, &rp_hash.b);
1580       CryptUpdateDigest2B(&hmacState, &nonceTPM->b);
1581       CryptUpdateDigest2B(&hmacState, &s_nonceCaller[sessionIndex].b);
1582
1583       // Add session attributes.
1584       buffer = marshalBuffer;
1585       marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL);
1586       CryptUpdateDigest(&hmacState, marshalSize, marshalBuffer);
1587
1588       // Finalize HMAC.
1589       CryptCompleteHMAC2B(&hmacState, &hmac->b);
1590
1591       return;
1592   }


       6.4.5.8    BuildSingleResponseAuth()

       Function to compute response for an authorization session.

1593   static void
1594   BuildSingleResponseAuth(
1595       UINT32              sessionIndex,          //   IN: session index to be processed
1596       TPM_CC              commandCode,           //   IN: commandCode
1597       UINT32              resParmBufferSize,     //   IN: size of response parameter buffer
1598       BYTE               *resParmBuffer,         //   IN: response parameter buffer
1599       TPM2B_AUTH         *auth                   //   OUT: authHMAC
1600       )


       Family "2.0"                               TCG Published                                   Page 71
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                    October 30, 2014
       Trusted Platform Module Library                                         Part 4: Supporting Routines

1601   {
1602       // For password authorization, field is empty.
1603       if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
1604       {
1605           auth->t.size = 0;
1606       }
1607       else
1608       {
1609           // Fill in policy/HMAC based session response.
1610           SESSION     *session = SessionGet(s_sessionHandles[sessionIndex]);
1611
1612              // If the session is a policy session with isPasswordNeeded SET, the auth
1613              // field is empty.
1614              if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION
1615                       && session->attributes.isPasswordNeeded == SET)
1616                   auth->t.size = 0;
1617              else
1618                   // Compute response HMAC.
1619                   ComputeResponseHMAC(sessionIndex,
1620                                       session,
1621                                       commandCode,
1622                                       &session->nonceTPM,
1623                                       resParmBufferSize,
1624                                       resParmBuffer,
1625                                       auth);
1626       }
1627
1628       return;
1629   }


       6.4.5.9     UpdateTPMNonce()

       Updates TPM nonce in both internal session or response if applicable.

1630   static void
1631   UpdateTPMNonce(
1632       UINT16               noncesSize,       // IN: number of elements in 'nonces' array
1633       TPM2B_NONCE          nonces[]          // OUT: nonceTPM
1634       )
1635   {
1636       UINT32      i;
1637       pAssert(noncesSize >= s_sessionNum);
1638       for(i = 0; i < s_sessionNum; i++)
1639       {
1640           SESSION     *session;
1641           // For PW session, nonce is 0.
1642           if(s_sessionHandles[i] == TPM_RS_PW)
1643           {
1644               nonces[i].t.size = 0;
1645               continue;
1646           }
1647           session = SessionGet(s_sessionHandles[i]);
1648           // Update nonceTPM in both internal session and response.
1649           CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer);
1650           nonces[i] = session->nonceTPM;
1651       }
1652       return;
1653   }


       6.4.5.10    UpdateInternalSession()

       Updates internal sessions:


       Page 72                                    TCG Published                              Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014            Level 00 Revision 01.16
       Part 4: Supporting Routines                                            Trusted Platform Module Library


       a) Restarts session time, and
       b) Clears a policy session since nonce is rolling.

1654   static void
1655   UpdateInternalSession(
1656       void
1657       )
1658   {
1659       UINT32      i;
1660       for(i = 0; i < s_sessionNum; i++)
1661       {
1662           // For PW session, no update.
1663           if(s_sessionHandles[i] == TPM_RS_PW) continue;
1664
1665              if(s_attributes[i].continueSession == CLEAR)
1666              {
1667                   // Close internal session.
1668                   SessionFlush(s_sessionHandles[i]);
1669              }
1670              else
1671              {
1672                   // If nonce is rolling in a policy session, the policy related data
1673                   // will be re-initialized.
1674                   if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION)
1675                   {
1676                       SESSION     *session = SessionGet(s_sessionHandles[i]);
1677
1678                       // When the nonce rolls it starts a new timing interval for the
1679                       // policy session.
1680                       SessionResetPolicyData(session);
1681                       session->startTime = go.clock;
1682                   }
1683              }
1684       }
1685       return;
1686   }


       6.4.5.11       BuildResponseSession()

       Function to build Session buffer in a response.

1687   void
1688   BuildResponseSession(
1689       TPM_ST               tag,               //    IN: tag
1690       TPM_CC               commandCode,       //    IN: commandCode
1691       UINT32               resHandleSize,     //    IN: size of response handle buffer
1692       UINT32               resParmSize,       //    IN: size of response parameter buffer
1693       UINT32              *resSessionSize     //    OUT: response session area
1694       )
1695   {
1696       BYTE                *resParmBuffer;
1697       TPM2B_NONCE      responseNonces[MAX_SESSION_NUM];
1698
1699       // Compute response parameter buffer start.
1700       resParmBuffer = MemoryGetResponseBuffer(commandCode) + sizeof(TPM_ST) +
1701                       sizeof(UINT32) + sizeof(TPM_RC) + resHandleSize;
1702
1703       // For TPM_ST_SESSIONS, there is parameterSize field.
1704       if(tag == TPM_ST_SESSIONS)
1705           resParmBuffer += sizeof(UINT32);
1706
1707       // Session nonce should be updated before parameter encryption
1708       if(tag == TPM_ST_SESSIONS)

       Family "2.0"                                TCG Published                                    Page 73
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                     October 30, 2014
       Trusted Platform Module Library                                   Part 4: Supporting Routines

1709       {
1710             UpdateTPMNonce(MAX_SESSION_NUM, responseNonces);
1711
1712             // Encrypt first parameter if applicable. Parameter encryption should
1713             // happen after nonce update and before any rpHash is computed.
1714             // If the encrypt session is associated with a handle, the authValue of
1715             // this handle will be concatenated with sessionAuth to generate
1716             // encryption key, no matter if the handle is the session bound entity
1717             // or not. The authValue is added to sessionAuth only when the authValue
1718             // is available.
1719             if(s_encryptSessionIndex != UNDEFINED_INDEX)
1720             {
1721                 UINT32          size;
1722                 TPM2B_AUTH      extraKey;
1723
1724                 // Get size of the leading size field
1725                 if(    s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED
1726                     && IsAuthValueAvailable(s_associatedHandles[s_encryptSessionIndex],
1727                                             commandCode, s_encryptSessionIndex)
1728                   )
1729                 {
1730                      extraKey.b.size =
1731                          EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex],
1732                                             &extraKey.t.buffer);
1733                 }
1734                 else
1735                 {
1736                      extraKey.b.size = 0;
1737                 }
1738                 size = EncryptSize(commandCode);
1739                 CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex],
1740                                           &s_nonceCaller[s_encryptSessionIndex].b,
1741                                           (UINT16)size,
1742                                           &extraKey,
1743                                           resParmBuffer);
1744
1745             }
1746
1747       }
1748       // Audit session should be updated first regardless of the tag.
1749       // A command with no session may trigger a change of the exclusivity state.
1750       UpdateAuditSessionStatus(commandCode, resParmSize, resParmBuffer);
1751
1752       // Audit command.
1753       CommandAudit(commandCode, resParmSize, resParmBuffer);
1754
1755       // Process command with sessions.
1756       if(tag == TPM_ST_SESSIONS)
1757       {
1758           UINT32           i;
1759           BYTE            *buffer;
1760           TPM2B_DIGEST     responseAuths[MAX_SESSION_NUM];
1761
1762             pAssert(s_sessionNum > 0);
1763
1764             // Iterate over each session in the command session area, and create
1765             // corresponding sessions for response.
1766             for(i = 0; i < s_sessionNum; i++)
1767             {
1768                 BuildSingleResponseAuth(
1769                                          i,
1770                                          commandCode,
1771                                          resParmSize,
1772                                          resParmBuffer,
1773                                          &responseAuths[i]);
1774                 // Make sure that continueSession is SET on any Password session.

       Page 74                                TCG Published                            Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014        Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

1775                  // This makes it marginally easier for the management software
1776                  // to keep track of the closed sessions.
1777                  if(    s_attributes[i].continueSession == CLEAR
1778                      && s_sessionHandles[i] == TPM_RS_PW)
1779                  {
1780                       s_attributes[i].continueSession = SET;
1781                  }
1782            }
1783
1784            // Assemble Response Sessions.
1785            *resSessionSize = 0;
1786            buffer = resParmBuffer + resParmSize;
1787            for(i = 0; i < s_sessionNum; i++)
1788            {
1789                *resSessionSize += TPM2B_NONCE_Marshal(&responseNonces[i],
1790                                                       &buffer, NULL);
1791                *resSessionSize += TPMA_SESSION_Marshal(&s_attributes[i],
1792                                                        &buffer, NULL);
1793                *resSessionSize += TPM2B_DIGEST_Marshal(&responseAuths[i],
1794                                                        &buffer, NULL);
1795            }
1796
1797            // Update internal sessions after completing response buffer computation.
1798            UpdateInternalSession();
1799       }
1800       else
1801       {
1802           // Process command with no session.
1803           *resSessionSize = 0;
1804       }
1805
1806       return;
1807   }




       Family "2.0"                           TCG Published                                 Page 75
       Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                                       Part 4: Supporting Routines


     7     Command Support Functions

     7.1     Introduction

     This clause contains support routines that are called by the command action code in TPM 2.0 Part 3. The
     functions are grouped by the command group that is supported by the functions.

     7.2     Attestation Command Support (Attest_spt.c)

     7.2.1     Includes

 1   #include "InternalRoutines.h"
 2   #include "Attest_spt_fp.h"


     7.2.2     Functions

     7.2.2.1     FillInAttestInfo()

     Fill in common fields of TPMS_ATTEST structure.

     Error Returns                     Meaning

     TPM_RC_KEY                        key referenced by signHandle is not a signing key
     TPM_RC_SCHEME                     both scheme and key's default scheme are empty; or scheme is
                                       empty while key's default scheme requires explicit input scheme (split
                                       signing); or non-empty default key scheme differs from scheme

 3   TPM_RC
 4   FillInAttestInfo(
 5         TPMI_DH_OBJECT         signHandle,            //   IN: handle of signing object
 6         TPMT_SIG_SCHEME       *scheme,                //   IN/OUT: scheme to be used for signing
 7         TPM2B_DATA            *data,                  //   IN: qualifying data
 8         TPMS_ATTEST           *attest                 //   OUT: attest structure
 9         )
10   {
11         TPM_RC                         result;
12         TPMI_RH_HIERARCHY              signHierarhcy;
13
14         result = CryptSelectSignScheme(signHandle, scheme);
15         if(result != TPM_RC_SUCCESS)
16             return result;
17
18         // Magic number
19         attest->magic = TPM_GENERATED_VALUE;
20
21         if(signHandle == TPM_RH_NULL)
22         {
23             BYTE     *buffer;
24             // For null sign handle, the QN is TPM_RH_NULL
25             buffer = attest->qualifiedSigner.t.name;
26             attest->qualifiedSigner.t.size =
27                  TPM_HANDLE_Marshal(&signHandle, &buffer, NULL);
28         }
29         else
30         {
31             // Certifying object qualified name
32             // if the scheme is anonymous, this is an empty buffer
33             if(CryptIsSchemeAnonymous(scheme->scheme))

     Page 76                                        TCG Published                                         Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
     Part 4: Supporting Routines                                          Trusted Platform Module Library

34                  attest->qualifiedSigner.t.size = 0;
35             else
36                  ObjectGetQualifiedName(signHandle, &attest->qualifiedSigner);
37       }
38
39       // current clock in plain text
40       TimeFillInfo(&attest->clockInfo);
41
42       // Firmware version in plain text
43       attest->firmwareVersion = ((UINT64) gp.firmwareV1 << (sizeof(UINT32) * 8));
44       attest->firmwareVersion += gp.firmwareV2;
45
46       // Get the hierarchy of sign object. For NULL sign handle, the hierarchy
47       // will be TPM_RH_NULL
48       signHierarhcy = EntityGetHierarchy(signHandle);
49       if(signHierarhcy != TPM_RH_PLATFORM && signHierarhcy != TPM_RH_ENDORSEMENT)
50       {
51           // For sign object is not in platform or endorsement hierarchy,
52           // obfuscate the clock and firmwereVersion information
53           UINT64          obfuscation[2];
54           TPMI_ALG_HASH   hashAlg;
55
56             // Get hash algorithm
57             if(signHandle == TPM_RH_NULL || signHandle == TPM_RH_OWNER)
58             {
59                  hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
60             }
61             else
62             {
63                  OBJECT          *signObject = NULL;
64                  signObject = ObjectGet(signHandle);
65                  hashAlg = signObject->publicArea.nameAlg;
66             }
67             KDFa(hashAlg, &gp.shProof.b, "OBFUSCATE",
68                   &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL);
69
70             // Obfuscate data
71             attest->firmwareVersion += obfuscation[0];
72             attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
73             attest->clockInfo.restartCount += (UINT32)obfuscation[1];
74       }
75
76       // External data
77       if(CryptIsSchemeAnonymous(scheme->scheme))
78           attest->extraData.t.size = 0;
79       else
80       {
81           // If we move the data to the attestation structure, then we will not use
82           // it in the signing operation except as part of the signed data
83           attest->extraData = *data;
84           data->t.size = 0;
85       }
86
87       return TPM_RC_SUCCESS;
88   }


     7.2.2.2     SignAttestInfo()

     Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned.




     Family "2.0"                             TCG Published                                      Page 77
     Level 00 Revision 01.16           Copyright © TCG 2006-2014                      October 30, 2014
      Trusted Platform Module Library                                                    Part 4: Supporting Routines


      Error Returns                     Meaning

      TPM_RC_ATTRIBUTES                 signHandle references not a signing key
      TPM_RC_SCHEME                     scheme is not compatible with signHandle type
      TPM_RC_VALUE                      digest generated for the given scheme is greater than the modulus of
                                        signHandle (for an RSA key); invalid commit status or failed to
                                        generate r value (for an ECC key)

 89   TPM_RC
 90   SignAttestInfo(
 91       TPMI_DH_OBJECT           signHandle,                //   IN: handle of sign object
 92       TPMT_SIG_SCHEME         *scheme,                    //   IN: sign scheme
 93       TPMS_ATTEST             *certifyInfo,               //   IN: the data to be signed
 94       TPM2B_DATA              *qualifyingData,            //   IN: extra data for the signing proce
 95       TPM2B_ATTEST            *attest,                    //   OUT: marshaled attest blob to be
 96                                                           //       signed
 97       TPMT_SIGNATURE          *signature                  //   OUT: signature
 98       )
 99   {
100       TPM_RC                         result;
101       TPMI_ALG_HASH                  hashAlg;
102       BYTE                           *buffer;
103       HASH_STATE                     hashState;
104       TPM2B_DIGEST                   digest;
105
106       // Marshal TPMS_ATTEST structure for hash
107       buffer = attest->t.attestationData;
108       attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL);
109
110       if(signHandle == TPM_RH_NULL)
111       {
112           signature->sigAlg = TPM_ALG_NULL;
113       }
114       else
115       {
116           // Attestation command may cause the orderlyState to be cleared due to
117           // the reporting of clock info. If this is the case, check if NV is
118           // available first
119           if(gp.orderlyState != SHUTDOWN_NONE)
120           {
121               // The command needs NV update. Check if NV is available.
122               // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
123               // this point
124               result = NvIsAvailable();
125               if(result != TPM_RC_SUCCESS)
126                   return result;
127           }
128
129             // Compute hash
130             hashAlg = scheme->details.any.hashAlg;
131             digest.t.size = CryptStartHash(hashAlg, &hashState);
132             CryptUpdateDigest(&hashState, attest->t.size, attest->t.attestationData);
133             CryptCompleteHash2B(&hashState, &digest.b);
134
135             // If there is qualifying data, need to rehash the the data
136             // hash(qualifyingData || hash(attestationData))
137             if(qualifyingData->t.size != 0)
138             {
139                 CryptStartHash(hashAlg, &hashState);
140                 CryptUpdateDigest(&hashState,
141                                   qualifyingData->t.size,
142                                   qualifyingData->t.buffer);
143                 CryptUpdateDigest(&hashState, digest.t.size, digest.t.buffer);
144                 CryptCompleteHash2B(&hashState, &digest.b);

      Page 78                                        TCG Published                                       Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
      Part 4: Supporting Routines                                      Trusted Platform Module Library

145              }
146
147              // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
148              // TPM_RC_ATTRIBUTES error may be returned at this point
149              return CryptSign(signHandle,
150                               scheme,
151                               &digest,
152                               signature);
153         }
154
155         return TPM_RC_SUCCESS;
156   }


      7.3       Context Management Command Support (Context_spt.c)

      7.3.1      Includes

  1   #include "InternalRoutines.h"
  2   #include "Context_spt_fp.h"


      7.3.2      Functions

      7.3.2.1        ComputeContextProtectionKey()

      This function retrieves the symmetric protection key for context encryption It is used by
      TPM2_ConextSave() and TPM2_ContextLoad() to create the symmetric encryption key and iv

  3   void
  4   ComputeContextProtectionKey(
  5         TPMS_CONTEXT      *contextBlob,    // IN: context blob
  6         TPM2B_SYM_KEY     *symKey,         // OUT: the symmetric key
  7         TPM2B_IV          *iv              // OUT: the IV.
  8         )
  9   {
 10         UINT16             symKeyBits;     // number of bits in the parent's
 11                                            //   symmetric key
 12         TPM2B_AUTH        *proof = NULL;   // the proof value to use. Is null for
 13                                            //   everything but a primary object in
 14                                            //   the Endorsement Hierarchy
 15
 16         BYTE               kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF
 17
 18         TPM2B_DATA         sequence2B, handle2B;
 19
 20         // Get proof value
 21         proof = HierarchyGetProof(contextBlob->hierarchy);
 22
 23         // Get sequence value in 2B format
 24         sequence2B.t.size = sizeof(contextBlob->sequence);
 25         MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence,
 26                    sizeof(contextBlob->sequence),
 27                    sizeof(sequence2B.t.buffer));
 28
 29         // Get handle value in 2B format
 30         handle2B.t.size = sizeof(contextBlob->savedHandle);
 31         MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle,
 32                    sizeof(contextBlob->savedHandle),
 33                    sizeof(handle2B.t.buffer));
 34
 35         // Get the symmetric encryption key size
 36         symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;


      Family "2.0"                             TCG Published                                 Page 79
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                  October 30, 2014
     Trusted Platform Module Library                                            Part 4: Supporting Routines

37       symKeyBits = CONTEXT_ENCRYPT_KEY_BITS;
38       // Get the size of the IV for the algorithm
39       iv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits);
40
41       // KDFa to generate symmetric key and IV value
42       KDFa(CONTEXT_INTEGRITY_HASH_ALG, &proof->b, "CONTEXT", &sequence2B.b,
43            &handle2B.b, (symKey->t.size + iv->t.size) * 8, kdfResult, NULL);
44
45       // Copy part of the returned value as the key
46       MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size,
47                  sizeof(symKey->t.buffer));
48
49       // Copy the rest as the IV
50       MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size,
51                  sizeof(iv->t.buffer));
52
53       return;
54   }


     7.3.2.2    ComputeContextIntegrity()

     Generate the integrity hash for a context It is used by TPM2_ContextSave() to create an integrity hash
     and by TPM2_ContextLoad() to compare an integrity hash

55   void
56   ComputeContextIntegrity(
57       TPMS_CONTEXT       *contextBlob,      // IN: context blob
58       TPM2B_DIGEST       *integrity         // OUT: integrity
59       )
60   {
61       HMAC_STATE              hmacState;
62       TPM2B_AUTH              *proof;
63       UINT16                  integritySize;
64
65       // Get proof value
66       proof = HierarchyGetProof(contextBlob->hierarchy);
67
68       // Start HMAC
69       integrity->t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG,
70                                            &proof->b, &hmacState);
71
72       // Compute integrity size at the beginning of context blob
73       integritySize = sizeof(integrity->t.size) + integrity->t.size;
74
75       // Adding total reset counter so that the context cannot be
76       // used after a TPM Reset
77       CryptUpdateDigestInt(&hmacState, sizeof(gp.totalResetCount),
78                            &gp.totalResetCount);
79
80       // If this is a ST_CLEAR object, add the clear count
81       // so that this contest cannot be loaded after a TPM Restart
82       if(contextBlob->savedHandle == 0x80000002)
83           CryptUpdateDigestInt(&hmacState, sizeof(gr.clearCount), &gr.clearCount);
84
85       // Adding sequence number to the HMAC to make sure that it doesn't
86       // get changed
87       CryptUpdateDigestInt(&hmacState, sizeof(contextBlob->sequence),
88                            &contextBlob->sequence);
89
90       // Protect the handle
91       CryptUpdateDigestInt(&hmacState, sizeof(contextBlob->savedHandle),
92                             &contextBlob->savedHandle);
93
94       // Adding sensitive contextData, skip the leading integrity area

     Page 80                                    TCG Published                                 Family "2.0"
     October 30, 2014                    Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                       Trusted Platform Module Library

 95         CryptUpdateDigest(&hmacState, contextBlob->contextBlob.t.size - integritySize,
 96                           contextBlob->contextBlob.t.buffer + integritySize);
 97
 98         // Complete HMAC
 99         CryptCompleteHMAC2B(&hmacState, &integrity->b);
100
101         return;
102   }


      7.3.2.3     SequenceDataImportExport()

      This function is used scan through the sequence object and either modify the hash state data for
      LIB_EXPORT or to import it into the internal format

103   void
104   SequenceDataImportExport(
105         OBJECT           *object,          // IN: the object containing the sequence data
106         OBJECT           *exportObject,    // IN/OUT: the object structure that will get
107                                            //     the exported hash state
108         IMPORT_EXPORT     direction
109         )
110   {
111         int                      count = 1;
112         HASH_OBJECT             *internalFmt = (HASH_OBJECT *)object;
113         HASH_OBJECT             *externalFmt = (HASH_OBJECT *)exportObject;
114
115         if(object->attributes.eventSeq)
116             count = HASH_COUNT;
117         for(; count; count--)
118             CryptHashStateImportExport(&internalFmt->state.hashState[count - 1],
119                                  externalFmt->state.hashState, direction);
120   }


      7.4     Policy Command Support (Policy_spt.c)

  1   #include   "InternalRoutines.h"
  2   #include   "Policy_spt_fp.h"
  3   #include   "PolicySigned_fp.h"
  4   #include   "PolicySecret_fp.h"
  5   #include   "PolicyTicket_fp.h"


      7.4.1     PolicyParameterChecks()

      This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The
      common parameters are nonceTPM, expiration, and cpHashA.

  6   TPM_RC
  7   PolicyParameterChecks(
  8         SESSION          *session,
  9         UINT64            authTimeout,
 10         TPM2B_DIGEST     *cpHashA,
 11         TPM2B_NONCE      *nonce,
 12         TPM_RC            nonceParameterNumber,
 13         TPM_RC            cpHashParameterNumber,
 14         TPM_RC            expirationParameterNumber
 15         )
 16   {
 17         TPM_RC            result;
 18
 19         // Validate that input nonceTPM is correct if present
 20         if(nonce != NULL && nonce->t.size != 0)


      Family "2.0"                             TCG Published                                  Page 81
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                           Part 4: Supporting Routines

21       {
22             if(!Memory2BEqual(&nonce->b, &session->nonceTPM.b))
23                 return TPM_RC_NONCE + RC_PolicySigned_nonceTPM;
24       }
25       // If authTimeout is set (expiration != 0...
26       if(authTimeout != 0)
27       {
28           // ...then nonce must be present
29           // nonce present isn't checked in PolicyTicket
30           if(nonce != NULL && nonce->t.size == 0)
31               // This error says that the time has expired but it is pointing
32               // at the nonceTPM value.
33               return TPM_RC_EXPIRED + nonceParameterNumber;
34
35             // Validate input expiration.
36             // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE
37             // or TPM_RC_NV_RATE error may be returned here.
38             result = NvIsAvailable();
39             if(result != TPM_RC_SUCCESS)
40                 return result;
41
42             if(authTimeout < go.clock)
43                 return TPM_RC_EXPIRED + expirationParameterNumber;
44       }
45       // If the cpHash is present, then check it
46       if(cpHashA != NULL && cpHashA->t.size != 0)
47       {
48           // The cpHash input has to have the correct size
49           if(cpHashA->t.size != session->u2.policyDigest.t.size)
50               return TPM_RC_SIZE + cpHashParameterNumber;
51
52             // If the cpHash has already been set, then this input value
53             // must match the current value.
54             if(     session->u1.cpHash.b.size != 0
55                 && !Memory2BEqual(&cpHashA->b, &session->u1.cpHash.b))
56                     return TPM_RC_CPHASH;
57       }
58       return TPM_RC_SUCCESS;
59   }


     7.4.2     PolicyContextUpdate()

     Update policy hash Update the policyDigest in policy session by extending policyRef and objectName to
     it. This will also update the cpHash if it is present.

60   void
61   PolicyContextUpdate(
62       TPM_CC              commandCode,     //   IN:   command code
63       TPM2B_NAME         *name,            //   IN:   name of entity
64       TPM2B_NONCE        *ref,             //   IN:   the reference data
65       TPM2B_DIGEST       *cpHash,          //   IN:   the cpHash (optional)
66       UINT64              policyTimeout,
67       SESSION            *session          // IN/OUT: policy session to be updated
68       )
69   {
70       HASH_STATE               hashState;
71       UINT16                   policyDigestSize;
72
73       // Start hash
74       policyDigestSize = CryptStartHash(session->authHashAlg, &hashState);
75
76       // policyDigest size should always be the digest size of session hash algorithm.
77       pAssert(session->u2.policyDigest.t.size == policyDigestSize);
78

     Page 82                                   TCG Published                                 Family "2.0"
     October 30, 2014                   Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                   Trusted Platform Module Library

 79         // add old digest
 80         CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
 81
 82         // add commandCode
 83         CryptUpdateDigestInt(&hashState, sizeof(commandCode), &commandCode);
 84
 85         // add name if applicable
 86         if(name != NULL)
 87             CryptUpdateDigest2B(&hashState, &name->b);
 88
 89         // Complete the digest and get the results
 90         CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
 91
 92         // Start second hash computation
 93         CryptStartHash(session->authHashAlg, &hashState);
 94
 95         // add policyDigest
 96         CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
 97
 98         // add policyRef
 99         if(ref != NULL)
100             CryptUpdateDigest2B(&hashState, &ref->b);
101
102         // Complete second digest
103         CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
104
105         // Deal with the cpHash. If the cpHash value is present
106         // then it would have already been checked to make sure that
107         // it is compatible with the current value so all we need
108         // to do here is copy it and set the iscoHashDefined attribute
109         if(cpHash != NULL && cpHash->t.size != 0)
110         {
111             session->u1.cpHash = *cpHash;
112             session->attributes.iscpHashDefined = SET;
113         }
114
115         // update the timeout if it is specified
116         if(policyTimeout!= 0)
117         {
118         // If the timeout has not been set, then set it to the new value
119             if(session->timeOut == 0)
120                 session->timeOut = policyTimeout;
121             else if(session->timeOut > policyTimeout)
122                 session->timeOut = policyTimeout;
123         }
124         return;
125   }


      7.5     NV Command Support (NV_spt.c)

      7.5.1     Includes

  1   #include "InternalRoutines.h"
  2   #include "NV_spt_fp.h"


      7.5.2     Fuctions

      7.5.2.1    NvReadAccessChecks()

      Common routine for validating a read Used by TPM2_NV_Read(), TPM2_NV_ReadLock() and
      TPM2_PolicyNV()

      Family "2.0"                          TCG Published                                 Page 83
      Level 00 Revision 01.16         Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                                     Part 4: Supporting Routines


     Error Returns                     Meaning

     TPM_RC_NV_AUTHORIZATION           autHandle is not allowed to authorize read of the index
     TPM_RC_NV_LOCKED                  Read locked
     TPM_RC_NV_UNINITIALIZED           Try to read an uninitialized index

 3   TPM_RC
 4   NvReadAccessChecks(
 5       TPM_HANDLE          authHandle,             // IN: the handle that provided the
 6                                                   //     authorization
 7       TPM_HANDLE          nvHandle                // IN: the handle of the NV index to be written
 8       )
 9   {
10       NV_INDEX            nvIndex;
11
12       // Get NV index info
13       NvGetIndexInfo(nvHandle, &nvIndex);
14
15   // This check may be done before doing authorization checks as is done in this
16   // version of the reference code. If not done there, then uncomment the next
17   // three lines.
18   //    // If data is read locked, returns an error
19   //    if(nvIndex.publicArea.attributes.TPMA_NV_READLOCKED == SET)
20   //        return TPM_RC_NV_LOCKED;
21
22       // If the authorization was provided by the owner or platform, then check
23       // that the attributes allow the read. If the authorization handle
24       // is the same as the index, then the checks were made when the authorization
25       // was checked..
26       if(authHandle == TPM_RH_OWNER)
27       {
28           // If Owner provided auth then ONWERWRITE must be SET
29           if(! nvIndex.publicArea.attributes.TPMA_NV_OWNERREAD)
30               return TPM_RC_NV_AUTHORIZATION;
31       }
32       else if(authHandle == TPM_RH_PLATFORM)
33       {
34           // If Platform provided auth then PPWRITE must be SET
35           if(!nvIndex.publicArea.attributes.TPMA_NV_PPREAD)
36               return TPM_RC_NV_AUTHORIZATION;
37       }
38       // If neither Owner nor Platform provided auth, make sure that it was
39       // provided by this index.
40       else if(authHandle != nvHandle)
41               return TPM_RC_NV_AUTHORIZATION;
42
43       // If the index has not been written, then the value cannot be read
44       // NOTE: This has to come after other access checks to make sure that
45       // the proper authorization is given to TPM2_NV_ReadLock()
46       if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
47           return TPM_RC_NV_UNINITIALIZED;
48
49       return TPM_RC_SUCCESS;
50   }


     7.5.2.2    NvWriteAccessChecks()

     Common routine for validating a write               Used    by    TPM2_NV_Write(),          TPM2_NV_Increment(),
     TPM2_SetBits(), and TPM2_NV_WriteLock()




     Page 84                                         TCG Published                                        Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                      Level 00 Revision 01.16
     Part 4: Supporting Routines                                           Trusted Platform Module Library


     Error Returns                  Meaning

     TPM_RC_NV_AUTHORIZATION        Authorization fails
     TPM_RC_NV_LOCKED               Write locked

51   TPM_RC
52   NvWriteAccessChecks(
53         TPM_HANDLE        authHandle,           // IN: the handle that provided the
54                                                 //     authorization
55         TPM_HANDLE        nvHandle              // IN: the handle of the NV index to be written
56         )
57   {
58         NV_INDEX          nvIndex;
59
60         // Get NV index info
61         NvGetIndexInfo(nvHandle, &nvIndex);
62
63   // This check may be done before doing authorization checks as is done in this
64   // version of the reference code. If not done there, then uncomment the next
65   // three lines.
66   //    // If data is write locked, returns an error
67   //    if(nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED == SET)
68   //        return TPM_RC_NV_LOCKED;
69
70         // If the authorization was provided by the owner or platform, then check
71         // that the attributes allow the write. If the authorization handle
72         // is the same as the index, then the checks were made when the authorization
73         // was checked..
74         if(authHandle == TPM_RH_OWNER)
75         {
76             // If Owner provided auth then ONWERWRITE must be SET
77             if(! nvIndex.publicArea.attributes.TPMA_NV_OWNERWRITE)
78                 return TPM_RC_NV_AUTHORIZATION;
79         }
80         else if(authHandle == TPM_RH_PLATFORM)
81         {
82             // If Platform provided auth then PPWRITE must be SET
83             if(!nvIndex.publicArea.attributes.TPMA_NV_PPWRITE)
84                 return TPM_RC_NV_AUTHORIZATION;
85         }
86         // If neither Owner nor Platform provided auth, make sure that it was
87         // provided by this index.
88         else if(authHandle != nvHandle)
89                 return TPM_RC_NV_AUTHORIZATION;
90
91         return TPM_RC_SUCCESS;
92   }


     7.6     Object Command Support (Object_spt.c)

     7.6.1    Includes

 1   #include "InternalRoutines.h"
 2   #include "Object_spt_fp.h"
 3   #include <Platform.h>




     Family "2.0"                                  TCG Published                                 Page 85
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                     October 30, 2014
     Trusted Platform Module Library                                            Part 4: Supporting Routines

     7.6.2     Local Functions

     7.6.2.1     EqualCryptSet()

     Check if the crypto sets in two public areas are equal

     Error Returns                     Meaning

     TPM_RC_ASYMMETRIC                 mismatched parameters
     TPM_RC_HASH                       mismatched name algorithm
     TPM_RC_TYPE                       mismatched type

 4   static TPM_RC
 5   EqualCryptSet(
 6       TPMT_PUBLIC         *publicArea1,        // IN: public area 1
 7       TPMT_PUBLIC         *publicArea2         // IN: public area 2
 8       )
 9   {
10       UINT16                   size1;
11       UINT16                   size2;
12       BYTE                     params1[sizeof(TPMU_PUBLIC_PARMS)];
13       BYTE                     params2[sizeof(TPMU_PUBLIC_PARMS)];
14       BYTE                     *buffer;
15
16       // Compare name hash
17       if(publicArea1->nameAlg != publicArea2->nameAlg)
18           return TPM_RC_HASH;
19
20       // Compare algorithm
21       if(publicArea1->type != publicArea2->type)
22           return TPM_RC_TYPE;
23
24       // TPMU_PUBLIC_PARMS field should be identical
25       buffer = params1;
26       size1 = TPMU_PUBLIC_PARMS_Marshal(&publicArea1->parameters, &buffer,
27                                         NULL, publicArea1->type);
28       buffer = params2;
29       size2 = TPMU_PUBLIC_PARMS_Marshal(&publicArea2->parameters, &buffer,
30                                         NULL, publicArea2->type);
31
32       if(size1 != size2 || !MemoryEqual(params1, params2, size1))
33           return TPM_RC_ASYMMETRIC;
34
35       return TPM_RC_SUCCESS;
36   }


     7.6.2.2     GetIV2BSize()

     Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive data. It
     includes both size of size field and size of iv data

     Return Value                      Meaning

37   static UINT16
38   GetIV2BSize(
39       TPM_HANDLE            protectorHandle           // IN: the protector handle
40       )
41   {
42       OBJECT                   *protector = NULL; // Pointer to the protector object
43       TPM_ALG_ID               symAlg;


     Page 86                                      TCG Published                               Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014              Level 00 Revision 01.16
     Part 4: Supporting Routines                                           Trusted Platform Module Library

44       UINT16                    keyBits;
45
46       // Determine the symmetric algorithm and size of key
47       if(protectorHandle == TPM_RH_NULL)
48       {
49           // Use the context encryption algorithm and key size
50           symAlg = CONTEXT_ENCRYPT_ALG;
51           keyBits = CONTEXT_ENCRYPT_KEY_BITS;
52       }
53       else
54       {
55           protector = ObjectGet(protectorHandle);
56           symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm;
57           keyBits= protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym;
58       }
59
60       // The IV size is a UINT16 size field plus the block size of the symmetric
61       // algorithm
62       return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits);
63   }


     7.6.2.3    ComputeProtectionKeyParms()

     This function retrieves the symmetric protection key parameters for the sensitive data The parameters
     retrieved from this function include encryption algorithm, key size in bit, and a TPM2B_SYM_KEY
     containing the key material as well as the key size in bytes This function is used for any action that
     requires encrypting or decrypting of the sensitive area of an object or a credential blob

64   static void
65   ComputeProtectionKeyParms(
66       TPM_HANDLE          protectorHandle,       //   IN: the protector handle
67       TPM_ALG_ID          hashAlg,               //   IN: hash algorithm for KDFa
68       TPM2B_NAME         *name,                  //   IN: name of the object
69       TPM2B_SEED         *seedIn,                //   IN: optional seed for duplication blob.
70                                                  //       For non duplication blob, this
71                                                  //       parameter should be NULL
72       TPM_ALG_ID         *symAlg,                //   OUT: the symmetric algorithm
73       UINT16             *keyBits,               //   OUT: the symmetric key size in bits
74       TPM2B_SYM_KEY      *symKey                 //   OUT: the symmetric key
75       )
76   {
77       TPM2B_SEED                *seed = NULL;
78       OBJECT                    *protector = NULL; // Pointer to the protector
79
80       // Determine the algorithms for the KDF and the encryption/decryption
81       // For TPM_RH_NULL, using context settings
82       if(protectorHandle == TPM_RH_NULL)
83       {
84           // Use the context encryption algorithm and key size
85           *symAlg = CONTEXT_ENCRYPT_ALG;
86           symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;
87           *keyBits = CONTEXT_ENCRYPT_KEY_BITS;
88       }
89       else
90       {
91           TPMT_SYM_DEF_OBJECT *symDef;
92           protector = ObjectGet(protectorHandle);
93           symDef = &protector->publicArea.parameters.asymDetail.symmetric;
94           *symAlg = symDef->algorithm;
95           *keyBits= symDef->keyBits.sym;
96           symKey->t.size = (*keyBits + 7) / 8;
97       }
98
99       // Get seed for KDF

     Family "2.0"                              TCG Published                                      Page 87
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                      October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

100       seed = GetSeedForKDF(protectorHandle, seedIn);
101
102       // KDFa to generate symmetric key and IV value
103       KDFa(hashAlg, (TPM2B *)seed, "STORAGE", (TPM2B *)name, NULL,
104            symKey->t.size * 8, symKey->t.buffer, NULL);
105
106       return;
107   }


      7.6.2.4     ComputeOuterIntegrity()

      The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaled
      sensitive area. The caller should skip over the area set aside for the integrity value and compute the hash
      of the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area
      contents is an array of bytes.

108   static void
109   ComputeOuterIntegrity(
110       TPM2B_NAME          *name,                   //   IN: the name of the object
111       TPM_HANDLE           protectorHandle,        //   IN: The handle of the object that
112                                                    //       provides protection. For object, it
113                                                    //       is parent handle. For credential, it
114                                                    //       is the handle of encrypt object. For
115                                                    //       a Temporary Object, it is TPM_RH_NULL
116       TPMI_ALG_HASH        hashAlg,                //   IN: algorithm to use for integrity
117       TPM2B_SEED          *seedIn,                 //   IN: an external seed may be provided for
118                                                    //       duplication blob. For non duplication
119                                                    //       blob, this parameter should be NULL
120       UINT32               sensitiveSize,          //   IN: size of the marshaled sensitive data
121       BYTE                *sensitiveData,          //   IN: sensitive area
122       TPM2B_DIGEST        *integrity               //   OUT: integrity
123       )
124   {
125       HMAC_STATE               hmacState;
126
127       TPM2B_DIGEST             hmacKey;
128       TPM2B_SEED               *seed = NULL;
129
130       // Get seed for KDF
131       seed = GetSeedForKDF(protectorHandle, seedIn);
132
133       // Determine the HMAC key bits
134       hmacKey.t.size = CryptGetHashDigestSize(hashAlg);
135
136       // KDFa to generate HMAC key
137       KDFa(hashAlg, (TPM2B *)seed, "INTEGRITY", NULL, NULL,
138            hmacKey.t.size * 8, hmacKey.t.buffer, NULL);
139
140       // Start HMAC and get the size of the digest which will become the integrity
141       integrity->t.size = CryptStartHMAC2B(hashAlg, &hmacKey.b, &hmacState);
142
143       // Adding the marshaled sensitive area to the integrity value
144       CryptUpdateDigest(&hmacState, sensitiveSize, sensitiveData);
145
146       // Adding name
147       CryptUpdateDigest2B(&hmacState, (TPM2B *)name);
148
149       // Compute HMAC
150       CryptCompleteHMAC2B(&hmacState, &integrity->b);
151
152       return;
153   }



      Page 88                                      TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      7.6.2.5     ComputeInnerIntegrity()

      This function computes the integrity of an inner wrap

154   static void
155   ComputeInnerIntegrity(
156        TPM_ALG_ID           hashAlg,           //   IN: hash algorithm for inner wrap
157        TPM2B_NAME          *name,              //   IN: the name of the object
158        UINT16               dataSize,          //   IN: the size of sensitive data
159        BYTE                *sensitiveData,     //   IN: sensitive data
160        TPM2B_DIGEST        *integrity          //   OUT: inner integrity
161        )
162   {
163        HASH_STATE          hashState;
164
165        // Start hash and get the size of the digest which will become the integrity
166        integrity->t.size = CryptStartHash(hashAlg, &hashState);
167
168        // Adding the marshaled sensitive area to the integrity value
169        CryptUpdateDigest(&hashState, dataSize, sensitiveData);
170
171        // Adding name
172        CryptUpdateDigest2B(&hashState, &name->b);
173
174        // Compute hash
175        CryptCompleteHash2B(&hashState, &integrity->b);
176
177        return;
178
179   }


      7.6.2.6     ProduceInnerIntegrity()

      This function produces an inner integrity for regular private, credential or duplication blob It requires the
      sensitive data being marshaled to the innerBuffer, with the leading bytes reserved for integrity hash. It
      assume the sensitive data starts at address (innerBuffer + integrity size). This function integrity at the
      beginning of the inner buffer It returns the total size of buffer with the inner wrap

180   static UINT16
181   ProduceInnerIntegrity(
182        TPM2B_NAME          *name,              //   IN: the name of the object
183        TPM_ALG_ID           hashAlg,           //   IN: hash algorithm for inner wrap
184        UINT16               dataSize,          //   IN: the size of sensitive data, excluding the
185                                                //       leading integrity buffer size
186        BYTE                *innerBuffer        //   IN/OUT: inner buffer with sensitive data in
187                                                //       it. At input, the leading bytes of this
188                                                //       buffer is reserved for integrity
189        )
190   {
191        BYTE                     *sensitiveData; // pointer to the sensitive data
192
193        TPM2B_DIGEST             integrity;
194        UINT16                   integritySize;
195        BYTE                     *buffer;             // Auxiliary buffer pointer
196
197        // sensitiveData points to the beginning of sensitive data in innerBuffer
198        integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
199        sensitiveData = innerBuffer + integritySize;
200
201        ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity);
202
203        // Add integrity at the beginning of inner buffer
204        buffer = innerBuffer;

      Family "2.0"                                 TCG Published                                         Page 89
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                   Part 4: Supporting Routines

205        TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
206
207        return dataSize + integritySize;
208   }


      7.6.2.7     CheckInnerIntegrity()

      This function check integrity of inner blob

      Error Returns                     Meaning

      TPM_RC_INTEGRITY                  if the outer blob integrity is bad
      unmarshal errors                  unmarshal errors while unmarshaling integrity

209   static TPM_RC
210   CheckInnerIntegrity(
211        TPM2B_NAME          *name,                //   IN: the name of the object
212        TPM_ALG_ID           hashAlg,             //   IN: hash algorithm for inner wrap
213        UINT16               dataSize,            //   IN: the size of sensitive data, including the
214                                                  //       leading integrity buffer size
215        BYTE                *innerBuffer          //   IN/OUT: inner buffer with sensitive data in
216                                                  //       it
217        )
218   {
219        TPM_RC              result;
220
221        TPM2B_DIGEST        integrity;
222        TPM2B_DIGEST        integrityToCompare;
223        BYTE                *buffer;                          // Auxiliary buffer pointer
224        INT32               size;
225
226        // Unmarshal integrity
227        buffer = innerBuffer;
228        size = (INT32) dataSize;
229        result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
230        if(result == TPM_RC_SUCCESS)
231        {
232            // Compute integrity to compare
233            ComputeInnerIntegrity(hashAlg, name, (UINT16) size, buffer,
234                                  &integrityToCompare);
235
236             // Compare outer blob integrity
237             if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
238                 result = TPM_RC_INTEGRITY;
239        }
240        return result;
241   }


      7.6.3     Public Functions

      7.6.3.1     AreAttributesForParent()

      This function is called by create, load, and import functions.

      Return Value                      Meaning

      TRUE                              properties are those of a parent
      FALSE                             properties are not those of a parent

242   BOOL

      Page 90                                         TCG Published                                   Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

243   AreAttributesForParent(
244       OBJECT             *parentObject        // IN: parent handle
245       )
246   {
247       // This function is only called when a parent is needed. Any
248       // time a "parent" is used, it must be authorized. When
249       // the authorization is checked, both the public and sensitive
250       // areas must be loaded. Just make sure...
251       pAssert(parentObject->attributes.publicOnly == CLEAR);
252
253       if(ObjectDataIsStorage(&parentObject->publicArea))
254           return TRUE;
255       else
256           return FALSE;
257   }


      7.6.3.2    SchemeChecks()

      This function validates the schemes in the public area of an object. This function is called by
      TPM2_LoadExternal() and PublicAttributesValidation().

      Error Returns                   Meaning

      TPM_RC_ASYMMETRIC               non-duplicable storage key and its parent have different public
                                      parameters
      TPM_RC_ATTRIBUTES               attempt to inject sensitive data for an asymmetric key; or attempt to
                                      create a symmetric cipher key that is not a decryption key
      TPM_RC_HASH                     non-duplicable storage key and its parent have different name
                                      algorithm
      TPM_RC_KDF                      incorrect KDF specified for decrypting keyed hash object
      TPM_RC_KEY                      invalid key size values in an asymmetric key public area
      TPM_RC_SCHEME                   inconsistent attributes decrypt, sign, restricted and key's scheme ID;
                                      or hash algorithm is inconsistent with the scheme ID for keyed hash
                                      object
      TPM_RC_SYMMETRIC                a storage key with no symmetric algorithm specified; or non-storage
                                      key with symmetric algorithm different from TPM_ALG_NULL
      TPM_RC_TYPE                     unexpected object type; or non-duplicable storage key and its parent
                                      have different types

258   TPM_RC
259   SchemeChecks(
260       BOOL                load,               // IN: TRUE if load checks, FALSE if
261                                               //     TPM2_Create()
262       TPMI_DH_OBJECT      parentHandle,       // IN: input parent handle
263       TPMT_PUBLIC        *publicArea          // IN: public area of the object
264       )
265   {
266
267       // Checks for an asymmetric key
268       if(CryptIsAsymAlgorithm(publicArea->type))
269       {
270           TPMT_ASYM_SCHEME        *keyScheme;
271           keyScheme = &publicArea->parameters.asymDetail.scheme;
272
273             // An asymmetric key can't be injected
274             // This is only checked when creating an object
275             if(!load && (publicArea->objectAttributes.sensitiveDataOrigin == CLEAR))
276                 return TPM_RC_ATTRIBUTES;
277

      Family "2.0"                                 TCG Published                                               Page 91
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                               October 30, 2014
      Trusted Platform Module Library                                    Part 4: Supporting Routines

278             if(load && !CryptAreKeySizesConsistent(publicArea))
279                 return TPM_RC_KEY;
280
281             // Keys that are both signing and decrypting must have TPM_ALG_NULL
282             // for scheme
283             if(     publicArea->objectAttributes.sign == SET
284                 && publicArea->objectAttributes.decrypt == SET
285                 && keyScheme->scheme != TPM_ALG_NULL)
286                  return TPM_RC_SCHEME;
287
288             // A restrict sign key must have a non-NULL scheme
289             if(     publicArea->objectAttributes.restricted == SET
290                 && publicArea->objectAttributes.sign == SET
291                 && keyScheme->scheme == TPM_ALG_NULL)
292                 return TPM_RC_SCHEME;
293
294             // Keys must have a valid sign or decrypt scheme, or a TPM_ALG_NULL
295             // scheme
296             // NOTE: The unmarshaling for a public area will unmarshal based on the
297             // object type. If the type is an RSA key, then only RSA schemes will be
298             // allowed because a TPMI_ALG_RSA_SCHEME will be unmarshaled and it
299             // consists only of those algorithms that are allowed with an RSA key.
300             // This means that there is no need to again make sure that the algorithm
301             // is compatible with the object type.
302             if(    keyScheme->scheme != TPM_ALG_NULL
303                 && (    (    publicArea->objectAttributes.sign == SET
304                           && !CryptIsSignScheme(keyScheme->scheme)
305                         )
306                      || (    publicArea->objectAttributes.decrypt == SET
307                           && !CryptIsDecryptScheme(keyScheme->scheme)
308                         )
309                    )
310               )
311                  return TPM_RC_SCHEME;
312
313           // Special checks for an ECC key
314   #ifdef TPM_ALG_ECC
315           if(publicArea->type == TPM_ALG_ECC)
316           {
317               TPM_ECC_CURVE        curveID = publicArea->parameters.eccDetail.curveID;
318               const TPMT_ECC_SCHEME *curveScheme = CryptGetCurveSignScheme(curveID);
319               // The curveId must be valid or the unmarshaling is busted.
320               pAssert(curveScheme != NULL);
321
322                 // If the curveID requires a specific scheme, then the key must select
323                 // the same scheme
324                 if(curveScheme->scheme != TPM_ALG_NULL)
325                 {
326                     if(keyScheme->scheme != curveScheme->scheme)
327                          return TPM_RC_SCHEME;
328                     // The scheme can allow any hash, or not...
329                     if(    curveScheme->details.anySig.hashAlg != TPM_ALG_NULL
330                         && (   keyScheme->details.anySig.hashAlg
331                             != curveScheme->details.anySig.hashAlg
332                            )
333                       )
334                          return TPM_RC_SCHEME;
335                 }
336                 // For now, the KDF must be TPM_ALG_NULL
337                 if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL)
338                     return TPM_RC_KDF;
339             }
340   #endif
341
342             // Checks for a storage key (restricted + decryption)
343             if(   publicArea->objectAttributes.restricted == SET

      Page 92                                TCG Published                             Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                      Trusted Platform Module Library

344                  && publicArea->objectAttributes.decrypt == SET)
345            {
346                  // A storage key must have a valid protection key
347                  if(    publicArea->parameters.asymDetail.symmetric.algorithm
348                      == TPM_ALG_NULL)
349                       return TPM_RC_SYMMETRIC;
350
351                  // A storage key must have a null scheme
352                  if(publicArea->parameters.asymDetail.scheme.scheme != TPM_ALG_NULL)
353                      return TPM_RC_SCHEME;
354
355                  // A storage key must match its parent algorithms unless
356                  // it is duplicable or a primary (including Temporary Primary Objects)
357                  if(    HandleGetType(parentHandle) != TPM_HT_PERMANENT
358                      && publicArea->objectAttributes.fixedParent == SET
359                    )
360                  {
361                       // If the object to be created is a storage key, and is fixedParent,
362                       // its crypto set has to match its parent's crypto set. TPM_RC_TYPE,
363                       // TPM_RC_HASH or TPM_RC_ASYMMETRIC may be returned at this point
364                       return EqualCryptSet(publicArea,
365                                            &(ObjectGet(parentHandle)->publicArea));
366                  }
367            }
368            else
369            {
370                  // Non-storage keys must have TPM_ALG_NULL for the symmetric algorithm
371                  if(    publicArea->parameters.asymDetail.symmetric.algorithm
372                      != TPM_ALG_NULL)
373                       return TPM_RC_SYMMETRIC;
374
375           }// End of asymmetric decryption key checks
376       } // End of asymmetric checks
377
378       // Check for bit attributes
379       else if(publicArea->type == TPM_ALG_KEYEDHASH)
380       {
381           TPMT_KEYEDHASH_SCHEME    *scheme
382               = &publicArea->parameters.keyedHashDetail.scheme;
383           // If both sign and decrypt are set the scheme must be TPM_ALG_NULL
384           // and the scheme selected when the key is used.
385           // If neither sign nor decrypt is set, the scheme must be TPM_ALG_NULL
386           // because this is a data object.
387           if(      publicArea->objectAttributes.sign
388               == publicArea->objectAttributes.decrypt)
389           {
390               if(scheme->scheme != TPM_ALG_NULL)
391                    return TPM_RC_SCHEME;
392               return TPM_RC_SUCCESS;
393           }
394           // If this is a decryption key, make sure that is is XOR and that there
395           // is a KDF
396           else if(publicArea->objectAttributes.decrypt)
397           {
398               if(    scheme->scheme != TPM_ALG_XOR
399                   || scheme->details.xor.hashAlg == TPM_ALG_NULL)
400                    return TPM_RC_SCHEME;
401               if(scheme->details.xor.kdf == TPM_ALG_NULL)
402                    return TPM_RC_KDF;
403               return TPM_RC_SUCCESS;
404
405            }
406            // only supported signing scheme for keyedHash object is HMAC
407            if(    scheme->scheme != TPM_ALG_HMAC
408                || scheme->details.hmac.hashAlg == TPM_ALG_NULL)
409                 return TPM_RC_SCHEME;

      Family "2.0"                            TCG Published                                  Page 93
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                                      Part 4: Supporting Routines

410
411             // end of the checks for keyedHash
412             return TPM_RC_SUCCESS;
413       }
414       else if (publicArea->type == TPM_ALG_SYMCIPHER)
415       {
416           // Must be a decrypting key and may not be a signing key
417           if(    publicArea->objectAttributes.decrypt == CLEAR
418               || publicArea->objectAttributes.sign == SET
419             )
420                return TPM_RC_ATTRIBUTES;
421       }
422       else
423           return TPM_RC_TYPE;
424
425       return TPM_RC_SUCCESS;
426   }


      7.6.3.3    PublicAttributesValidation()

      This function validates the values in the public area of an object. This function is called by
      TPM2_Create(), TPM2_Load(), and TPM2_CreatePrimary()

      Error Returns                     Meaning

      TPM_RC_ASYMMETRIC                 non-duplicable storage key and its parent have different public
                                        parameters
      TPM_RC_ATTRIBUTES                 fixedTPM, fixedParent, or encryptedDuplication attributes are
                                        inconsistent between themselves or with those of the parent object;
                                        inconsistent restricted, decrypt and sign attributes; attempt to inject
                                        sensitive data for an asymmetric key; attempt to create a symmetric
                                        cipher key that is not a decryption key
      TPM_RC_HASH                       non-duplicable storage key and its parent have different name
                                        algorithm
      TPM_RC_KDF                        incorrect KDF specified for decrypting keyed hash object
      TPM_RC_KEY                        invalid key size values in an asymmetric key public area
      TPM_RC_SCHEME                     inconsistent attributes decrypt, sign, restricted and key's scheme ID;
                                        or hash algorithm is inconsistent with the scheme ID for keyed hash
                                        object
      TPM_RC_SIZE                       authPolicy size does not match digest size of the name algorithm in
                                        publicArea
      TPM_RC_SYMMETRIC                  a storage key with no symmetric algorithm specified; or non-storage
                                        key with symmetric algorithm different from TPM_ALG_NULL
      TPM_RC_TYPE                       unexpected object type; or non-duplicable storage key and its parent
                                        have different types

427   TPM_RC
428   PublicAttributesValidation(
429       BOOL                load,                 // IN: TRUE if load checks, FALSE if
430                                                 //     TPM2_Create()
431       TPMI_DH_OBJECT      parentHandle,         // IN: input parent handle
432       TPMT_PUBLIC        *publicArea            // IN: public area of the object
433       )
434   {
435       OBJECT                  *parentObject = NULL;
436
437       if(HandleGetType(parentHandle) != TPM_HT_PERMANENT)
438           parentObject = ObjectGet(parentHandle);

      Page 94                                        TCG Published                                          Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

439
440        // Check authPolicy digest consistency
441        if(   publicArea->authPolicy.t.size != 0
442           && (    publicArea->authPolicy.t.size
443                != CryptGetHashDigestSize(publicArea->nameAlg)
444              )
445          )
446            return TPM_RC_SIZE;
447
448        // If the parent is fixedTPM (including a Primary Object) the object must have
449        // the same value for fixedTPM and fixedParent
450        if(     parentObject == NULL
451            || parentObject->publicArea.objectAttributes.fixedTPM == SET)
452        {
453            if(    publicArea->objectAttributes.fixedParent
454                != publicArea->objectAttributes.fixedTPM
455              )
456                 return TPM_RC_ATTRIBUTES;
457        }
458        else
459            // The parent is not fixedTPM so the object can't be fixedTPM
460            if(publicArea->objectAttributes.fixedTPM == SET)
461                 return TPM_RC_ATTRIBUTES;
462
463        // A restricted object cannot be both sign and decrypt and it can't be neither
464        // sign nor decrypt
465        if (    publicArea->objectAttributes.restricted == SET
466             && (    publicArea->objectAttributes.decrypt
467                  == publicArea->objectAttributes.sign)
468           )
469             return TPM_RC_ATTRIBUTES;
470
471        // A fixedTPM object can not have encryptedDuplication bit SET
472        if(    publicArea->objectAttributes.fixedTPM == SET
473            && publicArea->objectAttributes.encryptedDuplication == SET)
474            return TPM_RC_ATTRIBUTES;
475
476        // If a parent object has fixedTPM CLEAR, the child must have the
477        // same encryptedDuplication value as its parent.
478        // Primary objects are considered to have a fixedTPM parent (the seeds).
479       if(       (   parentObject != NULL
480                  && parentObject->publicArea.objectAttributes.fixedTPM == CLEAR)
481           // Get here if parent is not fixed TPM
482           && (     publicArea->objectAttributes.encryptedDuplication
483                 != parentObject->publicArea.objectAttributes.encryptedDuplication
484               )
485          )
486            return TPM_RC_ATTRIBUTES;
487
488       return SchemeChecks(load, parentHandle, publicArea);
489   }


      7.6.3.4      FillInCreationData()

      Fill in creation data for an object.

490   void
491   FillInCreationData(
492        TPMI_DH_OBJECT                     parentHandle,    //   IN: handle of parent
493        TPMI_ALG_HASH                      nameHashAlg,     //   IN: name hash algorithm
494        TPML_PCR_SELECTION                *creationPCR,     //   IN: PCR selection
495        TPM2B_DATA                        *outsideData,     //   IN: outside data
496        TPM2B_CREATION_DATA               *outCreation,     //   OUT: creation data for output
497        TPM2B_DIGEST                      *creationDigest   //   OUT: creation digest


      Family "2.0"                                   TCG Published                                     Page 95
      Level 00 Revision 01.16                  Copyright © TCG 2006-2014                     October 30, 2014
      Trusted Platform Module Library                                    Part 4: Supporting Routines

498       )
499   {
500       BYTE                     creationBuffer[sizeof(TPMS_CREATION_DATA)];
501       BYTE                    *buffer;
502       HASH_STATE               hashState;
503
504       // Fill in TPMS_CREATION_DATA in outCreation
505
506       // Compute PCR digest
507       PCRComputeCurrentDigest(nameHashAlg, creationPCR,
508                               &outCreation->t.creationData.pcrDigest);
509
510       // Put back PCR selection list
511       outCreation->t.creationData.pcrSelect = *creationPCR;
512
513       // Get locality
514       outCreation->t.creationData.locality
515           = LocalityGetAttributes(_plat__LocalityGet());
516
517       outCreation->t.creationData.parentNameAlg = TPM_ALG_NULL;
518
519       // If the parent is is either a primary seed or TPM_ALG_NULL, then the Name
520       // and QN of the parent are the parent's handle.
521       if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
522       {
523           BYTE         *buffer = &outCreation->t.creationData.parentName.t.name[0];
524           outCreation->t.creationData.parentName.t.size =
525                TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL);
526
527             // Parent qualified name of a Temporary Object is the same as parent's
528             // name
529             MemoryCopy2B(&outCreation->t.creationData.parentQualifiedName.b,
530                          &outCreation->t.creationData.parentName.b,
531                         sizeof(outCreation->t.creationData.parentQualifiedName.t.name));
532
533       }
534       else           // Regular object
535       {
536           OBJECT              *parentObject = ObjectGet(parentHandle);
537
538             // Set name algorithm
539             outCreation->t.creationData.parentNameAlg =
540                 parentObject->publicArea.nameAlg;
541             // Copy parent name
542             outCreation->t.creationData.parentName = parentObject->name;
543
544             // Copy parent qualified name
545             outCreation->t.creationData.parentQualifiedName =
546                 parentObject->qualifiedName;
547       }
548
549       // Copy outside information
550       outCreation->t.creationData.outsideInfo = *outsideData;
551
552       // Marshal creation data to canonical form
553       buffer = creationBuffer;
554       outCreation->t.size = TPMS_CREATION_DATA_Marshal(&outCreation->t.creationData,
555                             &buffer, NULL);
556
557       // Compute hash for creation field in public template
558       creationDigest->t.size = CryptStartHash(nameHashAlg, &hashState);
559       CryptUpdateDigest(&hashState, outCreation->t.size, creationBuffer);
560       CryptCompleteHash2B(&hashState, &creationDigest->b);
561
562       return;
563   }

      Page 96                                 TCG Published                             Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      7.6.3.5     GetSeedForKDF()

      Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. It returns a pointer to
      the seed

564   TPM2B_SEED*
565   GetSeedForKDF(
566        TPM_HANDLE           protectorHandle,          // IN: the protector handle
567        TPM2B_SEED          *seedIn                    // IN: the optional input seed
568        )
569   {
570        OBJECT                   *protector = NULL; // Pointer to the protector
571
572        // Get seed for encryption key. Use input seed if provided.
573        // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only
574        // exception that we may not have a loaded object as protector. In such a
575        // case, use nullProof as seed.
576        if(seedIn != NULL)
577        {
578            return seedIn;
579        }
580        else
581        {
582            if(protectorHandle == TPM_RH_NULL)
583            {
584                 return (TPM2B_SEED *) &gr.nullProof;
585            }
586            else
587            {
588                 protector = ObjectGet(protectorHandle);
589                 return (TPM2B_SEED *) &protector->sensitive.seedValue;
590            }
591        }
592   }


      7.6.3.6     ProduceOuterWrap()

      This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data
      being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv
      space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address
      (outerBuffer + integrity size {+ iv size}). This function performs:
      a) Add IV before sensitive area if required
      b) encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv
      c) add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap

593   UINT16
594   ProduceOuterWrap(
595        TPM_HANDLE           protector,          //   IN: The handle of the object that provides
596                                                 //       protection. For object, it is parent
597                                                 //       handle. For credential, it is the handle
598                                                 //       of encrypt object.
599        TPM2B_NAME          *name,               //   IN: the name of the object
600        TPM_ALG_ID           hashAlg,            //   IN: hash algorithm for outer wrap
601        TPM2B_SEED          *seed,               //   IN: an external seed may be provided for
602                                                 //       duplication blob. For non duplication
603                                                 //       blob, this parameter should be NULL
604        BOOL                 useIV,              //   IN: indicate if an IV is used
605        UINT16               dataSize,           //   IN: the size of sensitive data, excluding the
606                                                 //       leading integrity buffer size or the
607                                                 //       optional iv size
608        BYTE                *outerBuffer         //   IN/OUT: outer buffer with sensitive data in

      Family "2.0"                                  TCG Published                                        Page 97
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

609                                           //     it
610       )
611   {
612       TPM_ALG_ID         symAlg;
613       UINT16             keyBits;
614       TPM2B_SYM_KEY      symKey;
615       TPM2B_IV           ivRNG;           // IV from RNG
616       TPM2B_IV           *iv = NULL;
617       UINT16             ivSize = 0;      // size of iv area, including the size field
618
619       BYTE               *sensitiveData; // pointer to the sensitive data
620
621       TPM2B_DIGEST       integrity;
622       UINT16             integritySize;
623       BYTE               *buffer;         // Auxiliary buffer pointer
624
625       // Compute the beginning of sensitive data. The outer integrity should
626       // always exist if this function function is called to make an outer wrap
627       integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
628       sensitiveData = outerBuffer + integritySize;
629
630       // If iv is used, adjust the pointer of sensitive data and add iv before it
631       if(useIV)
632       {
633           ivSize = GetIV2BSize(protector);
634
635             // Generate IV from RNG. The iv data size should be the total IV area
636             // size minus the size of size field
637             ivRNG.t.size = ivSize - sizeof(UINT16);
638             CryptGenerateRandom(ivRNG.t.size, ivRNG.t.buffer);
639
640             // Marshal IV to buffer
641             buffer = sensitiveData;
642             TPM2B_IV_Marshal(&ivRNG, &buffer, NULL);
643
644             // adjust sensitive data starting after IV area
645             sensitiveData += ivSize;
646
647             // Use iv for encryption
648             iv = &ivRNG;
649       }
650
651       // Compute symmetric key parameters for outer buffer encryption
652       ComputeProtectionKeyParms(protector, hashAlg, name, seed,
653                                 &symAlg, &keyBits, &symKey);
654       // Encrypt inner buffer in place
655       CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits,
656                             TPM_ALG_CFB, symKey.t.buffer, iv, dataSize,
657                             sensitiveData);
658
659       // Compute outer integrity. Integrity computation includes the optional IV
660       // area
661       ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize,
662                             outerBuffer + integritySize, &integrity);
663
664       // Add integrity at the beginning of outer buffer
665       buffer = outerBuffer;
666       TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
667
668       // return the total size in outer wrap
669       return dataSize + integritySize + ivSize;
670
671   }




      Page 98                                 TCG Published                               Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                                     Trusted Platform Module Library

      7.6.3.7     UnwrapOuter()

      This function remove the outer wrap of a blob containing sensitive data This function performs:
      a) check integrity of outer blob
      b) decrypt outer blob

      Error Returns                      Meaning

      TPM_RC_INSUFFICIENT                error during sensitive data unmarshaling
      TPM_RC_INTEGRITY                   sensitive data integrity is broken
      TPM_RC_SIZE                        error during sensitive data unmarshaling
      TPM_RC_VALUE                       IV size for CFB does not match the encryption algorithm block size

672   TPM_RC
673   UnwrapOuter(
674       TPM_HANDLE           protector,             //   IN: The handle of the object that provides
675                                                   //       protection. For object, it is parent
676                                                   //       handle. For credential, it is the handle
677                                                   //       of encrypt object.
678       TPM2B_NAME          *name,                  //   IN: the name of the object
679       TPM_ALG_ID           hashAlg,               //   IN: hash algorithm for outer wrap
680       TPM2B_SEED          *seed,                  //   IN: an external seed may be provided for
681                                                   //       duplication blob. For non duplication
682                                                   //       blob, this parameter should be NULL.
683       BOOL                 useIV,                 //   IN: indicates if an IV is used
684       UINT16               dataSize,              //   IN: size of sensitive data in outerBuffer,
685                                                   //       including the leading integrity buffer
686                                                   //       size, and an optional iv area
687       BYTE                *outerBuffer            //   IN/OUT: sensitive data
688       )
689   {
690       TPM_RC              result;
691       TPM_ALG_ID          symAlg = TPM_ALG_NULL;
692       TPM2B_SYM_KEY       symKey;
693       UINT16              keyBits = 0;
694       TPM2B_IV            ivIn;               // input IV retrieved from input buffer
695       TPM2B_IV            *iv = NULL;
696
697       BYTE                *sensitiveData;               // pointer to the sensitive data
698
699       TPM2B_DIGEST        integrityToCompare;
700       TPM2B_DIGEST        integrity;
701       INT32               size;
702
703       // Unmarshal integrity
704       sensitiveData = outerBuffer;
705       size = (INT32) dataSize;
706       result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size);
707       if(result == TPM_RC_SUCCESS)
708       {
709           // Compute integrity to compare
710           ComputeOuterIntegrity(name, protector, hashAlg, seed,
711                                 (UINT16) size, sensitiveData,
712                                 &integrityToCompare);
713
714             // Compare outer blob integrity
715             if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
716                 return TPM_RC_INTEGRITY;
717
718             // Get the symmetric algorithm parameters used for encryption
719             ComputeProtectionKeyParms(protector, hashAlg, name, seed,

      Family "2.0"                                    TCG Published                                           Page 99
      Level 00 Revision 01.16                 Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

720                                              &symAlg, &keyBits, &symKey);
721
722             // Retrieve IV if it is used
723             if(useIV)
724             {
725                 result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size);
726                 if(result == TPM_RC_SUCCESS)
727                 {
728                     // The input iv size for CFB must match the encryption algorithm
729                     // block size
730                     if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits))
731                         result = TPM_RC_VALUE;
732                     else
733                         iv = &ivIn;
734                 }
735             }
736        }
737        // If no errors, decrypt private in place
738        if(result == TPM_RC_SUCCESS)
739            CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits,
740                                  TPM_ALG_CFB, symKey.t.buffer, iv,
741                                  (UINT16) size, sensitiveData);
742
743        return result;
744
745   }


      7.6.3.8     SensitiveToPrivate()

      This function prepare the private blob for off the chip storage The operations in this function:
      a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE
      b) apply encryption to the sensitive area.
      c) apply outer integrity computation.

746   void
747   SensitiveToPrivate(
748        TPMT_SENSITIVE      *sensitive,         //   IN: sensitive structure
749        TPM2B_NAME          *name,              //   IN: the name of the object
750        TPM_HANDLE           parentHandle,      //   IN: The parent's handle
751        TPM_ALG_ID           nameAlg,           //   IN: hash algorithm in public area. This
752                                                //       parameter is used when parentHandle is
753                                                //       NULL, in which case the object is
754                                                //       temporary.
755        TPM2B_PRIVATE       *outPrivate         //   OUT: output private structure
756        )
757   {
758        BYTE                     *buffer;                  //   Auxiliary buffer pointer
759        BYTE                     *sensitiveData;           //   pointer to the sensitive data
760        UINT16                   dataSize;                 //   data blob size
761        TPMI_ALG_HASH            hashAlg;                  //   hash algorithm for integrity
762        UINT16                   integritySize;
763        UINT16                   ivSize;
764
765        pAssert(name != NULL && name->t.size != 0);
766
767        // Find the hash algorithm for integrity computation
768        if(parentHandle == TPM_RH_NULL)
769        {
770            // For Temporary Object, using self name algorithm
771            hashAlg = nameAlg;
772        }
773        else

      Page 100                                      TCG Published                                        Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

774       {
775             // Otherwise, using parent's name algorithm
776             hashAlg = ObjectGetNameAlg(parentHandle);
777       }
778
779       // Starting of sensitive data without wrappers
780       sensitiveData = outPrivate->t.buffer;
781
782       // Compute the integrity size
783       integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
784
785       // Reserve space for integrity
786       sensitiveData += integritySize;
787
788       // Get iv size
789       ivSize = GetIV2BSize(parentHandle);
790
791       // Reserve space for iv
792       sensitiveData += ivSize;
793
794       // Marshal sensitive area, leaving the leading 2 bytes for size
795       buffer = sensitiveData + sizeof(UINT16);
796       dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL);
797
798       // Adding size before the data area
799       buffer = sensitiveData;
800       UINT16_Marshal(&dataSize, &buffer, NULL);
801
802       // Adjust the dataSize to include the size field
803       dataSize += sizeof(UINT16);
804
805       // Adjust the pointer to inner buffer including the iv
806       sensitiveData = outPrivate->t.buffer + ivSize;
807
808       //Produce outer wrap, including encryption and HMAC
809       outPrivate->t.size = ProduceOuterWrap(parentHandle, name, hashAlg, NULL,
810                                             TRUE, dataSize, outPrivate->t.buffer);
811
812       return;
813   }


      7.6.3.9     PrivateToSensitive()

      Unwrap a input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The
      operations in this function:
      a) check the integrity HMAC of the input private area
      b) decrypt the private buffer
      c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE

      Error Returns                   Meaning

      TPM_RC_INTEGRITY                if the private area integrity is bad
      TPM_RC_SENSITIVE                unmarshal errors while unmarshaling TPMS_ENCRYPT from input
                                      private
      TPM_RC_VALUE                    outer wrapper does not have an iV of the correct size

814   TPM_RC
815   PrivateToSensitive(
816       TPM2B_PRIVATE       *inPrivate,          // IN: input private structure
817       TPM2B_NAME          *name,               // IN: the name of the object

      Family "2.0"                                  TCG Published                                       Page 101
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                     Part 4: Supporting Routines

818       TPM_HANDLE          parentHandle,    // IN: The parent's handle
819       TPM_ALG_ID          nameAlg,         // IN: hash algorithm in public area. It is
820                                            //     passed separately because we only pass
821                                            //     name, rather than the whole public area
822                                            //     of the object. This parameter is used in
823                                            //     the following two cases: 1. primary
824                                            //     objects. 2. duplication blob with inner
825                                            //     wrap. In other cases, this parameter
826                                            //     will be ignored
827       TPMT_SENSITIVE     *sensitive        // OUT: sensitive structure
828       )
829   {
830       TPM_RC             result;
831
832       BYTE               *buffer;
833       INT32              size;
834       BYTE               *sensitiveData; // pointer to the sensitive data
835       UINT16             dataSize;
836       UINT16             dataSizeInput;
837       TPMI_ALG_HASH      hashAlg;        // hash algorithm for integrity
838       OBJECT             *parent = NULL;
839
840       UINT16             integritySize;
841       UINT16             ivSize;
842
843       // Make sure that name is provided
844       pAssert(name != NULL && name->t.size != 0);
845
846       // Find the hash algorithm for integrity computation
847       if(parentHandle == TPM_RH_NULL)
848       {
849           // For Temporary Object, using self name algorithm
850           hashAlg = nameAlg;
851       }
852       else
853       {
854           // Otherwise, using parent's name algorithm
855           hashAlg = ObjectGetNameAlg(parentHandle);
856       }
857
858       // unwrap outer
859       result = UnwrapOuter(parentHandle, name, hashAlg, NULL, TRUE,
860                            inPrivate->t.size, inPrivate->t.buffer);
861       if(result != TPM_RC_SUCCESS)
862           return result;
863
864       // Compute the inner integrity size.
865       integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
866
867       // Get iv size
868       ivSize = GetIV2BSize(parentHandle);
869
870       // The starting of sensitive data and data size without outer wrapper
871       sensitiveData = inPrivate->t.buffer + integritySize + ivSize;
872       dataSize = inPrivate->t.size - integritySize - ivSize;
873
874       // Unmarshal input data size
875       buffer = sensitiveData;
876       size = (INT32) dataSize;
877       result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);
878       if(result == TPM_RC_SUCCESS)
879       {
880           if((dataSizeInput + sizeof(UINT16)) != dataSize)
881                result = TPM_RC_SENSITIVE;
882           else
883           {

      Page 102                                 TCG Published                            Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014        Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

884                  // Unmarshal sensitive buffer to sensitive structure
885                  result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);
886                  if(result != TPM_RC_SUCCESS || size != 0)
887                  {
888                      pAssert(    (parent == NULL)
889                               || parent->publicArea.objectAttributes.fixedTPM == CLEAR);
890                      result = TPM_RC_SENSITIVE;
891                  }
892                  else
893                  {
894                      // Always remove trailing zeros at load so that it is not necessary
895                      // to check
896                      // each time auth is checked.
897                      MemoryRemoveTrailingZeros(&(sensitive->authValue));
898                  }
899            }
900        }
901        return result;
902   }


      7.6.3.10    SensitiveToDuplicate()

      This function prepare the duplication blob from the sensitive area. The operations in this function:
      a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE
      b) apply inner wrap to the sensitive area if required
      c) apply outer wrap if required

903   void
904   SensitiveToDuplicate(
905        TPMT_SENSITIVE                *sensitive,          //   IN: sensitive structure
906        TPM2B_NAME                    *name,               //   IN: the name of the object
907        TPM_HANDLE                     parentHandle,       //   IN: The new parent's handle
908        TPM_ALG_ID                     nameAlg,            //   IN: hash algorithm in public area. It
909                                                           //       is passed separately because we
910                                                           //       only pass name, rather than the
911                                                           //       whole public area of the object.
912        TPM2B_SEED                    *seed,               //   IN: the external seed. If external
913                                                           //       seed is provided with size of 0,
914                                                           //       no outer wrap should be applied
915                                                           //       to duplication blob.
916        TPMT_SYM_DEF_OBJECT           *symDef,             //   IN: Symmetric key definition. If the
917                                                           //       symmetric key algorithm is NULL,
918                                                           //       no inner wrap should be applied.
919        TPM2B_DATA                    *innerSymKey,        //   IN/OUT: a symmetric key may be
920                                                           //       provided to encrypt the inner
921                                                           //       wrap of a duplication blob. May
922                                                           //       be generated here if needed.
923        TPM2B_PRIVATE                 *outPrivate          //   OUT: output private structure
924        )
925   {
926        BYTE                *buffer;        // Auxiliary buffer pointer
927        BYTE                *sensitiveData; // pointer to the sensitive data
928        TPMI_ALG_HASH       outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap
929        TPMI_ALG_HASH       innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap
930        UINT16              dataSize;       // data blob size
931        BOOL                doInnerWrap = FALSE;
932        BOOL                doOuterWrap = FALSE;
933
934        // Make sure that name is provided
935        pAssert(name != NULL && name->t.size != 0);
936
937        // Make sure symDef and innerSymKey are not NULL

      Family "2.0"                                  TCG Published                                       Page 103
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
       Trusted Platform Module Library                                   Part 4: Supporting Routines

 938       pAssert(symDef != NULL && innerSymKey != NULL);
 939
 940       // Starting of sensitive data without wrappers
 941       sensitiveData = outPrivate->t.buffer;
 942
 943       // Find out if inner wrap is required
 944       if(symDef->algorithm != TPM_ALG_NULL)
 945       {
 946           doInnerWrap = TRUE;
 947           // Use self nameAlg as inner hash algorithm
 948           innerHash = nameAlg;
 949           // Adjust sensitive data pointer
 950           sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash);
 951       }
 952
 953       // Find out if outer wrap is required
 954       if(seed->t.size != 0)
 955       {
 956           doOuterWrap = TRUE;
 957           // Use parent nameAlg as outer hash algorithm
 958           outerHash = ObjectGetNameAlg(parentHandle);
 959           // Adjust sensitive data pointer
 960           sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
 961       }
 962
 963       // Marshal sensitive area, leaving the leading 2 bytes for size
 964       buffer = sensitiveData + sizeof(UINT16);
 965       dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL);
 966
 967       // Adding size before the data area
 968       buffer = sensitiveData;
 969       UINT16_Marshal(&dataSize, &buffer, NULL);
 970
 971       // Adjust the dataSize to include the size field
 972       dataSize += sizeof(UINT16);
 973
 974       // Apply inner wrap for duplication blob. It includes both integrity and
 975       // encryption
 976       if(doInnerWrap)
 977       {
 978           BYTE             *innerBuffer = NULL;
 979           BOOL             symKeyInput = TRUE;
 980           innerBuffer = outPrivate->t.buffer;
 981           // Skip outer integrity space
 982           if(doOuterWrap)
 983                innerBuffer += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
 984           dataSize = ProduceInnerIntegrity(name, innerHash, dataSize,
 985                                             innerBuffer);
 986
 987            // Generate inner encryption key if needed
 988            if(innerSymKey->t.size == 0)
 989            {
 990                innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8;
 991                CryptGenerateRandom(innerSymKey->t.size, innerSymKey->t.buffer);
 992
 993                 // TPM generates symmetric encryption.   Set the flag to FALSE
 994                 symKeyInput = FALSE;
 995            }
 996            else
 997            {
 998                 // assume the input key size should matches the symmetric definition
 999                 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);
1000
1001            }
1002
1003            // Encrypt inner buffer in place

       Page 104                               TCG Published                            Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                                  Trusted Platform Module Library

1004              CryptSymmetricEncrypt(innerBuffer, symDef->algorithm,
1005                                    symDef->keyBits.sym, TPM_ALG_CFB,
1006                                    innerSymKey->t.buffer, NULL, dataSize,
1007                                    innerBuffer);
1008
1009              // If the symmetric encryption key is imported, clear the buffer for
1010              // output
1011              if(symKeyInput)
1012                  innerSymKey->t.size = 0;
1013       }
1014
1015       // Apply outer wrap for duplication blob. It includes both integrity and
1016       // encryption
1017       if(doOuterWrap)
1018       {
1019           dataSize = ProduceOuterWrap(parentHandle, name, outerHash, seed, FALSE,
1020                                       dataSize, outPrivate->t.buffer);
1021       }
1022
1023       // Data size for output
1024       outPrivate->t.size = dataSize;
1025
1026       return;
1027   }


       7.6.3.11    DuplicateToSensitive()

       Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The
       operations in this function:
       a) check the integrity HMAC of the input private area
       b) decrypt the private buffer
       c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE

       Error Returns                   Meaning

       TPM_RC_INSUFFICIENT             unmarshaling sensitive data from inPrivate failed
       TPM_RC_INTEGRITY                inPrivate data integrity is broken
       TPM_RC_SIZE                     unmarshaling sensitive data from inPrivate failed

1028   TPM_RC
1029   DuplicateToSensitive(
1030       TPM2B_PRIVATE                 *inPrivate,           //   IN: input private structure
1031       TPM2B_NAME                    *name,                //   IN: the name of the object
1032       TPM_HANDLE                     parentHandle,        //   IN: The parent's handle
1033       TPM_ALG_ID                     nameAlg,             //   IN: hash algorithm in public area.
1034       TPM2B_SEED                    *seed,                //   IN: an external seed may be provided.
1035                                                           //       If external seed is provided with
1036                                                           //       size of 0, no outer wrap is
1037                                                           //       applied
1038       TPMT_SYM_DEF_OBJECT           *symDef,              //   IN: Symmetric key definition. If the
1039                                                           //       symmetric key algorithm is NULL,
1040                                                           //       no inner wrap is applied
1041       TPM2B_DATA                    *innerSymKey,         //   IN: a symmetric key may be provided
1042                                                           //       to decrypt the inner wrap of a
1043                                                           //       duplication blob.
1044       TPMT_SENSITIVE                *sensitive            //   OUT: sensitive structure
1045       )
1046   {
1047       TPM_RC              result;
1048

       Family "2.0"                                 TCG Published                                        Page 105
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
       Trusted Platform Module Library                                   Part 4: Supporting Routines

1049       BYTE               *buffer;
1050       INT32              size;
1051       BYTE               *sensitiveData; // pointer to the sensitive data
1052       UINT16             dataSize;
1053       UINT16             dataSizeInput;
1054
1055       // Make sure that name is provided
1056       pAssert(name != NULL && name->t.size != 0);
1057
1058       // Make sure symDef and innerSymKey are not NULL
1059       pAssert(symDef != NULL && innerSymKey != NULL);
1060
1061       // Starting of sensitive data
1062       sensitiveData = inPrivate->t.buffer;
1063       dataSize = inPrivate->t.size;
1064
1065       // Find out if outer wrap is applied
1066       if(seed->t.size != 0)
1067       {
1068           TPMI_ALG_HASH   outerHash = TPM_ALG_NULL;
1069
1070            // Use parent nameAlg as outer hash algorithm
1071            outerHash = ObjectGetNameAlg(parentHandle);
1072            result = UnwrapOuter(parentHandle, name, outerHash, seed, FALSE,
1073                                 dataSize, sensitiveData);
1074            if(result != TPM_RC_SUCCESS)
1075                return result;
1076
1077            // Adjust sensitive data pointer and size
1078            sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
1079            dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
1080       }
1081       // Find out if inner wrap is applied
1082       if(symDef->algorithm != TPM_ALG_NULL)
1083       {
1084           TPMI_ALG_HASH   innerHash = TPM_ALG_NULL;
1085
1086            // assume the input key size should matches the symmetric definition
1087            pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);
1088
1089            // Decrypt inner buffer in place
1090            CryptSymmetricDecrypt(sensitiveData, symDef->algorithm,
1091                                  symDef->keyBits.sym, TPM_ALG_CFB,
1092                                  innerSymKey->t.buffer, NULL, dataSize,
1093                                  sensitiveData);
1094
1095            // Use self nameAlg as inner hash algorithm
1096            innerHash = nameAlg;
1097
1098            // Check inner integrity
1099            result = CheckInnerIntegrity(name, innerHash, dataSize, sensitiveData);
1100            if(result != TPM_RC_SUCCESS)
1101                return result;
1102
1103            // Adjust sensitive data pointer and size
1104            sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash);
1105            dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(innerHash);
1106       }
1107
1108       // Unmarshal input data size
1109       buffer = sensitiveData;
1110       size = (INT32) dataSize;
1111       result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);
1112       if(result == TPM_RC_SUCCESS)
1113       {
1114           if((dataSizeInput + sizeof(UINT16)) != dataSize)

       Page 106                               TCG Published                            Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                                Trusted Platform Module Library

1115                  result = TPM_RC_SIZE;
1116              else
1117              {
1118                  // Unmarshal sensitive buffer to sensitive structure
1119                  result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);
1120                  // if the results is OK make sure that all the data was unmarshaled
1121                  if(result == TPM_RC_SUCCESS && size != 0)
1122                      result = TPM_RC_SIZE;
1123           }
1124       }
1125       // Always remove trailing zeros at load so that it is not necessary to check
1126       // each time auth is checked.
1127       if(result == TPM_RC_SUCCESS)
1128           MemoryRemoveTrailingZeros(&(sensitive->authValue));
1129       return result;
1130   }


       7.6.3.12    SecretToCredential()

       This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this
       function:
       a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT
       b) encrypt the private buffer, excluding the leading integrity HMAC area
       c) compute integrity HMAC and append to the beginning of the buffer.
       d) Set the total size of TPM2B_ID_OBJECT buffer

1131   void
1132   SecretToCredential(
1133       TPM2B_DIGEST              *secret,          //   IN: secret information
1134       TPM2B_NAME                *name,            //   IN: the name of the object
1135       TPM2B_SEED                *seed,            //   IN: an external seed.
1136       TPM_HANDLE                 protector,       //   IN: The protector's handle
1137       TPM2B_ID_OBJECT           *outIDObject      //   OUT: output credential
1138       )
1139   {
1140       BYTE                      *buffer;          //   Auxiliary buffer pointer
1141       BYTE                      *sensitiveData;   //   pointer to the sensitive data
1142       TPMI_ALG_HASH              outerHash;       //   The hash algorithm for outer wrap
1143       UINT16                     dataSize;        //   data blob size
1144
1145       pAssert(secret != NULL && outIDObject != NULL);
1146
1147       // use protector's name algorithm as outer hash
1148       outerHash = ObjectGetNameAlg(protector);
1149
1150       // Marshal secret area to credential buffer, leave space for integrity
1151       sensitiveData = outIDObject->t.credential
1152                       + sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
1153
1154       // Marshal secret area
1155       buffer = sensitiveData;
1156       dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL);
1157
1158       // Apply outer wrap
1159       outIDObject->t.size = ProduceOuterWrap(protector,
1160                                              name,
1161                                              outerHash,
1162                                              seed,
1163                                              FALSE,
1164                                              dataSize,
1165                                              outIDObject->t.credential);

       Family "2.0"                                 TCG Published                                      Page 107
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                          October 30, 2014
       Trusted Platform Module Library                                                      Part 4: Supporting Routines

1166       return;
1167   }


       7.6.3.13     CredentialToSecret()

       Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The
       operations in this function:
       a) check the integrity HMAC of the input credential area
       b) decrypt the credential buffer
       c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST

       Error Returns                      Meaning

       TPM_RC_INSUFFICIENT                error during credential unmarshaling
       TPM_RC_INTEGRITY                   credential integrity is broken
       TPM_RC_SIZE                        error during credential unmarshaling
       TPM_RC_VALUE                       IV size does not match the encryption algorithm block size

1168   TPM_RC
1169   CredentialToSecret(
1170       TPM2B_ID_OBJECT          *inIDObject,             //   IN: input credential blob
1171       TPM2B_NAME               *name,                   //   IN: the name of the object
1172       TPM2B_SEED               *seed,                   //   IN: an external seed.
1173       TPM_HANDLE                protector,              //   IN: The protector's handle
1174       TPM2B_DIGEST             *secret                  //   OUT: secret information
1175       )
1176   {
1177       TPM_RC                           result;
1178       BYTE                            *buffer;
1179       INT32                            size;
1180       TPMI_ALG_HASH                    outerHash;     // The hash algorithm for outer wrap
1181       BYTE                            *sensitiveData; // pointer to the sensitive data
1182       UINT16                           dataSize;
1183
1184       // use protector's name algorithm as outer hash
1185       outerHash = ObjectGetNameAlg(protector);
1186
1187       // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point
1188       result = UnwrapOuter(protector, name, outerHash, seed, FALSE,
1189                            inIDObject->t.size, inIDObject->t.credential);
1190       if(result == TPM_RC_SUCCESS)
1191       {
1192           // Compute the beginning of sensitive data
1193           sensitiveData = inIDObject->t.credential
1194                           + sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
1195           dataSize = inIDObject->t.size
1196                      - (sizeof(UINT16) + CryptGetHashDigestSize(outerHash));
1197
1198              // Unmarshal secret buffer to TPM2B_DIGEST structure
1199              buffer = sensitiveData;
1200              size = (INT32) dataSize;
1201              result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size);
1202              // If there were no other unmarshaling errors, make sure that the
1203              // expected amount of data was recovered
1204              if(result == TPM_RC_SUCCESS && size != 0)
1205                  return TPM_RC_SIZE;
1206       }
1207       return result;
1208   }


       Page 108                                         TCG Published                                     Family "2.0"
       October 30, 2014                        Copyright © TCG 2006-2014                      Level 00 Revision 01.16
     Part 4: Supporting Routines                                                 Trusted Platform Module Library


     8     Subsystem

     8.1       CommandAudit.c

     8.1.1      Introduction

     This file contains the functions that support command audit.

     8.1.2      Includes

 1   #include "InternalRoutines.h"


     8.1.3      Functions

     8.1.3.1      CommandAuditPreInstall_Init()

     This function initializes the command audit list. This function is simulates the behavior of manufacturing. A
     function is used instead of a structure definition because this is easier than figuring out the initialization
     value for a bit array.
     This function would not be implemented outside of a manufacturing or simulation environment.

 2   void
 3   CommandAuditPreInstall_Init(
 4         void
 5         )
 6   {
 7         // Clear all the audit commands
 8         MemorySet(gp.auditComands, 0x00,
 9                   ((TPM_CC_LAST - TPM_CC_FIRST + 1) + 7) / 8);
10
11         // TPM_CC_SetCommandCodeAuditStatus always being audited
12         if(CommandIsImplemented(TPM_CC_SetCommandCodeAuditStatus))
13             CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus);
14
15         // Set initial command audit hash algorithm to be context integrity hash
16         // algorithm
17         gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG;
18
19         // Set up audit counter to be 0
20         gp.auditCounter = 0;
21
22         // Write command audit persistent data to NV
23         NvWriteReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
24         NvWriteReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
25         NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
26
27         return;
28   }


     8.1.3.2      CommandAuditStartup()

     This function clears the command audit digest on a TPM Reset.

29   void
30   CommandAuditStartup(
31         STARTUP_TYPE        type               // IN: start up type
32         )

     Family "2.0"                                 TCG Published                                         Page 109
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
     Trusted Platform Module Library                                                   Part 4: Supporting Routines

33   {
34       if(type == SU_RESET)
35       {
36           // Reset the digest size to initialize the digest
37           gr.commandAuditDigest.t.size = 0;
38       }
39
40   }


     8.1.3.3    CommandAuditSet()

     This function will SET the audit flag for a command. This function will not SET the audit flag for a
     command that is not implemented. This ensures that the audit status is not SET when
     TPM2_GetCapability() is used to read the list of audited commands.
     This function is only used by TPM2_SetCommandCodeAuditStatus().
     The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to
     NV after it is setting and clearing bits.

     Return Value                      Meaning

     TRUE                              the command code audit status was changed
     FALSE                             the command code audit status was not changed

41   BOOL
42   CommandAuditSet(
43       TPM_CC              commandCode          // IN: command code
44       )
45   {
46       UINT32         bitPos;
47
48       // Only SET a bit if the corresponding command is implemented
49       if(CommandIsImplemented(commandCode))
50       {
51           // Can't audit shutdown
52           if(commandCode != TPM_CC_Shutdown)
53           {
54               bitPos = commandCode - TPM_CC_FIRST;
55               if(!BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)))
56               {
57                   // Set bit
58                   BitSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands));
59                   return TRUE;
60               }
61           }
62       }
63       // No change
64       return FALSE;
65   }


     8.1.3.4    CommandAuditClear()

     This function will CLEAR the audit flag for a command. It will not CLEAR the audit flag for
     TPM_CC_SetCommandCodeAuditStatus().
     This function is only used by TPM2_SetCommandCodeAuditStatus().
     The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to
     NV after it is setting and clearing bits.



     Page 110                                      TCG Published                                     Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                    Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library


      Return Value                     Meaning

      TRUE                             the command code audit status was changed
      FALSE                            the command code audit status was not changed

 66   BOOL
 67   CommandAuditClear(
 68        TPM_CC               commandCode        // IN: command code
 69        )
 70   {
 71        UINT32         bitPos;
 72
 73        // Do nothing if the command is not implemented
 74        if(CommandIsImplemented(commandCode))
 75        {
 76            // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be
 77            // cleared
 78            if(commandCode != TPM_CC_SetCommandCodeAuditStatus)
 79            {
 80                bitPos = commandCode - TPM_CC_FIRST;
 81                if(BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)))
 82                {
 83                    // Clear bit
 84                    BitClear(bitPos, &gp.auditComands[0], sizeof(gp.auditComands));
 85                    return TRUE;
 86                }
 87            }
 88        }
 89        // No change
 90        return FALSE;
 91   }


      8.1.3.5     CommandAuditIsRequired()

      This function indicates if the audit flag is SET for a command.

      Return Value                     Meaning

      TRUE                             if command is audited
      FALSE                            if command is not audited

 92   BOOL
 93   CommandAuditIsRequired(
 94        TPM_CC               commandCode        // IN: command code
 95        )
 96   {
 97        UINT32         bitPos;
 98
 99        bitPos = commandCode - TPM_CC_FIRST;
100
101        // Check the bit map. If the bit is SET, command audit is required
102        if((gp.auditComands[bitPos/8] & (1 << (bitPos % 8))) != 0)
103            return TRUE;
104        else
105            return FALSE;
106
107   }


      8.1.3.6     CommandAuditCapGetCCList()

      This function returns a list of commands that have their audit bit SET.
      Family "2.0"                                 TCG Published                                        Page 111
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines


      The list starts at the input commandCode.

      Return Value                      Meaning

      YES                               if there are more command code available
      NO                                all the available command code has been returned

108   TPMI_YES_NO
109   CommandAuditCapGetCCList(
110         TPM_CC            commandCode,          // IN: start command code
111         UINT32            count,                // IN: count of returned TPM_CC
112         TPML_CC          *commandList           // OUT: list of TPM_CC
113         )
114   {
115         TPMI_YES_NO      more = NO;
116         UINT32           i;
117
118         // Initialize output handle list
119         commandList->count = 0;
120
121         // The maximum count of command we may return is MAX_CAP_CC
122         if(count > MAX_CAP_CC) count = MAX_CAP_CC;
123
124         // If the command code is smaller than TPM_CC_FIRST, start from TPM_CC_FIRST
125         if(commandCode < TPM_CC_FIRST) commandCode = TPM_CC_FIRST;
126
127         // Collect audit commands
128         for(i = commandCode; i <= TPM_CC_LAST; i++)
129         {
130             if(CommandAuditIsRequired(i))
131             {
132                 if(commandList->count < count)
133                 {
134                     // If we have not filled up the return list, add this command
135                     // code to it
136                     commandList->commandCodes[commandList->count] = i;
137                     commandList->count++;
138                 }
139                 else
140                 {
141                     // If the return list is full but we still have command
142                     // available, report this and stop iterating
143                     more = YES;
144                     break;
145                 }
146             }
147         }
148
149         return more;
150
151   }


      8.1.3.7    CommandAuditGetDigest

      This command is used to create a digest of the commands being audited. The commands are processed
      in ascending numeric order with a list of TPM_CC being added to a hash. This operates as if all the
      audited command codes were concatenated and then hashed.

152   void
153   CommandAuditGetDigest(
154         TPM2B_DIGEST     *digest                // OUT: command digest
155         )
156   {

      Page 112                                      TCG Published                                     Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

157         TPM_CC                               i;
158         HASH_STATE                           hashState;
159
160         // Start hash
161         digest->t.size = CryptStartHash(gp.auditHashAlg, &hashState);
162
163         // Add command code
164         for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
165         {
166             if(CommandAuditIsRequired(i))
167             {
168                 CryptUpdateDigestInt(&hashState, sizeof(i), &i);
169             }
170         }
171
172         // Complete hash
173         CryptCompleteHash2B(&hashState, &digest->b);
174
175         return;
176   }


      8.2     DA.c

      8.2.1     Introduction

      This file contains the functions and data definitions relating to the dictionary attack logic.

      8.2.2     Includes and Data Definitions

  1   #define DA_C
  2   #include "InternalRoutines.h"


      8.2.3     Functions

      8.2.3.1      DAPreInstall_Init()

      This function initializes the DA parameters to their manufacturer-default values. The default values are
      determined by a platform-specific specification.
      This function should not be called outside of a manufacturing or simulation environment.
      The DA parameters will be restored to these initial values by TPM2_Clear().

  3   void
  4   DAPreInstall_Init(
  5         void
  6         )
  7   {
  8         gp.failedTries = 0;
  9         gp.maxTries = 3;
 10         gp.recoveryTime = 1000;                  // in seconds (~16.67 minutes)
 11         gp.lockoutRecovery = 1000;               // in seconds
 12         gp.lockOutAuthEnabled = TRUE;            // Use of lockoutAuth is enabled
 13
 14         // Record persistent DA parameter changes to NV
 15         NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
 16         NvWriteReserved(NV_MAX_TRIES, &gp.maxTries);
 17         NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime);
 18         NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery);
 19         NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
 20

      Family "2.0"                                   TCG Published                                        Page 113
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                             October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines

21        return;
22   }


     8.2.3.2     DAStartup()

     This function is called by TPM2_Startup() to initialize the DA parameters. In the case of Startup(CLEAR),
     use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, lockoutAuth will not be
     enabled until the TPM has been continuously powered for the lockoutRecovery time.
     This function requires that NV be available and not rate limiting.

23   void
24   DAStartup(
25        STARTUP_TYPE         type               // IN: startup type
26        )
27   {
28        // For TPM Reset, if lockoutRecovery is 0, enable use of lockoutAuth.
29        if(type == SU_RESET)
30        {
31            if(gp.lockoutRecovery == 0)
32            {
33                gp.lockOutAuthEnabled = TRUE;
34                // Record the changes to NV
35                NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
36            }
37        }
38
39        // If DA has not been disabled and the previous shutdown is not orderly
40        // failedTries is not already at its maximum then increment 'failedTries'
41        if(    gp.recoveryTime != 0
42            && g_prevOrderlyState == SHUTDOWN_NONE
43            && gp.failedTries < gp.maxTries)
44        {
45            gp.failedTries++;
46            // Record the change to NV
47            NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
48        }
49
50        // Reset self healing timers
51        s_selfHealTimer = g_time;
52        s_lockoutTimer = g_time;
53
54        return;
55   }


     8.2.3.3     DARegisterFailure()

     This function is called when a authorization failure occurs on an entity that is subject to dictionary-attack
     protection. When a DA failure is triggered, register the failure by resetting the relevant self-healing timer
     to the current time.

56   void
57   DARegisterFailure(
58        TPM_HANDLE           handle             // IN: handle for failure
59        )
60   {
61        // Reset the timer associated with lockout if the handle is the lockout auth.
62        if(handle == TPM_RH_LOCKOUT)
63             s_lockoutTimer = g_time;
64        else
65             s_selfHealTimer = g_time;
66


     Page 114                                      TCG Published                                    Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

 67       return;
 68   }


      8.2.3.4       DASelfHeal()

      This function is called to check if sufficient time has passed to allow decrement of failedTries or to re-
      enable use of lockoutAuth.
      This function should be called when the time interval is updated.

 69   void
 70   DASelfHeal(
 71       void
 72       )
 73   {
 74       // Regular auth self healing logic
 75       // If no failed authorization tries, do nothing. Otherwise, try to
 76       // decrease failedTries
 77       if(gp.failedTries != 0)
 78       {
 79           // if recovery time is 0, DA logic has been disabled. Clear failed tries
 80           // immediately
 81           if(gp.recoveryTime == 0)
 82           {
 83                gp.failedTries = 0;
 84                // Update NV record
 85                NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
 86           }
 87           else
 88           {
 89                UINT64          decreaseCount;
 90
 91                   // In the unlikely event that failedTries should become larger than
 92                   // maxTries
 93                   if(gp.failedTries > gp.maxTries)
 94                       gp.failedTries = gp.maxTries;
 95
 96                   // How much can failedTried be decreased
 97                   decreaseCount = ((g_time - s_selfHealTimer) / 1000) / gp.recoveryTime;
 98
 99                   if(gp.failedTries <= (UINT32) decreaseCount)
100                       // should not set failedTries below zero
101                       gp.failedTries = 0;
102                   else
103                       gp.failedTries -= (UINT32) decreaseCount;
104
105                   // the cast prevents overflow of the product
106                   s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000;
107                   if(decreaseCount != 0)
108                       // If there was a change to the failedTries, record the changes
109                       // to NV
110                       NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
111             }
112       }
113
114       // LockoutAuth self healing logic
115       // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we
116       // may enable it
117       if(!gp.lockOutAuthEnabled)
118       {
119           // if lockout authorization recovery time is 0, a reboot is required to
120           // re-enable use of lockout authorization. Self-healing would not
121           // apply in this case.
122           if(gp.lockoutRecovery != 0)


      Family "2.0"                                TCG Published                                      Page 115
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

123               {
124                     if(((g_time - s_lockoutTimer)/1000) >= gp.lockoutRecovery)
125                     {
126                         gp.lockOutAuthEnabled = TRUE;
127                         // Record the changes to NV
128                         NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
129                     }
130               }
131         }
132
133         return;
134   }


      8.3       Hierarchy.c

      8.3.1       Introduction

      This file contains the functions used for managing and accessing the hierarchy-related values.

      8.3.2       Includes

  1   #include "InternalRoutines.h"


      8.3.3       Functions

      8.3.3.1         HierarchyPreInstall()

      This function performs the initialization functions for the hierarchy when the TPM is simulated. This
      function should not be called if the TPM is not in a manufacturing mode at the manufacturer, or in a
      simulated environment.

  2   void
  3   HierarchyPreInstall_Init(
  4         void
  5         )
  6   {
  7         // Allow lockout clear command
  8         gp.disableClear = FALSE;
  9
 10         // Initialize Primary Seeds
 11         gp.EPSeed.t.size = PRIMARY_SEED_SIZE;
 12         CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer);
 13         gp.SPSeed.t.size = PRIMARY_SEED_SIZE;
 14         CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.SPSeed.t.buffer);
 15         gp.PPSeed.t.size = PRIMARY_SEED_SIZE;
 16         CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.PPSeed.t.buffer);
 17
 18         // Initialize owner, endorsement and lockout auth
 19         gp.ownerAuth.t.size = 0;
 20         gp.endorsementAuth.t.size = 0;
 21         gp.lockoutAuth.t.size = 0;
 22
 23         // Initialize owner, endorsement, and lockout policy
 24         gp.ownerAlg = TPM_ALG_NULL;
 25         gp.ownerPolicy.t.size = 0;
 26         gp.endorsementAlg = TPM_ALG_NULL;
 27         gp.endorsementPolicy.t.size = 0;
 28         gp.lockoutAlg = TPM_ALG_NULL;
 29         gp.lockoutPolicy.t.size = 0;
 30

      Page 116                                     TCG Published                                  Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014              Level 00 Revision 01.16
     Part 4: Supporting Routines                                                  Trusted Platform Module Library

31        // Initialize ehProof, shProof and phProof
32        gp.phProof.t.size = PROOF_SIZE;
33        gp.shProof.t.size = PROOF_SIZE;
34        gp.ehProof.t.size = PROOF_SIZE;
35        CryptGenerateRandom(gp.phProof.t.size, gp.phProof.t.buffer);
36        CryptGenerateRandom(gp.shProof.t.size, gp.shProof.t.buffer);
37        CryptGenerateRandom(gp.ehProof.t.size, gp.ehProof.t.buffer);
38
39        // Write hierarchy data to NV
40        NvWriteReserved(NV_DISABLE_CLEAR, &gp.disableClear);
41        NvWriteReserved(NV_EP_SEED, &gp.EPSeed);
42        NvWriteReserved(NV_SP_SEED, &gp.SPSeed);
43        NvWriteReserved(NV_PP_SEED, &gp.PPSeed);
44        NvWriteReserved(NV_OWNER_AUTH, &gp.ownerAuth);
45        NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
46        NvWriteReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
47        NvWriteReserved(NV_OWNER_ALG, &gp.ownerAlg);
48        NvWriteReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
49        NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
50        NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
51        NvWriteReserved(NV_LOCKOUT_ALG, &gp.lockoutAlg);
52        NvWriteReserved(NV_LOCKOUT_POLICY, &gp.lockoutPolicy);
53        NvWriteReserved(NV_PH_PROOF, &gp.phProof);
54        NvWriteReserved(NV_SH_PROOF, &gp.shProof);
55        NvWriteReserved(NV_EH_PROOF, &gp.ehProof);
56
57        return;
58   }


     8.3.3.2     HierarchyStartup()

     This function is called at TPM2_Startup() to initialize the hierarchy related values.

59   void
60   HierarchyStartup(
61        STARTUP_TYPE         type                // IN: start up type
62        )
63   {
64        // phEnable is SET on any startup
65        g_phEnable = TRUE;
66
67        // Reset platformAuth, platformPolicy; enable SH and EH at TPM_RESET and
68        // TPM_RESTART
69        if(type != SU_RESUME)
70        {
71            gc.platformAuth.t.size = 0;
72            gc.platformPolicy.t.size = 0;
73
74             // enable the storage and endorsement hierarchies and the platformNV
75             gc.shEnable = gc.ehEnable = gc.phEnableNV = TRUE;
76        }
77
78        // nullProof and nullSeed are updated at every TPM_RESET
79        if(type == SU_RESET)
80        {
81            gr.nullProof.t.size = PROOF_SIZE;
82            CryptGenerateRandom(gr.nullProof.t.size,
83                                gr.nullProof.t.buffer);
84            gr.nullSeed.t.size = PRIMARY_SEED_SIZE;
85            CryptGenerateRandom(PRIMARY_SEED_SIZE, gr.nullSeed.t.buffer);
86        }
87
88        return;
89   }


     Family "2.0"                                  TCG Published                                       Page 117
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

      8.3.3.3     HierarchyGetProof()

      This function finds the proof value associated with a hierarchy.It returns a pointer to the proof value.

 90   TPM2B_AUTH *
 91   HierarchyGetProof(
 92        TPMI_RH_HIERARCHY         hierarchy           // IN: hierarchy constant
 93        )
 94   {
 95        TPM2B_AUTH               *auth = NULL;
 96
 97        switch(hierarchy)
 98        {
 99        case TPM_RH_PLATFORM:
100            // phProof for TPM_RH_PLATFORM
101            auth = &gp.phProof;
102            break;
103        case TPM_RH_ENDORSEMENT:
104            // ehProof for TPM_RH_ENDORSEMENT
105            auth = &gp.ehProof;
106            break;
107        case TPM_RH_OWNER:
108            // shProof for TPM_RH_OWNER
109            auth = &gp.shProof;
110            break;
111        case TPM_RH_NULL:
112            // nullProof for TPM_RH_NULL
113            auth = &gr.nullProof;
114            break;
115        default:
116            pAssert(FALSE);
117            break;
118        }
119        return auth;
120
121   }


      8.3.3.4     HierarchyGetPrimarySeed()

      This function returns the primary seed of a hierarchy.

122   TPM2B_SEED *
123   HierarchyGetPrimarySeed(
124        TPMI_RH_HIERARCHY         hierarchy           // IN: hierarchy
125        )
126   {
127        TPM2B_SEED          *seed = NULL;
128        switch(hierarchy)
129        {
130        case TPM_RH_PLATFORM:
131            seed = &gp.PPSeed;
132            break;
133        case TPM_RH_OWNER:
134            seed = &gp.SPSeed;
135            break;
136        case TPM_RH_ENDORSEMENT:
137            seed = &gp.EPSeed;
138            break;
139        case TPM_RH_NULL:
140            return &gr.nullSeed;
141        default:
142            pAssert(FALSE);
143            break;
144        }

      Page 118                                      TCG Published                                     Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

145         return seed;
146   }


      8.3.3.5      HierarchyIsEnabled()

      This function checks to see if a hierarchy is enabled.

      NOTE:           The TPM_RH_NULL hierarchy is always enabled.


      Return Value                     Meaning

      TRUE                             hierarchy is enabled
      FALSE                            hierarchy is disabled

147   BOOL
148   HierarchyIsEnabled(
149         TPMI_RH_HIERARCHY        hierarchy           // IN: hierarchy
150         )
151   {
152         BOOL               enabled = FALSE;
153
154         switch(hierarchy)
155         {
156         case TPM_RH_PLATFORM:
157             enabled = g_phEnable;
158             break;
159         case TPM_RH_OWNER:
160             enabled = gc.shEnable;
161             break;
162         case TPM_RH_ENDORSEMENT:
163             enabled = gc.ehEnable;
164             break;
165         case TPM_RH_NULL:
166             enabled = TRUE;
167             break;
168         default:
169             pAssert(FALSE);
170             break;
171         }
172         return enabled;
173   }


      8.4     NV.c

      8.4.1     Introduction

      The NV memory is divided into two area: dynamic space for user defined NV Indices and evict objects,
      and reserved space for TPM persistent and state save data.

      8.4.2     Includes, Defines and Data Definitions

  1   #define NV_C
  2   #include "InternalRoutines.h"
  3   #include <Platform.h>

      NV Index/evict object iterator value

  4   typedef        UINT32              NV_ITER;              // type of a NV iterator
  5   #define        NV_ITER_INIT        0xFFFFFFFF            // initial value to start an

      Family "2.0"                                  TCG Published                                   Page 119
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                     October 30, 2014
     Trusted Platform Module Library                                               Part 4: Supporting Routines

 6                                                            // iterator


     8.4.3      NV Utility Functions

     8.4.3.1      NvCheckState()

     Function to check the NV state by accessing the platform-specific function to get the NV state. The result
     state is registered in s_NvIsAvailable that will be reported by NvIsAvailable().
     This function is called at the beginning of ExecuteCommand() before any potential call to NvIsAvailable().

 7   void
 8   NvCheckState(void)
 9   {
10        int        func_return;
11
12        func_return = _plat__IsNvAvailable();
13        if(func_return == 0)
14        {
15            s_NvStatus = TPM_RC_SUCCESS;
16        }
17        else if(func_return == 1)
18        {
19            s_NvStatus = TPM_RC_NV_UNAVAILABLE;
20        }
21        else
22        {
23            s_NvStatus = TPM_RC_NV_RATE;
24        }
25
26        return;
27   }


     8.4.3.2      NvIsAvailable()

     This function returns the NV availability parameter.

     Error Returns                     Meaning

     TPM_RC_SUCCESS                    NV is available
     TPM_RC_NV_RATE                    NV is unavailable because of rate limit
     TPM_RC_NV_UNAVAILABLE             NV is inaccessible

28   TPM_RC
29   NvIsAvailable(
30        void
31        )
32   {
33        return s_NvStatus;
34   }


     8.4.3.3      NvCommit

     This is a wrapper for the platform function to commit pending NV writes.

35   BOOL
36   NvCommit(
37        void
38        )

     Page 120                                       TCG Published                                 Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
     Part 4: Supporting Routines                                                  Trusted Platform Module Library

39   {
40        BOOL    success = (_plat__NvCommit() == 0);
41        return success;
42   }


     8.4.3.4     NvReadMaxCount()

     This function returns the max NV counter value.

43   static UINT64
44   NvReadMaxCount(
45        void
46        )
47   {
48        UINT64      countValue;
49        _plat__NvMemoryRead(s_maxCountAddr, sizeof(UINT64), &countValue);
50        return countValue;
51   }


     8.4.3.5     NvWriteMaxCount()

     This function updates the max counter value to NV memory.

52   static void
53   NvWriteMaxCount(
54        UINT64               maxCount
55        )
56   {
57        _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &maxCount);
58        return;
59   }


     8.4.4     NV Index and Persistent Object Access Functions

     8.4.4.1     Introduction

     These functions are used to access an NV Index and persistent object memory. In this implementation,
     the memory is simulated with RAM. The data in dynamic area is organized as a linked list, starting from
     address s_evictNvStart. The first 4 bytes of a node in this link list is the offset of next node, followed by
     the data entry. A 0-valued offset value indicates the end of the list. If the data entry area of the last node
     happens to reach the end of the dynamic area without space left for an additional 4 byte end marker, the
     end address, s_evictNvEnd, should serve as the mark of list end

     8.4.4.2     NvNext()

     This function provides a method to traverse every data entry in NV dynamic area.
     To begin with, parameter iter should be initialized to NV_ITER_INIT indicating the first element. Every
     time this function is called, the value in iter would be adjusted pointing to the next element in traversal. If
     there is no next element, iter value would be 0. This function returns the address of the 'data entry'
     pointed by the iter. If there is no more element in the set, a 0 value is returned indicating the end of
     traversal.

60   static UINT32
61   NvNext(
62        NV_ITER             *iter
63        )
64   {

     Family "2.0"                                  TCG Published                                         Page 121
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                          Part 4: Supporting Routines

 65       NV_ITER        currentIter;
 66
 67       // If iterator is at the beginning of list
 68       if(*iter == NV_ITER_INIT)
 69       {
 70           // Initialize iterator
 71           *iter = s_evictNvStart;
 72       }
 73
 74       // If iterator reaches the end of NV space, or iterator indicates list end
 75       if(*iter + sizeof(UINT32) > s_evictNvEnd || *iter == 0)
 76           return 0;
 77
 78       // Save the current iter offset
 79       currentIter = *iter;
 80
 81       // Adjust iter pointer pointing to next entity
 82       // Read pointer value
 83       _plat__NvMemoryRead(*iter, sizeof(UINT32), iter);
 84
 85       if(*iter == 0) return 0;
 86
 87       return currentIter + sizeof(UINT32);                // entity stores after the pointer
 88   }


      8.4.4.3     NvGetEnd()

      Function to find the end of the NV dynamic data list

 89   static UINT32
 90   NvGetEnd(
 91       void
 92       )
 93   {
 94       NV_ITER             iter = NV_ITER_INIT;
 95       UINT32              endAddr = s_evictNvStart;
 96       UINT32              currentAddr;
 97
 98       while((currentAddr = NvNext(&iter)) != 0)
 99           endAddr = currentAddr;
100
101       if(endAddr != s_evictNvStart)
102       {
103           // Read offset
104           endAddr -= sizeof(UINT32);
105           _plat__NvMemoryRead(endAddr, sizeof(UINT32), &endAddr);
106       }
107
108       return endAddr;
109   }


      8.4.4.4     NvGetFreeByte

      This function returns the number of free octets in NV space.

110   static UINT32
111   NvGetFreeByte(
112       void
113       )
114   {
115       return s_evictNvEnd - NvGetEnd();
116   }


      Page 122                                     TCG Published                             Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

      8.4.4.5     NvGetEvictObjectSize

      This function returns the size of an evict object in NV space

117   static UINT32
118   NvGetEvictObjectSize(
119        void
120        )
121   {
122        return sizeof(TPM_HANDLE) + sizeof(OBJECT) + sizeof(UINT32);
123   }


      8.4.4.6     NvGetCounterSize

      This function returns the size of a counter index in NV space.

124   static UINT32
125   NvGetCounterSize(
126        void
127        )
128   {
129        // It takes an offset field, a handle and the sizeof(NV_INDEX) and
130        // sizeof(UINT64) for counter data
131        return sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + sizeof(UINT64) + sizeof(UINT32);
132   }


      8.4.4.7     NvTestSpace()

      This function will test if there is enough space to add a new entity.

      Return Value                      Meaning

      TRUE                              space available
      FALSE                             no enough space

133   static BOOL
134   NvTestSpace(
135        UINT32               size,               // IN: size of the entity to be added
136        BOOL                 isIndex             // IN: TRUE if the entity is an index
137        )
138   {
139        UINT32         remainByte = NvGetFreeByte();
140
141        // For NV Index, need to make sure that we do not allocate and Index if this
142        // would mean that the TPM cannot allocate the minimum number of evict
143        // objects.
144        if(isIndex)
145        {
146            // Get the number of persistent objects allocated
147            UINT32      persistentNum = NvCapGetPersistentNumber();
148
149             // If we have not allocated the requisite number of evict objects, then we
150             // need to reserve space for them.
151             // NOTE: some of this is not written as simply as it might seem because
152             // the values are all unsigned and subtracting needs to be done carefully
153             // so that an underflow doesn't cause problems.
154             if(persistentNum < MIN_EVICT_OBJECTS)
155             {
156                 UINT32      needed = (MIN_EVICT_OBJECTS - persistentNum)
157                                     * NvGetEvictObjectSize();
158                 if(needed > remainByte)

      Family "2.0"                                  TCG Published                                  Page 123
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                     October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

159                     remainByte = 0;
160                 else
161                     remainByte -= needed;
162             }
163             // if the requisite number of evict objects have been allocated then
164             // no need to reserve additional space
165       }
166       // This checks for the size of the value being added plus the index value.
167       // NOTE: This does not check to see if the end marker can be placed in
168       // memory because the end marker will not be written if it will not fit.
169       return (size + sizeof(UINT32) <= remainByte);
170   }


      8.4.4.8     NvAdd()

      This function adds a new entity to NV.
      This function requires that there is enough space to add a new entity (i.e., that NvTestSpace() has been
      called and the available space is at least as large as the required space).

171   static void
172   NvAdd(
173       UINT32                totalSize,       // IN: total size needed for this        entity For
174                                              //     evict object, totalSize is        the same as
175                                              //     bufferSize. For NV Index,         totalSize is
176                                              //     bufferSize plus index data        size
177       UINT32                bufferSize,      // IN: size of initial buffer
178       BYTE                 *entity           // IN: initial buffer
179       )
180   {
181       UINT32               endAddr;
182       UINT32               nextAddr;
183       UINT32               listEnd = 0;
184
185       // Get the end of data list
186       endAddr = NvGetEnd();
187
188       // Calculate the value of next pointer, which is the size of a pointer +
189       // the entity data size
190       nextAddr = endAddr + sizeof(UINT32) + totalSize;
191
192       // Write next pointer
193       _plat__NvMemoryWrite(endAddr, sizeof(UINT32), &nextAddr);
194
195       // Write entity data
196       _plat__NvMemoryWrite(endAddr + sizeof(UINT32), bufferSize, entity);
197
198       // Write the end of list if it is not going to exceed the NV space
199       if(nextAddr + sizeof(UINT32) <= s_evictNvEnd)
200           _plat__NvMemoryWrite(nextAddr, sizeof(UINT32), &listEnd);
201
202       // Set the flag so that NV changes are committed before the command completes.
203       g_updateNV = TRUE;
204   }


      8.4.4.9     NvDelete()

      This function is used to delete an NV Index or persistent object from NV memory.

205   static void
206   NvDelete(
207       UINT32                entityAddr       // IN: address of entity to be deleted
208       )

      Page 124                                    TCG Published                                  Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

209   {
210       UINT32              next;
211       UINT32              entrySize;
212       UINT32              entryAddr = entityAddr - sizeof(UINT32);
213       UINT32              listEnd = 0;
214
215       // Get the offset of the next entry.
216       _plat__NvMemoryRead(entryAddr, sizeof(UINT32), &next);
217
218       // The size of this entry is the difference between the current entry and the
219       // next entry.
220       entrySize = next - entryAddr;
221
222       //    Move each entry after the current one to fill the freed space.
223       //    Stop when we have reached the end of all the indexes. There are two
224       //    ways to detect the end of the list. The first is to notice that there
225       //    is no room for anything else because we are at the end of NV. The other
226       //    indication is that we find an end marker.
227
228       // The loop condition checks for the end of NV.
229       while(next + sizeof(UINT32) <= s_evictNvEnd)
230       {
231           UINT32      size, oldAddr, newAddr;
232
233             // Now check for the end marker
234             _plat__NvMemoryRead(next, sizeof(UINT32), &oldAddr);
235             if(oldAddr == 0)
236                 break;
237
238             size = oldAddr - next;
239
240             // Move entry
241             _plat__NvMemoryMove(next, next - entrySize, size);
242
243             // Update forward link
244             newAddr = oldAddr - entrySize;
245             _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &newAddr);
246             next = oldAddr;
247       }
248       // Mark the end of list
249       _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &listEnd);
250
251       // Set the flag so that NV changes are committed before the command completes.
252       g_updateNV = TRUE;
253   }


      8.4.5     RAM-based NV Index Data Access Functions

      8.4.5.1     Introduction

      The data layout in ram buffer is {size of(NV_handle() + data), NV_handle(), data} for each NV Index data
      stored in RAM.
      NV storage is updated when a NV Index is added or deleted. We do NOT updated NV storage when the
      data is updated/

      8.4.5.2     NvTestRAMSpace()

      This function indicates if there is enough RAM space to add a data for a new NV Index.




      Family "2.0"                               TCG Published                                        Page 125
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines


      Return Value                      Meaning

      TRUE                              space available
      FALSE                             no enough space

254   static BOOL
255   NvTestRAMSpace(
256       UINT32                size                // IN: size of the data to be added to RAM
257       )
258   {
259       BOOL           success = (       s_ramIndexSize
260                                      + size
261                                      + sizeof(TPM_HANDLE) + sizeof(UINT32)
262                                      <= RAM_INDEX_SPACE);
263       return success;
264   }


      8.4.5.3     NvGetRamIndexOffset

      This function returns the offset of NV data in the RAM buffer
      This function requires that NV Index is in RAM. That is, the index must be known to exist.

265   static UINT32
266   NvGetRAMIndexOffset(
267       TPMI_RH_NV_INDEX           handle               // IN: NV handle
268       )
269   {
270       UINT32         currAddr = 0;
271
272       while(currAddr < s_ramIndexSize)
273       {
274           TPMI_RH_NV_INDEX    currHandle;
275           UINT32              currSize;
276           currHandle = * (TPM_HANDLE *) &s_ramIndex[currAddr + sizeof(UINT32)];
277
278             // Found a match
279             if(currHandle == handle)
280
281                  // data buffer follows the handle and size field
282                  break;
283
284             currSize = * (UINT32 *) &s_ramIndex[currAddr];
285             currAddr += sizeof(UINT32) + currSize;
286       }
287
288       // We assume the index data is existing in RAM space
289       pAssert(currAddr < s_ramIndexSize);
290       return currAddr + sizeof(TPMI_RH_NV_INDEX) + sizeof(UINT32);
291   }


      8.4.5.4     NvAddRAM()

      This function adds a new data area to RAM.
      This function requires that enough free RAM space is available to add the new data.

292   static void
293   NvAddRAM(
294       TPMI_RH_NV_INDEX           handle,              // IN: NV handle
295       UINT32                     size                 // IN: size of data
296       )

      Page 126                                      TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                        Trusted Platform Module Library

297   {
298       // Add data space at the end of reserved RAM buffer
299       * (UINT32 *) &s_ramIndex[s_ramIndexSize] = size + sizeof(TPMI_RH_NV_INDEX);
300       * (TPMI_RH_NV_INDEX *) &s_ramIndex[s_ramIndexSize + sizeof(UINT32)] = handle;
301       s_ramIndexSize += sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX) + size;
302
303       pAssert(s_ramIndexSize <= RAM_INDEX_SPACE);
304
305       // Update NV version of s_ramIndexSize
306       _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
307
308       // Write reserved RAM space to NV to reflect the newly added NV Index
309       _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
310
311       return;
312   }


      8.4.5.5    NvDeleteRAM()

      This function is used to delete a RAM-backed NV Index data area.
      This function assumes the data of NV Index exists in RAM

313   static void
314   NvDeleteRAM(
315       TPMI_RH_NV_INDEX          handle           // IN: NV handle
316       )
317   {
318       UINT32             nodeOffset;
319       UINT32             nextNode;
320       UINT32             size;
321
322       nodeOffset = NvGetRAMIndexOffset(handle);
323
324       // Move the pointer back to get the size field of this node
325       nodeOffset -= sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX);
326
327       // Get node size
328       size = * (UINT32 *) &s_ramIndex[nodeOffset];
329
330       // Get the offset of next node
331       nextNode = nodeOffset + sizeof(UINT32) + size;
332
333       // Move data
334       MemoryMove(s_ramIndex + nodeOffset, s_ramIndex + nextNode,
335                  s_ramIndexSize - nextNode, s_ramIndexSize - nextNode);
336
337       // Update RAM size
338       s_ramIndexSize -= size + sizeof(UINT32);
339
340       // Update NV version of s_ramIndexSize
341       _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
342
343       // Write reserved RAM space to NV to reflect the newly delete NV Index
344       _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
345
346       return;
347   }




      Family "2.0"                              TCG Published                                 Page 127
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                            Part 4: Supporting Routines

      8.4.6     Utility Functions

      8.4.6.1     NvInitStatic()

      This function initializes the static variables used in the NV subsystem.

348   static void
349   NvInitStatic(
350        void
351        )
352   {
353        UINT16         i;
354        UINT32         reservedAddr;
355
356        s_reservedSize[NV_DISABLE_CLEAR] = sizeof(gp.disableClear);
357        s_reservedSize[NV_OWNER_ALG] = sizeof(gp.ownerAlg);
358        s_reservedSize[NV_ENDORSEMENT_ALG] = sizeof(gp.endorsementAlg);
359        s_reservedSize[NV_LOCKOUT_ALG] = sizeof(gp.lockoutAlg);
360        s_reservedSize[NV_OWNER_POLICY] = sizeof(gp.ownerPolicy);
361        s_reservedSize[NV_ENDORSEMENT_POLICY] = sizeof(gp.endorsementPolicy);
362        s_reservedSize[NV_LOCKOUT_POLICY] = sizeof(gp.lockoutPolicy);
363        s_reservedSize[NV_OWNER_AUTH] = sizeof(gp.ownerAuth);
364        s_reservedSize[NV_ENDORSEMENT_AUTH] = sizeof(gp.endorsementAuth);
365        s_reservedSize[NV_LOCKOUT_AUTH] = sizeof(gp.lockoutAuth);
366        s_reservedSize[NV_EP_SEED] = sizeof(gp.EPSeed);
367        s_reservedSize[NV_SP_SEED] = sizeof(gp.SPSeed);
368        s_reservedSize[NV_PP_SEED] = sizeof(gp.PPSeed);
369        s_reservedSize[NV_PH_PROOF] = sizeof(gp.phProof);
370        s_reservedSize[NV_SH_PROOF] = sizeof(gp.shProof);
371        s_reservedSize[NV_EH_PROOF] = sizeof(gp.ehProof);
372        s_reservedSize[NV_TOTAL_RESET_COUNT] = sizeof(gp.totalResetCount);
373        s_reservedSize[NV_RESET_COUNT] = sizeof(gp.resetCount);
374        s_reservedSize[NV_PCR_POLICIES] = sizeof(gp.pcrPolicies);
375        s_reservedSize[NV_PCR_ALLOCATED] = sizeof(gp.pcrAllocated);
376        s_reservedSize[NV_PP_LIST] = sizeof(gp.ppList);
377        s_reservedSize[NV_FAILED_TRIES] = sizeof(gp.failedTries);
378        s_reservedSize[NV_MAX_TRIES] = sizeof(gp.maxTries);
379        s_reservedSize[NV_RECOVERY_TIME] = sizeof(gp.recoveryTime);
380        s_reservedSize[NV_LOCKOUT_RECOVERY] = sizeof(gp.lockoutRecovery);
381        s_reservedSize[NV_LOCKOUT_AUTH_ENABLED] = sizeof(gp.lockOutAuthEnabled);
382        s_reservedSize[NV_ORDERLY] = sizeof(gp.orderlyState);
383        s_reservedSize[NV_AUDIT_COMMANDS] = sizeof(gp.auditComands);
384        s_reservedSize[NV_AUDIT_HASH_ALG] = sizeof(gp.auditHashAlg);
385        s_reservedSize[NV_AUDIT_COUNTER] = sizeof(gp.auditCounter);
386        s_reservedSize[NV_ALGORITHM_SET] = sizeof(gp.algorithmSet);
387        s_reservedSize[NV_FIRMWARE_V1] = sizeof(gp.firmwareV1);
388        s_reservedSize[NV_FIRMWARE_V2] = sizeof(gp.firmwareV2);
389        s_reservedSize[NV_ORDERLY_DATA] = sizeof(go);
390        s_reservedSize[NV_STATE_CLEAR] = sizeof(gc);
391        s_reservedSize[NV_STATE_RESET] = sizeof(gr);
392
393        // Initialize reserved data address. In this implementation, reserved data
394        // is stored at the start of NV memory
395        reservedAddr = 0;
396        for(i = 0; i < NV_RESERVE_LAST; i++)
397        {
398            s_reservedAddr[i] = reservedAddr;
399            reservedAddr += s_reservedSize[i];
400        }
401
402        // Initialize auxiliary variable space for index/evict implementation.
403        // Auxiliary variables are stored after reserved data area
404        // RAM index copy starts at the beginning
405        s_ramIndexSizeAddr = reservedAddr;

      Page 128                                      TCG Published                              Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014             Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library

406        s_ramIndexAddr = s_ramIndexSizeAddr + sizeof(UINT32);
407
408        // Maximum counter value
409        s_maxCountAddr = s_ramIndexAddr + RAM_INDEX_SPACE;
410
411        // dynamic memory start
412        s_evictNvStart = s_maxCountAddr + sizeof(UINT64);
413
414        // dynamic memory ends at the end of NV memory
415        s_evictNvEnd = NV_MEMORY_SIZE;
416
417        return;
418   }


      8.4.6.2     NvInit()

      This function initializes the NV system at pre-install time.
      This function should only be called in a manufacturing environment or in a simulation.
      The layout of NV memory space is an implementation choice.

419   void
420   NvInit(
421        void
422        )
423   {
424        UINT32         nullPointer = 0;
425        UINT64         zeroCounter = 0;
426
427        // Initialize static variables
428        NvInitStatic();
429
430        // Initialize RAM index space as unused
431        _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &nullPointer);
432
433        // Initialize max counter value to 0
434        _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &zeroCounter);
435
436        // Initialize the next offset of the first entry in evict/index list to 0
437        _plat__NvMemoryWrite(s_evictNvStart, sizeof(TPM_HANDLE), &nullPointer);
438
439        return;
440
441   }


      8.4.6.3     NvReadReserved()

      This function is used to move reserved data from NV memory to RAM.

442   void
443   NvReadReserved(
444        NV_RESERVE           type,               // IN: type of reserved data
445        void                *buffer              // OUT: buffer receives the data.
446        )
447   {
448        // Input type should be valid
449        pAssert(type >= 0 && type < NV_RESERVE_LAST);
450
451        _plat__NvMemoryRead(s_reservedAddr[type], s_reservedSize[type], buffer);
452        return;
453   }



      Family "2.0"                                   TCG Published                                    Page 129
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                            Part 4: Supporting Routines

      8.4.6.4     NvWriteReserved()

      This function is used to post a reserved data for writing to NV memory. Before the TPM completes the
      operation, the value will be written.

454   void
455   NvWriteReserved(
456       NV_RESERVE           type,              // IN: type of reserved data
457       void                *buffer             // IN: data buffer
458       )
459   {
460       // Input type should be valid
461       pAssert(type >= 0 && type < NV_RESERVE_LAST);
462
463       _plat__NvMemoryWrite(s_reservedAddr[type], s_reservedSize[type], buffer);
464
465       // Set the flag that a NV write happens
466       g_updateNV = TRUE;
467       return;
468   }


      8.4.6.5     NvReadPersistent()

      This function reads persistent data to the RAM copy of the gp structure.

469   void
470   NvReadPersistent(
471       void
472       )
473   {
474       // Hierarchy persistent data
475       NvReadReserved(NV_DISABLE_CLEAR, &gp.disableClear);
476       NvReadReserved(NV_OWNER_ALG, &gp.ownerAlg);
477       NvReadReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
478       NvReadReserved(NV_LOCKOUT_ALG, &gp.lockoutAlg);
479       NvReadReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
480       NvReadReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
481       NvReadReserved(NV_LOCKOUT_POLICY, &gp.lockoutPolicy);
482       NvReadReserved(NV_OWNER_AUTH, &gp.ownerAuth);
483       NvReadReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
484       NvReadReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
485       NvReadReserved(NV_EP_SEED, &gp.EPSeed);
486       NvReadReserved(NV_SP_SEED, &gp.SPSeed);
487       NvReadReserved(NV_PP_SEED, &gp.PPSeed);
488       NvReadReserved(NV_PH_PROOF, &gp.phProof);
489       NvReadReserved(NV_SH_PROOF, &gp.shProof);
490       NvReadReserved(NV_EH_PROOF, &gp.ehProof);
491
492       // Time persistent data
493       NvReadReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
494       NvReadReserved(NV_RESET_COUNT, &gp.resetCount);
495
496       // PCR persistent data
497       NvReadReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
498       NvReadReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated);
499
500       // Physical Presence persistent data
501       NvReadReserved(NV_PP_LIST, &gp.ppList);
502
503       // Dictionary attack values persistent data
504       NvReadReserved(NV_FAILED_TRIES, &gp.failedTries);
505       NvReadReserved(NV_MAX_TRIES, &gp.maxTries);
506       NvReadReserved(NV_RECOVERY_TIME, &gp.recoveryTime);


      Page 130                                     TCG Published                               Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library

507        NvReadReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery);
508        NvReadReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
509
510        // Orderly State persistent data
511        NvReadReserved(NV_ORDERLY, &gp.orderlyState);
512
513        // Command audit values persistent data
514        NvReadReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
515        NvReadReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
516        NvReadReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
517
518        // Algorithm selection persistent data
519        NvReadReserved(NV_ALGORITHM_SET, &gp.algorithmSet);
520
521        // Firmware version persistent data
522        NvReadReserved(NV_FIRMWARE_V1, &gp.firmwareV1);
523        NvReadReserved(NV_FIRMWARE_V2, &gp.firmwareV2);
524
525        return;
526   }


      8.4.6.6     NvIsPlatformPersistentHandle()

      This function indicates if a handle references a persistent object in the range belonging to the platform.

      Return Value                      Meaning

      TRUE                              handle references a platform persistent object
      FALSE                             handle does not reference platform persistent object and may
                                        reference an owner persistent object either

527   BOOL
528   NvIsPlatformPersistentHandle(
529        TPM_HANDLE           handle              // IN: handle
530        )
531   {
532        return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST);
533   }


      8.4.6.7     NvIsOwnerPersistentHandle()

      This function indicates if a handle references a persistent object in the range belonging to the owner.

      Return Value                      Meaning

      TRUE                              handle is owner persistent handle
      FALSE                             handle is not owner persistent handle and may not be a persistent
                                        handle at all

534   BOOL
535   NvIsOwnerPersistentHandle(
536        TPM_HANDLE           handle              // IN: handle
537        )
538   {
539        return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT);
540   }


      8.4.6.8     NvNextIndex()

      This function returns the offset in NV of the next NV Index entry. A value of 0 indicates the end of the list.
      Family "2.0"                                   TCG Published                                          Page 131
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

541   static UINT32
542   NvNextIndex(
543       NV_ITER             *iter
544       )
545   {
546       UINT32         addr;
547       TPM_HANDLE     handle;
548
549       while((addr = NvNext(iter)) != 0)
550       {
551           // Read handle
552           _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle);
553           if(HandleGetType(handle) == TPM_HT_NV_INDEX)
554               return addr;
555       }
556
557       pAssert(addr == 0);
558       return addr;
559   }


      8.4.6.9     NvNextEvict()

      This function returns the offset in NV of the next evict object entry. A value of 0 indicates the end of the
      list.

560   static UINT32
561   NvNextEvict(
562       NV_ITER             *iter
563       )
564   {
565       UINT32         addr;
566       TPM_HANDLE     handle;
567
568       while((addr = NvNext(iter)) != 0)
569       {
570           // Read handle
571           _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle);
572           if(HandleGetType(handle) == TPM_HT_PERSISTENT)
573               return addr;
574       }
575
576       pAssert(addr == 0);
577       return addr;
578   }


      8.4.6.10    NvFindHandle()

      this function returns the offset in NV memory of the entity associated with the input handle. A value of
      zero indicates that handle does not exist reference an existing persistent object or defined NV Index.

579   static UINT32
580   NvFindHandle(
581       TPM_HANDLE            handle
582       )
583   {
584       UINT32              addr;
585       NV_ITER             iter = NV_ITER_INIT;
586
587       while((addr = NvNext(&iter)) != 0)
588       {
589           TPM_HANDLE          entityHandle;
590           // Read handle


      Page 132                                     TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

591              _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle);
592              if(entityHandle == handle)
593                  return addr;
594        }
595
596        pAssert(addr == 0);
597        return addr;
598   }


      8.4.6.11    NvPowerOn()

      This function is called at _TPM_Init() to initialize the NV environment.

      Return Value                      Meaning

      TRUE                              all NV was initialized
      FALSE                             the NV     containing saved     state    had   an   error   and
                                        TPM2_Startup(CLEAR) is required

599   BOOL
600   NvPowerOn(
601        void
602        )
603   {
604        int          nvError = 0;
605        // If power was lost, need to re-establish the RAM data that is loaded from
606        // NV and initialize the static variables
607        if(_plat__WasPowerLost(TRUE))
608        {
609            if((nvError = _plat__NVEnable(0)) < 0)
610                FAIL(FATAL_ERROR_NV_UNRECOVERABLE);
611
612              NvInitStatic();
613        }
614
615        return nvError == 0;
616   }


      8.4.6.12    NvStateSave()

      This function is used to cause the memory containing the RAM backed NV Indices to be written to NV.

617   void
618   NvStateSave(
619        void
620        )
621   {
622        // Write RAM backed NV Index info to NV
623        // No need to save s_ramIndexSize because we save it to NV whenever it is
624        // updated.
625        _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
626
627        // Set the flag so that an NV write happens before the command completes.
628        g_updateNV = TRUE;
629
630        return;
631   }




      Family "2.0"                                   TCG Published                                        Page 133
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                        October 30, 2014
      Trusted Platform Module Library                                                     Part 4: Supporting Routines

      8.4.6.13     NvEntityStartup()

      This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is
      taken. If the startup is a TPM Reset or a TPM Restart, then this function will:
      a) clear read/write lock;
      b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and
      c) set the lower bits in orderly counters to 1 for a non-orderly startup
      It is a prerequisite that NV be available for writing before this function is called.

632   void
633   NvEntityStartup(
634        STARTUP_TYPE           type               // IN: start up type
635        )
636   {
637        NV_ITER                   iter = NV_ITER_INIT;
638        UINT32                    currentAddr;         // offset points to the current entity
639
640        // Restore RAM index data
641        _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
642        _plat__NvMemoryRead(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
643
644        // If recovering from state save, do nothing
645        if(type == SU_RESUME)
646            return;
647
648        // Iterate all the NV Index to clear the locks
649        while((currentAddr = NvNextIndex(&iter)) != 0)
650        {
651            NV_INDEX    nvIndex;
652            UINT32      indexAddr;              // NV address points to index info
653            TPMA_NV     attributes;
654
655              indexAddr = currentAddr + sizeof(TPM_HANDLE);
656
657              // Read NV Index info structure
658              _plat__NvMemoryRead(indexAddr, sizeof(NV_INDEX), &nvIndex);
659              attributes = nvIndex.publicArea.attributes;
660
661              // Clear read/write lock
662              if(attributes.TPMA_NV_READLOCKED == SET)
663                  attributes.TPMA_NV_READLOCKED = CLEAR;
664
665              if(         attributes.TPMA_NV_WRITELOCKED == SET
666                     &&   (   attributes.TPMA_NV_WRITTEN == CLEAR
667                          || attributes.TPMA_NV_WRITEDEFINE == CLEAR
668                          )
669                    )
670                     attributes.TPMA_NV_WRITELOCKED = CLEAR;
671
672              // Reset NV data for TPMA_NV_CLEAR_STCLEAR
673              if(attributes.TPMA_NV_CLEAR_STCLEAR == SET)
674              {
675                  attributes.TPMA_NV_WRITTEN = CLEAR;
676                  attributes.TPMA_NV_WRITELOCKED = CLEAR;
677              }
678
679              // Reset NV data for orderly values that are not counters
680              // NOTE: The function has already exited on a TPM Resume, so the only
681              // things being processed are TPM Restart and TPM Reset
682              if(     type == SU_RESET
683                  && attributes.TPMA_NV_ORDERLY == SET
684                  && attributes.TPMA_NV_COUNTER == CLEAR

      Page 134                                        TCG Published                                      Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                       Trusted Platform Module Library

685                 )
686                     attributes.TPMA_NV_WRITTEN = CLEAR;
687
688             // Write NV Index info back if it has changed
689             if(*((UINT32 *)&attributes) != *((UINT32 *)&nvIndex.publicArea.attributes))
690             {
691                 nvIndex.publicArea.attributes = attributes;
692                 _plat__NvMemoryWrite(indexAddr, sizeof(NV_INDEX), &nvIndex);
693
694                     // Set the flag that a NV write happens
695                     g_updateNV = TRUE;
696             }
697             // Set the lower bits in an orderly counter to 1 for a non-orderly startup
698             if(    g_prevOrderlyState == SHUTDOWN_NONE
699                 && attributes.TPMA_NV_WRITTEN == SET)
700             {
701                  if(    attributes.TPMA_NV_ORDERLY == SET
702                      && attributes.TPMA_NV_COUNTER == SET)
703                  {
704                       TPMI_RH_NV_INDEX    nvHandle;
705                       UINT64              counter;
706
707                         // Read NV handle
708                         _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
709
710                         // Read the counter value saved to NV upon the last roll over.
711                         // Do not use RAM backed storage for this once.
712                         nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = CLEAR;
713                         NvGetIntIndexData(nvHandle, &nvIndex, &counter);
714                         nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = SET;
715
716                         // Set the lower bits of counter to 1's
717                         counter |= MAX_ORDERLY_COUNT;
718
719                         // Write back to RAM
720                         NvWriteIndexData(nvHandle, &nvIndex, 0, sizeof(counter), &counter);
721
722                         // No write to NV because an orderly shutdown will update the
723                         // counters.
724
725                     }
726             }
727       }
728
729       return;
730
731   }


      8.4.7     NV Access Functions

      8.4.7.1       Introduction

      This set of functions provide accessing NV Index and persistent objects based using a handle for
      reference to the entity.

      8.4.7.2       NvIsUndefinedIndex()

      This function is used to verify that an NV Index is not defined. This is only used by
      TPM2_NV_DefineSpace().




      Family "2.0"                              TCG Published                                Page 135
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines


      Return Value                      Meaning

      TRUE                              the handle points to an existing NV Index
      FALSE                             the handle points to a non-existent Index

732   BOOL
733   NvIsUndefinedIndex(
734       TPMI_RH_NV_INDEX         handle                 // IN: handle
735       )
736   {
737       UINT32             entityAddr;                  // offset points to the entity
738
739       pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
740
741       // Find the address of index
742       entityAddr = NvFindHandle(handle);
743
744       // If handle is not found, return TPM_RC_SUCCESS
745       if(entityAddr == 0)
746           return TPM_RC_SUCCESS;
747
748       // NV Index is defined
749       return TPM_RC_NV_DEFINED;
750   }


      8.4.7.3    NvIndexIsAccessible()

      This function validates that a handle references a defined NV Index and that the Index is currently
      accessible.

      Error Returns                     Meaning

      TPM_RC_HANDLE                     the handle points to an undefined NV Index If shEnable is CLEAR,
                                        this would include an index created using ownerAuth. If phEnableNV
                                        is CLEAR, this would include and index created using platform auth
      TPM_RC_NV_READLOCKED              Index is present but locked for reading and command does not write
                                        to the index
      TPM_RC_NV_WRITELOCKED             Index is present but locked for writing and command writes to the
                                        index

751   TPM_RC
752   NvIndexIsAccessible(
753       TPMI_RH_NV_INDEX         handle,                // IN: handle
754       TPM_CC                   commandCode            // IN: the command
755       )
756   {
757       UINT32                  entityAddr;             // offset points to the entity
758       NV_INDEX                nvIndex;                //
759
760       pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
761
762       // Find the address of index
763       entityAddr = NvFindHandle(handle);
764
765       // If handle is not found, return TPM_RC_HANDLE
766       if(entityAddr == 0)
767           return TPM_RC_HANDLE;
768
769       // Read NV Index info structure
770       _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
771                               &nvIndex);

      Page 136                                       TCG Published                                     Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

772
773       if(gc.shEnable == FALSE || gc.phEnableNV == FALSE)
774       {
775           // if shEnable is CLEAR, an ownerCreate NV Index should not be
776           // indicated as present
777           if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
778           {
779               if(gc.shEnable == FALSE)
780                   return TPM_RC_HANDLE;
781           }
782           // if phEnableNV is CLEAR, a platform created Index should not
783           // be visible
784           else if(gc.phEnableNV == FALSE)
785               return TPM_RC_HANDLE;
786       }
787
788       // If the Index is write locked and this is an NV Write operation...
789       if(     nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED
790           && IsWriteOperation(commandCode))
791       {
792           // then return a locked indication unless the command is TPM2_NV_WriteLock
793           if(commandCode != TPM_CC_NV_WriteLock)
794               return TPM_RC_NV_LOCKED;
795           return TPM_RC_SUCCESS;
796       }
797       // If the Index is read locked and this is an NV Read operation...
798       if(     nvIndex.publicArea.attributes.TPMA_NV_READLOCKED
799           && IsReadOperation(commandCode))
800       {
801           // then return a locked indication unless the command is TPM2_NV_ReadLock
802           if(commandCode != TPM_CC_NV_ReadLock)
803               return TPM_RC_NV_LOCKED;
804           return TPM_RC_SUCCESS;
805       }
806
807       // NV Index is accessible
808       return TPM_RC_SUCCESS;
809   }


      8.4.7.4     NvIsUndefinedEvictHandle()

      This function indicates if a handle does not reference an existing persistent object. This function requires
      that the handle be in the proper range for persistent objects.

      Return Value                     Meaning

      TRUE                             handle does not reference an existing persistent object
      FALSE                            handle does reference an existing persistent object

810   static BOOL
811   NvIsUndefinedEvictHandle(
812       TPM_HANDLE            handle             // IN: handle
813       )
814   {
815       UINT32           entityAddr;    // offset points to the entity
816       pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
817
818       // Find the address of evict object
819       entityAddr = NvFindHandle(handle);
820
821       // If handle is not found, return TRUE
822       if(entityAddr == 0)
823           return TRUE;

      Family "2.0"                                  TCG Published                                        Page 137
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                                      Part 4: Supporting Routines

824        else
825            return FALSE;
826   }


      8.4.7.5     NvGetEvictObject()

      This function is used to dereference an evict object handle and get a pointer to the object.

      Error Returns                     Meaning

      TPM_RC_HANDLE                     the handle does not point to an existing persistent object

827   TPM_RC
828   NvGetEvictObject(
829        TPM_HANDLE           handle,              // IN: handle
830        OBJECT              *object               // OUT: object data
831        )
832   {
833        UINT32              entityAddr;         // offset points to the entity
834        TPM_RC              result = TPM_RC_SUCCESS;
835
836        pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
837
838        // Find the address of evict object
839        entityAddr = NvFindHandle(handle);
840
841        // If handle is not found, return an error
842        if(entityAddr == 0)
843            result = TPM_RC_HANDLE;
844        else
845            // Read evict object
846            _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
847                                 sizeof(OBJECT),
848                                 object);
849
850        // whether there is an error or not, make sure that the evict
851        // status of the object is set so that the slot will get freed on exit
852        object->attributes.evict = SET;
853
854        return result;
855   }


      8.4.7.6     NvGetIndexInfo()

      This function is used to retrieve the contents of an NV Index.
      An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different
      from the default used by the reference code, then this function would be changed to reformat the data into
      the default format.
      A prerequisite to calling this function is that the handle must be known to reference a defined NV Index.

856   void
857   NvGetIndexInfo(
858        TPMI_RH_NV_INDEX          handle,              // IN: handle
859        NV_INDEX                 *nvIndex              // OUT: NV index structure
860        )
861   {
862        UINT32                    entityAddr;          // offset points to the entity
863
864        pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
865
866        // Find the address of NV index

      Page 138                                       TCG Published                                       Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

867        entityAddr = NvFindHandle(handle);
868        pAssert(entityAddr != 0);
869
870        // This implementation uses the default format so just
871        // read the data in
872        _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
873                            nvIndex);
874
875        return;
876   }


      8.4.7.7     NvInitialCounter()

      This function returns the value to be used when a counter index is initialized. It will scan the NV counters
      and find the highest value in any active counter. It will use that value as the starting point. If there are no
      active counters, it will use the value of the previous largest counter.

877   UINT64
878   NvInitialCounter(
879        void
880        )
881   {
882        UINT64              maxCount;
883        NV_ITER             iter = NV_ITER_INIT;
884        UINT32              currentAddr;
885
886        // Read the maxCount value
887        maxCount = NvReadMaxCount();
888
889        // Iterate all existing counters
890        while((currentAddr = NvNextIndex(&iter)) != 0)
891        {
892            TPMI_RH_NV_INDEX    nvHandle;
893            NV_INDEX            nvIndex;
894
895             // Read NV handle
896             _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
897
898             // Get NV Index
899             NvGetIndexInfo(nvHandle, &nvIndex);
900             if(    nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
901                 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
902             {
903                 UINT64      countValue;
904                 // Read counter value
905                 NvGetIntIndexData(nvHandle, &nvIndex, &countValue);
906                 if(countValue > maxCount)
907                     maxCount = countValue;
908             }
909        }
910        // Initialize the new counter value to be maxCount + 1
911        // A counter is only initialized the first time it is written. The
912        // way to write a counter is with TPM2_NV_INCREMENT(). Since the
913        // "initial" value of a defined counter is the largest count value that
914        // may have existed in this index previously, then the first use would
915        // add one to that value.
916        return maxCount;
917   }


      8.4.7.8     NvGetIndexData()

      This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since
      counter values are kept in native format, they are converted to canonical form before being returned.
      Family "2.0"                                  TCG Published                                         Page 139
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines


      This function requires that the NV Index be defined, and that the required data is within the data range. It
      also requires that TPMA_NV_WRITTEN of the Index is SET.

918   void
919   NvGetIndexData(
920        TPMI_RH_NV_INDEX          handle,            //   IN: handle
921        NV_INDEX                 *nvIndex,           //   IN: RAM image of index header
922        UINT32                    offset,            //   IN: offset of NV data
923        UINT16                    size,              //   IN: size of NV data
924        void                     *data               //   OUT: data buffer
925        )
926   {
927
928        pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET);
929
930        if(   nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
931           || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET)
932        {
933            // Read bit or counter data in canonical form
934            UINT64      dataInInt;
935            NvGetIntIndexData(handle, nvIndex, &dataInInt);
936            UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data);
937        }
938        else
939        {
940            if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
941            {
942                UINT32      ramAddr;
943
944                  // Get data from RAM buffer
945                  ramAddr = NvGetRAMIndexOffset(handle);
946                  MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size);
947             }
948             else
949             {
950                  UINT32      entityAddr;
951                  entityAddr = NvFindHandle(handle);
952                  // Get data from NV
953                  // Skip NV Index info, read data buffer
954                  entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
955                  // Read the data
956                  _plat__NvMemoryRead(entityAddr, size, data);
957            }
958        }
959        return;
960   }


      8.4.7.9     NvGetIntIndexData()

      Get data in integer format of a bit or counter NV Index.
      This function requires that the NV Index is defined and that the NV Index previously has been written.

961   void
962   NvGetIntIndexData(
963        TPMI_RH_NV_INDEX          handle,            // IN: handle
964        NV_INDEX                 *nvIndex,           // IN: RAM image of NV Index header
965        UINT64                   *data               // IN: UINT64 pointer for counter or bit
966        )
967   {
968        // Validate that index has been written and is the right type
969        pAssert(   nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET
970                && (   nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
971                    || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET

      Page 140                                     TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
       Part 4: Supporting Routines                                                 Trusted Platform Module Library

 972                       )
 973                  );
 974
 975        // bit and counter value is store in native format for TPM CPU.                  So we directly
 976        // copy the contents of NV to output data buffer
 977        if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
 978        {
 979            UINT32      ramAddr;
 980
 981              // Get data from RAM buffer
 982              ramAddr = NvGetRAMIndexOffset(handle);
 983              MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data));
 984        }
 985        else
 986        {
 987            UINT32      entityAddr;
 988            entityAddr = NvFindHandle(handle);
 989
 990              // Get data from NV
 991              // Skip NV Index info, read data buffer
 992              _plat__NvMemoryRead(
 993                  entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX),
 994                  sizeof(UINT64), data);
 995        }
 996
 997        return;
 998   }


       8.4.7.10    NvWriteIndexInfo()

       This function is called to queue the write of NV Index data to persistent memory.
       This function requires that NV Index is defined.

       Error Returns                        Meaning

       TPM_RC_NV_RATE                       NV is rate limiting so retry
       TPM_RC_NV_UNAVAILABLE                NV is not available

 999   TPM_RC
1000   NvWriteIndexInfo(
1001        TPMI_RH_NV_INDEX            handle,                // IN: handle
1002        NV_INDEX                   *nvIndex                // IN: NV Index info to be written
1003        )
1004   {
1005        UINT32             entryAddr;
1006        TPM_RC             result;
1007
1008        // Get the starting offset for the index in the RAM image of NV
1009        entryAddr = NvFindHandle(handle);
1010        pAssert(entryAddr != 0);
1011
1012        // Step over the link value
1013        entryAddr = entryAddr + sizeof(TPM_HANDLE);
1014
1015        // If the index data is actually changed, then a write to NV is required
1016        if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex))
1017        {
1018            // Make sure that NV is available
1019            result = NvIsAvailable();
1020            if(result != TPM_RC_SUCCESS)
1021                return result;
1022            _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex);
1023            g_updateNV = TRUE;

       Family "2.0"                                       TCG Published                                 Page 141
       Level 00 Revision 01.16                   Copyright © TCG 2006-2014                     October 30, 2014
       Trusted Platform Module Library                                               Part 4: Supporting Routines

1024        }
1025        return TPM_RC_SUCCESS;
1026   }


       8.4.7.11     NvWriteIndexData()

       This function is used to write NV index data.
       This function requires that the NV Index is defined, and the data is within the defined data range for the
       index.

       Error Returns                     Meaning

       TPM_RC_NV_RATE                    NV is rate limiting so retry
       TPM_RC_NV_UNAVAILABLE             NV is not available

1027   TPM_RC
1028   NvWriteIndexData(
1029        TPMI_RH_NV_INDEX          handle,               //   IN: handle
1030        NV_INDEX                 *nvIndex,              //   IN: RAM copy of NV Index
1031        UINT32                    offset,               //   IN: offset of NV data
1032        UINT32                    size,                 //   IN: size of NV data
1033        void                     *data                  //   OUT: data buffer
1034        )
1035   {
1036        TPM_RC               result;
1037        // Validate that write falls within range of the index
1038        pAssert(nvIndex->publicArea.dataSize >= offset + size);
1039
1040        // Update TPMA_NV_WRITTEN bit if necessary
1041        if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
1042        {
1043            nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET;
1044            result = NvWriteIndexInfo(handle, nvIndex);
1045            if(result != TPM_RC_SUCCESS)
1046                return result;
1047        }
1048
1049        // Check to see if process for an orderly index is required.
1050        if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1051        {
1052            UINT32      ramAddr;
1053
1054              // Write data to RAM buffer
1055              ramAddr = NvGetRAMIndexOffset(handle);
1056              MemoryCopy(s_ramIndex + ramAddr + offset, data, size,
1057                         sizeof(s_ramIndex) - ramAddr - offset);
1058
1059              // NV update does not happen for orderly index. Have
1060              // to clear orderlyState to reflect that we have changed the
1061              // NV and an orderly shutdown is required. Only going to do this if we
1062              // are not processing a counter that has just rolled over
1063              if(g_updateNV == FALSE)
1064                  g_clearOrderly = TRUE;
1065        }
1066        // Need to process this part if the Index isn't orderly or if it is
1067        // an orderly counter that just rolled over.
1068        if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR)
1069        {
1070            // Processing for an index with TPMA_NV_ORDERLY CLEAR
1071            UINT32      entryAddr = NvFindHandle(handle);
1072
1073              pAssert(entryAddr != 0);


       Page 142                                        TCG Published                               Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
       Part 4: Supporting Routines                                           Trusted Platform Module Library

1074
1075              // Offset into the index to the first byte of the data to be written
1076              entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
1077
1078              // If the data is actually changed, then a write to NV is required
1079              if(_plat__NvIsDifferent(entryAddr, size, data))
1080              {
1081                  // Make sure that NV is available
1082                  result = NvIsAvailable();
1083                  if(result != TPM_RC_SUCCESS)
1084                      return result;
1085                  _plat__NvMemoryWrite(entryAddr, size, data);
1086                  g_updateNV = TRUE;
1087              }
1088        }
1089        return TPM_RC_SUCCESS;
1090   }


       8.4.7.12     NvGetName()

       This function is used to compute the Name of an NV Index.
       The name buffer receives the bytes of the Name and the return value is the number of octets in the
       Name.
       This function requires that the NV Index is defined.

1091   UINT16
1092   NvGetName(
1093        TPMI_RH_NV_INDEX          handle,            // IN: handle of the index
1094        NAME                     *name               // OUT: name of the index
1095        )
1096   {
1097        UINT16                    dataSize, digestSize;
1098        NV_INDEX                  nvIndex;
1099        BYTE                      marshalBuffer[sizeof(TPMS_NV_PUBLIC)];
1100        BYTE                     *buffer;
1101        HASH_STATE                hashState;
1102
1103        // Get NV public info
1104        NvGetIndexInfo(handle, &nvIndex);
1105
1106        // Marshal public area
1107        buffer = marshalBuffer;
1108        dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, NULL);
1109
1110        // hash public area
1111        digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState);
1112        CryptUpdateDigest(&hashState, dataSize, marshalBuffer);
1113
1114        // Complete digest leaving room for the nameAlg
1115        CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]);
1116
1117        // Include the nameAlg
1118        UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name);
1119        return digestSize + 2;
1120   }


       8.4.7.13     NvDefineIndex()

       This function is used to assign NV memory to an NV Index.



       Family "2.0"                                 TCG Published                                 Page 143
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                    October 30, 2014
       Trusted Platform Module Library                                            Part 4: Supporting Routines


       Error Returns                     Meaning

       TPM_RC_NV_SPACE                   insufficient NV space

1121   TPM_RC
1122   NvDefineIndex(
1123       TPMS_NV_PUBLIC      *publicArea,          // IN: A template for an area to create.
1124       TPM2B_AUTH          *authValue            // IN: The initial authorization value
1125       )
1126   {
1127       // The buffer to be written to NV memory
1128       BYTE            nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)];
1129
1130       NV_INDEX            *nvIndex;                  // a pointer to the NV_INDEX data in
1131                                                      //   nvBuffer
1132       UINT16              entrySize;                 // size of entry
1133
1134       entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize;
1135
1136       // Check if we have enough space to create the NV Index
1137       // In this implementation, the only resource limitation is the available NV
1138       // space. Other implementation may have other limitation on counter or on
1139       // NV slot
1140       if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE;
1141
1142       // if the index to be defined is RAM backed, check RAM space availability
1143       // as well
1144       if(publicArea->attributes.TPMA_NV_ORDERLY == SET
1145               && !NvTestRAMSpace(publicArea->dataSize))
1146           return TPM_RC_NV_SPACE;
1147
1148       // Copy input value to nvBuffer
1149           // Copy handle
1150       * (TPM_HANDLE *) nvBuffer = publicArea->nvIndex;
1151
1152           // Copy NV_INDEX
1153       nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE));
1154       nvIndex->publicArea = *publicArea;
1155       nvIndex->authValue = *authValue;
1156
1157       // Add index to NV memory
1158       NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer);
1159
1160       // If the data of NV Index is RAM backed, add the data area in RAM as well
1161       if(publicArea->attributes.TPMA_NV_ORDERLY == SET)
1162           NvAddRAM(publicArea->nvIndex, publicArea->dataSize);
1163
1164       return TPM_RC_SUCCESS;
1165   }


       8.4.7.14    NvAddEvictObject()

       This function is used to assign NV memory to a persistent object.

       Error Returns                     Meaning

       TPM_RC_NV_HANDLE                  the requested handle is already in use
       TPM_RC_NV_SPACE                   insufficient NV space

1166   TPM_RC
1167   NvAddEvictObject(
1168       TPMI_DH_OBJECT       evictHandle,         // IN: new evict handle


       Page 144                                       TCG Published                             Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014            Level 00 Revision 01.16
       Part 4: Supporting Routines                                            Trusted Platform Module Library

1169        OBJECT              *object              // IN: object to be added
1170        )
1171   {
1172        // The buffer to be written to NV memory
1173        BYTE            nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)];
1174
1175        OBJECT              *nvObject;                // a pointer to the OBJECT data in
1176                                                      // nvBuffer
1177        UINT16              entrySize;                // size of entry
1178
1179        // evict handle type should match the object hierarchy
1180        pAssert(   (   NvIsPlatformPersistentHandle(evictHandle)
1181                    && object->attributes.ppsHierarchy == SET)
1182                || (   NvIsOwnerPersistentHandle(evictHandle)
1183                    && (   object->attributes.spsHierarchy == SET
1184                        || object->attributes.epsHierarchy == SET)));
1185
1186        // An evict needs 4 bytes of handle + sizeof OBJECT
1187        entrySize = sizeof(TPM_HANDLE) + sizeof(OBJECT);
1188
1189        // Check if we have enough space to add the evict object
1190        // An evict object needs 8 bytes in index table + sizeof OBJECT
1191        // In this implementation, the only resource limitation is the available NV
1192        // space. Other implementation may have other limitation on evict object
1193        // handle space
1194        if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE;
1195
1196        // Allocate a new evict handle
1197        if(!NvIsUndefinedEvictHandle(evictHandle))
1198            return TPM_RC_NV_DEFINED;
1199
1200        // Copy evict object to nvBuffer
1201            // Copy handle
1202        * (TPM_HANDLE *) nvBuffer = evictHandle;
1203
1204            // Copy OBJECT
1205        nvObject = (OBJECT *) (nvBuffer + sizeof(TPM_HANDLE));
1206        *nvObject = *object;
1207
1208        // Set evict attribute and handle
1209        nvObject->attributes.evict = SET;
1210        nvObject->evictHandle = evictHandle;
1211
1212        // Add evict to NV memory
1213        NvAdd(entrySize, entrySize, nvBuffer);
1214
1215        return TPM_RC_SUCCESS;
1216
1217   }


       8.4.7.15    NvDeleteEntity()

       This function will delete a NV Index or an evict object.
       This function requires that the index/evict object has been defined.

1218   void
1219   NvDeleteEntity(
1220        TPM_HANDLE           handle              // IN: handle of entity to be deleted
1221        )
1222   {
1223        UINT32         entityAddr;         // pointer to entity
1224
1225        entityAddr = NvFindHandle(handle);
1226        pAssert(entityAddr != 0);

       Family "2.0"                                  TCG Published                                 Page 145
       Level 00 Revision 01.16               Copyright © TCG 2006-2014                    October 30, 2014
       Trusted Platform Module Library                                                 Part 4: Supporting Routines

1227
1228        if(HandleGetType(handle) == TPM_HT_NV_INDEX)
1229        {
1230            NV_INDEX    nvIndex;
1231
1232              // Read the NV Index info
1233              _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1234                                  &nvIndex);
1235
1236              // If the entity to be deleted is a counter with the maximum counter
1237              // value, record it in NV memory
1238              if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
1239                      && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
1240              {
1241                  UINT64      countValue;
1242                  UINT64      maxCount;
1243                  NvGetIntIndexData(handle, &nvIndex, &countValue);
1244                  maxCount = NvReadMaxCount();
1245                  if(countValue > maxCount)
1246                      NvWriteMaxCount(countValue);
1247              }
1248              // If the NV Index is RAM back, delete the RAM data as well
1249              if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
1250                  NvDeleteRAM(handle);
1251        }
1252        NvDelete(entityAddr);
1253
1254        return;
1255
1256   }


       8.4.7.16     NvFlushHierarchy()

       This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected,
       the function will also delete any NV Index define using ownerAuth.

1257   void
1258   NvFlushHierarchy(
1259        TPMI_RH_HIERARCHY         hierarchy          // IN: hierarchy to be flushed.
1260        )
1261   {
1262        NV_ITER             iter = NV_ITER_INIT;
1263        UINT32              currentAddr;
1264
1265        while((currentAddr = NvNext(&iter)) != 0)
1266        {
1267            TPM_HANDLE      entityHandle;
1268
1269              // Read handle information.
1270              _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1271
1272              if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX)
1273              {
1274                  // Handle NV Index
1275                  NV_INDEX    nvIndex;
1276
1277                  // If flush endorsement or platform hierarchy, no NV Index would be
1278                  // flushed
1279                  if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
1280                      continue;
1281                  _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1282                                      sizeof(NV_INDEX), &nvIndex);
1283
1284                  // For storage hierarchy, flush OwnerCreated index

       Page 146                                      TCG Published                                    Family "2.0"
       October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
       Part 4: Supporting Routines                                         Trusted Platform Module Library

1285                   if(    nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
1286                   {
1287                         // Delete the NV Index
1288                         NvDelete(currentAddr);
1289
1290                         // Re-iterate from beginning after a delete
1291                         iter = NV_ITER_INIT;
1292
1293                         // If the NV Index is RAM back, delete the RAM data as well
1294                         if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
1295                             NvDeleteRAM(entityHandle);
1296                  }
1297              }
1298              else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT)
1299              {
1300                  OBJECT          object;
1301
1302                   // Get evict object
1303                   NvGetEvictObject(entityHandle, &object);
1304
1305                   // If the evict object belongs to the hierarchy to be flushed
1306                   if(     (    hierarchy == TPM_RH_PLATFORM
1307                            && object.attributes.ppsHierarchy == SET)
1308                       || (     hierarchy == TPM_RH_OWNER
1309                            && object.attributes.spsHierarchy == SET)
1310                       || (     hierarchy == TPM_RH_ENDORSEMENT
1311                            && object.attributes.epsHierarchy == SET)
1312                       )
1313                   {
1314                         // Delete the evict object
1315                         NvDelete(currentAddr);
1316
1317                         // Re-iterate from beginning after a delete
1318                         iter = NV_ITER_INIT;
1319                   }
1320              }
1321              else
1322              {
1323                   pAssert(FALSE);
1324              }
1325       }
1326
1327       return;
1328   }


       8.4.7.17       NvSetGlobalLock()

       This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have
       TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock().

1329   void
1330   NvSetGlobalLock(
1331       void
1332       )
1333   {
1334       NV_ITER               iter = NV_ITER_INIT;
1335       UINT32                currentAddr;
1336
1337       // Check all Indices
1338       while((currentAddr = NvNextIndex(&iter)) != 0)
1339       {
1340           NV_INDEX    nvIndex;
1341
1342              // Read the index data

       Family "2.0"                              TCG Published                                  Page 147
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                   October 30, 2014
       Trusted Platform Module Library                                             Part 4: Supporting Routines

1343              _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1344                                  sizeof(NV_INDEX), &nvIndex);
1345
1346              // See if it should be locked
1347              if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET)
1348              {
1349
1350                    // if so, lock it
1351                    nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET;
1352
1353                    _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE),
1354                                         sizeof(NV_INDEX), &nvIndex);
1355                    // Set the flag that a NV write happens
1356                    g_updateNV = TRUE;
1357              }
1358       }
1359
1360       return;
1361
1362   }


       8.4.7.18       InsertSort()

       Sort a handle into handle list in ascending order. The total handle number in the list should not exceed
       MAX_CAP_HANDLES

1363   static void
1364   InsertSort(
1365       TPML_HANDLE           *handleList,     // IN/OUT: sorted handle list
1366       UINT32                 count,          // IN: maximum count in the handle list
1367       TPM_HANDLE             entityHandle    // IN: handle to be inserted
1368       )
1369   {
1370       UINT32                i, j;
1371       UINT32                originalCount;
1372
1373       // For a corner case that the maximum count is 0, do nothing
1374       if(count == 0) return;
1375
1376       // For empty list, add the handle at the beginning and return
1377       if(handleList->count == 0)
1378       {
1379           handleList->handle[0] = entityHandle;
1380           handleList->count++;
1381           return;
1382       }
1383
1384       // Check if the maximum of the list has been reached
1385       originalCount = handleList->count;
1386       if(originalCount < count)
1387           handleList->count++;
1388
1389       // Insert the handle to the list
1390       for(i = 0; i < originalCount; i++)
1391       {
1392           if(handleList->handle[i] > entityHandle)
1393           {
1394               for(j = handleList->count - 1; j > i; j--)
1395               {
1396                   handleList->handle[j] = handleList->handle[j-1];
1397               }
1398               break;
1399           }
1400       }

       Page 148                                   TCG Published                                   Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014                 Level 00 Revision 01.16
       Part 4: Supporting Routines                                                     Trusted Platform Module Library

1401
1402         // If a slot was found, insert the handle in this position
1403         if(i < originalCount || handleList->count > originalCount)
1404             handleList->handle[i] = entityHandle;
1405
1406         return;
1407   }


       8.4.7.19     NvCapGetPersistent()

       This function is used to get a list of handles of the persistent objects, starting at handle.
       Handle must be in valid persistent object handle range, but does not have to reference an existing
       persistent object.

       Return Value                      Meaning

       YES                               if there are more handles available
       NO                                all the available handles has been returned

1408   TPMI_YES_NO
1409   NvCapGetPersistent(
1410         TPMI_DH_OBJECT       handle,            // IN: start handle
1411         UINT32               count,             // IN: maximum number of returned handle
1412         TPML_HANDLE         *handleList         // OUT: list of handle
1413         )
1414   {
1415         TPMI_YES_NO               more = NO;
1416         NV_ITER                   iter = NV_ITER_INIT;
1417         UINT32                    currentAddr;
1418
1419         pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1420
1421         // Initialize output handle list
1422         handleList->count = 0;
1423
1424         // The maximum count of handles we may return is MAX_CAP_HANDLES
1425         if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1426
1427         while((currentAddr = NvNextEvict(&iter)) != 0)
1428         {
1429             TPM_HANDLE      entityHandle;
1430
1431              // Read handle information.
1432              _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1433
1434              // Ignore persistent handles that have values less than the input handle
1435              if(entityHandle < handle)
1436                  continue;
1437
1438              // if the handles in the list have reached the requested count, and there
1439              // are still handles need to be inserted, indicate that there are more.
1440              if(handleList->count == count)
1441                  more = YES;
1442
1443              // A handle with a value larger than start handle is a candidate
1444              // for return. Insert sort it to the return list. Insert sort algorithm
1445              // is chosen here for simplicity based on the assumption that the total
1446              // number of NV Indices is small. For an implementation that may allow
1447              // large number of NV Indices, a more efficient sorting algorithm may be
1448              // used here.
1449              InsertSort(handleList, count, entityHandle);
1450


       Family "2.0"                                   TCG Published                                         Page 149
       Level 00 Revision 01.16                Copyright © TCG 2006-2014                            October 30, 2014
       Trusted Platform Module Library                                                 Part 4: Supporting Routines

1451         }
1452         return more;
1453   }


       8.4.7.20     NvCapGetIndex()

       This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of
       NV Indices, but does not have to reference an existing NV Index.

       Return Value                      Meaning

       YES                               if there are more handles to report
       NO                                all the available handles has been reported

1454   TPMI_YES_NO
1455   NvCapGetIndex(
1456         TPMI_DH_OBJECT     handle,              // IN: start handle
1457         UINT32             count,               // IN: maximum number of returned handle
1458         TPML_HANDLE       *handleList           // OUT: list of handle
1459         )
1460   {
1461         TPMI_YES_NO             more = NO;
1462         NV_ITER                 iter = NV_ITER_INIT;
1463         UINT32                  currentAddr;
1464
1465         pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1466
1467         // Initialize output handle list
1468         handleList->count = 0;
1469
1470         // The maximum count of handles we may return is MAX_CAP_HANDLES
1471         if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1472
1473         while((currentAddr = NvNextIndex(&iter)) != 0)
1474         {
1475             TPM_HANDLE      entityHandle;
1476
1477              // Read handle information.
1478              _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1479
1480              // Ignore index handles that have values less than the 'handle'
1481              if(entityHandle < handle)
1482                  continue;
1483
1484              // if the count of handles in the list has reached the requested count,
1485              // and there are still handles to report, set more.
1486              if(handleList->count == count)
1487                  more = YES;
1488
1489              // A handle with a value larger than start handle is a candidate
1490              // for return. Insert sort it to the return list. Insert sort algorithm
1491              // is chosen here for simplicity based on the assumption that the total
1492              // number of NV Indices is small. For an implementation that may allow
1493              // large number of NV Indices, a more efficient sorting algorithm may be
1494              // used here.
1495              InsertSort(handleList, count, entityHandle);
1496         }
1497         return more;
1498   }




       Page 150                                       TCG Published                                  Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
       Part 4: Supporting Routines                                                Trusted Platform Module Library

       8.4.7.21    NvCapGetIndexNumber()

       This function returns the count of NV Indexes currently defined.

1499   UINT32
1500   NvCapGetIndexNumber(
1501       void
1502       )
1503   {
1504       UINT32              num = 0;
1505       NV_ITER             iter = NV_ITER_INIT;
1506
1507       while(NvNextIndex(&iter) != 0) num++;
1508
1509       return num;
1510   }


       8.4.7.22    NvCapGetPersistentNumber()

       Function returns the count of persistent objects currently in NV memory.

1511   UINT32
1512   NvCapGetPersistentNumber(
1513       void
1514       )
1515   {
1516       UINT32              num = 0;
1517       NV_ITER             iter = NV_ITER_INIT;
1518
1519       while(NvNextEvict(&iter) != 0) num++;
1520
1521       return num;
1522   }


       8.4.7.23    NvCapGetPersistentAvail()

       This function returns an estimate of the number of additional persistent objects that could be loaded into
       NV memory.

1523   UINT32
1524   NvCapGetPersistentAvail(
1525       void
1526       )
1527   {
1528       UINT32              availSpace;
1529       UINT32              objectSpace;
1530
1531       // Compute the available space in NV storage
1532       availSpace = NvGetFreeByte();
1533
1534       // Get the space needed to add a persistent object to NV storage
1535       objectSpace = NvGetEvictObjectSize();
1536
1537       return availSpace / objectSpace;
1538   }


       8.4.7.24    NvCapGetCounterNumber()

       Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET.



       Family "2.0"                                TCG Published                                       Page 151
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
       Trusted Platform Module Library                                               Part 4: Supporting Routines

1539   UINT32
1540   NvCapGetCounterNumber(
1541       void
1542       )
1543   {
1544       NV_ITER             iter = NV_ITER_INIT;
1545       UINT32              currentAddr;
1546       UINT32              num = 0;
1547
1548       while((currentAddr = NvNextIndex(&iter)) != 0)
1549       {
1550           NV_INDEX    nvIndex;
1551
1552              // Get NV Index info
1553              _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1554                                   sizeof(NV_INDEX), &nvIndex);
1555              if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++;
1556       }
1557
1558       return num;
1559   }


       8.4.7.25     NvCapGetCounterAvail()

       This function returns an estimate of the number of additional counter type NV Indices that can be defined.

1560   UINT32
1561   NvCapGetCounterAvail(
1562       void
1563       )
1564   {
1565       UINT32              availNVSpace;
1566       UINT32              availRAMSpace;
1567       UINT32              counterNVSpace;
1568       UINT32              counterRAMSpace;
1569       UINT32              persistentNum = NvCapGetPersistentNumber();
1570
1571       // Get the available space in NV storage
1572       availNVSpace = NvGetFreeByte();
1573
1574       if (persistentNum < MIN_EVICT_OBJECTS)
1575       {
1576           // Some space have to be reserved for evict object. Adjust availNVSpace.
1577           UINT32       reserved = (MIN_EVICT_OBJECTS - persistentNum)
1578                                  * NvGetEvictObjectSize();
1579           if (reserved > availNVSpace)
1580                availNVSpace = 0;
1581           else
1582                availNVSpace -= reserved;
1583       }
1584
1585       // Get the space needed to add a counter index to NV storage
1586       counterNVSpace = NvGetCounterSize();
1587
1588       // Compute the available space in RAM
1589       availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize;
1590
1591       // Compute the space needed to add a counter index to RAM storage
1592       // It takes an size field, a handle and sizeof(UINT64) for counter data
1593       counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64);
1594
1595       // Return the min of counter number in NV and in RAM
1596       if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace)
1597           return availRAMSpace / counterRAMSpace;

       Page 152                                    TCG Published                                    Family "2.0"
       October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
       Part 4: Supporting Routines                                                 Trusted Platform Module Library

1598         else
1599             return availNVSpace / counterNVSpace;
1600   }


       8.5     Object.c

       8.5.1     Introduction

       This file contains the functions that manage the object store of the TPM.

       8.5.2     Includes and Data Definitions

   1   #define OBJECT_C
   2   #include "InternalRoutines.h"
   3   #include <Platform.h>


       8.5.3     Functions

       8.5.3.1      ObjectStartup()

       This function is called at TPM2_Startup() to initialize the object subsystem.

   4   void
   5   ObjectStartup(
   6         void
   7         )
   8   {
   9         UINT32        i;
  10
  11         // object slots initialization
  12         for(i = 0; i < MAX_LOADED_OBJECTS; i++)
  13         {
  14             //Set the slot to not occupied
  15             s_objects[i].occupied = FALSE;
  16         }
  17         return;
  18   }


       8.5.3.2      ObjectCleanupEvict()

       In this implementation, a persistent object is moved from NV into an object slot for processing. It is
       flushed after command execution. This function is called from ExecuteCommand().

  19   void
  20   ObjectCleanupEvict(
  21         void
  22         )
  23   {
  24         UINT32        i;
  25
  26         // This has to be iterated because a command may have two handles
  27         // and they may both be persistent.
  28         // This could be made to be more efficient so that a search is not needed.
  29         for(i = 0; i < MAX_LOADED_OBJECTS; i++)
  30         {
  31             // If an object is a temporary evict object, flush it from slot
  32             if(s_objects[i].object.entity.attributes.evict == SET)
  33                 s_objects[i].occupied = FALSE;
  34         }

       Family "2.0"                                 TCG Published                                       Page 153
       Level 00 Revision 01.16               Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                    Part 4: Supporting Routines

35
36       return;
37   }


     8.5.3.3     ObjectIsPresent()

     This function checks to see if a transient handle references a loaded object. This routine should not be
     called if the handle is not a transient handle. The function validates that the handle is in the
     implementation-dependent allowed in range for loaded transient objects.

     Return Value                      Meaning

     TRUE                              if the handle references a loaded object
     FALSE                             if the handle is not an object handle, or it does not reference to a
                                       loaded object

38   BOOL
39   ObjectIsPresent(
40       TPMI_DH_OBJECT        handle              // IN: handle to be checked
41       )
42   {
43       UINT32              slotIndex;                  // index of object slot
44
45       pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
46
47       // The index in the loaded object array is found by subtracting the first
48       // object handle number from the input handle number. If the indicated
49       // slot is occupied, then indicate that there is already is a loaded
50       // object associated with the handle.
51       slotIndex = handle - TRANSIENT_FIRST;
52       if(slotIndex >= MAX_LOADED_OBJECTS)
53           return FALSE;
54
55       return s_objects[slotIndex].occupied;
56   }


     8.5.3.4     ObjectIsSequence()

     This function is used to check if the object is a sequence object. This function should not be called if the
     handle does not reference a loaded object.

     Return Value                      Meaning

     TRUE                              object is an HMAC, hash, or event sequence object
     FALSE                             object is not an HMAC, hash, or event sequence object

57   BOOL
58   ObjectIsSequence(
59       OBJECT              *object               // IN: handle to be checked
60       )
61   {
62       pAssert (object != NULL);
63       if(   object->attributes.hmacSeq == SET
64          || object->attributes.hashSeq == SET
65          || object->attributes.eventSeq == SET)
66           return TRUE;
67       else
68           return FALSE;
69   }



     Page 154                                       TCG Published                                       Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                      Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library

      8.5.3.5     ObjectGet()

      This function is used to find the object structure associated with a handle.
      This function requires that handle references a loaded object.

 70   OBJECT*
 71   ObjectGet(
 72        TPMI_DH_OBJECT       handle             // IN: handle of the object
 73        )
 74   {
 75        pAssert(   handle >= TRANSIENT_FIRST
 76                && handle - TRANSIENT_FIRST < MAX_LOADED_OBJECTS);
 77        pAssert(s_objects[handle - TRANSIENT_FIRST].occupied == TRUE);
 78
 79        // In this implementation, the handle is determined by the slot occupied by the
 80        // object.
 81        return &s_objects[handle - TRANSIENT_FIRST].object.entity;
 82   }


      8.5.3.6     ObjectGetName()

      This function is used to access the Name of the object. In this implementation, the Name is computed
      when the object is loaded and is saved in the internal representation of the object. This function copies
      the Name data from the object into the buffer at name and returns the number of octets copied.
      This function requires that handle references a loaded object.

 83   UINT16
 84   ObjectGetName(
 85        TPMI_DH_OBJECT       handle,            // IN: handle of the object
 86        NAME                *name               // OUT: name of the object
 87        )
 88   {
 89        OBJECT      *object = ObjectGet(handle);
 90        if(object->publicArea.nameAlg == TPM_ALG_NULL)
 91            return 0;
 92
 93        // Copy the Name data to the output
 94        MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME));
 95        return object->name.t.size;
 96   }


      8.5.3.7     ObjectGetNameAlg()

      This function is used to get the Name algorithm of a object.
      This function requires that handle references a loaded object.

 97   TPMI_ALG_HASH
 98   ObjectGetNameAlg(
 99        TPMI_DH_OBJECT       handle             // IN: handle of the object
100        )
101   {
102        OBJECT                   *object = ObjectGet(handle);
103
104        return object->publicArea.nameAlg;
105   }




      Family "2.0"                                 TCG Published                                          Page 155
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines

      8.5.3.8     ObjectGetQualifiedName()

      This function returns the Qualified Name of the object. In this implementation, the Qualified Name is
      computed when the object is loaded and is saved in the internal representation of the object. The
      alternative would be to retain the Name of the parent and compute the QN when needed. This would take
      the same amount of space so it is not recommended that the alternate be used.
      This function requires that handle references a loaded object.

106   void
107   ObjectGetQualifiedName(
108        TPMI_DH_OBJECT       handle,            // IN: handle of the object
109        TPM2B_NAME          *qualifiedName      // OUT: qualified name of the object
110        )
111   {
112        OBJECT      *object = ObjectGet(handle);
113        if(object->publicArea.nameAlg == TPM_ALG_NULL)
114            qualifiedName->t.size = 0;
115        else
116            // Copy the name
117            *qualifiedName = object->qualifiedName;
118
119        return;
120   }


      8.5.3.9     ObjectDataGetHierarchy()

      This function returns the handle for the hierarchy of an object.

121   TPMI_RH_HIERARCHY
122   ObjectDataGetHierarchy(
123        OBJECT              *object             // IN :object
124        )
125   {
126        if(object->attributes.spsHierarchy)
127        {
128            return TPM_RH_OWNER;
129        }
130        else if(object->attributes.epsHierarchy)
131        {
132            return TPM_RH_ENDORSEMENT;
133        }
134        else if(object->attributes.ppsHierarchy)
135        {
136            return TPM_RH_PLATFORM;
137        }
138        else
139        {
140            return TPM_RH_NULL;
141        }
142
143   }


      8.5.3.10    ObjectGetHierarchy()

      This function returns the handle of the hierarchy to which a handle belongs. This function is similar to
      ObjectDataGetHierarchy() but this routine takes a handle but ObjectDataGetHierarchy() takes an pointer
      to an object.
      This function requires that handle references a loaded object.

144   TPMI_RH_HIERARCHY

      Page 156                                      TCG Published                                Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

145   ObjectGetHierarchy(
146        TPMI_DH_OBJECT        handle              // IN :object handle
147        )
148   {
149        OBJECT               *object = ObjectGet(handle);
150
151        return ObjectDataGetHierarchy(object);
152   }


      8.5.3.11     ObjectAllocateSlot()

      This function is used to allocate a slot in internal object array.

      Return Value                       Meaning

      TRUE                               allocate success
      FALSE                              do not have free slot

153   static BOOL
154   ObjectAllocateSlot(
155        TPMI_DH_OBJECT       *handle,             // OUT: handle of allocated object
156        OBJECT               **object             // OUT: points to the allocated object
157        )
158   {
159        UINT32          i;
160
161        // find an unoccupied handle slot
162        for(i = 0; i < MAX_LOADED_OBJECTS; i++)
163        {
164            if(!s_objects[i].occupied)          // If found a free slot
165            {
166                // Mark the slot as occupied
167                s_objects[i].occupied = TRUE;
168                break;
169            }
170        }
171        // If we reach the end of object slot without finding a free one, return
172        // error.
173        if(i == MAX_LOADED_OBJECTS) return FALSE;
174
175        *handle = i + TRANSIENT_FIRST;
176        *object = &s_objects[i].object.entity;
177
178        // Initialize the object attributes
179        MemorySet(&((*object)->attributes), 0, sizeof(OBJECT_ATTRIBUTES));
180
181        return TRUE;
182   }


      8.5.3.12     ObjectLoad()

      This function loads an object into an internal object structure. If an error is returned, the internal state is
      unchanged.




      Family "2.0"                                    TCG Published                                       Page 157
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                        Part 4: Supporting Routines


      Error Returns                     Meaning

      TPM_RC_BINDING                    if the public and sensitive parts of the object are not matched
      TPM_RC_KEY                        if the parameters in the public area of the object are not consistent
      TPM_RC_OBJECT_MEMORY              if there is no free slot for an object
      TPM_RC_TYPE                       the public and private parts are not the same type

183   TPM_RC
184   ObjectLoad(
185       TPMI_RH_HIERARCHY        hierarchy,               //   IN: hierarchy to which the object belongs
186       TPMT_PUBLIC             *publicArea,              //   IN: public area
187       TPMT_SENSITIVE          *sensitive,               //   IN: sensitive area (may be null)
188       TPM2B_NAME              *name,                    //   IN: object's name (may be null)
189       TPM_HANDLE               parentHandle,            //   IN: handle of parent
190       BOOL                     skipChecks,              //   IN: flag to indicate if it is OK to skip
191                                                         //       consistency checks.
192       TPMI_DH_OBJECT          *handle                   //   OUT: object handle
193       )
194   {
195       OBJECT                   *object = NULL;
196       OBJECT                   *parent = NULL;
197       TPM_RC                    result = TPM_RC_SUCCESS;
198       TPM2B_NAME                parentQN;         // Parent qualified name
199
200       // Try to allocate a slot for new object
201       if(!ObjectAllocateSlot(handle, &object))
202           return TPM_RC_OBJECT_MEMORY;
203
204       // Initialize public
205       object->publicArea = *publicArea;
206       if(sensitive != NULL)
207           object->sensitive = *sensitive;
208
209       // Are the consistency checks needed
210       if(!skipChecks)
211       {
212           // Check if key size matches
213           if(!CryptObjectIsPublicConsistent(&object->publicArea))
214           {
215               result = TPM_RC_KEY;
216               goto ErrorExit;
217           }
218           if(sensitive != NULL)
219           {
220               // Check if public type matches sensitive type
221               result = CryptObjectPublicPrivateMatch(object);
222               if(result != TPM_RC_SUCCESS)
223                   goto ErrorExit;
224           }
225       }
226       object->attributes.publicOnly = (sensitive == NULL);
227
228       // If 'name' is NULL, then there is nothing left to do for this
229       // object as it has no qualified name and it is not a member of any
230       // hierarchy and it is temporary
231       if(name == NULL || name->t.size == 0)
232       {
233           object->qualifiedName.t.size = 0;
234           object->name.t.size = 0;
235           object->attributes.temporary = SET;
236           return TPM_RC_SUCCESS;
237       }
238       // If parent handle is a permanent handle, it is a primary or temporary

      Page 158                                         TCG Published                                            Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                        Level 00 Revision 01.16
      Part 4: Supporting Routines                                   Trusted Platform Module Library

239       // object
240       if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
241       {
242           // initialize QN
243           parentQN.t.size = 4;
244
245            // for a primary key, parent qualified name is the handle of hierarchy
246            UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name);
247       }
248       else
249       {
250           // Get hierarchy and qualified name of parent
251           ObjectGetQualifiedName(parentHandle, &parentQN);
252
253            // Check for stClear object
254            parent = ObjectGet(parentHandle);
255            if(    publicArea->objectAttributes.stClear == SET
256                || parent->attributes.stClear == SET)
257                 object->attributes.stClear = SET;
258
259       }
260       object->name = *name;
261
262       // Compute object qualified name
263       ObjectComputeQualifiedName(&parentQN, publicArea->nameAlg,
264                                  name, &object->qualifiedName);
265
266       // Any object in TPM_RH_NULL hierarchy is temporary
267       if(hierarchy == TPM_RH_NULL)
268       {
269           object->attributes.temporary = SET;
270       }
271       else if(parentQN.t.size == sizeof(TPM_HANDLE))
272       {
273           // Otherwise, if the size of parent's qualified name is the size of a
274           // handle, this object is a primary object
275           object->attributes.primary = SET;
276       }
277       switch(hierarchy)
278       {
279           case TPM_RH_PLATFORM:
280               object->attributes.ppsHierarchy = SET;
281               break;
282           case TPM_RH_OWNER:
283               object->attributes.spsHierarchy = SET;
284               break;
285           case TPM_RH_ENDORSEMENT:
286               object->attributes.epsHierarchy = SET;
287               break;
288           case TPM_RH_NULL:
289               break;
290           default:
291               pAssert(FALSE);
292               break;
293       }
294       return TPM_RC_SUCCESS;
295
296   ErrorExit:
297       ObjectFlush(*handle);
298       return result;
299   }




      Family "2.0"                         TCG Published                                 Page 159
      Level 00 Revision 01.16        Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

      8.5.3.13    AllocateSequenceSlot()

      This function allocates a sequence slot and initializes the parts that are used by the normal objects so
      that a sequence object is not inadvertently used for an operation that is not appropriate for a sequence.

300   static BOOL
301   AllocateSequenceSlot(
302       TPM_HANDLE          *newHandle,             // OUT: receives the allocated handle
303       HASH_OBJECT         **object,               // OUT: receives pointer to allocated object
304       TPM2B_AUTH          *auth                   // IN: the authValue for the slot
305       )
306   {
307       OBJECT                   *objectHash;                   // the hash as an object
308
309       if(!ObjectAllocateSlot(newHandle, &objectHash))
310           return FALSE;
311
312       *object = (HASH_OBJECT *)objectHash;
313
314       // Validate that the proper location of the hash state data relative to the
315       // object state data.
316       pAssert(&((*object)->auth) == &objectHash->publicArea.authPolicy);
317
318       // Set the common values that a sequence object shares with an ordinary object
319       // The type is TPM_ALG_NULL
320       (*object)->type = TPM_ALG_NULL;
321
322       // This has no name algorithm and the name is the Empty Buffer
323       (*object)->nameAlg = TPM_ALG_NULL;
324
325       // Clear the attributes
326       MemorySet(&((*object)->objectAttributes), 0, sizeof(TPMA_OBJECT));
327
328       // A sequence object is considered to be in the NULL hierarchy so it should
329       // be marked as temporary so that it can't be persisted
330       (*object)->attributes.temporary = SET;
331
332       // A sequence object is DA exempt.
333       (*object)->objectAttributes.noDA = SET;
334
335       if(auth != NULL)
336       {
337           MemoryRemoveTrailingZeros(auth);
338           (*object)->auth = *auth;
339       }
340       else
341           (*object)->auth.t.size = 0;
342       return TRUE;
343   }


      8.5.3.14    ObjectCreateHMACSequence()

      This function creates an internal HMAC sequence object.

      Error Returns                     Meaning

      TPM_RC_OBJECT_MEMORY              if there is no free slot for an object

344   TPM_RC
345   ObjectCreateHMACSequence(
346       TPMI_ALG_HASH        hashAlg,               // IN: hash algorithm
347       TPM_HANDLE           handle,                // IN: the handle associated with sequence
348                                                   //     object

      Page 160                                         TCG Published                               Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

349       TPM2B_AUTH         *auth,                 // IN: authValue
350       TPMI_DH_OBJECT     *newHandle             // OUT: HMAC sequence object handle
351       )
352   {
353       HASH_OBJECT               *hmacObject;
354       OBJECT                    *keyObject;
355
356       // Try to allocate a slot for new object
357       if(!AllocateSequenceSlot(newHandle, &hmacObject, auth))
358           return TPM_RC_OBJECT_MEMORY;
359
360       // Set HMAC sequence bit
361       hmacObject->attributes.hmacSeq = SET;
362
363       // Get pointer to the HMAC key object
364       keyObject = ObjectGet(handle);
365
366       CryptStartHMACSequence2B(hashAlg, &keyObject->sensitive.sensitive.bits.b,
367                                &hmacObject->state.hmacState);
368
369       return TPM_RC_SUCCESS;
370   }


      8.5.3.15   ObjectCreateHashSequence()

      This function creates a hash sequence object.

      Error Returns                   Meaning

      TPM_RC_OBJECT_MEMORY            if there is no free slot for an object

371   TPM_RC
372   ObjectCreateHashSequence(
373       TPMI_ALG_HASH       hashAlg,              // IN: hash algorithm
374       TPM2B_AUTH         *auth,                 // IN: authValue
375       TPMI_DH_OBJECT     *newHandle             // OUT: sequence object handle
376       )
377   {
378       HASH_OBJECT               *hashObject;
379
380       // Try to allocate a slot for new object
381       if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
382           return TPM_RC_OBJECT_MEMORY;
383
384       // Set hash sequence bit
385       hashObject->attributes.hashSeq = SET;
386
387       // Start hash for hash sequence
388       CryptStartHashSequence(hashAlg, &hashObject->state.hashState[0]);
389
390       return TPM_RC_SUCCESS;
391   }


      8.5.3.16   ObjectCreateEventSequence()

      This function creates an event sequence object.

      Error Returns                   Meaning

      TPM_RC_OBJECT_MEMORY            if there is no free slot for an object

392   TPM_RC

      Family "2.0"                                  TCG Published                                   Page 161
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

393   ObjectCreateEventSequence(
394       TPM2B_AUTH          *auth,              // IN: authValue
395       TPMI_DH_OBJECT      *newHandle          // OUT: sequence object handle
396       )
397   {
398       HASH_OBJECT              *hashObject;
399       UINT32                    count;
400       TPM_ALG_ID                hash;
401
402       // Try to allocate a slot for new object
403       if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
404           return TPM_RC_OBJECT_MEMORY;
405
406       // Set the event sequence attribute
407       hashObject->attributes.eventSeq = SET;
408
409       // Initialize hash states for each implemented PCR algorithms
410       for(count = 0; (hash = CryptGetHashAlgByIndex(count)) != TPM_ALG_NULL; count++)
411       {
412           // If this is a _TPM_Init or _TPM_HashStart, the sequence object will
413           // not leave the TPM so it doesn't need the sequence handling
414           if(auth == NULL)
415                CryptStartHash(hash, &hashObject->state.hashState[count]);
416           else
417                CryptStartHashSequence(hash, &hashObject->state.hashState[count]);
418       }
419       return TPM_RC_SUCCESS;
420   }


      8.5.3.17    ObjectTerminateEvent()

      This function is called to close out the event sequence and clean up the hash context states.

421   void
422   ObjectTerminateEvent(
423       void
424       )
425   {
426       HASH_OBJECT         *hashObject;
427       int                  count;
428       BYTE                 buffer[MAX_DIGEST_SIZE];
429       hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
430
431       // Don't assume that this is a proper sequence object
432       if(hashObject->attributes.eventSeq)
433       {
434           // If it is, close any open hash contexts. This is done in case
435           // the crypto implementation has some context values that need to be
436           // cleaned up (hygiene).
437           //
438           for(count = 0; CryptGetHashAlgByIndex(count) != TPM_ALG_NULL; count++)
439           {
440               CryptCompleteHash(&hashObject->state.hashState[count], 0, buffer);
441           }
442           // Flush sequence object
443           ObjectFlush(g_DRTMHandle);
444       }
445
446       g_DRTMHandle = TPM_RH_UNASSIGNED;
447   }




      Page 162                                     TCG Published                                      Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      8.5.3.18    ObjectContextLoad()

      This function loads an object from a saved object context.

      Error Returns                     Meaning

      TPM_RC_OBJECT_MEMORY              if there is no free slot for an object

448   TPM_RC
449   ObjectContextLoad(
450        OBJECT              *object,               // IN: object structure from saved context
451        TPMI_DH_OBJECT      *handle                // OUT: object handle
452        )
453   {
454        OBJECT         *newObject;
455
456        // Try to allocate a slot for new object
457        if(!ObjectAllocateSlot(handle, &newObject))
458            return TPM_RC_OBJECT_MEMORY;
459
460        // Copy input object data to internal structure
461        *newObject = *object;
462
463        return TPM_RC_SUCCESS;
464   }


      8.5.3.19    ObjectFlush()

      This function frees an object slot.
      This function requires that the object is loaded.

465   void
466   ObjectFlush(
467        TPMI_DH_OBJECT        handle               // IN: handle to be freed
468        )
469   {
470        UINT32      index = handle - TRANSIENT_FIRST;
471        pAssert(ObjectIsPresent(handle));
472
473        // Mark the handle slot as unoccupied
474        s_objects[index].occupied = FALSE;
475
476        // With no attributes
477        MemorySet((BYTE*)&(s_objects[index].object.entity.attributes),
478                   0, sizeof(OBJECT_ATTRIBUTES));
479        return;
480   }


      8.5.3.20    ObjectFlushHierarchy()

      This function is called to flush all the loaded transient objects associated with a hierarchy when the
      hierarchy is disabled.

481   void
482   ObjectFlushHierarchy(
483        TPMI_RH_HIERARCHY          hierarchy             // IN: hierarchy to be flush
484        )
485   {
486        UINT16              i;
487
488        // iterate object slots

      Family "2.0"                                    TCG Published                                   Page 163
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                                   Part 4: Supporting Routines

489        for(i = 0; i < MAX_LOADED_OBJECTS; i++)
490        {
491            if(s_objects[i].occupied)           // If found an occupied slot
492            {
493                switch(hierarchy)
494                {
495                    case TPM_RH_PLATFORM:
496                        if(s_objects[i].object.entity.attributes.ppsHierarchy == SET)
497                             s_objects[i].occupied = FALSE;
498                        break;
499                    case TPM_RH_OWNER:
500                        if(s_objects[i].object.entity.attributes.spsHierarchy == SET)
501                             s_objects[i].occupied = FALSE;
502                        break;
503                    case TPM_RH_ENDORSEMENT:
504                        if(s_objects[i].object.entity.attributes.epsHierarchy == SET)
505                             s_objects[i].occupied = FALSE;
506                        break;
507                    default:
508                        pAssert(FALSE);
509                        break;
510                }
511            }
512        }
513
514        return;
515
516   }


      8.5.3.21     ObjectLoadEvict()

      This function loads a persistent object into a transient object slot.
      This function requires that handle is associated with a persistent object.

      Error Returns                     Meaning

      TPM_RC_HANDLE                     the persistent object does not exist or the associated hierarchy is
                                        disabled.
      TPM_RC_OBJECT_MEMORY              no object slot

517   TPM_RC
518   ObjectLoadEvict(
519        TPM_HANDLE           *handle,             // IN:OUT: evict object handle. If success, it
520                                                  // will be replace by the loaded object handle
521        TPM_CC                commandCode         // IN: the command being processed
522        )
523   {
524        TPM_RC               result;
525        TPM_HANDLE           evictHandle = *handle;           // Save the evict handle
526        OBJECT               *object;
527
528        // If this is an index that references a persistent object created by
529        // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE
530        if(*handle >= PLATFORM_PERSISTENT)
531        {
532            // belongs to platform
533            if(g_phEnable == CLEAR)
534                return TPM_RC_HANDLE;
535        }
536        // belongs to owner
537        else if(gc.shEnable == CLEAR)
538            return TPM_RC_HANDLE;
539

      Page 164                                           TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                    Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

540       // Try to allocate a slot for an object
541       if(!ObjectAllocateSlot(handle, &object))
542           return TPM_RC_OBJECT_MEMORY;
543
544       // Copy persistent object to transient object slot. A TPM_RC_HANDLE
545       // may be returned at this point. This will mark the slot as containing
546       // a transient object so that it will be flushed at the end of the
547       // command
548       result = NvGetEvictObject(evictHandle, object);
549
550       // Bail out if this failed
551       if(result != TPM_RC_SUCCESS)
552           return result;
553
554       // check the object to see if it is in the endorsement hierarchy
555       // if it is and this is not a TPM2_EvictControl() command, indicate
556       // that the hierarchy is disabled.
557       // If the associated hierarchy is disabled, make it look like the
558       // handle is not defined
559       if(     ObjectDataGetHierarchy(object) == TPM_RH_ENDORSEMENT
560            && gc.ehEnable == CLEAR
561            && commandCode != TPM_CC_EvictControl
562          )
563            return TPM_RC_HANDLE;
564
565       return result;
566   }


      8.5.3.22    ObjectComputeName()

      This function computes the Name of an object from its public area.

567   void
568   ObjectComputeName(
569       TPMT_PUBLIC         *publicArea,       // IN: public area of an object
570       TPM2B_NAME          *name              // OUT: name of the object
571       )
572   {
573       TPM2B_PUBLIC               marshalBuffer;
574       BYTE                      *buffer;               // auxiliary marshal buffer pointer
575       HASH_STATE                 hashState;            // hash state
576
577       // if the nameAlg is NULL then there is no name.
578       if(publicArea->nameAlg == TPM_ALG_NULL)
579       {
580           name->t.size = 0;
581           return;
582       }
583       // Start hash stack
584       name->t.size = CryptStartHash(publicArea->nameAlg, &hashState);
585
586       // Marshal the public area into its canonical form
587       buffer = marshalBuffer.b.buffer;
588
589       marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL);
590
591       // Adding public area
592       CryptUpdateDigest2B(&hashState, &marshalBuffer.b);
593
594       // Complete hash leaving room for the name algorithm
595       CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]);
596
597       // set the nameAlg
598       UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name);


      Family "2.0"                                TCG Published                                 Page 165
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

599       name->t.size += 2;
600       return;
601   }


      8.5.3.23    ObjectComputeQualifiedName()

      This function computes the qualified name of an object.

602   void
603   ObjectComputeQualifiedName(
604       TPM2B_NAME          *parentQN,             //   IN: parent's qualified name
605       TPM_ALG_ID           nameAlg,              //   IN: name hash
606       TPM2B_NAME          *name,                 //   IN: name of the object
607       TPM2B_NAME          *qualifiedName         //   OUT: qualified name of the object
608       )
609   {
610       HASH_STATE          hashState;         // hash state
611
612       //         QN_A = hash_A (QN of parent || NAME_A)
613
614       // Start hash
615       qualifiedName->t.size = CryptStartHash(nameAlg, &hashState);
616
617       // Add parent's qualified name
618       CryptUpdateDigest2B(&hashState, &parentQN->b);
619
620       // Add self name
621       CryptUpdateDigest2B(&hashState, &name->b);
622
623       // Complete hash leaving room for the name algorithm
624       CryptCompleteHash(&hashState, qualifiedName->t.size,
625                         &qualifiedName->t.name[2]);
626       UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
627       qualifiedName->t.size += 2;
628       return;
629   }


      8.5.3.24    ObjectDataIsStorage()

      This function determines if a public area has the attributes associated with a storage key. A storage key is
      an asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR.

      Return Value                      Meaning

      TRUE                              if the object is a storage key
      FALSE                             if the object is not a storage key

630   BOOL
631   ObjectDataIsStorage(
632       TPMT_PUBLIC         *publicArea            // IN: public area of the object
633       )
634   {
635       if(   CryptIsAsymAlgorithm(publicArea->type)                          //   must be asymmetric,
636          && publicArea->objectAttributes.restricted == SET                  //   restricted,
637          && publicArea->objectAttributes.decrypt == SET                     //   decryption key
638          && publicArea->objectAttributes.sign == CLEAR                      //   can not be sign key
639         )
640           return TRUE;
641       else
642           return FALSE;
643   }


      Page 166                                        TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

      8.5.3.25    ObjectIsStorage()

      This function determines if an object has the attributes associated with a storage key. A storage key is an
      asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR.

      Return Value                    Meaning

      TRUE                            if the object is a storage key
      FALSE                           if the object is not a storage key

644   BOOL
645   ObjectIsStorage(
646         TPMI_DH_OBJECT     handle              // IN: object handle
647         )
648   {
649         OBJECT           *object = ObjectGet(handle);
650         return ObjectDataIsStorage(&object->publicArea);
651   }


      8.5.3.26    ObjectCapGetLoaded()

      This function returns a a list of handles of loaded object, starting from handle. Handle must be in the
      range of valid transient object handles, but does not have to be the handle of a loaded transient object.

      Return Value                    Meaning

      YES                             if there are more handles available
      NO                              all the available handles has been returned

652   TPMI_YES_NO
653   ObjectCapGetLoaded(
654         TPMI_DH_OBJECT     handle,             // IN: start handle
655         UINT32             count,              // IN: count of returned handles
656         TPML_HANDLE       *handleList          // OUT: list of handle
657         )
658   {
659         TPMI_YES_NO             more = NO;
660         UINT32                  i;
661
662         pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
663
664         // Initialize output handle list
665         handleList->count = 0;
666
667         // The maximum count of handles we may return is MAX_CAP_HANDLES
668         if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
669
670         // Iterate object slots to get loaded object handles
671         for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
672         {
673             if(s_objects[i].occupied == TRUE)
674             {
675                 // A valid transient object can not be the copy of a persistent object
676                 pAssert(s_objects[i].object.entity.attributes.evict == CLEAR);
677
678                  if(handleList->count < count)
679                  {
680                      // If we have not filled up the return list, add this object
681                      // handle to it
682                      handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
683                      handleList->count++;


      Family "2.0"                                 TCG Published                                         Page 167
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

684                     }
685                     else
686                     {
687                         // If the return list is full but we still have loaded object
688                         // available, report this and stop iterating
689                         more = YES;
690                         break;
691                     }
692              }
693         }
694
695         return more;
696   }


      8.5.3.27       ObjectCapGetTransientAvail()

      This function returns an estimate of the number of additional transient objects that could be loaded into
      the TPM.

697   UINT32
698   ObjectCapGetTransientAvail(
699         void
700         )
701   {
702         UINT32          i;
703         UINT32          num = 0;
704
705         // Iterate object slot to get the number of unoccupied slots
706         for(i = 0; i < MAX_LOADED_OBJECTS; i++)
707         {
708             if(s_objects[i].occupied == FALSE) num++;
709         }
710
711         return num;
712   }


      8.6       PCR.c

      8.6.1      Introduction

      This function contains the functions needed for PCR access and manipulation.
      This implementation uses a static allocation for the PCR. The amount of memory is allocated based on
      the number of PCR in the implementation and the number of implemented hash algorithms. This is not
      the expected implementation. PCR SPACE DEFINITIONS.
      In the definitions below, the g_hashPcrMap is a bit array that indicates which of the PCR are
      implemented. The g_hashPcr array is an array of digests. In this implementation, the space is allocated
      whether the PCR is implemented or not.

      8.6.2      Includes, Defines, and Data Definitions

  1   #define PCR_C
  2   #include "InternalRoutines.h"
  3   #include <Platform.h>

      The initial value of PCR attributes. The value of these fields should be consistent with PC Client
      specification In this implementation, we assume the total number of implemented PCR is 24.

  4   static const PCR_Attributes s_initAttributes[] =

      Page 168                                    TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                 Level 00 Revision 01.16
     Part 4: Supporting Routines                                                      Trusted Platform Module Library

 5   {
 6        // PCR    0 - 15, static RTM
 7        {1, 0,    0x1F}, {1, 0, 0x1F},     {1,   0,    0x1F},   {1,   0,   0x1F},
 8        {1, 0,    0x1F}, {1, 0, 0x1F},     {1,   0,    0x1F},   {1,   0,   0x1F},
 9        {1, 0,    0x1F}, {1, 0, 0x1F},     {1,   0,    0x1F},   {1,   0,   0x1F},
10        {1, 0,    0x1F}, {1, 0, 0x1F},     {1,   0,    0x1F},   {1,   0,   0x1F},
11
12        {0,   0x0F,   0x1F},         //   PCR    16,   Debug
13        {0,   0x10,   0x1C},         //   PCR    17,   Locality 4
14        {0,   0x10,   0x1C},         //   PCR    18,   Locality 3
15        {0,   0x10,   0x0C},         //   PCR    19,   Locality 2
16        {0,   0x14,   0x0E},         //   PCR    20,   Locality 1
17        {0,   0x14,   0x04},         //   PCR    21,   Dynamic OS
18        {0,   0x14,   0x04},         //   PCR    22,   Dynamic OS
19        {0,   0x0F,   0x1F},         //   PCR    23,   App specific
20        {0,   0x0F,   0x1F}          //   PCR    24,   testing policy
21   };


     8.6.3      Functions

     8.6.3.1     PCRBelongsAuthGroup()

     This function indicates if a PCR belongs to a group that requires an authValue in order to modify the
     PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is decided by the
     platform specification.

     Return Value                    Meaning

     TRUE:                           PCR belongs an auth group
     FALSE:                          PCR does not belong an auth group

22   BOOL
23   PCRBelongsAuthGroup(
24        TPMI_DH_PCR          handle,              // IN: handle of PCR
25        UINT32              *groupIndex           // OUT: group index if PCR belongs a
26                                                  //      group that allows authValue. If PCR
27                                                  //      does not belong to an auth group,
28                                                  //      the value in this parameter is
29                                                  //      invalid
30   )
31   {
32   #if NUM_AUTHVALUE_PCR_GROUP > 0
33       // Platform specification determines to which auth group a PCR belongs (if
34       // any). In this implementation, we assume there is only
35       // one auth group which contains PCR[20-22]. If the platform specification
36       // requires differently, the implementation should be changed accordingly
37       if(handle >= 20 && handle <= 22)
38       {
39           *groupIndex = 0;
40           return TRUE;
41       }
42
43   #endif
44       return FALSE;
45   }


     8.6.3.2     PCRBelongsPolicyGroup()

     This function indicates if a PCR belongs to a group that requires a policy authorization in order to modify
     the PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is decided by the
     platform specification.
     Family "2.0"                                   TCG Published                                          Page 169
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                             October 30, 2014
     Trusted Platform Module Library                                          Part 4: Supporting Routines


     Return Value                      Meaning

     TRUE:                             PCR belongs a policy group
     FALSE:                            PCR does not belong a policy group

46   BOOL
47   PCRBelongsPolicyGroup(
48        TPMI_DH_PCR           handle,            // IN: handle of PCR
49        UINT32               *groupIndex         // OUT: group index if PCR belongs a group that
50                                                 //     allows policy. If PCR does not belong to
51                                                 //     a policy group, the value in this
52                                                 //     parameter is invalid
53       )
54   {
55   #if NUM_POLICY_PCR_GROUP > 0
56       // Platform specification decides if a PCR belongs to a policy group and
57       // belongs to which group. In this implementation, we assume there is only
58       // one policy group which contains PCR20-22. If the platform specification
59       // requires differently, the implementation should be changed accordingly
60       if(handle >= 20 && handle <= 22)
61       {
62           *groupIndex = 0;
63           return TRUE;
64       }
65   #endif
66       return FALSE;
67   }


     8.6.3.3      PCRBelongsTCBGroup()

     This function indicates if a PCR belongs to the TCB group.

     Return Value                      Meaning

     TRUE:                             PCR belongs to TCB group
     FALSE:                            PCR does not belong to TCB group

68   static BOOL
69   PCRBelongsTCBGroup(
70        TPMI_DH_PCR           handle             // IN: handle of PCR
71        )
72   {
73   #if ENABLE_PCR_NO_INCREMENT == YES
74       // Platform specification decides if a PCR belongs to a TCB group. In this
75       // implementation, we assume PCR[20-22] belong to TCB group. If the platform
76       // specification requires differently, the implementation should be
77       // changed accordingly
78       if(handle >= 20 && handle <= 22)
79           return TRUE;
80
81   #endif
82       return FALSE;
83   }


     8.6.3.4      PCRPolicyIsAvailable()

     This function indicates if a policy is available for a PCR.




     Page 170                                       TCG Published                           Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014          Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library


      Return Value                     Meaning

      TRUE                             the PCR should be authorized by policy
      FALSE                            the PCR does not allow policy

 84   BOOL
 85   PCRPolicyIsAvailable(
 86        TPMI_DH_PCR          handle             // IN: PCR handle
 87        )
 88   {
 89        UINT32              groupIndex;
 90
 91        return PCRBelongsPolicyGroup(handle, &groupIndex);
 92   }


      8.6.3.5     PCRGetAuthValue()

      This function is used to access the authValue of a PCR. If PCR does not belong to an authValue group,
      an Empty Auth will be returned.

 93   void
 94   PCRGetAuthValue(
 95        TPMI_DH_PCR          handle,            // IN: PCR handle
 96        TPM2B_AUTH          *auth               // OUT: authValue of PCR
 97        )
 98   {
 99        UINT32         groupIndex;
100
101        if(PCRBelongsAuthGroup(handle, &groupIndex))
102        {
103            *auth = gc.pcrAuthValues.auth[groupIndex];
104        }
105        else
106        {
107            auth->t.size = 0;
108        }
109
110        return;
111   }


      8.6.3.6     PCRGetAuthPolicy()

      This function is used to access the authorization policy of a PCR. It sets policy to the authorization policy
      and returns the hash algorithm for policy If the PCR does not allow a policy, TPM_ALG_NULL is returned.

112   TPMI_ALG_HASH
113   PCRGetAuthPolicy(
114        TPMI_DH_PCR          handle,            // IN: PCR handle
115        TPM2B_DIGEST        *policy             // OUT: policy of PCR
116        )
117   {
118        UINT32               groupIndex;
119
120        if(PCRBelongsPolicyGroup(handle, &groupIndex))
121        {
122            *policy = gp.pcrPolicies.policy[groupIndex];
123            return gp.pcrPolicies.hashAlg[groupIndex];
124        }
125        else
126        {
127            policy->t.size = 0;

      Family "2.0"                                 TCG Published                                        Page 171
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

128              return TPM_ALG_NULL;
129       }
130   }


      8.6.3.7      PCRSimStart()

      This function is used to initialize the policies when a TPM is manufactured. This function would only be
      called in a manufacturing environment or in a TPM simulator.

131   void
132   PCRSimStart(
133       void
134       )
135   {
136       UINT32 i;
137       for(i = 0; i < NUM_POLICY_PCR_GROUP; i++)
138       {
139           gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
140           gp.pcrPolicies.policy[i].t.size = 0;
141       }
142
143       for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++)
144       {
145           gc.pcrAuthValues.auth[i].t.size = 0;
146       }
147
148       // We need to give an initial configuration on allocated PCR before
149       // receiving any TPM2_PCR_Allocate command to change this configuration
150       // When the simulation environment starts, we allocate all the PCRs
151       for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT;
152               gp.pcrAllocated.count++)
153       {
154           gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash
155               = CryptGetHashAlgByIndex(gp.pcrAllocated.count);
156
157              gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect
158                  = PCR_SELECT_MAX;
159              for(i = 0; i < PCR_SELECT_MAX; i++)
160                  gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i]
161                      = 0xFF;
162       }
163
164       // Store the initial configuration to NV
165       NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
166       NvWriteReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated);
167
168       return;
169   }


      8.6.3.8      GetSavedPcrPointer()

      This function returns the address of an array of state saved PCR based on the hash algorithm.

      Return Value                      Meaning

      NULL                              no such algorithm
      not NULL                          pointer to the 0th byte of the 0th PCR

170   static BYTE *
171   GetSavedPcrPointer (
172       TPM_ALG_ID           alg,                 // IN: algorithm for bank
173       UINT32               pcrIndex             // IN: PCR index in PCR_SAVE

      Page 172                                       TCG Published                               Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

174        )
175   {
176       switch(alg)
177       {
178   #ifdef TPM_ALG_SHA1
179       case TPM_ALG_SHA1:
180           return gc.pcrSave.sha1[pcrIndex];
181           break;
182   #endif
183   #ifdef TPM_ALG_SHA256
184       case TPM_ALG_SHA256:
185           return gc.pcrSave.sha256[pcrIndex];
186           break;
187   #endif
188   #ifdef TPM_ALG_SHA384
189       case TPM_ALG_SHA384:
190           return gc.pcrSave.sha384[pcrIndex];
191           break;
192   #endif
193
194   #ifdef TPM_ALG_SHA512
195       case TPM_ALG_SHA512:
196           return gc.pcrSave.sha512[pcrIndex];
197           break;
198   #endif
199   #ifdef TPM_ALG_SM3_256
200       case TPM_ALG_SM3_256:
201           return gc.pcrSave.sm3_256[pcrIndex];
202           break;
203   #endif
204       default:
205           FAIL(FATAL_ERROR_INTERNAL);
206       }
207       //return NULL; // Can't be reached
208   }


      8.6.3.9     PcrIsAllocated()

      This function indicates if a PCR number for the particular hash algorithm is allocated.

      Return Value                     Meaning

      FALSE                            PCR is not allocated
      TRUE                             PCR is allocated

209   BOOL
210   PcrIsAllocated (
211        UINT32               pcr,               // IN: The number of the PCR
212        TPMI_ALG_HASH        hashAlg            // IN: The PCR algorithm
213        )
214   {
215        UINT32                    i;
216        BOOL                      allocated = FALSE;
217
218        if(pcr < IMPLEMENTATION_PCR)
219        {
220
221             for(i = 0; i < gp.pcrAllocated.count; i++)
222             {
223                 if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg)
224                 {
225                     if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr/8])
226                             & (1 << (pcr % 8))) != 0)


      Family "2.0"                                 TCG Published                                       Page 173
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

227                            allocated = TRUE;
228                        else
229                            allocated = FALSE;
230                        break;
231                    }
232              }
233       }
234       return allocated;
235   }


      8.6.3.10       GetPcrPointer()

      This function returns the address of an array of PCR based on the hash algorithm.

      Return Value                      Meaning

      NULL                              no such algorithm
      not NULL                          pointer to the 0th byte of the 0th PCR

236   static BYTE *
237   GetPcrPointer (
238       TPM_ALG_ID            alg,                // IN: algorithm for bank
239       UINT32                pcrNumber           // IN: PCR number
240       )
241   {
242       static BYTE          *pcr = NULL;
243
244       if(!PcrIsAllocated(pcrNumber, alg))
245           return NULL;
246
247       switch(alg)
248       {
249   #ifdef TPM_ALG_SHA1
250       case TPM_ALG_SHA1:
251           pcr = s_pcrs[pcrNumber].sha1Pcr;
252           break;
253   #endif
254   #ifdef TPM_ALG_SHA256
255       case TPM_ALG_SHA256:
256           pcr = s_pcrs[pcrNumber].sha256Pcr;
257           break;
258   #endif
259   #ifdef TPM_ALG_SHA384
260       case TPM_ALG_SHA384:
261           pcr = s_pcrs[pcrNumber].sha384Pcr;
262           break;
263   #endif
264   #ifdef TPM_ALG_SHA512
265       case TPM_ALG_SHA512:
266           pcr = s_pcrs[pcrNumber].sha512Pcr;
267           break;
268   #endif
269   #ifdef TPM_ALG_SM3_256
270       case TPM_ALG_SM3_256:
271           pcr = s_pcrs[pcrNumber].sm3_256Pcr;
272           break;
273   #endif
274       default:
275           pAssert(FALSE);
276           break;
277       }
278
279       return pcr;


      Page 174                                       TCG Published                               Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library

280   }


      8.6.3.11    IsPcrSelected()

      This function indicates if an indicated PCR number is selected by the bit map in selection.

      Return Value                     Meaning

      FALSE                            PCR is not selected
      TRUE                             PCR is selected

281   static BOOL
282   IsPcrSelected (
283       UINT32                     pcr,                // IN: The number of the PCR
284       TPMS_PCR_SELECTION        *selection           // IN: The selection structure
285       )
286   {
287       BOOL                 selected = FALSE;
288       if(   pcr < IMPLEMENTATION_PCR
289          && ((selection->pcrSelect[pcr/8]) & (1 << (pcr % 8))) != 0)
290           selected = TRUE;
291
292       return selected;
293   }


      8.6.3.12    FilterPcr()

      This function modifies a PCR selection array based on the implemented PCR.

294   static void
295   FilterPcr(
296       TPMS_PCR_SELECTION        *selection           // IN: input PCR selection
297       )
298   {
299       UINT32     i;
300       TPMS_PCR_SELECTION            *allocated = NULL;
301
302       // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR
303       for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++)
304           selection->pcrSelect[i] = 0;
305
306       // Find the internal configuration for the bank
307       for(i = 0; i < gp.pcrAllocated.count; i++)
308       {
309           if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash)
310           {
311               allocated = &gp.pcrAllocated.pcrSelections[i];
312               break;
313           }
314       }
315
316       for (i = 0; i < selection->sizeofSelect; i++)
317       {
318           if(allocated == NULL)
319           {
320                // If the required bank does not exist, clear input selection
321                selection->pcrSelect[i] = 0;
322           }
323           else
324                selection->pcrSelect[i] &= allocated->pcrSelect[i];
325       }
326

      Family "2.0"                                 TCG Published                                     Page 175
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                        Part 4: Supporting Routines

327       return;
328   }


      8.6.3.13     PcrDrtm()

      This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End().

329   void
330   PcrDrtm(
331       const TPMI_DH_PCR              pcrHandle,       // IN: the index of the PCR to be
332                                                       //     modified
333       const TPMI_ALG_HASH            hash,            // IN: the bank identifier
334       const TPM2B_DIGEST            *digest           // IN: the digest to modify the PCR
335       )
336   {
337       BYTE           *pcrData = GetPcrPointer(hash, pcrHandle);
338
339       if(pcrData != NULL)
340       {
341           // Rest the PCR to zeros
342           MemorySet(pcrData, 0, digest->t.size);
343
344              // if the TPM has not started, then set the PCR to 0...04 and then extend
345              if(!TPMIsStarted())
346              {
347                  pcrData[digest->t.size - 1] = 4;
348              }
349              // Now, extend the value
350              PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer);
351       }
352   }


      8.6.3.14     PCRStartup()

      This function initializes the PCR subsystem at TPM2_Startup().

353   void
354   PCRStartup(
355       STARTUP_TYPE         type,              // IN: startup type
356       BYTE                 locality           // IN: startup locality
357       )
358   {
359       UINT32                  pcr, j;
360       UINT32                  saveIndex = 0;
361
362       g_pcrReConfig = FALSE;
363
364       if(type != SU_RESUME)
365       {
366           // PCR generation counter is cleared at TPM_RESET and TPM_RESTART
367           gr.pcrCounter = 0;
368       }
369
370       // Initialize/Restore PCR values
371       for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
372       {
373           // On resume, need to know if this PCR had its state saved or not
374           UINT32      stateSaved =
375               (type == SU_RESUME && s_initAttributes[pcr].stateSave == SET) ? 1 : 0;
376
377              // If this is the H-CRTM PCR and we are not doing a resume and we
378              // had an H-CRTM event, then we don't change this PCR
379              if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE)

      Page 176                                    TCG Published                              Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                            Trusted Platform Module Library

380                  continue;
381
382              // Iterate each hash algorithm bank
383              for(j = 0; j < gp.pcrAllocated.count; j++)
384              {
385                  TPMI_ALG_HASH    hash = gp.pcrAllocated.pcrSelections[j].hash;
386                  BYTE            *pcrData = GetPcrPointer(hash, pcr);
387                  UINT16           pcrSize = CryptGetHashDigestSize(hash);
388
389                  if(pcrData != NULL)
390                  {
391                      // if state was saved
392                      if(stateSaved == 1)
393                      {
394                          // Restore saved PCR value
395                          BYTE     *pcrSavedData;
396                          pcrSavedData = GetSavedPcrPointer(
397                                              gp.pcrAllocated.pcrSelections[j].hash,
398                                              saveIndex);
399                          MemoryCopy(pcrData, pcrSavedData, pcrSize, pcrSize);
400                      }
401                      else
402                          // PCR was not restored by state save
403                      {
404                          // If the reset locality of the PCR is 4, then
405                          // the reset value is all one's, otherwise it is
406                          // all zero.
407                          if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
408                               MemorySet(pcrData, 0xFF, pcrSize);
409                          else
410                          {
411                               MemorySet(pcrData, 0, pcrSize);
412                               if(pcr == HCRTM_PCR)
413                                   pcrData[pcrSize-1] = locality;
414                          }
415                      }
416                  }
417              }
418              saveIndex += stateSaved;
419       }
420
421       // Reset authValues
422       if(type != SU_RESUME)
423       {
424           for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++)
425           {
426               gc.pcrAuthValues.auth[j].t.size = 0;
427           }
428       }
429
430   }


      8.6.3.15     PCRStateSave()

      This function is used to save the PCR values that will be restored on TPM Resume.

431   void
432   PCRStateSave(
433       TPM_SU                 type             // IN: startup type
434       )
435   {
436       UINT32                 pcr, j;
437       UINT32                 saveIndex = 0;
438


      Family "2.0"                                TCG Published                                   Page 177
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                           Part 4: Supporting Routines

439       // if state save CLEAR, nothing to be done.            Return here
440       if(type == TPM_SU_CLEAR) return;
441
442       // Copy PCR values to the structure that should be saved to NV
443       for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
444       {
445           UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0;
446
447              // Iterate each hash algorithm bank
448              for(j = 0; j < gp.pcrAllocated.count; j++)
449              {
450                  BYTE    *pcrData;
451                  UINT32 pcrSize;
452
453                  pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr);
454
455                  if(pcrData != NULL)
456                  {
457                      pcrSize
458                          = CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[j].hash);
459
460                      if(stateSaved == 1)
461                      {
462                          // Restore saved PCR value
463                          BYTE     *pcrSavedData;
464                          pcrSavedData
465                               = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash,
466                                                    saveIndex);
467                          MemoryCopy(pcrSavedData, pcrData, pcrSize, pcrSize);
468                      }
469                  }
470              }
471              saveIndex += stateSaved;
472       }
473
474       return;
475   }


      8.6.3.16     PCRIsStateSaved()

      This function indicates if the selected PCR is a PCR that is state saved on TPM2_Shutdown(STATE). The
      return value is based on PCR attributes.

      Return Value                      Meaning

      TRUE                              PCR is state saved
      FALSE                             PCR is not state saved

476   BOOL
477   PCRIsStateSaved(
478       TPMI_DH_PCR         handle                // IN: PCR handle to be extended
479       )
480   {
481       UINT32                  pcr = handle - PCR_FIRST;
482
483       if(s_initAttributes[pcr].stateSave == SET)
484           return TRUE;
485       else
486           return FALSE;
487   }




      Page 178                                      TCG Published                             Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

      8.6.3.17    PCRIsResetAllowed()

      This function indicates if a PCR may be reset by the current command locality. The return value is based
      on PCR attributes, and not the PCR allocation.

      Return Value                    Meaning

      TRUE                            TPM2_PCR_Reset() is allowed
      FALSE                           TPM2_PCR_Reset() is not allowed

488   BOOL
489   PCRIsResetAllowed(
490       TPMI_DH_PCR          handle            // IN: PCR handle to be extended
491       )
492   {
493       UINT8                     commandLocality;
494       UINT8                     localityBits = 1;
495       UINT32                    pcr = handle - PCR_FIRST;
496
497       // Check for the locality
498       commandLocality = _plat__LocalityGet();
499
500   #ifdef DRTM_PCR
501       // For a TPM that does DRTM, Reset is not allowed at locality 4
502       if(commandLocality == 4)
503           return FALSE;
504   #endif
505
506       localityBits = localityBits << commandLocality;
507       if((localityBits & s_initAttributes[pcr].resetLocality) == 0)
508           return FALSE;
509       else
510           return TRUE;
511
512   }


      8.6.3.18    PCRChanged()

      This function checks a PCR handle to see if the attributes for the PCR are set so that any change to the
      PCR causes an increment of the pcrCounter. If it does, then the function increments the counter.

513   void
514   PCRChanged(
515       TPM_HANDLE           pcrHandle         // IN: the handle of the PCR that changed.
516       )
517   {
518       // For the reference implementation, the only change that does not cause
519       // increment is a change to a PCR in the TCB group.
520       if(!PCRBelongsTCBGroup(pcrHandle))
521           gr.pcrCounter++;
522   }


      8.6.3.19    PCRIsExtendAllowed()

      This function indicates a PCR may be extended at the current command locality. The return value is
      based on PCR attributes, and not the PCR allocation.




      Family "2.0"                               TCG Published                                     Page 179
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines


      Return Value                      Meaning

      TRUE                              extend is allowed
      FALSE                             extend is not allowed

523   BOOL
524   PCRIsExtendAllowed(
525       TPMI_DH_PCR          handle               // IN: PCR handle to be extended
526       )
527   {
528       UINT8                    commandLocality;
529       UINT8                    localityBits = 1;
530       UINT32                   pcr = handle - PCR_FIRST;
531
532       // Check for the locality
533       commandLocality = _plat__LocalityGet();
534       localityBits = localityBits << commandLocality;
535       if((localityBits & s_initAttributes[pcr].extendLocality) == 0)
536           return FALSE;
537       else
538           return TRUE;
539
540   }


      8.6.3.20     PCRExtend()

      This function is used to extend a PCR in a specific bank.

541   void
542   PCRExtend(
543       TPMI_DH_PCR          handle,              //   IN:    PCR handle to be extended
544       TPMI_ALG_HASH        hash,                //   IN:    hash algorithm of PCR
545       UINT32               size,                //   IN:    size of data to be extended
546       BYTE                *data                 //   IN:    data to be extended
547       )
548   {
549       UINT32                    pcr = handle - PCR_FIRST;
550       BYTE                     *pcrData;
551       HASH_STATE                hashState;
552       UINT16                    pcrSize;
553
554       pcrData = GetPcrPointer(hash, pcr);
555
556       // Extend PCR if it is allocated
557       if(pcrData != NULL)
558       {
559           pcrSize = CryptGetHashDigestSize(hash);
560           CryptStartHash(hash, &hashState);
561           CryptUpdateDigest(&hashState, pcrSize, pcrData);
562           CryptUpdateDigest(&hashState, size, data);
563           CryptCompleteHash(&hashState, pcrSize, pcrData);
564
565              // If PCR does not belong to TCB group, increment PCR counter
566              if(!PCRBelongsTCBGroup(handle))
567                  gr.pcrCounter++;
568       }
569
570       return;
571   }




      Page 180                                       TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

      8.6.3.21    PCRComputeCurrentDigest()

      This function computes the digest of the selected PCR.
      As a side-effect, selection is modified so that only the implemented PCR will have their bits still set.

572   void
573   PCRComputeCurrentDigest(
574        TPMI_ALG_HASH             hashAlg,            // IN: hash algorithm to compute digest
575        TPML_PCR_SELECTION       *selection,          // IN/OUT: PCR selection (filtered on
576                                                      //     output)
577        TPM2B_DIGEST             *digest              // OUT: digest
578        )
579   {
580        HASH_STATE                      hashState;
581        TPMS_PCR_SELECTION             *select;
582        BYTE                           *pcrData;   // will point to a digest
583        UINT32                          pcrSize;
584        UINT32                          pcr;
585        UINT32                          i;
586
587        // Initialize the hash
588        digest->t.size = CryptStartHash(hashAlg, &hashState);
589        pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX);
590
591        // Iterate through the list of PCR selection structures
592        for(i = 0; i < selection->count; i++)
593        {
594            // Point to the current selection
595            select = &selection->pcrSelections[i]; // Point to the current selection
596            FilterPcr(select);      // Clear out the bits for unimplemented PCR
597
598              // Need the size of each digest
599              pcrSize = CryptGetHashDigestSize(selection->pcrSelections[i].hash);
600
601              // Iterate through the selection
602              for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
603              {
604                  if(IsPcrSelected(pcr, select))         // Is this PCR selected
605                  {
606                      // Get pointer to the digest data for the bank
607                      pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr);
608                      pAssert(pcrData != NULL);
609                      CryptUpdateDigest(&hashState, pcrSize, pcrData); // add to digest
610                  }
611              }
612        }
613        // Complete hash stack
614        CryptCompleteHash2B(&hashState, &digest->b);
615
616        return;
617   }


      8.6.3.22    PCRRead()

      This function is used to read a list of selected PCR. If the requested PCR number exceeds the maximum
      number that can be output, the selection is adjusted to reflect the actual output PCR.

618   void
619   PCRRead(
620        TPML_PCR_SELECTION       *selection,          // IN/OUT: PCR selection (filtered on
621                                                      //     output)
622        TPML_DIGEST              *digest,             // OUT: digest
623        UINT32                   *pcrCounter          // OUT: the current value of PCR generation

      Family "2.0"                                  TCG Published                                         Page 181
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

624                                                 //     number
625       )
626   {
627       TPMS_PCR_SELECTION            *select;
628       BYTE                          *pcrData;        // will point to a digest
629       UINT32                         pcr;
630       UINT32                         i;
631
632       digest->count = 0;
633
634       // Iterate through the list of PCR selection structures
635       for(i = 0; i < selection->count; i++)
636       {
637           // Point to the current selection
638           select = &selection->pcrSelections[i]; // Point to the current selection
639           FilterPcr(select);      // Clear out the bits for unimplemented PCR
640
641            // Iterate through the selection
642            for (pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
643            {
644                if(IsPcrSelected(pcr, select))          // Is this PCR selected
645                {
646                    // Check if number of digest exceed upper bound
647                    if(digest->count > 7)
648                    {
649                        // Clear rest of the current select bitmap
650                        while(    pcr < IMPLEMENTATION_PCR
651                                  // do not round up!
652                               && (pcr / 8) < select->sizeofSelect)
653                        {
654                            // do not round up!
655                            select->pcrSelect[pcr/8] &= (BYTE) ~(1 << (pcr % 8));
656                            pcr++;
657                        }
658                        // Exit inner loop
659                        break;;
660                    }
661                    // Need the size of each digest
662                    digest->digests[digest->count].t.size =
663                        CryptGetHashDigestSize(selection->pcrSelections[i].hash);
664
665                      // Get pointer to the digest data for the bank
666                      pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr);
667                      pAssert(pcrData != NULL);
668                      // Add to the data to digest
669                      MemoryCopy(digest->digests[digest->count].t.buffer,
670                                 pcrData,
671                                 digest->digests[digest->count].t.size,
672                                 digest->digests[digest->count].t.size);
673                      digest->count++;
674                }
675            }
676            // If we exit inner loop because we have exceed the output upper bound
677            if(digest->count > 7 && pcr < IMPLEMENTATION_PCR)
678            {
679                // Clear rest of the selection
680                while(i < selection->count)
681                {
682                    MemorySet(selection->pcrSelections[i].pcrSelect, 0,
683                              selection->pcrSelections[i].sizeofSelect);
684                    i++;
685                }
686                // exit outer loop
687                break;
688            }
689       }

      Page 182                                  TCG Published                             Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014           Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

690
691       *pcrCounter = gr.pcrCounter;
692
693       return;
694   }


      8.6.3.23    PcrWrite()

      This function is used by _TPM_Hash_End() to set a PCR to the computed hash of the H-CRTM event.

695   void
696   PcrWrite(
697       TPMI_DH_PCR           handle,            // IN: PCR handle to be extended
698       TPMI_ALG_HASH         hash,              // IN: hash algorithm of PCR
699       TPM2B_DIGEST         *digest             // IN: the new value
700       )
701   {
702       UINT32                     pcr = handle - PCR_FIRST;
703       BYTE                      *pcrData;
704
705       // Copy value to the PCR if it is allocated
706       pcrData = GetPcrPointer(hash, pcr);
707       if(pcrData != NULL)
708       {
709           MemoryCopy(pcrData, digest->t.buffer, digest->t.size, digest->t.size); ;
710       }
711
712       return;
713   }


      8.6.3.24    PCRAllocate()

      This function is used to change the PCR allocation.

      Error Returns                   Meaning

      TPM_RC_SUCCESS                  allocate success
      TPM_RC_NO_RESULTS               allocate failed
      TPM_RC_PCR                      improper allocation

714   TPM_RC
715   PCRAllocate(
716       TPML_PCR_SELECTION        *allocate,           //   IN: required allocation
717       UINT32                    *maxPCR,             //   OUT: Maximum number of PCR
718       UINT32                    *sizeNeeded,         //   OUT: required space
719       UINT32                    *sizeAvailable       //   OUT: available space
720       )
721   {
722       UINT32                        i, j, k;
723       TPML_PCR_SELECTION            newAllocate;
724       // Initialize the flags       to indicate if HCRTM PCR and DRTM PCR are allocated.
725       BOOL                          pcrHcrtm = FALSE;
726       BOOL                          pcrDrtm = FALSE;
727
728       // Create the expected new PCR allocation based on the existing allocation
729       // and the new input:
730       // 1. if a PCR bank does not appear in the new allocation, the existing
731       //     allocation of this PCR bank will be preserved.
732       // 2. if a PCR bank appears multiple times in the new allocation, only the
733       //     last one will be in effect.
734       newAllocate = gp.pcrAllocated;

      Family "2.0"                                  TCG Published                                   Page 183
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

735       for(i = 0; i < allocate->count; i++)
736       {
737           for(j = 0; j < newAllocate.count; j++)
738           {
739               // If hash matches, the new allocation covers the old allocation
740               // for this particular bank.
741               // The assumption is the initial PCR allocation (from manufacture)
742               // has all the supported hash algorithms with an assigned bank
743               // (possibly empty). So there must be a match for any new bank
744               // allocation from the input.
745               if(newAllocate.pcrSelections[j].hash ==
746                   allocate->pcrSelections[i].hash)
747               {
748                   newAllocate.pcrSelections[j] = allocate->pcrSelections[i];
749                   break;
750               }
751           }
752           // The j loop must exit with a match.
753           pAssert(j < newAllocate.count);
754       }
755
756       // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined)
757       *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes);
758       if(*maxPCR > IMPLEMENTATION_PCR)
759           *maxPCR = IMPLEMENTATION_PCR;
760
761       // Compute required size for allocation
762       *sizeNeeded = 0;
763       for(i = 0; i < newAllocate.count; i++)
764       {
765           UINT32      digestSize
766               = CryptGetHashDigestSize(newAllocate.pcrSelections[i].hash);
767   #if defined(DRTM_PCR)
768           // Make sure that we end up with at least one DRTM PCR
769   #   define PCR_DRTM (PCR_FIRST + DRTM_PCR)     // for cosmetics
770           pcrDrtm =    pcrDrtm || TEST_BIT(PCR_DRTM, newAllocate.pcrSelections[i]);
771   #else   // if DRTM PCR is not required, indicate that the allocation is OK
772           pcrDrtm = TRUE;
773   #endif
774
775   #if defined(HCRTM_PCR)
776           // and one HCRTM PCR (since this is usually PCR 0...)
777   #   define PCR_HCRTM (PCR_FIRST + HCRTM_PCR)
778           pcrHcrtm =    pcrDrtm || TEST_BIT(PCR_HCRTM, newAllocate.pcrSelections[i]);
779   #else
780           pcrHcrtm = TRUE;
781   #endif
782           for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++)
783           {
784               BYTE         mask = 1;
785               for(k = 0; k < 8; k++)
786               {
787                   if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0)
788                       *sizeNeeded += digestSize;
789                   mask = mask << 1;
790               }
791           }
792       }
793
794       if(!pcrDrtm || !pcrHcrtm)
795           return TPM_RC_PCR;
796
797       // In this particular implementation, we always have enough space to
798       // allocate PCR. Different implementation may return a sizeAvailable less
799       // than the sizeNeed.
800       *sizeAvailable = sizeof(s_pcrs);

      Page 184                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

801
802        // Save the required allocation to NV. Note that after NV is written, the
803        // PCR allocation in NV is no longer consistent with the RAM data
804        // gp.pcrAllocated. The NV version reflect the allocate after next
805        // TPM_RESET, while the RAM version reflects the current allocation
806        NvWriteReserved(NV_PCR_ALLOCATED, &newAllocate);
807
808        return TPM_RC_SUCCESS;
809
810   }


      8.6.3.25       PCRSetValue()

      This function is used to set the designated PCR in all banks to an initial value. The initial value is signed
      and will be sign extended into the entire PCR.

811   void
812   PCRSetValue(
813        TPM_HANDLE           handle,            // IN: the handle of the PCR to set
814        INT8                 initialValue       // IN: the value to set
815        )
816   {
817        int                  i;
818        UINT32               pcr = handle - PCR_FIRST;
819        TPMI_ALG_HASH        hash;
820        UINT16               digestSize;
821        BYTE                *pcrData;
822
823        // Iterate supported PCR bank algorithms to reset
824        for(i = 0; i < HASH_COUNT; i++)
825        {
826            hash = CryptGetHashAlgByIndex(i);
827            // Prevent runaway
828            if(hash == TPM_ALG_NULL)
829                break;
830
831              // Get a pointer to the data
832              pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);
833
834              // If the PCR is allocated
835              if(pcrData != NULL)
836              {
837                  // And the size of the digest
838                  digestSize = CryptGetHashDigestSize(hash);
839
840                   // Set the LSO to the input value
841                   pcrData[digestSize - 1] = initialValue;
842
843                   // Sign extend
844                   if(initialValue >= 0)
845                       MemorySet(pcrData, 0, digestSize - 1);
846                   else
847                       MemorySet(pcrData, -1, digestSize - 1);
848              }
849        }
850   }


      8.6.3.26       PCRResetDynamics

      This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence.

851   void
852   PCRResetDynamics(

      Family "2.0"                                 TCG Published                                        Page 185
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines

853          void
854          )
855   {
856          UINT32                  pcr, i;
857
858          // Initialize PCR values
859          for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
860          {
861              // Iterate each hash algorithm bank
862              for(i = 0; i < gp.pcrAllocated.count; i++)
863              {
864                  BYTE    *pcrData;
865                  UINT32 pcrSize;
866
867                    pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);
868
869                    if(pcrData != NULL)
870                    {
871                        pcrSize =
872                            CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[i].hash);
873
874                        // Reset PCR
875                        // Any PCR can be reset by locality 4 should be reset to 0
876                        if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
877                            MemorySet(pcrData, 0, pcrSize);
878                    }
879              }
880          }
881          return;
882   }


      8.6.3.27       PCRCapGetAllocation()

      This function is used to get the current allocation of PCR banks.

      Return Value                      Meaning

      YES:                              if the return count is 0
      NO:                               if the return count is not 0

883   TPMI_YES_NO
884   PCRCapGetAllocation(
885          UINT32                   count,               // IN: count of return
886          TPML_PCR_SELECTION      *pcrSelection         // OUT: PCR allocation list
887          )
888   {
889          if(count == 0)
890          {
891              pcrSelection->count = 0;
892              return YES;
893          }
894          else
895          {
896              *pcrSelection = gp.pcrAllocated;
897              return NO;
898          }
899   }


      8.6.3.28       PCRSetSelectBit()

      This function sets a bit in a bitmap array.


      Page 186                                        TCG Published                             Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                            Trusted Platform Module Library

900   static void
901   PCRSetSelectBit(
902       UINT32               pcr,               // IN: PCR number
903       BYTE                *bitmap             // OUT: bit map to be set
904       )
905   {
906       bitmap[pcr / 8] |= (1 << (pcr % 8));
907       return;
908   }


      8.6.3.29    PCRGetProperty()

      This function returns the selected PCR property.

      Return Value                    Meaning

      TRUE                            the property type is implemented
      FALSE                           the property type is not implemented

909   static BOOL
910   PCRGetProperty(
911       TPM_PT_PCR                     property,
912       TPMS_TAGGED_PCR_SELECT        *select
913       )
914   {
915       UINT32                    pcr;
916       UINT32                    groupIndex;
917
918       select->tag = property;
919       // Always set the bitmap to be the size of all PCR
920       select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8;
921
922       // Initialize bitmap
923       MemorySet(select->pcrSelect, 0, select->sizeofSelect);
924
925       // Collecting properties
926       for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
927       {
928           switch(property)
929           {
930               case TPM_PT_PCR_SAVE:
931                   if(s_initAttributes[pcr].stateSave == SET)
932                       PCRSetSelectBit(pcr, select->pcrSelect);
933                   break;
934               case TPM_PT_PCR_EXTEND_L0:
935                   if((s_initAttributes[pcr].extendLocality & 0x01) != 0)
936                       PCRSetSelectBit(pcr, select->pcrSelect);
937                   break;
938               case TPM_PT_PCR_RESET_L0:
939                   if((s_initAttributes[pcr].resetLocality & 0x01) != 0)
940                       PCRSetSelectBit(pcr, select->pcrSelect);
941                   break;
942               case TPM_PT_PCR_EXTEND_L1:
943                   if((s_initAttributes[pcr].extendLocality & 0x02) != 0)
944                       PCRSetSelectBit(pcr, select->pcrSelect);
945                   break;
946               case TPM_PT_PCR_RESET_L1:
947                   if((s_initAttributes[pcr].resetLocality & 0x02) != 0)
948                       PCRSetSelectBit(pcr, select->pcrSelect);
949                   break;
950               case TPM_PT_PCR_EXTEND_L2:
951                   if((s_initAttributes[pcr].extendLocality & 0x04) != 0)
952                       PCRSetSelectBit(pcr, select->pcrSelect);


      Family "2.0"                                TCG Published                                   Page 187
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                      October 30, 2014
       Trusted Platform Module Library                                        Part 4: Supporting Routines

 953                   break;
 954               case TPM_PT_PCR_RESET_L2:
 955                   if((s_initAttributes[pcr].resetLocality & 0x04) != 0)
 956                        PCRSetSelectBit(pcr, select->pcrSelect);
 957                   break;
 958               case TPM_PT_PCR_EXTEND_L3:
 959                   if((s_initAttributes[pcr].extendLocality & 0x08) != 0)
 960                        PCRSetSelectBit(pcr, select->pcrSelect);
 961                   break;
 962               case TPM_PT_PCR_RESET_L3:
 963                   if((s_initAttributes[pcr].resetLocality & 0x08) != 0)
 964                        PCRSetSelectBit(pcr, select->pcrSelect);
 965                   break;
 966               case TPM_PT_PCR_EXTEND_L4:
 967                   if((s_initAttributes[pcr].extendLocality & 0x10) != 0)
 968                        PCRSetSelectBit(pcr, select->pcrSelect);
 969                   break;
 970               case TPM_PT_PCR_RESET_L4:
 971                   if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
 972                        PCRSetSelectBit(pcr, select->pcrSelect);
 973                   break;
 974               case TPM_PT_PCR_DRTM_RESET:
 975                   // DRTM reset PCRs are the PCR reset by locality 4
 976                   if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
 977                        PCRSetSelectBit(pcr, select->pcrSelect);
 978                   break;
 979   #if NUM_POLICY_PCR_GROUP > 0
 980               case TPM_PT_PCR_POLICY:
 981                   if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex))
 982                        PCRSetSelectBit(pcr, select->pcrSelect);
 983                   break;
 984   #endif
 985   #if NUM_AUTHVALUE_PCR_GROUP > 0
 986               case TPM_PT_PCR_AUTH:
 987                   if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex))
 988                        PCRSetSelectBit(pcr, select->pcrSelect);
 989                   break;
 990   #endif
 991   #if ENABLE_PCR_NO_INCREMENT == YES
 992               case TPM_PT_PCR_NO_INCREMENT:
 993                   if(PCRBelongsTCBGroup(pcr + PCR_FIRST))
 994                        PCRSetSelectBit(pcr, select->pcrSelect);
 995                   break;
 996   #endif
 997               default:
 998                   // If property is not supported, stop scanning PCR attributes
 999                   // and return.
1000                   return FALSE;
1001                   break;
1002           }
1003       }
1004       return TRUE;
1005   }


       8.6.3.30    PCRCapGetProperties()

       This function returns a list of PCR properties starting at property.




       Page 188                                       TCG Published                         Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014        Level 00 Revision 01.16
       Part 4: Supporting Routines                                                   Trusted Platform Module Library


       Return Value                    Meaning

       YES:                            if no more property is available
       NO:                             if there are more properties not reported

1006   TPMI_YES_NO
1007   PCRCapGetProperties(
1008          TPM_PT_PCR                       property,             // IN: the starting PCR property
1009          UINT32                           count,                // IN: count of returned propertie
1010          TPML_TAGGED_PCR_PROPERTY        *select                // OUT: PCR select
1011          )
1012   {
1013          TPMI_YES_NO      more = NO;
1014          UINT32           i;
1015
1016          // Initialize output property list
1017          select->count = 0;
1018
1019          // The maximum count of properties we may return is MAX_PCR_PROPERTIES
1020          if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES;
1021
1022          // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property
1023          // value would never be less than TPM_PT_PCR_FIRST
1024          pAssert(TPM_PT_PCR_FIRST == 0);
1025
1026          // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property
1027          // implemented on the TPM.
1028          for(i = property; i <= TPM_PT_PCR_LAST; i++)
1029          {
1030              if(select->count < count)
1031              {
1032                   // If we have not filled up the return list, add more properties to it
1033                   if(PCRGetProperty(i, &select->pcrProperty[select->count]))
1034                       // only increment if the property is implemented
1035                   select->count++;
1036              }
1037              else
1038              {
1039                   // If the return list is full but we still have properties
1040                   // available, report this and stop iterating.
1041                   more = YES;
1042                   break;
1043              }
1044          }
1045          return more;
1046   }


       8.6.3.31     PCRCapGetHandles()

       This function is used to get a list of handles of PCR, started from handle. If handle exceeds the maximum
       PCR handle range, an empty list will be returned and the return value will be NO.

       Return Value                    Meaning

       YES                             if there are more handles available
       NO                              all the available handles has been returned

1047   TPMI_YES_NO
1048   PCRCapGetHandles(
1049          TPMI_DH_PCR       handle,             // IN: start handle
1050          UINT32            count,              // IN: count of returned handle
1051          TPML_HANDLE      *handleList          // OUT: list of handle

       Family "2.0"                                 TCG Published                                         Page 189
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                            October 30, 2014
       Trusted Platform Module Library                                                Part 4: Supporting Routines

1052         )
1053   {
1054         TPMI_YES_NO         more = NO;
1055         UINT32              i;
1056
1057         pAssert(HandleGetType(handle) == TPM_HT_PCR);
1058
1059         // Initialize output handle list
1060         handleList->count = 0;
1061
1062         // The maximum count of handles we may return is MAX_CAP_HANDLES
1063         if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1064
1065         // Iterate PCR handle range
1066         for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++)
1067         {
1068             if(handleList->count < count)
1069             {
1070                  // If we have not filled up the return list, add this PCR
1071                  // handle to it
1072                  handleList->handle[handleList->count] = i + PCR_FIRST;
1073                  handleList->count++;
1074             }
1075             else
1076             {
1077                  // If the return list is full but we still have PCR handle
1078                  // available, report this and stop iterating
1079                  more = YES;
1080                  break;
1081             }
1082         }
1083         return more;
1084   }


       8.7       PP.c

       8.7.1      Introduction

       This file contains the functions that support the physical presence operations of the TPM.

       8.7.2      Includes

   1   #include "InternalRoutines.h"


       8.7.3      Functions

       8.7.3.1      PhysicalPresencePreInstall_Init()

       This function is used to initialize the array of commands that require confirmation with physical presence.
       The array is an array of bits that has a correspondence with the command code.
       This command should only ever be executable in a manufacturing setting or in a simulation.

   2   void
   3   PhysicalPresencePreInstall_Init(
   4         void
   5         )
   6   {
   7         // Clear all the PP commands
   8         MemorySet(&gp.ppList, 0,


       Page 190                                     TCG Published                                   Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
     Part 4: Supporting Routines                                              Trusted Platform Module Library

 9                    ((TPM_CC_PP_LAST - TPM_CC_PP_FIRST + 1) + 7) / 8);
10
11       // TPM_CC_PP_Commands always requires PP
12       if(CommandIsImplemented(TPM_CC_PP_Commands))
13           PhysicalPresenceCommandSet(TPM_CC_PP_Commands);
14
15       // Write PP list to NV
16       NvWriteReserved(NV_PP_LIST, &gp.ppList);
17
18       return;
19   }


     8.7.3.2     PhysicalPresenceCommandSet()

     This function is used to indicate a command that requires PP confirmation.

20   void
21   PhysicalPresenceCommandSet(
22       TPM_CC               commandCode       // IN: command code
23       )
24   {
25       UINT32         bitPos;
26
27       // Assume command is implemented. It should be checked before this
28       // function is called
29       pAssert(CommandIsImplemented(commandCode));
30
31       // If the command is not a PP command, ignore it
32       if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST)
33           return;
34
35       bitPos = commandCode - TPM_CC_PP_FIRST;
36
37       // Set bit
38       gp.ppList[bitPos/8] |= 1 << (bitPos % 8);
39
40       return;
41   }


     8.7.3.3     PhysicalPresenceCommandClear()

     This function is used to indicate a command that no longer requires PP confirmation.

42   void
43   PhysicalPresenceCommandClear(
44       TPM_CC               commandCode       // IN: command code
45       )
46   {
47       UINT32         bitPos;
48
49       // Assume command is implemented. It should be checked before this
50       // function is called
51       pAssert(CommandIsImplemented(commandCode));
52
53       // If the command is not a PP command, ignore it
54       if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST)
55           return;
56
57       // if the input code is TPM_CC_PP_Commands, it can not be cleared
58       if(commandCode == TPM_CC_PP_Commands)
59           return;
60
61       bitPos = commandCode - TPM_CC_PP_FIRST;

     Family "2.0"                                TCG Published                                     Page 191
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

 62
 63         // Set bit
 64         gp.ppList[bitPos/8] |= (1 << (bitPos % 8));
 65         // Flip it to off
 66         gp.ppList[bitPos/8] ^= (1 << (bitPos % 8));
 67
 68         return;
 69   }


      8.7.3.4     PhysicalPresenceIsRequired()

      This function indicates if PP confirmation is required for a command.

      Return Value                      Meaning

      TRUE                              if physical presence is required
      FALSE                             if physical presence is not required

 70   BOOL
 71   PhysicalPresenceIsRequired(
 72         TPM_CC             commandCode           // IN: command code
 73         )
 74   {
 75         UINT32        bitPos;
 76
 77         // if the input commandCode is not a PP command, return FALSE
 78         if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST)
 79             return FALSE;
 80
 81         bitPos = commandCode - TPM_CC_PP_FIRST;
 82
 83         // Check the bit map. If the bit is SET, PP authorization is required
 84         return ((gp.ppList[bitPos/8] & (1 << (bitPos % 8))) != 0);
 85
 86   }


      8.7.3.5     PhysicalPresenceCapGetCCList()

      This function returns a list of commands that require PP confirmation. The list starts from the first
      implemented command that has a command code that the same or greater than commandCode.

      Return Value                      Meaning

      YES                               if there are more command codes available
      NO                                all the available command codes have been returned

 87   TPMI_YES_NO
 88   PhysicalPresenceCapGetCCList(
 89         TPM_CC             commandCode,          // IN: start command code
 90         UINT32             count,                // IN: count of returned TPM_CC
 91         TPML_CC           *commandList           // OUT: list of TPM_CC
 92         )
 93   {
 94         TPMI_YES_NO       more = NO;
 95         UINT32            i;
 96
 97         // Initialize output handle list
 98         commandList->count = 0;
 99
100         // The maximum count of command we may return is MAX_CAP_CC
101         if(count > MAX_CAP_CC) count = MAX_CAP_CC;

      Page 192                                       TCG Published                                   Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

102
103         // Collect PP commands
104         for(i = commandCode; i <= TPM_CC_PP_LAST; i++)
105         {
106             if(PhysicalPresenceIsRequired(i))
107             {
108                 if(commandList->count < count)
109                 {
110                     // If we have not filled up the return list, add this command
111                     // code to it
112                     commandList->commandCodes[commandList->count] = i;
113                     commandList->count++;
114                 }
115                 else
116                 {
117                     // If the return list is full but we still have PP command
118                     // available, report this and stop iterating
119                     more = YES;
120                     break;
121                 }
122             }
123         }
124         return more;
125   }


      8.8     Session.c

      8.8.1    Introduction

      The code in this file is used to manage the session context counter. The scheme implemented here is a
      "truncated counter". This scheme allows the TPM to not need TPM_SU_CLEAR for a very long period of
      time and still not have the context count for a session repeated.
      The counter (contextCounter)in this implementation is a UINT64 but can be smaller. The "tracking array"
      (contextArray) only has 16-bits per context. The tracking array is the data that needs to be saved and
      restored across TPM_SU_STATE so that sessions are not lost when the system enters the sleep state.
      Also, when the TPM is active, the tracking array is kept in RAM making it important that the number of
      bytes for each entry be kept as small as possible.
      The TPM prevents collisions of these truncated values by not allowing a contextID to be assigned if it
      would be the same as an existing value. Since the array holds 16 bits, after a context has been saved,
      an additional 2^16-1 contexts may be saved before the count would again match. The normal
      expectation is that the context will be flushed before its count value is needed again but it is always
      possible to have long-lived sessions.
      The contextID is assigned when the context is saved (TPM2_ContextSave()). At that time, the TPM will
      compare the low-order 16 bits of contextCounter to the existing values in contextArray and if one
      matches, the TPM will return TPM_RC_CONTEXT_GAP (by construction, the entry that contains the
      matching value is the oldest context).
      The expected remediation by the TRM is to load the oldest saved session context (the one found by the
      TPM), and save it. Since loading the oldest session also eliminates its contextID value from contextArray,
      there TPM will always be able to load and save the oldest existing context.
      In the worst case, software may have to load and save several contexts in order to save an additional
      one. This should happen very infrequently.
      When the TPM searches contextArray and finds that none of the contextIDs match the low-order 16-bits
      of contextCount, the TPM can copy the low bits to the contextArray associated with the session, and
      increment contextCount.



      Family "2.0"                                TCG Published                                      Page 193
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                             Part 4: Supporting Routines


     There is one entry in contextArray for each of the active sessions allowed by the TPM implementation.
     This array contains either a context count, an index, or a value indicating the slot is available (0).
     The index into the contextArray is the handle for the session with the region selector byte of the session
     set to zero. If an entry in contextArray contains 0, then the corresponding handle may be assigned to a
     session. If the entry contains a value that is less than or equal to the number of loaded sessions for the
     TPM, then the array entry is the slot in which the context is loaded.

     EXAMPLE:        If the TPM allows 8 loaded sessions, then the slot numbers would be 1-8 and a contextArrary value in that
                     range would represent the loaded session.

     NOTE:           When the TPM firmware determines that the array entry is for a loaded session, it will subtract 1 to create the
                     zero-based slot number.

     There is one significant corner case in this scheme. When the contextCount is equal to a value in the
     contextArray, the oldest session needs to be recycled or flushed. In order to recycle the session, it must
     be loaded. To be loaded, there must be an available slot. Rather than require that a spare slot be
     available all the time, the TPM will check to see if the contextCount is equal to some value in the
     contextArray when a session is created. This prevents the last session slot from being used when it is
     likely that a session will need to be recycled.
     If a TPM with both 1.2 and 2.0 functionality uses this scheme for both 1.2 and 2.0 sessions, and the list of
     active contexts is read with TPM_GetCapabiltiy(), the TPM will create 32-bit representations of the list that
     contains 16-bit values (the TPM2_GetCapability() returns a list of handles for active sessions rather than
     a list of contextID). The full contextID has high-order bits that are either the same as the current
     contextCount or one less. It is one less if the 16-bits of the contextArray has a value that is larger than
     the low-order 16 bits of contextCount.

     8.8.2      Includes, Defines, and Local Variables

 1   #define SESSION_C
 2   #include "InternalRoutines.h"
 3   #include "Platform.h"
 4   #include "SessionProcess_fp.h"


     8.8.3      File Scope Function -- ContextIdSetOldest()

     This function is called when the oldest contextID is being loaded or deleted. Once a saved context
     becomes the oldest, it stays the oldest until it is deleted.
     Finding the oldest is a bit tricky. It is not just the numeric comparison of values but is dependent on the
     value of contextCounter.
     Assume we have a small contextArray with 8, 4-bit values with values 1 and 2 used to indicate the loaded
     context slot number. Also assume that the array contains hex values of (0 0 1 0 3 0 9 F) and that the
     contextCounter is an 8-bit counter with a value of 0x37. Since the low nibble is 7, that means that values
     above 7 are older than values below it and, in this example, 9 is the oldest value.
     Note if we subtract the counter value, from each slot that contains a saved contextID we get (- - - - B - 2 -
     8) and the oldest entry is now easy to find.

 5   static void
 6   ContextIdSetOldest(
 7        void
 8        )
 9   {
10        CONTEXT_SLOT         lowBits;
11        CONTEXT_SLOT         entry;
12        CONTEXT_SLOT         smallest = ((CONTEXT_SLOT) ~0);
13        UINT32 i;


     Page 194                                           TCG Published                                              Family "2.0"
     October 30, 2014                          Copyright © TCG 2006-2014                           Level 00 Revision 01.16
     Part 4: Supporting Routines                                          Trusted Platform Module Library

14
15       // Set oldestSaveContext to a value indicating none assigned
16       s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
17
18       lowBits = (CONTEXT_SLOT)gr.contextCounter;
19       for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
20       {
21           entry = gr.contextArray[i];
22
23            // only look at entries that are saved contexts
24            if(entry > MAX_LOADED_SESSIONS)
25            {
26                // Use a less than or equal in case the oldest
27                // is brand new (= lowBits-1) and equal to our initial
28                // value for smallest.
29                if(((CONTEXT_SLOT) (entry - lowBits)) <= smallest)
30                {
31                    smallest = (entry - lowBits);
32                    s_oldestSavedSession = i;
33                }
34            }
35       }
36       // When we finish, either the s_oldestSavedSession still has its initial
37       // value, or it has the index of the oldest saved context.
38   }


     8.8.4    Startup Function -- SessionStartup()

     This function initializes the session subsystem on TPM2_Startup().

39   void
40   SessionStartup(
41       STARTUP_TYPE         type
42       )
43   {
44       UINT32                    i;
45
46       // Initialize session slots. At startup, all the in-memory session slots
47       // are cleared and marked as not occupied
48       for(i = 0; i < MAX_LOADED_SESSIONS; i++)
49           s_sessions[i].occupied = FALSE;   // session slot is not occupied
50
51       // The free session slots the number of maximum allowed loaded sessions
52       s_freeSessionSlots = MAX_LOADED_SESSIONS;
53
54       // Initialize context ID data. On a ST_SAVE or hibernate sequence, it             will
55       // scan the saved array of session context counts, and clear any entry            that
56       // references a session that was in memory during the state save since            that
57       // memory was not preserved over the ST_SAVE.
58       if(type == SU_RESUME || type == SU_RESTART)
59       {
60           // On ST_SAVE we preserve the contexts that were saved but not the            ones
61           // in memory
62           for (i = 0; i < MAX_ACTIVE_SESSIONS; i++)
63           {
64               // If the array value is unused or references a loaded session            then
65               // that loaded session context is lost and the array entry is
66               // reclaimed.
67               if (gr.contextArray[i] <= MAX_LOADED_SESSIONS)
68                   gr.contextArray[i] = 0;
69           }
70           // Find the oldest session in context ID data and set it in
71           // s_oldestSavedSession
72           ContextIdSetOldest();


     Family "2.0"                               TCG Published                                  Page 195
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                           Part 4: Supporting Routines

 73       }
 74       else
 75       {
 76           // For STARTUP_CLEAR, clear out the contextArray
 77           for (i = 0; i < MAX_ACTIVE_SESSIONS; i++)
 78               gr.contextArray[i] = 0;
 79
 80             // reset the context counter
 81             gr.contextCounter = MAX_LOADED_SESSIONS + 1;
 82
 83             // Initialize oldest saved session
 84             s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
 85       }
 86       return;
 87   }


      8.8.5     Access Functions

      8.8.5.1     SessionIsLoaded()

      This function test a session handle references a loaded session. The handle must have previously been
      checked to make sure that it is a valid handle for an authorization session.

      NOTE:           A PWAP authorization does not have a session.


      Return Value                       Meaning

      TRUE                               if session is loaded
      FALSE                              if it is not loaded

 88   BOOL
 89   SessionIsLoaded(
 90       TPM_HANDLE             handle                // IN: session handle
 91       )
 92   {
 93       pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
 94               || HandleGetType(handle) == TPM_HT_HMAC_SESSION);
 95
 96       handle = handle & HR_HANDLE_MASK;
 97
 98       // if out of range of possible active session, or not assigned to a loaded
 99       // session return false
100       if(   handle >= MAX_ACTIVE_SESSIONS
101          || gr.contextArray[handle] == 0
102          || gr.contextArray[handle] > MAX_LOADED_SESSIONS
103         )
104           return FALSE;
105
106       return TRUE;
107   }


      8.8.5.2     SessionIsSaved()

      This function test a session handle references a saved session. The handle must have previously been
      checked to make sure that it is a valid handle for an authorization session.

      NOTE:           An password authorization does not have a session.

      This function requires that the handle be a valid session handle.


      Page 196                                          TCG Published                         Family "2.0"
      October 30, 2014                         Copyright © TCG 2006-2014          Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library


      Return Value                     Meaning

      TRUE                             if session is saved
      FALSE                            if it is not saved

108   BOOL
109   SessionIsSaved(
110       TPM_HANDLE            handle                // IN: session handle
111       )
112   {
113       pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
114               || HandleGetType(handle) == TPM_HT_HMAC_SESSION);
115
116       handle = handle & HR_HANDLE_MASK;
117       // if out of range of possible active session, or not assigned, or
118       // assigned to a loaded session, return false
119       if(   handle >= MAX_ACTIVE_SESSIONS
120          || gr.contextArray[handle] == 0
121          || gr.contextArray[handle] <= MAX_LOADED_SESSIONS
122         )
123           return FALSE;
124
125       return TRUE;
126   }


      8.8.5.3     SessionPCRValueIsCurrent()

      This function is used to check if PCR values have been updated since the last time they were checked in
      a policy session.
      This function requires the session is loaded.

      Return Value                     Meaning

      TRUE                             if PCR value is current
      FALSE                            if PCR value is not current

127   BOOL
128   SessionPCRValueIsCurrent(
129       TPMI_SH_POLICY        handle                // IN: session handle
130       )
131   {
132       SESSION                   *session;
133
134       pAssert(SessionIsLoaded(handle));
135
136       session = SessionGet(handle);
137       if(   session->pcrCounter != 0
138          && session->pcrCounter != gr.pcrCounter
139         )
140           return FALSE;
141       else
142           return TRUE;
143   }


      8.8.5.4     SessionGet()

      This function returns a pointer to the session object associated with a session handle.
      The function requires that the session is loaded.


      Family "2.0"                                    TCG Published                                    Page 197
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                     Part 4: Supporting Routines

144   SESSION *
145   SessionGet(
146        TPM_HANDLE           handle              // IN: session handle
147        )
148   {
149        CONTEXT_SLOT        sessionIndex;
150
151        pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
152                || HandleGetType(handle) == TPM_HT_HMAC_SESSION
153               );
154
155        pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS);
156
157        // get the contents of the session array. Because session is loaded, we
158        // should always get a valid sessionIndex
159        sessionIndex = gr.contextArray[handle & HR_HANDLE_MASK] - 1;
160
161        pAssert(sessionIndex < MAX_LOADED_SESSIONS);
162
163        return &s_sessions[sessionIndex].session;
164   }


      8.8.6     Utility Functions

      8.8.6.1       ContextIdSessionCreate()

      This function is called when a session is created. It will check to see if the current gap would prevent a
      context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find an
      open slot in contextArray, set contextArray to the slot.
      This routine requires that the caller has determined the session array index for the session.

      return type                       TPM_RC

      TPM_RC_SUCCESS                    context ID was assigned
      TPM_RC_CONTEXT_GAP                can't assign a new contextID until the oldest saved session context is
                                        recycled
      TPM_RC_SESSION_HANDLE             there is no slot available in the context array for tracking of this
                                        session context

165   static TPM_RC
166   ContextIdSessionCreate (
167        TPM_HANDLE          *handle,             // OUT: receives the assigned handle. This will
168                                                 //     be an index that must be adjusted by the
169                                                 //     caller according to the type of the
170                                                 //     session created
171        UINT32               sessionIndex        // IN: The session context array entry that will
172                                                 //     be occupied by the created session
173        )
174   {
175
176        pAssert(sessionIndex < MAX_LOADED_SESSIONS);
177
178        // check to see if creating the context is safe
179        // Is this going to be an assignment for the last session context
180        // array entry? If so, then there will be no room to recycle the
181        // oldest context if needed. If the gap is not at maximum, then
182        // it will be possible to save a context if it becomes necessary.
183        if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
184           && s_freeSessionSlots == 1)
185        {
186            // See if the gap is at maximum

      Page 198                                       TCG Published                                         Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                      Level 00 Revision 01.16
      Part 4: Supporting Routines                                            Trusted Platform Module Library

187             if(      (CONTEXT_SLOT)gr.contextCounter
188                   == gr.contextArray[s_oldestSavedSession])
189
190                   // Note: if this is being used on a TPM.combined, this return
191                   //       code should be transformed to an appropriate 1.2 error
192                   //       code for this case.
193                   return TPM_RC_CONTEXT_GAP;
194       }
195
196       // Find an unoccupied entry in the contextArray
197       for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++)
198       {
199           if(gr.contextArray[*handle] == 0)
200           {
201               // indicate that the session associated with this handle
202               // references a loaded session
203               gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex+1);
204               return TPM_RC_SUCCESS;
205           }
206       }
207       return TPM_RC_SESSION_HANDLES;
208   }


      8.8.6.2     SessionCreate()

      This function does the detailed work for starting an authorization session. This is done in a support
      routine rather than in the action code because the session management may differ in implementations.
      This implementation uses a fixed memory allocation to hold sessions and a fixed allocation to hold the
      contextID for the saved contexts.

      Error Returns                   Meaning

      TPM_RC_CONTEXT_GAP              need to recycle sessions
      TPM_RC_SESSION_HANDLE           active session space is full
      TPM_RC_SESSION_MEMORY           loaded session space is full

209   TPM_RC
210   SessionCreate(
211       TPM_SE               sessionType,        //   IN: the session type
212       TPMI_ALG_HASH        authHash,           //   IN: the hash algorithm
213       TPM2B_NONCE         *nonceCaller,        //   IN: initial nonceCaller
214       TPMT_SYM_DEF        *symmetric,          //   IN: the symmetric algorithm
215       TPMI_DH_ENTITY       bind,               //   IN: the bind object
216       TPM2B_DATA          *seed,               //   IN: seed data
217       TPM_HANDLE          *sessionHandle       //   OUT: the session handle
218       )
219   {
220       TPM_RC                     result = TPM_RC_SUCCESS;
221       CONTEXT_SLOT               slotIndex;
222       SESSION                   *session = NULL;
223
224       pAssert(   sessionType == TPM_SE_HMAC
225               || sessionType == TPM_SE_POLICY
226               || sessionType == TPM_SE_TRIAL);
227
228       // If there are no open spots in the session array, then no point in searching
229       if(s_freeSessionSlots == 0)
230           return TPM_RC_SESSION_MEMORY;
231
232       // Find a space for loading a session
233       for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
234       {

      Family "2.0"                                 TCG Published                                  Page 199
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                     October 30, 2014
      Trusted Platform Module Library                                    Part 4: Supporting Routines

235            // Is this available?
236            if(s_sessions[slotIndex].occupied == FALSE)
237            {
238                session = &s_sessions[slotIndex].session;
239                break;
240            }
241       }
242       // if no spot found, then this is an internal error
243       pAssert (slotIndex < MAX_LOADED_SESSIONS);
244
245       // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be
246       // returned from ContextIdHandelAssign()
247       result = ContextIdSessionCreate(sessionHandle, slotIndex);
248       if(result != TPM_RC_SUCCESS)
249           return result;
250
251       //*** Only return from this point on is TPM_RC_SUCCESS
252
253       // Can now indicate that the session array entry is occupied.
254       s_freeSessionSlots--;
255       s_sessions[slotIndex].occupied = TRUE;
256
257       // Initialize the session data
258       MemorySet(session, 0, sizeof(SESSION));
259
260       // Initialize internal session data
261       session->authHashAlg = authHash;
262       // Initialize session type
263       if(sessionType == TPM_SE_HMAC)
264       {
265           *sessionHandle += HMAC_SESSION_FIRST;
266
267       }
268       else
269       {
270           *sessionHandle += POLICY_SESSION_FIRST;
271
272            // For TPM_SE_POLICY or TPM_SE_TRIAL
273            session->attributes.isPolicy = SET;
274            if(sessionType == TPM_SE_TRIAL)
275                session->attributes.isTrialPolicy = SET;
276
277            // Initialize policy session data
278            SessionInitPolicyData(session);
279       }
280       // Create initial session nonce
281       session->nonceTPM.t.size = nonceCaller->t.size;
282       CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer);
283
284       // Set up session parameter encryption algorithm
285       session->symmetric = *symmetric;
286
287       // If there is a bind object or a session secret, then need to compute
288       // a sessionKey.
289       if(bind != TPM_RH_NULL || seed->t.size != 0)
290       {
291           // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM,
292           //                      nonceCaller, bits)
293           // The HMAC key for generating the sessionSecret can be the concatenation
294           // of an authorization value and a seed value
295           TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer)));
296           TPM2B_KEY            key;
297
298            UINT16                   hashSize;     // The size of the hash used by the
299                                                   // session crated by this command
300            TPM2B_AUTH    entityAuth;              // The authValue of the entity

      Page 200                                 TCG Published                           Family "2.0"
      October 30, 2014                   Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

301                                                         // associated with HMAC session
302
303             // Get hash size, which is also the length of sessionKey
304             hashSize = CryptGetHashDigestSize(session->authHashAlg);
305
306             // Get authValue of associated entity
307             entityAuth.t.size = EntityGetAuthValue(bind, &entityAuth.t.buffer);
308
309             // Concatenate authValue and seed
310             pAssert(entityAuth.t.size + seed->t.size <= sizeof(key.t.buffer));
311             MemoryCopy2B(&key.b, &entityAuth.b, sizeof(key.t.buffer));
312             MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer));
313
314             session->sessionKey.t.size = hashSize;
315
316             // Compute the session key
317             KDFa(session->authHashAlg, &key.b, "ATH", &session->nonceTPM.b,
318                  &nonceCaller->b, hashSize * 8, session->sessionKey.t.buffer, NULL);
319       }
320
321       // Copy the name of the entity that the HMAC session is bound to
322       // Policy session is not bound to an entity
323       if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC)
324       {
325           session->attributes.isBound = SET;
326           SessionComputeBoundEntity(bind, &session->u1.boundEntity);
327       }
328       // If there is a bind object and it is subject to DA, then use of this session
329       // is subject to DA regardless of how it is used.
330       session->attributes.isDaBound =    (bind != TPM_RH_NULL)
331                                       && (IsDAExempted(bind) == FALSE);
332
333       // If the session is bound, then check to see if it is bound to lockoutAuth
334       session->attributes.isLockoutBound =    (session->attributes.isDaBound == SET)
335                                            && (bind == TPM_RH_LOCKOUT);
336       return TPM_RC_SUCCESS;
337
338   }


      8.8.6.3     SessionContextSave()

      This function is called when a session context is to be saved. The contextID of the saved session is
      returned. If no contextID can be assigned, then the routine returns TPM_RC_CONTEXT_GAP. If the
      function completes normally, the session slot will be freed.
      This function requires that handle references a loaded session. Otherwise, it should not be called at the
      first place.

      Error Returns                      Meaning

      TPM_RC_CONTEXT_GAP                 a contextID could not be assigned.
      TPM_RC_TOO_MANY_CONTEXTS           the counter maxed out

339   TPM_RC
340   SessionContextSave (
341       TPM_HANDLE                 handle,           // IN: session handle
342       CONTEXT_COUNTER           *contextID         // OUT: assigned contextID
343       )
344   {
345       UINT32                            contextIndex;
346       CONTEXT_SLOT                      slotIndex;
347
348       pAssert(SessionIsLoaded(handle));

      Family "2.0"                                TCG Published                                     Page 201
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                           Part 4: Supporting Routines

349
350       // check to see if the gap is already maxed out
351       // Need to have a saved session
352       if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
353             // if the oldest saved session has the same value as the low bits
354             // of the contextCounter, then the GAP is maxed out.
355          && gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter)
356           return TPM_RC_CONTEXT_GAP;
357
358       // if the caller wants the context counter, set it
359       if(contextID != NULL)
360           *contextID = gr.contextCounter;
361
362       pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS);
363
364       contextIndex = handle & HR_HANDLE_MASK;
365
366       // Extract the session slot number referenced by the contextArray
367       // because we are going to overwrite this with the low order
368       // contextID value.
369       slotIndex = gr.contextArray[contextIndex] - 1;
370
371       // Set the contextID for the contextArray
372       gr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter;
373
374       // Increment the counter
375       gr.contextCounter++;
376
377       // In the unlikely event that the 64-bit context counter rolls over...
378       if(gr.contextCounter == 0)
379       {
380           // back it up
381           gr.contextCounter--;
382           // return an error
383           return TPM_RC_TOO_MANY_CONTEXTS;
384       }
385       // if the low-order bits wrapped, need to advance the value to skip over
386       // the values used to indicate that a session is loaded
387       if(((CONTEXT_SLOT)gr.contextCounter) == 0)
388           gr.contextCounter += MAX_LOADED_SESSIONS + 1;
389
390       // If no other sessions are saved, this is now the oldest.
391       if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS)
392           s_oldestSavedSession = contextIndex;
393
394       // Mark the session slot as unoccupied
395       s_sessions[slotIndex].occupied = FALSE;
396
397       // and indicate that there is an additional open slot
398       s_freeSessionSlots++;
399
400       return TPM_RC_SUCCESS;
401   }


      8.8.6.4     SessionContextLoad()

      This function is used to load a session from saved context. The session handle must be for a saved
      context.
      If the gap is at a maximum, then the only session that can be loaded is the oldest session, otherwise
      TPM_RC_CONTEXT_GAP is returned.
      This function requires that handle references a valid saved session.



      Page 202                                     TCG Published                              Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library


      Error Returns                   Meaning

      TPM_RC_SESSION_MEMORY           no free session slots
      TPM_RC_CONTEXT_GAP              the gap count is maximum and this is not the oldest saved context

402   TPM_RC
403   SessionContextLoad(
404       SESSION            *session,            // IN: session structure from saved context
405       TPM_HANDLE         *handle              // IN/OUT: session handle
406       )
407   {
408       UINT32                    contextIndex;
409       CONTEXT_SLOT              slotIndex;
410
411       pAssert(   HandleGetType(*handle) == TPM_HT_POLICY_SESSION
412               || HandleGetType(*handle) == TPM_HT_HMAC_SESSION);
413
414       // Don't bother looking if no openings
415       if(s_freeSessionSlots == 0)
416           return TPM_RC_SESSION_MEMORY;
417
418       // Find a free session slot to load the session
419       for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
420           if(s_sessions[slotIndex].occupied == FALSE) break;
421
422       // if no spot found, then this is an internal error
423       pAssert (slotIndex < MAX_LOADED_SESSIONS);
424
425       contextIndex = *handle & HR_HANDLE_MASK;               // extract the index
426
427       // If there is only one slot left, and the gap is at maximum, the only session
428       // context that we can safely load is the oldest one.
429       if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
430          && s_freeSessionSlots == 1
431          && (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession]
432          && contextIndex != s_oldestSavedSession
433         )
434           return TPM_RC_CONTEXT_GAP;
435
436       pAssert(contextIndex < MAX_ACTIVE_SESSIONS);
437
438       // set the contextArray value to point to the session slot where
439       // the context is loaded
440       gr.contextArray[contextIndex] = slotIndex + 1;
441
442       // if this was the oldest context, find the new oldest
443       if(contextIndex == s_oldestSavedSession)
444           ContextIdSetOldest();
445
446       // Copy session data to session slot
447       s_sessions[slotIndex].session = *session;
448
449       // Set session slot as occupied
450       s_sessions[slotIndex].occupied = TRUE;
451
452       // Reduce the number of open spots
453       s_freeSessionSlots--;
454
455       return TPM_RC_SUCCESS;
456   }




      Family "2.0"                                 TCG Published                                          Page 203
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                              October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

      8.8.6.5     SessionFlush()

      This function is used to flush a session referenced by its handle. If the session associated with handle is
      loaded, the session array entry is marked as available.
      This function requires that handle be a valid active session.

457   void
458   SessionFlush(
459        TPM_HANDLE           handle             // IN: loaded or saved session handle
460        )
461   {
462        CONTEXT_SLOT              slotIndex;
463        UINT32                    contextIndex;       // Index into contextArray
464
465        pAssert(      (    HandleGetType(handle) == TPM_HT_POLICY_SESSION
466                        || HandleGetType(handle) == TPM_HT_HMAC_SESSION
467                      )
468                   && (SessionIsLoaded(handle) || SessionIsSaved(handle))
469                  );
470
471        // Flush context ID of this session
472        // Convert handle to an index into the contextArray
473        contextIndex = handle & HR_HANDLE_MASK;
474
475        pAssert(contextIndex < sizeof(gr.contextArray)/sizeof(gr.contextArray[0]));
476
477        // Get the current contents of the array
478        slotIndex = gr.contextArray[contextIndex];
479
480        // Mark context array entry as available
481        gr.contextArray[contextIndex] = 0;
482
483        // Is this a saved session being flushed
484        if(slotIndex > MAX_LOADED_SESSIONS)
485        {
486            // Flushing the oldest session?
487            if(contextIndex == s_oldestSavedSession)
488                // If so, find a new value for oldest.
489                ContextIdSetOldest();
490        }
491        else
492        {
493            // Adjust slot index to point to session array index
494            slotIndex -= 1;
495
496             // Free session array index
497             s_sessions[slotIndex].occupied = FALSE;
498             s_freeSessionSlots++;
499        }
500
501        return;
502   }


      8.8.6.6     SessionComputeBoundEntity()

      This function computes the binding value for a session. The binding value for a reserved handle is the
      handle itself. For all the other entities, the authValue at the time of binding is included to prevent
      squatting. For those values, the Name and the authValue are concatenated into the bind buffer. If they
      will not both fit, the will be overlapped by XORing() bytes. If XOR is required, the bind value will be full.

503   void
504   SessionComputeBoundEntity(

      Page 204                                      TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

505        TPMI_DH_ENTITY      entityHandle,     // IN: handle of entity
506        TPM2B_NAME         *bind              // OUT: binding value
507        )
508   {
509        TPM2B_AUTH               auth;
510        INT16                    overlap;
511
512        // Get name
513        bind->t.size = EntityGetName(entityHandle, &bind->t.name);
514
515   //     // The bound value of a reserved handle is the handle itself
516   //     if(bind->t.size == sizeof(TPM_HANDLE)) return;
517
518        // For all the other entities, concatenate the auth value to the name.
519        // Get a local copy of the auth value because some overlapping
520        // may be necessary.
521        auth.t.size = EntityGetAuthValue(entityHandle, &auth.t.buffer);
522        pAssert(auth.t.size <= sizeof(TPMU_HA));
523
524        // Figure out if there will be any overlap
525        overlap = bind->t.size + auth.t.size - sizeof(bind->t.name);
526
527        // There is overlap if the combined sizes are greater than will fit
528        if(overlap > 0)
529        {
530            // The overlap area is at the end of the Name
531            BYTE    *result = &bind->t.name[bind->t.size - overlap];
532            int     i;
533
534             // XOR the auth value into the Name for the overlap area
535             for(i = 0; i < overlap; i++)
536                 result[i] ^= auth.t.buffer[i];
537        }
538        else
539        {
540            // There is no overlap
541            overlap = 0;
542        }
543        //copy the remainder of the authData to the end of the name
544        MemoryCopy(&bind->t.name[bind->t.size], &auth.t.buffer[overlap],
545                   auth.t.size - overlap, sizeof(bind->t.name) - bind->t.size);
546
547        // Increase the size of the bind data by the size of the auth - the overlap
548        bind->t.size += auth.t.size-overlap;
549
550        return;
551   }


      8.8.6.7     SessionInitPolicyData()

      This function initializes the portions of the session policy data that are not set by the allocation of a
      session.

552   void
553   SessionInitPolicyData(
554        SESSION            *session           // IN: session handle
555        )
556   {
557        // Initialize start time
558        session->startTime = go.clock;
559
560        // Initialize policyDigest. policyDigest is initialized with a string of 0 of
561        // session algorithm digest size. Since the policy already contains all zeros
562        // it is only necessary to set the size

      Family "2.0"                               TCG Published                                      Page 205
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

563         session->u2.policyDigest.t.size = CryptGetHashDigestSize(session->authHashAlg);
564         return;
565   }


      8.8.6.8     SessionResetPolicyData()

      This function is used to reset the policy data without changing the nonce or the start time of the session.

566   void
567   SessionResetPolicyData(
568         SESSION            *session             // IN: the session to reset
569         )
570   {
571         session->commandCode = 0;              // No command
572
573         // No locality selected
574         MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality));
575
576         // The cpHash size to zero
577         session->u1.cpHash.b.size = 0;
578
579         // No timeout
580         session->timeOut = 0;
581
582         // Reset the pcrCounter
583         session->pcrCounter = 0;
584
585         // Reset the policy hash
586         MemorySet(&session->u2.policyDigest.t.buffer, 0,
587                   session->u2.policyDigest.t.size);
588
589         // Reset the session attributes
590         MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES));
591
592         // set the policy attribute
593         session->attributes.isPolicy = SET;
594   }


      8.8.6.9     SessionCapGetLoaded()

      This function returns a list of handles of loaded session, started from input handle
      Handle must be in valid loaded session handle range, but does not have to point to a loaded session.

      Return Value                      Meaning

      YES                               if there are more handles available
      NO                                all the available handles has been returned

595   TPMI_YES_NO
596   SessionCapGetLoaded(
597         TPMI_SH_POLICY      handle,             // IN: start handle
598         UINT32              count,              // IN: count of returned handle
599         TPML_HANDLE        *handleList          // OUT: list of handle
600         )
601   {
602         TPMI_YES_NO        more = NO;
603         UINT32             i;
604
605         pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION);
606
607         // Initialize output handle list

      Page 206                                       TCG Published                                   Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                     Trusted Platform Module Library

608         handleList->count = 0;
609
610         // The maximum count of handles we may return is MAX_CAP_HANDLES
611         if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
612
613         // Iterate session context ID slots to get loaded session handles
614         for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++)
615         {
616             // If session is active
617             if(gr.contextArray[i] != 0)
618             {
619                 // If session is loaded
620                 if (gr.contextArray[i] <= MAX_LOADED_SESSIONS)
621                 {
622                     if(handleList->count < count)
623                     {
624                         SESSION         *session;
625
626                            // If we have not filled up the return list, add this
627                            // session handle to it
628                            // assume that this is going to be an HMAC session
629                            handle = i + HMAC_SESSION_FIRST;
630                            session = SessionGet(handle);
631                            if(session->attributes.isPolicy)
632                                handle = i + POLICY_SESSION_FIRST;
633                            handleList->handle[handleList->count] = handle;
634                            handleList->count++;
635                       }
636                       else
637                       {
638                           // If the return list is full but we still have loaded object
639                           // available, report this and stop iterating
640                           more = YES;
641                           break;
642                       }
643                   }
644              }
645         }
646
647         return more;
648
649   }


      8.8.6.10       SessionCapGetSaved()

      This function returns a list of handles for saved session, starting at handle.
      Handle must be in a valid handle range, but does not have to point to a saved session

      Return Value                      Meaning

      YES                               if there are more handles available
      NO                                all the available handles has been returned

650   TPMI_YES_NO
651   SessionCapGetSaved(
652         TPMI_SH_HMAC        handle,             // IN: start handle
653         UINT32              count,              // IN: count of returned handle
654         TPML_HANDLE        *handleList          // OUT: list of handle
655         )
656   {
657         TPMI_YES_NO        more = NO;
658         UINT32             i;
659

      Family "2.0"                                   TCG Published                                         Page 207
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                                               Part 4: Supporting Routines

660       pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION);
661
662       // Initialize output handle list
663       handleList->count = 0;
664
665       // The maximum count of handles we may return is MAX_CAP_HANDLES
666       if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
667
668       // Iterate session context ID slots to get loaded session handles
669       for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++)
670       {
671           // If session is active
672           if(gr.contextArray[i] != 0)
673           {
674               // If session is saved
675               if (gr.contextArray[i] > MAX_LOADED_SESSIONS)
676               {
677                   if(handleList->count < count)
678                   {
679                       // If we have not filled up the return list, add this
680                       // session handle to it
681                       handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST;
682                       handleList->count++;
683                   }
684                   else
685                   {
686                       // If the return list is full but we still have loaded object
687                       // available, report this and stop iterating
688                       more = YES;
689                       break;
690                   }
691               }
692           }
693       }
694
695       return more;
696
697   }


      8.8.6.11    SessionCapGetLoadedNumber()

      This function return the number of authorization sessions currently loaded into TPM RAM.

698   UINT32
699   SessionCapGetLoadedNumber(
700       void
701       )
702   {
703       return MAX_LOADED_SESSIONS - s_freeSessionSlots;
704   }


      8.8.6.12    SessionCapGetLoadedAvail()

      This function returns the number of additional authorization sessions, of any type, that could be loaded
      into TPM RAM.

      NOTE:           In other implementations, this number may just be an estimate. The only requirement for the estimate is, if it is
                      one or more, then at least one session must be loadable.

705   UINT32
706   SessionCapGetLoadedAvail(
707       void
708       )

      Page 208                                           TCG Published                                                Family "2.0"
      October 30, 2014                          Copyright © TCG 2006-2014                             Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

709   {
710         return s_freeSessionSlots;
711   }


      8.8.6.13     SessionCapGetActiveNumber()

      This function returns the number of active authorization sessions currently being tracked by the TPM.

712   UINT32
713   SessionCapGetActiveNumber(
714         void
715         )
716   {
717         UINT32                  i;
718         UINT32                  num = 0;
719
720         // Iterate the context array to find the number of non-zero slots
721         for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
722         {
723             if(gr.contextArray[i] != 0) num++;
724         }
725
726         return num;
727   }


      8.8.6.14     SessionCapGetActiveAvail()

      This function returns the number of additional authorization sessions, of any type, that could be created.
      This not the number of slots for sessions, but the number of additional sessions that the TPM is capable
      of tracking.

728   UINT32
729   SessionCapGetActiveAvail(
730         void
731         )
732   {
733         UINT32                  i;
734         UINT32                  num = 0;
735
736         // Iterate the context array to find the number of zero slots
737         for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
738         {
739             if(gr.contextArray[i] == 0) num++;
740         }
741
742         return num;
743   }


      8.9     Time.c

      8.9.1      Introduction

      This file contains the functions relating to the TPM's time functions including the interface to the
      implementation-specific time functions.

      8.9.2      Includes

  1   #include "InternalRoutines.h"
  2   #include "Platform.h"

      Family "2.0"                                TCG Published                                      Page 209
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                       Part 4: Supporting Routines

     8.9.3     Functions

     8.9.3.1      TimePowerOn()

     This function initialize time info at _TPM_Init().

 3   void
 4   TimePowerOn(
 5        void
 6        )
 7   {
 8        TPM_SU               orderlyShutDown;
 9
10        // Read orderly data info from NV memory
11        NvReadReserved(NV_ORDERLY_DATA, &go);
12
13        // Read orderly shut down state flag
14        NvReadReserved(NV_ORDERLY, &orderlyShutDown);
15
16        // If the previous cycle is orderly shut down, the value of the safe bit
17        // the same as previously saved. Otherwise, it is not safe.
18        if(orderlyShutDown == SHUTDOWN_NONE)
19            go.clockSafe= NO;
20        else
21            go.clockSafe = YES;
22
23        // Set the initial state of the DRBG
24        CryptDrbgGetPutState(PUT_STATE);
25
26        // Clear time since TPM power on
27        g_time = 0;
28
29        return;
30   }


     8.9.3.2      TimeStartup()

     This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at
     TPM2_Startup().

31   void
32   TimeStartup(
33        STARTUP_TYPE          type                // IN: start up type
34        )
35   {
36        if(type == SU_RESUME)
37        {
38            // Resume sequence
39            gr.restartCount++;
40        }
41        else
42        {
43            if(type == SU_RESTART)
44            {
45                 // Hibernate sequence
46                 gr.clearCount++;
47                 gr.restartCount++;
48            }
49            else
50            {
51                 // Reset sequence
52                 // Increase resetCount
53                 gp.resetCount++;

     Page 210                                        TCG Published                       Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014       Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library

 54
 55                  // Write resetCount to NV
 56                  NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
 57                  gp.totalResetCount++;
 58
 59                  // We do not expect the total reset counter overflow during the life
 60                  // time of TPM. if it ever happens, TPM will be put to failure mode
 61                  // and there is no way to recover it.
 62                  // The reason that there is no recovery is that we don't increment
 63                  // the NV totalResetCount when incrementing would make it 0. When the
 64                  // TPM starts up again, the old value of totalResetCount will be read
 65                  // and we will get right back to here with the increment failing.
 66                  if(gp.totalResetCount == 0)
 67                      FAIL(FATAL_ERROR_INTERNAL);
 68
 69                  // Write total reset counter to NV
 70                  NvWriteReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
 71
 72                  // Reset restartCount
 73                  gr.restartCount = 0;
 74             }
 75       }
 76
 77       return;
 78   }


      8.9.3.3       TimeUpdateToCurrent()

      This function updates the Time and Clock in the global TPMS_TIME_INFO structure.
      In this implementation, Time and Clock are updated at the beginning of each command and the values
      are unchanged for the duration of the command.
      Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance if
      NV is not available. When clock is not advancing, any function that uses Clock will fail and return
      TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE.
      This implementations does not do rate limiting. If the implementation does do rate limiting, then the Clock
      update should not be inhibited even when doing rather limiting.

 79   void
 80   TimeUpdateToCurrent(
 81       void
 82       )
 83   {
 84       UINT64          oldClock;
 85       UINT64          elapsed;
 86   #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
 87
 88       // Can't update time during the dark interval or when rate limiting.
 89       if(NvIsAvailable() != TPM_RC_SUCCESS)
 90           return;
 91
 92       // Save the old clock value
 93       oldClock = go.clock;
 94
 95       // Update the time info to current
 96       elapsed = _plat__ClockTimeElapsed();
 97       go.clock += elapsed;
 98       g_time += elapsed;
 99
100       // Check to see if the update has caused a need for an nvClock update
101       // CLOCK_UPDATE_MASK is measured by second, while the value in go.clock is
102       // recorded by millisecond. Align the clock value to second before the bit


      Family "2.0"                                TCG Published                                       Page 211
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                          Part 4: Supporting Routines

103       // operations
104       if( ((go.clock/1000) | CLOCK_UPDATE_MASK)
105               > ((oldClock/1000) | CLOCK_UPDATE_MASK))
106       {
107           // Going to update the time state so the safe flag
108           // should be set
109           go.clockSafe = YES;
110
111             // Get the DRBG state before updating orderly data
112             CryptDrbgGetPutState(GET_STATE);
113
114             NvWriteReserved(NV_ORDERLY_DATA, &go);
115       }
116
117       // Call self healing logic for dictionary attack parameters
118       DASelfHeal();
119
120       return;
121   }


      8.9.3.4     TimeSetAdjustRate()

      This function is used to perform rate adjustment on Time and Clock.

122   void
123   TimeSetAdjustRate(
124       TPM_CLOCK_ADJUST          adjust            // IN: adjust constant
125       )
126   {
127       switch(adjust)
128       {
129           case TPM_CLOCK_COARSE_SLOWER:
130               _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
131               break;
132           case TPM_CLOCK_COARSE_FASTER:
133               _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
134               break;
135           case TPM_CLOCK_MEDIUM_SLOWER:
136               _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
137               break;
138           case TPM_CLOCK_MEDIUM_FASTER:
139               _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
140               break;
141           case TPM_CLOCK_FINE_SLOWER:
142               _plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
143               break;
144           case TPM_CLOCK_FINE_FASTER:
145               _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
146               break;
147           case TPM_CLOCK_NO_CHANGE:
148               break;
149           default:
150               pAssert(FALSE);
151               break;
152       }
153
154       return;
155   }


      8.9.3.5     TimeGetRange()

      This function is used to access TPMS_TIME_INFO. The TPMS_TIME_INFO structure is treaded as an
      array of bytes, and a byte offset and length determine what bytes are returned.

      Page 212                                    TCG Published                              Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014             Level 00 Revision 01.16
      Part 4: Supporting Routines                                            Trusted Platform Module Library


      Error Returns                   Meaning

      TPM_RC_RANGE                    invalid data range

156   TPM_RC
157   TimeGetRange(
158       UINT16              offset,             // IN: offset in TPMS_TIME_INFO
159       UINT16              size,               // IN: size of data
160       TIME_INFO          *dataBuffer          // OUT: result buffer
161       )
162   {
163       TPMS_TIME_INFO            timeInfo;
164       UINT16                    infoSize;
165       BYTE                      infoData[sizeof(TPMS_TIME_INFO)];
166       BYTE                      *buffer;
167
168       // Fill TPMS_TIME_INFO structure
169       timeInfo.time = g_time;
170       TimeFillInfo(&timeInfo.clockInfo);
171
172       // Marshal TPMS_TIME_INFO to canonical form
173       buffer = infoData;
174       infoSize = TPMS_TIME_INFO_Marshal(&timeInfo, &buffer, NULL);
175
176       // Check if the input range is valid
177       if(offset + size > infoSize) return TPM_RC_RANGE;
178
179       // Copy info data to output buffer
180       MemoryCopy(dataBuffer, infoData + offset, size, sizeof(TIME_INFO));
181
182       return TPM_RC_SUCCESS;
183   }


      8.9.3.6    TimeFillInfo

      This function gathers information to fill in a TPMS_CLOCK_INFO structure.

184   void
185   TimeFillInfo(
186       TPMS_CLOCK_INFO           *clockInfo
187       )
188   {
189       clockInfo->clock = go.clock;
190       clockInfo->resetCount = gp.resetCount;
191       clockInfo->restartCount = gr.restartCount;
192
193       // If NV is not available, clock stopped advancing and the value reported is
194       // not "safe".
195       if(NvIsAvailable() == TPM_RC_SUCCESS)
196           clockInfo->safe = go.clockSafe;
197       else
198           clockInfo->safe = NO;
199
200       return;
201   }




      Family "2.0"                                 TCG Published                                  Page 213
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                      October 30, 2014
     Trusted Platform Module Library                                     Part 4: Supporting Routines


     9     Support

     9.1     AlgorithmCap.c

     9.1.1    Description

     This file contains the algorithm property definitions for the algorithms and the code for the
     TPM2_GetCapability() to return the algorithm properties.

     9.1.2    Includes and Defines

 1   #include "InternalRoutines.h"
 2   typedef struct
 3   {
 4       TPM_ALG_ID          algID;
 5       TPMA_ALGORITHM      attributes;
 6   } ALGORITHM;
 7   static const ALGORITHM    s_algorithms[]      =
 8   {
 9   #ifdef TPM_ALG_RSA
10       {TPM_ALG_RSA,           {1, 0, 0, 1,       0, 0, 0, 0, 0}},
11   #endif
12   #ifdef TPM_ALG_DES
13       {TPM_ALG_DES,           {0, 1, 0, 0,       0, 0, 0, 0, 0}},
14   #endif
15   #ifdef TPM_ALG_3DES
16       {TPM_ALG__3DES,         {0, 1, 0, 0,       0, 0, 0, 0, 0}},
17   #endif
18   #ifdef TPM_ALG_SHA1
19       {TPM_ALG_SHA1,          {0, 0, 1, 0,       0, 0, 0, 0, 0}},
20   #endif
21   #ifdef TPM_ALG_HMAC
22       {TPM_ALG_HMAC,          {0, 0, 1, 0,       0, 1, 0, 0, 0}},
23   #endif
24   #ifdef TPM_ALG_AES
25       {TPM_ALG_AES,           {0, 1, 0, 0,       0, 0, 0, 0, 0}},
26   #endif
27   #ifdef TPM_ALG_MGF1
28       {TPM_ALG_MGF1,          {0, 0, 1, 0,       0, 0, 0, 1, 0}},
29   #endif
30
31         {TPM_ALG_KEYEDHASH,         {0, 0, 1, 1, 0, 1, 1, 0, 0}},
32
33   #ifdef TPM_ALG_XOR
34       {TPM_ALG_XOR,                 {0, 1, 1, 0, 0, 0, 0, 0, 0}},
35   #endif
36
37   #ifdef TPM_ALG_SHA256
38       {TPM_ALG_SHA256,              {0, 0, 1, 0, 0, 0, 0, 0, 0}},
39   #endif
40   #ifdef TPM_ALG_SHA384
41       {TPM_ALG_SHA384,              {0, 0, 1, 0, 0, 0, 0, 0, 0}},
42   #endif
43   #ifdef TPM_ALG_SHA512
44       {TPM_ALG_SHA512,              {0, 0, 1, 0, 0, 0, 0, 0, 0}},
45   #endif
46   #ifdef TPM_ALG_WHIRLPOOL512
47       {TPM_ALG_WHIRLPOOL512,        {0, 0, 1, 0, 0, 0, 0, 0, 0}},
48   #endif
49   #ifdef TPM_ALG_SM3_256
50       {TPM_ALG_SM3_256,             {0, 0, 1, 0, 0, 0, 0, 0, 0}},
51   #endif

     Page 214                                  TCG Published                           Family "2.0"
     October 30, 2014                    Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

 52   #ifdef TPM_ALG_SM4
 53       {TPM_ALG_SM4,          {0, 1, 0, 0, 0, 0, 0, 0, 0}},
 54   #endif
 55   #ifdef TPM_ALG_RSASSA
 56       {TPM_ALG_RSASSA,        {1, 0, 0, 0, 0, 1, 0, 0, 0}},
 57   #endif
 58   #ifdef TPM_ALG_RSAES
 59       {TPM_ALG_RSAES,         {1, 0, 0, 0, 0, 0, 1, 0, 0}},
 60   #endif
 61   #ifdef TPM_ALG_RSAPSS
 62       {TPM_ALG_RSAPSS,        {1, 0, 0, 0, 0, 1, 0, 0, 0}},
 63   #endif
 64   #ifdef TPM_ALG_OAEP
 65       {TPM_ALG_OAEP,          {1, 0, 0, 0, 0, 0, 1, 0, 0}},
 66   #endif
 67   #ifdef TPM_ALG_ECDSA
 68       {TPM_ALG_ECDSA,         {1, 0, 0, 0, 0, 1, 0, 1, 0}},
 69   #endif
 70   #ifdef TPM_ALG_ECDH
 71       {TPM_ALG_ECDH,          {1, 0, 0, 0, 0, 0, 0, 1, 0}},
 72   #endif
 73   #ifdef TPM_ALG_ECDAA
 74       {TPM_ALG_ECDAA,         {1, 0, 0, 0, 0, 1, 0, 0, 0}},
 75   #endif
 76   #ifdef TPM_ALG_ECSCHNORR
 77       {TPM_ALG_ECSCHNORR,     {1, 0, 0, 0, 0, 1, 0, 0, 0}},
 78   #endif
 79   #ifdef TPM_ALG_KDF1_SP800_56a
 80       {TPM_ALG_KDF1_SP800_56a,{0, 0, 1, 0, 0, 0, 0, 1, 0}},
 81   #endif
 82   #ifdef TPM_ALG_KDF2
 83       {TPM_ALG_KDF2,          {0, 0, 1, 0, 0, 0, 0, 1, 0}},
 84   #endif
 85   #ifdef TPM_ALG_KDF1_SP800_108
 86       {TPM_ALG_KDF1_SP800_108,{0, 0, 1, 0, 0, 0, 0, 1, 0}},
 87   #endif
 88   #ifdef TPM_ALG_ECC
 89       {TPM_ALG_ECC,           {1, 0, 0, 1, 0, 0, 0, 0, 0}},
 90   #endif
 91
 92       {TPM_ALG_SYMCIPHER,           {0, 0, 0, 1, 0, 0, 0, 0, 0}},
 93
 94   #ifdef TPM_ALG_CTR
 95       {TPM_ALG_CTR,                 {0, 1, 0, 0, 0, 0, 1, 0, 0}},
 96   #endif
 97   #ifdef TPM_ALG_OFB
 98       {TPM_ALG_OFB,                 {0, 1, 0, 0, 0, 0, 1, 0, 0}},
 99   #endif
100   #ifdef TPM_ALG_CBC
101       {TPM_ALG_CBC,                 {0, 1, 0, 0, 0, 0, 1, 0, 0}},
102   #endif
103   #ifdef TPM_ALG_CFB
104       {TPM_ALG_CFB,                 {0, 1, 0, 0, 0, 0, 1, 0, 0}},
105   #endif
106   #ifdef TPM_ALG_ECB
107       {TPM_ALG_ECB,                 {0, 1, 0, 0, 0, 0, 1, 0, 0}},
108   #endif
109   };


      9.1.3    AlgorithmCapGetImplemented()

      This function is used by TPM2_GetCapability() to return a list of the implemented algorithms.




      Family "2.0"                                TCG Published                                       Page 215
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines


      Return Value                      Meaning

      YES                               more algorithms to report
      NO                                no more algorithms to report

110   TPMI_YES_NO
111   AlgorithmCapGetImplemented(
112         TPM_ALG_ID                          algID,         // IN: the starting algorithm ID
113         UINT32                              count,         // IN: count of returned algorithms
114         TPML_ALG_PROPERTY                  *algList        // OUT: algorithm list
115   )
116   {
117         TPMI_YES_NO      more = NO;
118         UINT32           i;
119         UINT32           algNum;
120
121         // initialize output algorithm list
122         algList->count = 0;
123
124         // The maximum count of algorithms we may return is MAX_CAP_ALGS.
125         if(count > MAX_CAP_ALGS)
126             count = MAX_CAP_ALGS;
127
128         // Compute how many algorithms are defined in s_algorithms array.
129         algNum = sizeof(s_algorithms) / sizeof(s_algorithms[0]);
130
131         // Scan the implemented algorithm list to see if there is a match to 'algID'.
132         for(i = 0; i < algNum; i++)
133         {
134             // If algID is less than the starting algorithm ID, skip it
135             if(s_algorithms[i].algID < algID)
136                  continue;
137             if(algList->count < count)
138             {
139                  // If we have not filled up the return list, add more algorithms
140                  // to it
141                  algList->algProperties[algList->count].alg = s_algorithms[i].algID;
142                  algList->algProperties[algList->count].algProperties =
143                      s_algorithms[i].attributes;
144                  algList->count++;
145             }
146             else
147             {
148                  // If the return list is full but we still have algorithms
149                  // available, report this and stop scanning.
150                  more = YES;
151                  break;
152             }
153
154         }
155
156         return more;
157
158   }
159   LIB_EXPORT
160   void
161   AlgorithmGetImplementedVector(
162         ALGORITHM_VECTOR      *implemented            // OUT: the implemented bits are SET
163         )
164   {
165         int                            index;
166
167         // Nothing implemented until we say it is
168         MemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR));

      Page 216                                       TCG Published                              Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                                                Trusted Platform Module Library

169
170         for(index = (sizeof(s_algorithms) / sizeof(s_algorithms[0])) - 1;
171             index >= 0;
172             index--)
173                 SET_BIT(s_algorithms[index].algID, *implemented);
174         return;
175   }


      9.2     Bits.c

      9.2.1     Introduction

      This file contains bit manipulation routines. They operate on bit arrays.
      The 0th bit in the array is the right-most bit in the 0th octet in the array.

      NOTE:            If pAssert() is defined, the functions will assert if the indicated bit number is outside of the range of bArray. How
                       the assert is handled is implementation dependent.


      9.2.2     Includes

  1   #include "InternalRoutines.h"


      9.2.3     Functions

      9.2.3.1      BitIsSet()

      This function is used to check the setting of a bit in an array of bits.

      Return Value                          Meaning

      TRUE                                  bit is set
      FALSE                                 bit is not set

  2   BOOL
  3   BitIsSet(
  4         unsigned int          bitNum,                    // IN: number of the bit in 'bArray'
  5         BYTE                 *bArray,                    // IN: array containing the bit
  6         unsigned int          arraySize                  // IN: size in bytes of 'bArray'
  7         )
  8   {
  9         pAssert(arraySize > (bitNum >> 3));
 10         return((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0);
 11   }


      9.2.3.2      BitSet()

      This function will set the indicated bit in bArray.

 12   void
 13   BitSet(
 14         unsigned int          bitNum,                    // IN: number of the bit in 'bArray'
 15         BYTE                 *bArray,                    // IN: array containing the bit
 16         unsigned int          arraySize                  // IN: size in bytes of 'bArray'
 17         )
 18   {
 19         pAssert(arraySize > bitNum/8);
 20         bArray[bitNum >> 3] |= (1 << (bitNum & 7));

      Family "2.0"                                           TCG Published                                                    Page 217
      Level 00 Revision 01.16                    Copyright © TCG 2006-2014                                         October 30, 2014
     Trusted Platform Module Library                                             Part 4: Supporting Routines

21   }


     9.2.3.3      BitClear()

     This function will clear the indicated bit in bArray.

22   void
23   BitClear(
24         unsigned int         bitNum,             // IN: number of the bit in 'bArray'.
25         BYTE                *bArray,             // IN: array containing the bit
26         unsigned int         arraySize           // IN: size in bytes of 'bArray'
27         )
28   {
29         pAssert(arraySize > bitNum/8);
30         bArray[bitNum >> 3] &= ~(1 << (bitNum & 7));
31   }


     9.3    CommandAttributeData.c

     This is the command code attribute array for GetCapability(). Both this array and s_commandAttributes
     provides command code attributes, but tuned for different purpose

 1   static const TPMA_CC           s_ccAttr [] =      {
 2           {0x011f, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_UndefineSpaceSpecial
 3           {0x0120, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_EvictControl
 4           {0x0121, 0, 1,        1, 0, 1, 0, 0,      0},    //   TPM_CC_HierarchyControl
 5           {0x0122, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_UndefineSpace
 6           {0x0123, 0, 0,        0, 0, 0, 0, 0,      0},    //   No command
 7           {0x0124, 0, 1,        1, 0, 1, 0, 0,      0},    //   TPM_CC_ChangeEPS
 8           {0x0125, 0, 1,        1, 0, 1, 0, 0,      0},    //   TPM_CC_ChangePPS
 9           {0x0126, 0, 1,        1, 0, 1, 0, 0,      0},    //   TPM_CC_Clear
10           {0x0127, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_ClearControl
11           {0x0128, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_ClockSet
12           {0x0129, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_HierarchyChangeAuth
13           {0x012a, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_NV_DefineSpace
14           {0x012b, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_PCR_Allocate
15           {0x012c, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_PCR_SetAuthPolicy
16           {0x012d, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_PP_Commands
17           {0x012e, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_SetPrimaryPolicy
18           {0x012f, 0, 0,        0, 0, 2, 0, 0,      0},    //   TPM_CC_FieldUpgradeStart
19           {0x0130, 0, 0,        0, 0, 1, 0, 0,      0},    //   TPM_CC_ClockRateAdjust
20           {0x0131, 0, 0,        0, 0, 1, 1, 0,      0},    //   TPM_CC_CreatePrimary
21           {0x0132, 0, 0,        0, 0, 1, 0, 0,      0},    //   TPM_CC_NV_GlobalWriteLock
22           {0x0133, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_GetCommandAuditDigest
23           {0x0134, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_Increment
24           {0x0135, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_SetBits
25           {0x0136, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_Extend
26           {0x0137, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_Write
27           {0x0138, 0, 1,        0, 0, 2, 0, 0,      0},    //   TPM_CC_NV_WriteLock
28           {0x0139, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_DictionaryAttackLockReset
29           {0x013a, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_DictionaryAttackParameters
30           {0x013b, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_NV_ChangeAuth
31           {0x013c, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_PCR_Event
32           {0x013d, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_PCR_Reset
33           {0x013e, 0, 0,        0, 1, 1, 0, 0,      0},    //   TPM_CC_SequenceComplete
34           {0x013f, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_SetAlgorithmSet
35           {0x0140, 0, 1,        0, 0, 1, 0, 0,      0},    //   TPM_CC_SetCommandCodeAuditStatus
36           {0x0141, 0, 1,        0, 0, 0, 0, 0,      0},    //   TPM_CC_FieldUpgradeData
37           {0x0142, 0, 1,        0, 0, 0, 0, 0,      0},    //   TPM_CC_IncrementalSelfTest
38           {0x0143, 0, 1,        0, 0, 0, 0, 0,      0},    //   TPM_CC_SelfTest
39           {0x0144, 0, 1,        0, 0, 0, 0, 0,      0},    //   TPM_CC_Startup
40           {0x0145, 0, 1,        0, 0, 0, 0, 0,      0},    //   TPM_CC_Shutdown
41           {0x0146, 0, 1,        0, 0, 0, 0, 0,      0},    //   TPM_CC_StirRandom

     Page 218                                        TCG Published                             Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014             Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

 42            {0x0147,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_ActivateCredential
 43            {0x0148,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_Certify
 44            {0x0149,   0,   0,   0,   0,   3,   0,   0,   0},   //   TPM_CC_PolicyNV
 45            {0x014a,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_CertifyCreation
 46            {0x014b,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_Duplicate
 47            {0x014c,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_GetTime
 48            {0x014d,   0,   0,   0,   0,   3,   0,   0,   0},   //   TPM_CC_GetSessionAuditDigest
 49            {0x014e,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_NV_Read
 50            {0x014f,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_NV_ReadLock
 51            {0x0150,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_ObjectChangeAuth
 52            {0x0151,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_PolicySecret
 53            {0x0152,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_Rewrap
 54            {0x0153,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_Create
 55            {0x0154,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_ECDH_ZGen
 56            {0x0155,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_HMAC
 57            {0x0156,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_Import
 58            {0x0157,   0,   0,   0,   0,   1,   1,   0,   0},   //   TPM_CC_Load
 59            {0x0158,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_Quote
 60            {0x0159,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_RSA_Decrypt
 61            {0x015a,   0,   0,   0,   0,   0,   0,   0,   0},   //   No command
 62            {0x015b,   0,   0,   0,   0,   1,   1,   0,   0},   //   TPM_CC_HMAC_Start
 63            {0x015c,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_SequenceUpdate
 64            {0x015d,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_Sign
 65            {0x015e,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_Unseal
 66            {0x015f,   0,   0,   0,   0,   0,   0,   0,   0},   //   No command
 67            {0x0160,   0,   0,   0,   0,   2,   0,   0,   0},   //   TPM_CC_PolicySigned
 68            {0x0161,   0,   0,   0,   0,   0,   1,   0,   0},   //   TPM_CC_ContextLoad
 69            {0x0162,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_ContextSave
 70            {0x0163,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_ECDH_KeyGen
 71            {0x0164,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_EncryptDecrypt
 72            {0x0165,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_FlushContext
 73            {0x0166,   0,   0,   0,   0,   0,   0,   0,   0},   //   No command
 74            {0x0167,   0,   0,   0,   0,   0,   1,   0,   0},   //   TPM_CC_LoadExternal
 75            {0x0168,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_MakeCredential
 76            {0x0169,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_NV_ReadPublic
 77            {0x016a,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyAuthorize
 78            {0x016b,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyAuthValue
 79            {0x016c,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyCommandCode
 80            {0x016d,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyCounterTimer
 81            {0x016e,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyCpHash
 82            {0x016f,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyLocality
 83            {0x0170,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyNameHash
 84            {0x0171,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyOR
 85            {0x0172,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyTicket
 86            {0x0173,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_ReadPublic
 87            {0x0174,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_RSA_Encrypt
 88            {0x0175,   0,   0,   0,   0,   0,   0,   0,   0},   //   No command
 89            {0x0176,   0,   0,   0,   0,   2,   1,   0,   0},   //   TPM_CC_StartAuthSession
 90            {0x0177,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_VerifySignature
 91            {0x0178,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_ECC_Parameters
 92            {0x0179,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_FirmwareRead
 93            {0x017a,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_GetCapability
 94            {0x017b,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_GetRandom
 95            {0x017c,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_GetTestResult
 96            {0x017d,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_Hash
 97            {0x017e,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_PCR_Read
 98            {0x017f,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyPCR
 99            {0x0180,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyRestart
100            {0x0181,   0,   0,   0,   0,   0,   0,   0,   0},   //   TPM_CC_ReadClock
101            {0x0182,   0,   1,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PCR_Extend
102            {0x0183,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PCR_SetAuthValue
103            {0x0184,   0,   0,   0,   0,   3,   0,   0,   0},   //   TPM_CC_NV_Certify
104            {0x0185,   0,   1,   0,   1,   2,   0,   0,   0},   //   TPM_CC_EventSequenceComplete
105            {0x0186,   0,   0,   0,   0,   0,   1,   0,   0},   //   TPM_CC_HashSequenceStart
106            {0x0187,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyPhysicalPresence
107            {0x0188,   0,   0,   0,   0,   1,   0,   0,   0},   //   TPM_CC_PolicyDuplicationSelect

      Family "2.0"                                       TCG Published                                  Page 219
      Level 00 Revision 01.16                  Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                                    Part 4: Supporting Routines

108             {0x0189,   0,   0,   0,   0,   1,   0,   0,   0},     //   TPM_CC_PolicyGetDigest
109             {0x018a,   0,   0,   0,   0,   0,   0,   0,   0},     //   TPM_CC_TestParms
110             {0x018b,   0,   0,   0,   0,   1,   0,   0,   0},     //   TPM_CC_Commit
111             {0x018c,   0,   0,   0,   0,   1,   0,   0,   0},     //   TPM_CC_PolicyPassword
112             {0x018d,   0,   0,   0,   0,   1,   0,   0,   0},     //   TPM_CC_ZGen_2Phase
113             {0x018e,   0,   0,   0,   0,   0,   0,   0,   0},     //   TPM_CC_EC_Ephemeral
114             {0x018f,   0,   0,   0,   0,   1,   0,   0,   0}      //   TPM_CC_PolicyNvWritten
115   };
116   typedef    UINT16                    _ATTR_;
117   #define    NOT_IMPLEMENTED           (_ATTR_)(0)
118   #define    ENCRYPT_2                (_ATTR_)(1 <<          0)
119   #define    ENCRYPT_4                (_ATTR_)(1 <<          1)
120   #define    DECRYPT_2                (_ATTR_)(1 <<          2)
121   #define    DECRYPT_4                (_ATTR_)(1 <<          3)
122   #define    HANDLE_1_USER            (_ATTR_)(1 <<          4)
123   #define    HANDLE_1_ADMIN           (_ATTR_)(1 <<          5)
124   #define    HANDLE_1_DUP             (_ATTR_)(1 <<          6)
125   #define    HANDLE_2_USER            (_ATTR_)(1 <<          7)
126   #define    PP_COMMAND               (_ATTR_)(1 <<          8)
127   #define    IS_IMPLEMENTED           (_ATTR_)(1 <<          9)
128   #define    NO_SESSIONS              (_ATTR_)(1 <<         10)
129   #define    NV_COMMAND               (_ATTR_)(1 <<         11)
130   #define    PP_REQUIRED              (_ATTR_)(1 <<         12)
131   #define    R_HANDLE                 (_ATTR_)(1 <<         13)

      This is the command code attribute structure.

132   typedef UINT16 COMMAND_ATTRIBUTES;
133   static const COMMAND_ATTRIBUTES    s_commandAttributes [] = {
134       (_ATTR_)(CC_NV_UndefineSpaceSpecial     *
      (IS_IMPLEMENTED+HANDLE_1_ADMIN+HANDLE_2_USER+PP_COMMAND)),                                    // 0x011f
135       (_ATTR_)(CC_EvictControl                *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0120
136       (_ATTR_)(CC_HierarchyControl            *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0121
137       (_ATTR_)(CC_NV_UndefineSpace            *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0122
138       (_ATTR_)                                  (NOT_IMPLEMENTED),
      // 0x0123 - Not assigned
139       (_ATTR_)(CC_ChangeEPS                   *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0124
140       (_ATTR_)(CC_ChangePPS                   *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0125
141       (_ATTR_)(CC_Clear                       *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0126
142       (_ATTR_)(CC_ClearControl                *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0127
143       (_ATTR_)(CC_ClockSet                    *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0128
144       (_ATTR_)(CC_HierarchyChangeAuth         *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),                                         // 0x0129
145       (_ATTR_)(CC_NV_DefineSpace              *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),                                         // 0x012a
146       (_ATTR_)(CC_PCR_Allocate                *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x012b
147       (_ATTR_)(CC_PCR_SetAuthPolicy           *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),                                         // 0x012c
148       (_ATTR_)(CC_PP_Commands                 *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_REQUIRED)),                                                  // 0x012d
149       (_ATTR_)(CC_SetPrimaryPolicy            *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),                                         // 0x012e
150       (_ATTR_)(CC_FieldUpgradeStart           *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+PP_COMMAND)),                                        // 0x012f
151       (_ATTR_)(CC_ClockRateAdjust             *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                                   // 0x0130


      Page 220                                            TCG Published                                Family "2.0"
      October 30, 2014                          Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                  Trusted Platform Module Library

152       (_ATTR_)(CC_CreatePrimary               *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)), // 0x0131
153       (_ATTR_)(CC_NV_GlobalWriteLock          *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                // 0x0132
154       (_ATTR_)(CC_GetCommandAuditDigest       *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),         // 0x0133
155       (_ATTR_)(CC_NV_Increment                * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x0134
156       (_ATTR_)(CC_NV_SetBits                  * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x0135
157       (_ATTR_)(CC_NV_Extend                   *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                 // 0x0136
158       (_ATTR_)(CC_NV_Write                    *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                 // 0x0137
159       (_ATTR_)(CC_NV_WriteLock                * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x0138
160       (_ATTR_)(CC_DictionaryAttackLockReset * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x0139
161       (_ATTR_)(CC_DictionaryAttackParameters * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x013a
162       (_ATTR_)(CC_NV_ChangeAuth               *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN)),                                // 0x013b
163       (_ATTR_)(CC_PCR_Event                   *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                 // 0x013c
164       (_ATTR_)(CC_PCR_Reset                   * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x013d
165       (_ATTR_)(CC_SequenceComplete            *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                       // 0x013e
166       (_ATTR_)(CC_SetAlgorithmSet             * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x013f
167       (_ATTR_)(CC_SetCommandCodeAuditStatus *
      (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),                                // 0x0140
168       (_ATTR_)(CC_FieldUpgradeData            * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x0141
169       (_ATTR_)(CC_IncrementalSelfTest         * (IS_IMPLEMENTED)),
      // 0x0142
170       (_ATTR_)(CC_SelfTest                    * (IS_IMPLEMENTED)),
      // 0x0143
171       (_ATTR_)(CC_Startup                     * (IS_IMPLEMENTED+NO_SESSIONS)),
      // 0x0144
172       (_ATTR_)(CC_Shutdown                    * (IS_IMPLEMENTED)),
      // 0x0145
173       (_ATTR_)(CC_StirRandom                  * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x0146
174       (_ATTR_)(CC_ActivateCredential          *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)),        // 0x0147
175       (_ATTR_)(CC_Certify                     *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)),        // 0x0148
176       (_ATTR_)(CC_PolicyNV                    *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                 // 0x0149
177       (_ATTR_)(CC_CertifyCreation             *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                       // 0x014a
178       (_ATTR_)(CC_Duplicate                   *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+ENCRYPT_2)),                        // 0x014b
179       (_ATTR_)(CC_GetTime                     *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),         // 0x014c
180       (_ATTR_)(CC_GetSessionAuditDigest       *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),         // 0x014d
181       (_ATTR_)(CC_NV_Read                     *
      (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)),                                 // 0x014e
182       (_ATTR_)(CC_NV_ReadLock                 * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x014f
183       (_ATTR_)(CC_ObjectChangeAuth            *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+ENCRYPT_2)),                      // 0x0150
184       (_ATTR_)(CC_PolicySecret                *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                       // 0x0151

      Family "2.0"                         TCG Published                                Page 221
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

185       (_ATTR_)(CC_Rewrap                     *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0152
186       (_ATTR_)(CC_Create                     *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0153
187       (_ATTR_)(CC_ECDH_ZGen                  *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0154
188       (_ATTR_)(CC_HMAC                       *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0155
189       (_ATTR_)(CC_Import                     *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0156
190       (_ATTR_)(CC_Load                       *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2+R_HANDLE)),             // 0x0157
191       (_ATTR_)(CC_Quote                      *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0158
192       (_ATTR_)(CC_RSA_Decrypt                *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x0159
193       (_ATTR_)                                 (NOT_IMPLEMENTED),
      // 0x015a - Not assigned
194       (_ATTR_)(CC_HMAC_Start                 *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+R_HANDLE)),                       // 0x015b
195       (_ATTR_)(CC_SequenceUpdate             *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                // 0x015c
196       (_ATTR_)(CC_Sign                       *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                // 0x015d
197       (_ATTR_)(CC_Unseal                     *
      (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)),                                // 0x015e
198       (_ATTR_)                                 (NOT_IMPLEMENTED),
      // 0x015f - Not assigned
199       (_ATTR_)(CC_PolicySigned               * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),
      // 0x0160
200       (_ATTR_)(CC_ContextLoad                * (IS_IMPLEMENTED+NO_SESSIONS+R_HANDLE)),
      // 0x0161
201       (_ATTR_)(CC_ContextSave                * (IS_IMPLEMENTED+NO_SESSIONS)),
      // 0x0162
202       (_ATTR_)(CC_ECDH_KeyGen                * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x0163
203       (_ATTR_)(CC_EncryptDecrypt             *
      (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)),                                // 0x0164
204       (_ATTR_)(CC_FlushContext               * (IS_IMPLEMENTED+NO_SESSIONS)),
      // 0x0165
205       (_ATTR_)                                 (NOT_IMPLEMENTED),
      // 0x0166 - Not assigned
206       (_ATTR_)(CC_LoadExternal               *
      (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)),                           // 0x0167
207       (_ATTR_)(CC_MakeCredential             * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),
      // 0x0168
208       (_ATTR_)(CC_NV_ReadPublic              * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x0169
209       (_ATTR_)(CC_PolicyAuthorize            * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x016a
210       (_ATTR_)(CC_PolicyAuthValue            * (IS_IMPLEMENTED)),
      // 0x016b
211       (_ATTR_)(CC_PolicyCommandCode          * (IS_IMPLEMENTED)),
      // 0x016c
212       (_ATTR_)(CC_PolicyCounterTimer         * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x016d
213       (_ATTR_)(CC_PolicyCpHash               * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x016e
214       (_ATTR_)(CC_PolicyLocality             * (IS_IMPLEMENTED)),
      // 0x016f
215       (_ATTR_)(CC_PolicyNameHash             * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x0170
216       (_ATTR_)(CC_PolicyOR                   * (IS_IMPLEMENTED)),
      // 0x0171
217       (_ATTR_)(CC_PolicyTicket               * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x0172

      Page 222                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

218       (_ATTR_)(CC_ReadPublic                 * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x0173
219       (_ATTR_)(CC_RSA_Encrypt                * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),
      // 0x0174
220       (_ATTR_)                                 (NOT_IMPLEMENTED),
      // 0x0175 - Not assigned
221       (_ATTR_)(CC_StartAuthSession           *
      (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)),                           // 0x0176
222       (_ATTR_)(CC_VerifySignature            * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x0177
223       (_ATTR_)(CC_ECC_Parameters             * (IS_IMPLEMENTED)),
      // 0x0178
224       (_ATTR_)(CC_FirmwareRead               * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x0179
225       (_ATTR_)(CC_GetCapability              * (IS_IMPLEMENTED)),
      // 0x017a
226       (_ATTR_)(CC_GetRandom                  * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x017b
227       (_ATTR_)(CC_GetTestResult              * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x017c
228       (_ATTR_)(CC_Hash                       * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),
      // 0x017d
229       (_ATTR_)(CC_PCR_Read                   * (IS_IMPLEMENTED)),
      // 0x017e
230       (_ATTR_)(CC_PolicyPCR                  * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x017f
231       (_ATTR_)(CC_PolicyRestart              * (IS_IMPLEMENTED)),
      // 0x0180
232       (_ATTR_)(CC_ReadClock                  * (IS_IMPLEMENTED+NO_SESSIONS)),
      // 0x0181
233       (_ATTR_)(CC_PCR_Extend                 * (IS_IMPLEMENTED+HANDLE_1_USER)),
      // 0x0182
234       (_ATTR_)(CC_PCR_SetAuthValue           *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),                                // 0x0183
235       (_ATTR_)(CC_NV_Certify                 *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),        // 0x0184
236       (_ATTR_)(CC_EventSequenceComplete      *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER)),                  // 0x0185
237       (_ATTR_)(CC_HashSequenceStart          * (IS_IMPLEMENTED+DECRYPT_2+R_HANDLE)),
      // 0x0186
238       (_ATTR_)(CC_PolicyPhysicalPresence     * (IS_IMPLEMENTED)),
      // 0x0187
239       (_ATTR_)(CC_PolicyDuplicationSelect    * (IS_IMPLEMENTED+DECRYPT_2)),
      // 0x0188
240       (_ATTR_)(CC_PolicyGetDigest            * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x0189
241       (_ATTR_)(CC_TestParms                  * (IS_IMPLEMENTED)),
      // 0x018a
242       (_ATTR_)(CC_Commit                     *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x018b
243       (_ATTR_)(CC_PolicyPassword             * (IS_IMPLEMENTED)),
      // 0x018c
244       (_ATTR_)(CC_ZGen_2Phase                *
      (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),                      // 0x018d
245       (_ATTR_)(CC_EC_Ephemeral               * (IS_IMPLEMENTED+ENCRYPT_2)),
      // 0x018e
246       (_ATTR_)(CC_PolicyNvWritten            * (IS_IMPLEMENTED))
      // 0x018f
247   };




      Family "2.0"                        TCG Published                                Page 223
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                                           Part 4: Supporting Routines

     9.4     CommandCodeAttributes.c

     9.4.1     Introduction

     This file contains the functions for testing various command properties.

     9.4.2     Includes and Defines

 1   #include    "Tpm.h"
 2   #include    "InternalRoutines.h"
 3   typedef UINT16          ATTRIBUTE_TYPE;

     The following file is produced from the command tables in part 3 of the specification. It defines the
     attributes for each of the commands.

     NOTE:           This file is currently produced by an automated process. Files produced from Part 2 or Part 3 tables through
                     automated processes are not included in the specification so that their is no ambiguity about the table
                     containing the information being the normative definition.

 4   #include       "CommandAttributeData.c"


     9.4.3     Command Attribute Functions

     9.4.3.1     CommandAuthRole()

     This function returns the authorization role required of a handle.

     Return Value                       Meaning

     AUTH_NONE                          no authorization is required
     AUTH_USER                          user role authorization is required
     AUTH_ADMIN                         admin role authorization is required
     AUTH_DUP                           duplication role authorization is required

 5   AUTH_ROLE
 6   CommandAuthRole(
 7         TPM_CC        commandCode,                 // IN: command code
 8         UINT32        handleIndex                  // IN: handle index (zero based)
 9         )
10   {
11       if(handleIndex > 1)
12           return AUTH_NONE;
13       if(handleIndex == 0) {
14           ATTRIBUTE_TYPE properties = s_commandAttributes[commandCode - TPM_CC_FIRST];
15           if(properties & HANDLE_1_USER) return AUTH_USER;
16           if(properties & HANDLE_1_ADMIN) return AUTH_ADMIN;
17           if(properties & HANDLE_1_DUP) return AUTH_DUP;
18           return AUTH_NONE;
19       }
20       if(s_commandAttributes[commandCode - TPM_CC_FIRST] & HANDLE_2_USER) return
     AUTH_USER;
21       return AUTH_NONE;
22   }


     9.4.3.2     CommandIsImplemented()

     This function indicates if a command is implemented.

     Page 224                                          TCG Published                                             Family "2.0"
     October 30, 2014                         Copyright © TCG 2006-2014                          Level 00 Revision 01.16
     Part 4: Supporting Routines                                                   Trusted Platform Module Library


     Return Value                      Meaning

     TRUE                              if the command is implemented
     FALSE                             if the command is not implemented

23   BOOL
24   CommandIsImplemented(
25        TPM_CC                commandCode          // IN: command code
26        )
27   {
28        if(commandCode < TPM_CC_FIRST || commandCode > TPM_CC_LAST)
29            return FALSE;
30        if((s_commandAttributes[commandCode - TPM_CC_FIRST] & IS_IMPLEMENTED))
31            return TRUE;
32        else
33            return FALSE;
34   }


     9.4.3.3     CommandGetAttribute()

     return a TPMA_CC structure for the given command code

35   TPMA_CC
36   CommandGetAttribute(
37        TPM_CC                commandCode          // IN: command code
38        )
39   {
40        UINT32      size = sizeof(s_ccAttr) / sizeof(s_ccAttr[0]);
41        UINT32      i;
42        for(i = 0; i < size; i++) {
43            if(s_ccAttr[i].commandIndex == (UINT16) commandCode)
44                return s_ccAttr[i];
45        }
46
47        // This function should be called in the way that the command code
48        // attribute is available.
49        FAIL(FATAL_ERROR_INTERNAL);
50   }


     9.4.3.4     EncryptSize()

     This function returns the size of the decrypt size field. This function returns 0 if encryption is not allowed

     Return Value                      Meaning

     0                                 encryption not allowed
     2                                 size field is two bytes
     4                                 size field is four bytes

51   int
52   EncryptSize(
53        TPM_CC                commandCode          // IN: commandCode
54        )
55   {
56        COMMAND_ATTRIBUTES        ca = s_commandAttributes[commandCode - TPM_CC_FIRST];
57        if(ca & ENCRYPT_2)
58            return 2;
59        if(ca & ENCRYPT_4)
60            return 4;
61        return 0;

     Family "2.0"                                    TCG Published                                        Page 225
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                            October 30, 2014
     Trusted Platform Module Library                                                    Part 4: Supporting Routines

62   }


     9.4.3.5     DecryptSize()

     This function returns the size of the decrypt size field. This function returns 0 if decryption is not allowed

     Return Value                      Meaning

     0                                 encryption not allowed
     2                                 size field is two bytes
     4                                 size field is four bytes

63   int
64   DecryptSize(
65        TPM_CC                commandCode          // IN: commandCode
66        )
67   {
68        COMMAND_ATTRIBUTES        ca = s_commandAttributes[commandCode - TPM_CC_FIRST];
69
70        if(ca & DECRYPT_2)
71            return 2;
72        if(ca & DECRYPT_4)
73            return 4;
74        return 0;
75   }


     9.4.3.6     IsSessionAllowed()

     This function indicates if the command is allowed to have sessions.
     This function must not be called if the command is not known to be implemented.

     Return Value                      Meaning

     TRUE                              session is allowed with this command
     FALSE                             session is not allowed with this command

76   BOOL
77   IsSessionAllowed(
78        TPM_CC                commandCode          // IN: the command to be checked
79        )
80   {
81        if(s_commandAttributes[commandCode - TPM_CC_FIRST] & NO_SESSIONS)
82            return FALSE;
83        else
84            return TRUE;
85   }


     9.4.3.7     IsHandleInResponse()

86   BOOL
87   IsHandleInResponse(
88        TPM_CC                commandCode
89        )
90   {
91        if(s_commandAttributes[commandCode - TPM_CC_FIRST] & R_HANDLE)
92            return TRUE;
93        else
94            return FALSE;


     Page 226                                        TCG Published                                     Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                    Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

 95   }


      9.4.3.8     IsWriteOperation()

      Checks to see if an operation will write to NV memory

 96   BOOL
 97   IsWriteOperation(
 98       TPM_CC               command           // IN: Command to check
 99       )
100   {
101       switch (command)
102       {
103           case TPM_CC_NV_Write:
104           case TPM_CC_NV_Increment:
105           case TPM_CC_NV_SetBits:
106           case TPM_CC_NV_Extend:
107           // Nv write lock counts as a write operation for authorization purposes.
108           // We check to see if the NV is write locked before we do the authorization
109           // If it is locked, we fail the command early.
110           case TPM_CC_NV_WriteLock:
111               return TRUE;
112           default:
113               break;
114       }
115       return FALSE;
116   }


      9.4.3.9     IsReadOperation()

      Checks to see if an operation will write to NV memory

117   BOOL
118   IsReadOperation(
119       TPM_CC               command           // IN: Command to check
120       )
121   {
122       switch (command)
123       {
124           case TPM_CC_NV_Read:
125           case TPM_CC_PolicyNV:
126           case TPM_CC_NV_Certify:
127           // Nv read lock counts as a read operation for authorization purposes.
128           // We check to see if the NV is read locked before we do the authorization
129           // If it is locked, we fail the command early.
130           case TPM_CC_NV_ReadLock:
131               return TRUE;
132           default:
133               break;
134       }
135       return FALSE;
136   }


      9.4.3.10    CommandCapGetCCList()

      This function returns a list of implemented commands and command attributes starting from the
      command in commandCode.




      Family "2.0"                               TCG Published                                  Page 227
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines


      Return Value                      Meaning

      YES                               more command attributes are available
      NO                                no more command attributes are available

137   TPMI_YES_NO
138   CommandCapGetCCList(
139         TPM_CC            commandCode,         // IN: start command code
140         UINT32            count,               // IN: maximum count for number of entries in
141                                                //     'commandList'
142         TPML_CCA         *commandList          // OUT: list of TPMA_CC
143         )
144   {
145         TPMI_YES_NO       more = NO;
146         UINT32            i;
147
148         // initialize output handle list count
149         commandList->count = 0;
150
151         // The maximum count of commands that may be return is MAX_CAP_CC.
152         if(count > MAX_CAP_CC) count = MAX_CAP_CC;
153
154         // If the command code is smaller than TPM_CC_FIRST, start from TPM_CC_FIRST
155         if(commandCode < TPM_CC_FIRST) commandCode = TPM_CC_FIRST;
156
157         // Collect command attributes
158         for(i = commandCode; i <= TPM_CC_LAST; i++)
159         {
160             if(CommandIsImplemented(i))
161             {
162                 if(commandList->count < count)
163                 {
164                     // If the list is not full, add the attributes for this command.
165                     commandList->commandAttributes[commandList->count]
166                         = CommandGetAttribute(i);
167                     commandList->count++;
168                 }
169                 else
170                 {
171                     // If the list is full but there are more commands to report,
172                     // indicate this and return.
173                     more = YES;
174                     break;
175                 }
176             }
177         }
178         return more;
179   }


      9.5     DRTM.c

      9.5.1    Description

      This file contains functions that simulate the DRTM events. Its primary purpose is to isolate the name
      space of the simulator from the name space of the TPM. This is only an issue with the parameters to
      _TPM_Hash_Data().

      9.5.2    Includes

  1   #include       "InternalRoutines.h"


      Page 228                                      TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library

     9.5.3     Functions

     9.5.3.1      Signal_Hash_Start()

     This function interfaces between the platform code and _TPM_Hash_Start().

 2   LIB_EXPORT void
 3   Signal_Hash_Start(
 4         void
 5         )
 6   {
 7         _TPM_Hash_Start();
 8         return;
 9   }


     9.5.3.2      Signal_Hash_Data()

     This function interfaces between the platform code and _TPM_Hash_Data().

10   LIB_EXPORT void
11   Signal_Hash_Data(
12         unsigned int        size,
13         unsigned char      *buffer
14         )
15   {
16         _TPM_Hash_Data(size, buffer);
17         return;
18   }


     9.5.3.3      Signal_Hash_End()

     This function interfaces between the platform code and _TPM_Hash_End().

19   LIB_EXPORT void
20   Signal_Hash_End(
21         void
22         )
23   {
24         _TPM_Hash_End();
25         return;
26   }


     9.6     Entity.c

     9.6.1     Description

     The functions in this file are used for accessing properties for handles of various types. Functions in other
     files require handles of a specific type but the functions in this file allow use of any handle type.

     9.6.2     Includes

 1   #include "InternalRoutines.h"




     Family "2.0"                                 TCG Published                                        Page 229
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                       Part 4: Supporting Routines

     9.6.3     Functions

     9.6.3.1     EntityGetLoadStatus()

     This function will indicate if the entity associated with a handle is present in TPM memory. If the handle is
     a persistent object handle, and the object exists, the persistent object is moved from NV memory into a
     RAM object slot and the persistent handle is replaced with the transient object handle for the slot.

     Error Returns                     Meaning

     TPM_RC_HANDLE                     handle type does not match
     TPM_RC_REFERENCE_H0               entity is not present
     TPM_RC_HIERARCHY                  entity belongs to a disabled hierarchy
     TPM_RC_OBJECT_MEMORY              handle is an evict object but there is no space to load it to RAM

 2   TPM_RC
 3   EntityGetLoadStatus(
 4        TPM_HANDLE          *handle,              // IN/OUT: handle of the entity
 5        TPM_CC               commandCode          // IN: the commmandCode
 6        )
 7   {
 8        TPM_RC              result = TPM_RC_SUCCESS;
 9
10        switch(HandleGetType(*handle))
11        {
12            // For handles associated with hierarchies, the entity is present
13            // only if the associated enable is SET.
14            case TPM_HT_PERMANENT:
15                switch(*handle)
16                {
17                    case TPM_RH_OWNER:
18                        if(!gc.shEnable)
19                            result = TPM_RC_HIERARCHY;
20                        break;
21
22   #ifdef    VENDOR_PERMANENT
23                     case VENDOR_PERMANENT:
24   #endif
25                       case TPM_RH_ENDORSEMENT:
26                           if(!gc.ehEnable)
27                                result = TPM_RC_HIERARCHY;
28                           break;
29                       case TPM_RH_PLATFORM:
30                           if(!g_phEnable)
31                                result = TPM_RC_HIERARCHY;
32                           break;
33                           // null handle, PW session handle and lockout
34                           // handle are always available
35                       case TPM_RH_NULL:
36                       case TPM_RS_PW:
37                       case TPM_RH_LOCKOUT:
38                           break;
39                       default:
40                           // handling of the manufacture_specific handles
41                           if(      ((TPM_RH)*handle >= TPM_RH_AUTH_00)
42                                && ((TPM_RH)*handle <= TPM_RH_AUTH_FF))
43                                // use the value that would have been returned from
44                                // unmarshaling if it did the handle filtering
45                                    result = TPM_RC_VALUE;
46                           else
47                                pAssert(FALSE);
48                           break;

     Page 230                                        TCG Published                                         Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                  Trusted Platform Module Library

 49                }
 50                break;
 51            case TPM_HT_TRANSIENT:
 52                // For a transient object, check if the handle is associated
 53                // with a loaded object.
 54                if(!ObjectIsPresent(*handle))
 55                     result = TPM_RC_REFERENCE_H0;
 56                break;
 57            case TPM_HT_PERSISTENT:
 58                // Persistent object
 59                // Copy the persistent object to RAM and replace the handle with the
 60                // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY,
 61                // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by
 62                // ObjectLoadEvict()
 63                result = ObjectLoadEvict(handle, commandCode);
 64                break;
 65            case TPM_HT_HMAC_SESSION:
 66                // For an HMAC session, see if the session is loaded
 67                // and if the session in the session slot is actually
 68                // an HMAC session.
 69                if(SessionIsLoaded(*handle))
 70                {
 71                     SESSION             *session;
 72                     session = SessionGet(*handle);
 73                     // Check if the session is a HMAC session
 74                     if(session->attributes.isPolicy == SET)
 75                         result = TPM_RC_HANDLE;
 76                }
 77                else
 78                     result = TPM_RC_REFERENCE_H0;
 79                break;
 80            case TPM_HT_POLICY_SESSION:
 81                // For a policy session, see if the session is loaded
 82                // and if the session in the session slot is actually
 83                // a policy session.
 84                if(SessionIsLoaded(*handle))
 85                {
 86                     SESSION             *session;
 87                     session = SessionGet(*handle);
 88                     // Check if the session is a policy session
 89                     if(session->attributes.isPolicy == CLEAR)
 90                         result = TPM_RC_HANDLE;
 91                }
 92                else
 93                     result = TPM_RC_REFERENCE_H0;
 94                break;
 95            case TPM_HT_NV_INDEX:
 96                // For an NV Index, use the platform-specific routine
 97                // to search the IN Index space.
 98                result = NvIndexIsAccessible(*handle, commandCode);
 99                break;
100            case TPM_HT_PCR:
101                // Any PCR handle that is unmarshaled successfully referenced
102                // a PCR that is defined.
103                break;
104            default:
105                // Any other handle type is a defect in the unmarshaling code.
106                pAssert(FALSE);
107                break;
108       }
109       return result;
110   }




      Family "2.0"                         TCG Published                                Page 231
      Level 00 Revision 01.16        Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines

      9.6.3.2     EntityGetAuthValue()

      This function is used to access the authValue associated with a handle. This function assumes that the
      handle references an entity that is accessible and the handle is not for a persistent objects. That is
      EntityGetLoadStatus() should have been called. Also, the accessibility of the authValue should have been
      verified by IsAuthValueAvailable().
      This function copies the authorization value of the entity to auth.
      Return value is the number of octets copied to auth.

111   UINT16
112   EntityGetAuthValue(
113        TPMI_DH_ENTITY       handle,             // IN: handle of entity
114        AUTH_VALUE          *auth                // OUT: authValue of the entity
115        )
116   {
117        TPM2B_AUTH           authValue = {0};
118
119       switch(HandleGetType(handle))
120       {
121           case TPM_HT_PERMANENT:
122               switch(handle)
123               {
124                   case TPM_RH_OWNER:
125                       // ownerAuth for TPM_RH_OWNER
126                       authValue = gp.ownerAuth;
127                       break;
128                   case TPM_RH_ENDORSEMENT:
129                       // endorsementAuth for TPM_RH_ENDORSEMENT
130                       authValue = gp.endorsementAuth;
131                       break;
132                   case TPM_RH_PLATFORM:
133                       // platformAuth for TPM_RH_PLATFORM
134                       authValue = gc.platformAuth;
135                       break;
136                   case TPM_RH_LOCKOUT:
137                       // lockoutAuth for TPM_RH_LOCKOUT
138                       authValue = gp.lockoutAuth;
139                       break;
140                   case TPM_RH_NULL:
141                       // nullAuth for TPM_RH_NULL. Return 0 directly here
142                       return 0;
143                       break;
144   #ifdef VENDOR_PERMANENT
145                   case VENDOR_PERMANENT:
146                       // vendor auth value
147                       authValue = g_platformUniqueDetails;
148   #endif
149                   default:
150                       // If any other permanent handle is present it is
151                       // a code defect.
152                       pAssert(FALSE);
153                       break;
154               }
155               break;
156           case TPM_HT_TRANSIENT:
157               // authValue for an object
158               // A persistent object would have been copied into RAM
159               // and would have an transient object handle here.
160               {
161                   OBJECT          *object;
162                   object = ObjectGet(handle);
163                   // special handling if this is a sequence object
164                   if(ObjectIsSequence(object))

      Page 232                                      TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

165                       {
166                           authValue = ((HASH_OBJECT *)object)->auth;
167                       }
168                       else
169                       {
170                           // Auth value is available only when the private portion of
171                           // the object is loaded. The check should be made before
172                           // this function is called
173                           pAssert(object->attributes.publicOnly == CLEAR);
174                           authValue = object->sensitive.authValue;
175                       }
176                 }
177                 break;
178             case TPM_HT_NV_INDEX:
179                 // authValue for an NV index
180                 {
181                      NV_INDEX        nvIndex;
182                      NvGetIndexInfo(handle, &nvIndex);
183                      authValue = nvIndex.authValue;
184                 }
185                 break;
186             case TPM_HT_PCR:
187                 // authValue for PCR
188                 PCRGetAuthValue(handle, &authValue);
189                 break;
190             default:
191                 // If any other handle type is present here, then there is a defect
192                 // in the unmarshaling code.
193                 pAssert(FALSE);
194                 break;
195        }
196
197        // Copy the authValue
198        pAssert(authValue.t.size <= sizeof(authValue.t.buffer));
199        MemoryCopy(auth, authValue.t.buffer, authValue.t.size, sizeof(TPMU_HA));
200
201        return authValue.t.size;
202   }


      9.6.3.3     EntityGetAuthPolicy()

      This function is used to access the authPolicy associated with a handle. This function assumes that the
      handle references an entity that is accessible and the handle is not for a persistent objects. That is
      EntityGetLoadStatus() should have been called. Also, the accessibility of the authPolicy should have
      been verified by IsAuthPolicyAvailable().
      This function copies the authorization policy of the entity to authPolicy.
      The return value is the hash algorithm for the policy.

203   TPMI_ALG_HASH
204   EntityGetAuthPolicy(
205        TPMI_DH_ENTITY       handle,             // IN: handle of entity
206        TPM2B_DIGEST        *authPolicy          // OUT: authPolicy of the entity
207        )
208   {
209        TPMI_ALG_HASH            hashAlg = TPM_ALG_NULL;
210
211        switch(HandleGetType(handle))
212        {
213            case TPM_HT_PERMANENT:
214                switch(handle)
215                {
216                    case TPM_RH_OWNER:


      Family "2.0"                                  TCG Published                                       Page 233
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

217                          // ownerPolicy for TPM_RH_OWNER
218                          *authPolicy = gp.ownerPolicy;
219                          hashAlg = gp.ownerAlg;
220                          break;
221                      case TPM_RH_ENDORSEMENT:
222                          // endorsementPolicy for TPM_RH_ENDORSEMENT
223                          *authPolicy = gp.endorsementPolicy;
224                          hashAlg = gp.endorsementAlg;
225                          break;
226                      case TPM_RH_PLATFORM:
227                          // platformPolicy for TPM_RH_PLATFORM
228                          *authPolicy = gc.platformPolicy;
229                          hashAlg = gc.platformAlg;
230                          break;
231                      case TPM_RH_LOCKOUT:
232                          // lockoutPolicy for TPM_RH_LOCKOUT
233                          *authPolicy = gp.lockoutPolicy;
234                          hashAlg = gp.lockoutAlg;
235                          break;
236                      default:
237                          // If any other permanent handle is present it is
238                          // a code defect.
239                          pAssert(FALSE);
240                          break;
241                 }
242                 break;
243             case TPM_HT_TRANSIENT:
244                 // authPolicy for an object
245                 {
246                      OBJECT *object = ObjectGet(handle);
247                      *authPolicy = object->publicArea.authPolicy;
248                      hashAlg = object->publicArea.nameAlg;
249                 }
250                 break;
251             case TPM_HT_NV_INDEX:
252                 // authPolicy for a NV index
253                 {
254                      NV_INDEX        nvIndex;
255                      NvGetIndexInfo(handle, &nvIndex);
256                      *authPolicy = nvIndex.publicArea.authPolicy;
257                      hashAlg = nvIndex.publicArea.nameAlg;
258                 }
259                 break;
260             case TPM_HT_PCR:
261                 // authPolicy for a PCR
262                 hashAlg = PCRGetAuthPolicy(handle, authPolicy);
263                 break;
264             default:
265                 // If any other handle type is present it is a code defect.
266                 pAssert(FALSE);
267                 break;
268       }
269       return hashAlg;
270   }


      9.6.3.4     EntityGetName()

      This function returns the Name associated with a handle. It will set name to the Name and return the size
      of the Name string.

271   UINT16
272   EntityGetName(
273       TPMI_DH_ENTITY       handle,           // IN: handle of entity
274       NAME                *name              // OUT: name of entity

      Page 234                                    TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

275        )
276   {
277        UINT16              nameSize;
278
279        switch(HandleGetType(handle))
280        {
281            case TPM_HT_TRANSIENT:
282                // Name for an object
283                nameSize = ObjectGetName(handle, name);
284                break;
285            case TPM_HT_NV_INDEX:
286                // Name for a NV index
287                nameSize = NvGetName(handle, name);
288                break;
289            default:
290                // For all other types, the handle is the Name
291                nameSize = TPM_HANDLE_Marshal(&handle, (BYTE **)&name, NULL);
292                break;
293        }
294        return nameSize;
295   }


      9.6.3.5     EntityGetHierarchy()

      This function returns the hierarchy handle associated with an entity.
      a) A handle that is a hierarchy handle is associated with itself.
      b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET,
         otherwise it belongs to TPM_RH_OWNER
      c) An object handle belongs to its hierarchy. All other handles belong to the platform hierarchy. or an NV
         Index.

296   TPMI_RH_HIERARCHY
297   EntityGetHierarchy(
298        TPMI_DH_ENTITY       handle             // IN :handle of entity
299        )
300   {
301        TPMI_RH_HIERARCHY             hierarcy = TPM_RH_NULL;
302
303        switch(HandleGetType(handle))
304        {
305            case TPM_HT_PERMANENT:
306                // hierarchy for a permanent handle
307                switch(handle)
308                {
309                    case TPM_RH_PLATFORM:
310                    case TPM_RH_ENDORSEMENT:
311                    case TPM_RH_NULL:
312                        hierarcy = handle;
313                        break;
314                    // all other permanent handles are associated with the owner
315                    // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT)
316                    default:
317                        hierarcy = TPM_RH_OWNER;
318                        break;
319                }
320                break;
321            case TPM_HT_NV_INDEX:
322                // hierarchy for NV index
323                {
324                    NV_INDEX        nvIndex;
325                    NvGetIndexInfo(handle, &nvIndex);
326                    // If only the platform can delete the index, then it is

      Family "2.0"                                 TCG Published                                     Page 235
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

327                      // considered to be in the platform hierarchy, otherwise it
328                      // is in the owner hierarchy.
329                      if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET)
330                          hierarcy = TPM_RH_PLATFORM;
331                      else
332                          hierarcy = TPM_RH_OWNER;
333                 }
334                 break;
335             case TPM_HT_TRANSIENT:
336                 // hierarchy for an object
337                 {
338                     OBJECT          *object;
339                     object = ObjectGet(handle);
340                     if(object->attributes.ppsHierarchy)
341                     {
342                         hierarcy = TPM_RH_PLATFORM;
343                     }
344                     else if(object->attributes.epsHierarchy)
345                     {
346                         hierarcy = TPM_RH_ENDORSEMENT;
347                     }
348                     else if(object->attributes.spsHierarchy)
349                     {
350                         hierarcy = TPM_RH_OWNER;
351                     }
352
353                 }
354                 break;
355             case TPM_HT_PCR:
356                 hierarcy = TPM_RH_OWNER;
357                 break;
358             default:
359                 pAssert(0);
360                 break;
361         }
362         // this is unreachable but it provides a return value for the default
363         // case which makes the complier happy
364         return hierarcy;
365   }


      9.7     Global.c

      9.7.1     Description

      This file will instance the TPM variables that are not stack allocated. The descriptions for these variables
      is in Global.h.

      9.7.2     Includes and Defines

  1   #define GLOBAL_C
  2   #include "InternalRoutines.h"


      9.7.3     Global Data Values

      These values are visible across multiple modules.

  3   BOOL                      g_phEnable;
  4   const UINT16              g_rcIndex[15] = {TPM_RC_1,       TPM_RC_2,    TPM_RC_3, TPM_RC_4,
  5                                              TPM_RC_5,       TPM_RC_6,    TPM_RC_7, TPM_RC_8,
  6                                              TPM_RC_9,       TPM_RC_A,    TPM_RC_B, TPM_RC_C,
  7                                              TPM_RC_D,       TPM_RC_E,    TPM_RC_F

      Page 236                                     TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                      Trusted Platform Module Library

 8                                           };
 9   TPM_HANDLE              g_exclusiveAuditSession;
10   UINT64                  g_time;
11   BOOL                    g_pcrReConfig;
12   TPMI_DH_OBJECT          g_DRTMHandle;
13   BOOL                    g_DrtmPreStartup;
14   BOOL                    g_StartupLocality3;
15   BOOL                    g_clearOrderly;
16   TPM_SU                  g_prevOrderlyState;
17   BOOL                    g_updateNV;
18   BOOL                    g_nvOk;
19   TPM2B_AUTH              g_platformUniqueDetails;
20   STATE_CLEAR_DATA        gc;
21   STATE_RESET_DATA        gr;
22   PERSISTENT_DATA         gp;
23   ORDERLY_DATA            go;


     9.7.4     Private Values

     9.7.4.1     SessionProcess.c

24   #ifndef __IGNORE_STATE__           // DO NOT DEFINE THIS VALUE

     These values do not need to be retained between commands.

25   TPM_HANDLE           s_sessionHandles[MAX_SESSION_NUM];
26   TPMA_SESSION         s_attributes[MAX_SESSION_NUM];
27   TPM_HANDLE           s_associatedHandles[MAX_SESSION_NUM];
28   TPM2B_NONCE          s_nonceCaller[MAX_SESSION_NUM];
29   TPM2B_AUTH           s_inputAuthValues[MAX_SESSION_NUM];
30   UINT32               s_encryptSessionIndex;
31   UINT32               s_decryptSessionIndex;
32   UINT32               s_auditSessionIndex;
33   TPM2B_DIGEST         s_cpHashForAudit;
34   UINT32               s_sessionNum;
35   #endif // __IGNORE_STATE__
36   BOOL                 s_DAPendingOnNV;
37   #ifdef TPM_CC_GetCommandAuditDigest
38   TPM2B_DIGEST         s_cpHashForCommandAudit;
39   #endif


     9.7.4.2     DA.c

40   UINT64                  s_selfHealTimer;
41   UINT64                  s_lockoutTimer;


     9.7.4.3     NV.c

42   UINT32                  s_reservedAddr[NV_RESERVE_LAST];
43   UINT32                  s_reservedSize[NV_RESERVE_LAST];
44   UINT32                  s_ramIndexSize;
45   BYTE                    s_ramIndex[RAM_INDEX_SPACE];
46   UINT32                  s_ramIndexSizeAddr;
47   UINT32                  s_ramIndexAddr;
48   UINT32                  s_maxCountAddr;
49   UINT32                  s_evictNvStart;
50   UINT32                  s_evictNvEnd;
51   TPM_RC                  s_NvStatus;




     Family "2.0"                            TCG Published                                 Page 237
     Level 00 Revision 01.16          Copyright © TCG 2006-2014                   October 30, 2014
     Trusted Platform Module Library                                           Part 4: Supporting Routines

     9.7.4.4     Object.c

52   OBJECT_SLOT               s_objects[MAX_LOADED_OBJECTS];


     9.7.4.5     PCR.c

53   PCR                       s_pcrs[IMPLEMENTATION_PCR];


     9.7.4.6     Session.c

54   SESSION_SLOT              s_sessions[MAX_LOADED_SESSIONS];
55   UINT32                    s_oldestSavedSession;
56   int                       s_freeSessionSlots;


     9.7.4.7     Manufacture.c

57   BOOL                      g_manufactured = FALSE;


     9.7.4.8     Power.c

58   BOOL                      s_initialized = FALSE;


     9.7.4.9     MemoryLib.c

     The s_actionOutputBuffer should not be modifiable by the host system until the TPM has returned a
     response code. The s_actionOutputBuffer should not be accessible until response parameter encryption,
     if any, is complete. This memory is not used between commands

59   #ifndef __IGNORE_STATE__        // DO NOT DEFINE THIS VALUE
60   UINT32   s_actionInputBuffer[1024];          // action input buffer
61   UINT32   s_actionOutputBuffer[1024];         // action output buffer
62   BYTE     s_responseBuffer[MAX_RESPONSE_SIZE];// response buffer
63   #endif


     9.7.4.10    SelfTest.c

     Define these values here if the AlgorithmTests() project is not used

64   #ifndef SELF_TEST
65   ALGORITHM_VECTOR          g_implementedAlgorithms;
66   ALGORITHM_VECTOR          g_toTest;
67   #endif


     9.7.4.11    TpmFail.c

68   jmp_buf                   g_jumpBuffer;
69   BOOL                      g_forceFailureMode;
70   BOOL                      g_inFailureMode;
71   UINT32                    s_failFunction;
72   UINT32                    s_failLine;
73   UINT32                    s_failCode;




     Page 238                                     TCG Published                              Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014             Level 00 Revision 01.16
     Part 4: Supporting Routines                                                  Trusted Platform Module Library

     9.8     Handle.c

     9.8.1     Description

     This file contains the functions that return the type of a handle.

     9.8.2     Includes

 1   #include "Tpm.h"
 2   #include "InternalRoutines.h"


     9.8.3     Functions

     9.8.3.1     HandleGetType()

     This function returns the type of a handle which is the MSO of the handle.

 3   TPM_HT
 4   HandleGetType(
 5         TPM_HANDLE           handle             // IN: a handle to be checked
 6         )
 7   {
 8         // return the upper bytes of input data
 9         return (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT);
10   }


     9.8.3.2     NextPermanentHandle()

     This function returns the permanent handle that is equal to the input value or is the next higher value. If
     there is no handle with the input value and there is no next higher value, it returns 0:

     Return Value                      Meaning

11   TPM_HANDLE
12   NextPermanentHandle(
13         TPM_HANDLE           inHandle           // IN: the handle to check
14         )
15   {
16         // If inHandle is below the start of the range of permanent handles
17         // set it to the start and scan from there
18         if(inHandle < TPM_RH_FIRST)
19             inHandle = TPM_RH_FIRST;
20         // scan from input value untill we find an implemented permanent handle
21         // or go out of range
22         for(; inHandle <= TPM_RH_LAST; inHandle++)
23         {
24             switch (inHandle)
25             {
26                 case TPM_RH_OWNER:
27                 case TPM_RH_NULL:
28                 case TPM_RS_PW:
29                 case TPM_RH_LOCKOUT:
30                 case TPM_RH_ENDORSEMENT:
31                 case TPM_RH_PLATFORM:
32                 case TPM_RH_PLATFORM_NV:
33         #ifdef VENDOR_PERMANENT
34                 case VENDOR_PERMANENT:
35         #endif
36                     return inHandle;

     Family "2.0"                                  TCG Published                                       Page 239
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines

37                      break;
38                  default:
39                      break;
40             }
41         }
42         // Out of range on the top
43         return 0;
44   }


     9.8.3.3     PermanentCapGetHandles()

     This function returns a list of the permanent handles of PCR, started from handle. If handle is larger than
     the largest permanent handle, an empty list will be returned with more set to NO.

     Return Value                      Meaning

     YES                               if there are more handles available
     NO                                all the available handles has been returned

45   TPMI_YES_NO
46   PermanentCapGetHandles(
47         TPM_HANDLE         handle,              // IN: start handle
48         UINT32             count,               // IN: count of returned handle
49         TPML_HANDLE       *handleList           // OUT: list of handle
50         )
51   {
52         TPMI_YES_NO       more = NO;
53         UINT32            i;
54
55         pAssert(HandleGetType(handle) == TPM_HT_PERMANENT);
56
57         // Initialize output handle list
58         handleList->count = 0;
59
60         // The maximum count of handles we may return is MAX_CAP_HANDLES
61         if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
62
63         // Iterate permanent handle range
64         for(i = NextPermanentHandle(handle);
65                  i != 0; i = NextPermanentHandle(i+1))
66         {
67             if(handleList->count < count)
68             {
69                  // If we have not filled up the return list, add this permanent
70                  // handle to it
71                  handleList->handle[handleList->count] = i;
72                  handleList->count++;
73             }
74             else
75             {
76                  // If the return list is full but we still have permanent handle
77                  // available, report this and stop iterating
78                  more = YES;
79                  break;
80             }
81         }
82         return more;
83   }




     Page 240                                       TCG Published                                  Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
     Part 4: Supporting Routines                                            Trusted Platform Module Library

     9.9      Locality.c

     9.9.1      Includes

 1   #include "InternalRoutines.h"


     9.9.2      LocalityGetAttributes()

     This function will convert a locality expressed as an integer into TPMA_LOCALITY form.
     The function returns the locality attribute.

 2   TPMA_LOCALITY
 3   LocalityGetAttributes(
 4          UINT8               locality            // IN: locality value
 5          )
 6   {
 7          TPMA_LOCALITY                 locality_attributes;
 8          BYTE                         *localityAsByte = (BYTE *)&locality_attributes;
 9
10          MemorySet(&locality_attributes, 0, sizeof(TPMA_LOCALITY));
11          switch(locality)
12          {
13              case 0:
14                  locality_attributes.TPM_LOC_ZERO = SET;
15                  break;
16              case 1:
17                  locality_attributes.TPM_LOC_ONE = SET;
18                  break;
19              case 2:
20                  locality_attributes.TPM_LOC_TWO = SET;
21                  break;
22              case 3:
23                  locality_attributes.TPM_LOC_THREE = SET;
24                  break;
25              case 4:
26                  locality_attributes.TPM_LOC_FOUR = SET;
27                  break;
28              default:
29                  pAssert(locality < 256 && locality > 31);
30                  *localityAsByte = locality;
31                  break;
32          }
33          return locality_attributes;
34   }


     9.10     Manufacture.c

     9.10.1     Description

     This file contains the function that performs the manufacturing of the TPM in a simulated environment.
     These functions should not be used outside of a manufacturing or simulation environment.

     9.10.2     Includes and Data Definitions

 1   #define MANUFACTURE_C
 2   #include "InternalRoutines.h"
 3   #include "Global.h"



     Family "2.0"                                   TCG Published                               Page 241
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                    October 30, 2014
     Trusted Platform Module Library                                                Part 4: Supporting Routines

     9.10.3     Functions

     9.10.3.1    TPM_Manufacture()

     This function initializes the TPM values in preparation for the TPM's first use. This function will fail if
     previously called. The TPM can be re-manufactured by calling TPM_Teardown() first and then calling this
     function again.

     Return Value                      Meaning

     0                                 success
     1                                 manufacturing process previously performed

 4   LIB_EXPORT int
 5   TPM_Manufacture(
 6       BOOL                 firstTime           // IN: indicates if this is the first call from
 7                                                //     main()
 8       )
 9   {
10       TPM_SU              orderlyShutdown;
11       UINT64              totalResetCount = 0;
12
13       // If TPM has been manufactured, return indication.
14       if(!firstTime && g_manufactured)
15           return 1;
16
17       // initialize crypto units
18       //CryptInitUnits();
19
20       //
21       s_selfHealTimer = 0;
22       s_lockoutTimer = 0;
23       s_DAPendingOnNV = FALSE;
24
25       // initialize NV
26       NvInit();
27
28   #ifdef _DRBG_STATE_SAVE
29       // Initialize the drbg. This needs to come before the install
30       // of the hierarchies
31       if(!_cpri__Startup())               // Have to start the crypto units first
32           FAIL(FATAL_ERROR_INTERNAL);
33       _cpri__DrbgGetPutState(PUT_STATE, 0, NULL);
34   #endif
35
36       // default configuration for PCR
37       PCRSimStart();
38
39       // initialize pre-installed hierarchy data
40       // This should happen after NV is initialized because hierarchy data is
41       // stored in NV.
42       HierarchyPreInstall_Init();
43
44       // initialize dictionary attack parameters
45       DAPreInstall_Init();
46
47       // initialize PP list
48       PhysicalPresencePreInstall_Init();
49
50       // initialize command audit list
51       CommandAuditPreInstall_Init();
52
53       // first start up is required to be Startup(CLEAR)

     Page 242                                      TCG Published                                  Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

 54        orderlyShutdown = TPM_SU_CLEAR;
 55        NvWriteReserved(NV_ORDERLY, &orderlyShutdown);
 56
 57       // initialize the firmware version
 58       gp.firmwareV1 = FIRMWARE_V1;
 59   #ifdef FIRMWARE_V2
 60       gp.firmwareV2 = FIRMWARE_V2;
 61   #else
 62       gp.firmwareV2 = 0;
 63   #endif
 64       NvWriteReserved(NV_FIRMWARE_V1, &gp.firmwareV1);
 65       NvWriteReserved(NV_FIRMWARE_V2, &gp.firmwareV2);
 66
 67        // initialize the total reset counter to 0
 68        NvWriteReserved(NV_TOTAL_RESET_COUNT, &totalResetCount);
 69
 70        // initialize the clock stuff
 71        go.clock = 0;
 72        go.clockSafe = YES;
 73
 74   #ifdef _DRBG_STATE_SAVE
 75       // initialize the current DRBG state in NV
 76
 77       _cpri__DrbgGetPutState(GET_STATE, sizeof(go.drbgState), (BYTE *)&go.drbgState);
 78   #endif
 79
 80        NvWriteReserved(NV_ORDERLY_DATA, &go);
 81
 82        // Commit NV writes. Manufacture process is an artificial process existing
 83        // only in simulator environment and it is not defined in the specification
 84        // that what should be the expected behavior if the NV write fails at this
 85        // point. Therefore, it is assumed the NV write here is always success and
 86        // no return code of this function is checked.
 87        NvCommit();
 88
 89        g_manufactured = TRUE;
 90
 91        return 0;
 92   }


      9.10.3.2    TPM_TearDown()

      This function prepares the TPM for re-manufacture. It should not be implemented in anything other than a
      simulated TPM.
      In this implementation, all that is needs is to stop the cryptographic units and set a flag to indicate that the
      TPM can be re-manufactured. This should be all that is necessary to start the manufacturing process
      again.

      Return Value                      Meaning

      0                                 success
      1                                 TPM not previously manufactured

 93   LIB_EXPORT int
 94   TPM_TearDown(
 95        void
 96        )
 97   {
 98        // stop crypt units
 99        CryptStopUnits();
100
101        g_manufactured = FALSE;

      Family "2.0"                                  TCG Published                                          Page 243
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

102          return 0;
103   }


      9.11     Marshal.c

      9.11.1    Introduction

      This file contains the marshaling and unmarshaling code.
      The marshaling and unmarshaling code and function prototypes are not listed, as the code is repetitive,
      long, and not very useful to read. Examples of a few unmarshaling routines are provided. Most of the
      others are similar.
      Depending on the table header flags, a type will have an unmarshaling routine and a marshaling routine
      The table header flags that control the generation of the unmarshaling and marshaling code are delimited
      by angle brackets ("<>") in the table header. If no brackets are present, then both unmarshaling and
      marshaling code is generated (i.e., generation of both marshaling and unmarshaling code is the default).

      9.11.2    Unmarshal and Marshal a Value

      In TPM 2.0 Part 2, a TPMI_DI_OBJECT is defined by this table:

                         Table xxx — Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type
      Values                                              Comments

      {TRANSIENT_FIRST:TRANSIENT_LAST}                    allowed range for transient objects
      {PERSISTENT_FIRST:PERSISTENT_LAST}                  allowed range for persistent objects
      +TPM_RH_NULL                                        the null handle
      #TPM_RC_VALUE

      This generates the following unmarshaling code:

  1   TPM_RC
  2   TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size,
  3                                     bool flag)
  4   {
  5          TPM_RC     result;
  6          result = TPM_HANDLE_Unmarshal((TPM_HANDLE *)target, buffer, size);
  7          if(result != TPM_RC_SUCCESS)
  8              return result;
  9          if (*target == TPM_RH_NULL) {
 10              if(flag)
 11                   return TPM_RC_SUCCESS;
 12              else
 13                   return TPM_RC_VALUE;
 14          }
 15          if((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST))
 16              if((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST))
 17                   return TPM_RC_VALUE;
 18          return TPM_RC_SUCCESS;
 19   }




      Page 244                                   TCG Published                                     Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                   Level 00 Revision 01.16
     Part 4: Supporting Routines                                                                      Trusted Platform Module Library


     and the following marshaling code:

     NOTE                The marshaling code does not do parameter checking, as the TPM is the source of the marshaling data.

 1   UINT16
 2   TPMI_DH_OBJECT_Marshal(TPMI_DH_OBJECT *source, BYTE **buffer, INT32 *size)
 3   {
 4        return UINT32_Marshal((UINT32 *)source, buffer, size);
 5   }


     9.11.3      Unmarshal and Marshal a Union

     In TPM 2.0 Part 2, a TPMU_PUBLIC_PARMS union is defined by:

                         Table xxx — Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S>
     Parameter              Type                                         Selector                          Description

     keyedHash              TPMS_KEYEDHASH_PARMS                         TPM_ALG_KEYEDHASH                 sign | encrypt | neither
     symDetail              TPMT_SYM_DEF_OBJECT                          TPM_ALG_SYMCIPHER                 a symmetric block cipher
     rsaDetail              TPMS_RSA_PARMS                               TPM_ALG_RSA                       decrypt + sign
     eccDetail              TPMS_ECC_PARMS                               TPM_ALG_ECC                       decrypt + sign
     asymDetail             TPMS_ASYM_PARMS                                                                common scheme structure
                                                                                                           for RSA and ECC keys
     NOTE The Description column indicates which of TPMA_OBJECT.decrypt or TPMA_OBJECT.sign may be set.
      “+” indicates that both may be set but one shall be set. “|” indicates the optional settings.

     From this table, the following unmarshaling code is generated.

 1   TPM_RC
 2   TPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size,
 3                                                 UINT32 selector)
 4   {
 5       switch(selector) {
 6   #ifdef TPM_ALG_KEYEDHASH
 7           case TPM_ALG_KEYEDHASH:
 8               return TPMS_KEYEDHASH_PARMS_Unmarshal(
 9                             (TPMS_KEYEDHASH_PARMS *)&(target->keyedHash), buffer, size);
10   #endif
11   #ifdef TPM_ALG_SYMCIPHER
12           case TPM_ALG_SYMCIPHER:
13               return TPMT_SYM_DEF_OBJECT_Unmarshal(
14                       (TPMT_SYM_DEF_OBJECT *)&(target->symDetail), buffer, size, FALSE);
15   #endif
16   #ifdef TPM_ALG_RSA
17           case TPM_ALG_RSA:
18               return TPMS_RSA_PARMS_Unmarshal(
19                                   (TPMS_RSA_PARMS *)&(target->rsaDetail), buffer, size);
20   #endif
21   #ifdef TPM_ALG_ECC
22           case TPM_ALG_ECC:
23               return TPMS_ECC_PARMS_Unmarshal(
24                                   (TPMS_ECC_PARMS *)&(target->eccDetail), buffer, size);
25   #endif
26       }
27       return TPM_RC_SELECTOR;
28   }




     Family "2.0"                                             TCG Published                                                   Page 245
     Level 00 Revision 01.16                         Copyright © TCG 2006-2014                                      October 30, 2014
     Trusted Platform Module Library                                                  Part 4: Supporting Routines

     NOTE            The #ifdef/#endif directives are added whenever a value is dependent on an algorithm ID so that
                     removing the algorithm definition will remove the related code.

     The marshaling code for the union is:

 1   UINT16
 2   TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size,
 3                                     UINT32 selector)
 4   {
 5       switch(selector) {
 6   #ifdef TPM_ALG_KEYEDHASH
 7           case TPM_ALG_KEYEDHASH:
 8               return TPMS_KEYEDHASH_PARMS_Marshal(
 9                             (TPMS_KEYEDHASH_PARMS *)&(source->keyedHash), buffer, size);
10   #endif
11   #ifdef TPM_ALG_SYMCIPHER
12           case TPM_ALG_SYMCIPHER:
13               return TPMT_SYM_DEF_OBJECT_Marshal(
14                              (TPMT_SYM_DEF_OBJECT *)&(source->symDetail), buffer, size);
15   #endif
16   #ifdef TPM_ALG_RSA
17           case TPM_ALG_RSA:
18               return TPMS_RSA_PARMS_Marshal(
19                               (TPMS_RSA_PARMS *)&(source->rsaDetail), buffer, size);
20   #endif
21   #ifdef TPM_ALG_ECC
22           case TPM_ALG_ECC:
23               return TPMS_ECC_PARMS_Marshal(
24                                (TPMS_ECC_PARMS *)&(source->eccDetail), buffer, size);
25   #endif
26       }
27       assert(1);
28       return 0;
29   }

     For the marshaling and unmarshaling code, a value in the structure containing the union provides the
     value used for selector. The example in the next section illustrates this.




     Page 246                                      TCG Published                                      Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                                       Trusted Platform Module Library

     9.11.4    Unmarshal and Marshal a Structure

     In TPM 2.0 Part 2, the TPMT_PUBLiC structure is defined by:

                               Table xxx — Definition of TPMT_PUBLIC Structure
     Parameter          Type                     Description

     type               TPMI_ALG_PUBLIC          “algorithm” associated with this object
     nameAlg            +TPMI_ALG_HASH           algorithm used for computing the Name of the object
                                                 NOTE       The "+" indicates that the instance of a TPMT_PUBLIC may have
                                                            a "+" to indicate that the nameAlg may be TPM_ALG_NULL.

     objectAttributes   TPMA_OBJECT              attributes that, along with type, determine the manipulations of this
                                                 object
     authPolicy         TPM2B_DIGEST             optional policy for using this key
                                                 The policy is computed using the nameAlg of the object.
                                                 NOTE       shall be the Empty Buffer if no authorization policy is present

     [type]parameters   TPMU_PUBLIC_PARMS the algorithm or structure details
     [type]unique       TPMU_PUBLIC_ID           the unique identifier of the structure
                                                 For an asymmetric key, this would be the public key.

     This structure is tagged (the first value indicates the structure type), and that tag is used to determine how
     the parameters and unique fields are unmarshaled and marshaled. The use of the type for specifying the
     union selector is emphasized below.
     The unmarshaling code for the structure in the table above is:

 1   TPM_RC
 2   TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, bool flag)
 3   {
 4          TPM_RC    result;
 5          result = TPMI_ALG_PUBLIC_Unmarshal((TPMI_ALG_PUBLIC *)&(target->type),
 6                                             buffer, size);
 7          if(result != TPM_RC_SUCCESS)
 8              return result;
 9          result = TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH *)&(target->nameAlg),
10                                           buffer, size, flag);
11          if(result != TPM_RC_SUCCESS)
12              return result;
13          result = TPMA_OBJECT_Unmarshal((TPMA_OBJECT *)&(target->objectAttributes),
14                                         buffer, size);
15          if(result != TPM_RC_SUCCESS)
16              return result;
17          result = TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST *)&(target->authPolicy),
18                                          buffer, size);
19          if(result != TPM_RC_SUCCESS)
20              return result;
21
22          result = TPMU_PUBLIC_PARMS_Unmarshal((TPMU_PUBLIC_PARMS *)&(target->parameters),
23                                               buffer, size,                     );
24          if(result != TPM_RC_SUCCESS)
25              return result;
26
27          result = TPMU_PUBLIC_ID_Unmarshal((TPMU_PUBLIC_ID *)&(target->unique),
28                                            buffer, size,                     )
29          if(result != TPM_RC_SUCCESS)
30              return result;
31
32          return TPM_RC_SUCCESS;
33   }

     Family "2.0"                                  TCG Published                                                    Page 247
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                                     October 30, 2014
     Trusted Platform Module Library                                Part 4: Supporting Routines


     The marshaling code for the TPMT_PUBLIC structure is:

 1   UINT16
 2   TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size)
 3   {
 4       UINT16    result = 0;
 5       result = (UINT16)(result + TPMI_ALG_PUBLIC_Marshal(
 6                                      (TPMI_ALG_PUBLIC *)&(source->type), buffer, size));
 7       result = (UINT16)(result + TPMI_ALG_HASH_Marshal(
 8                                     (TPMI_ALG_HASH *)&(source->nameAlg), buffer, size))
 9   ;
10       result = (UINT16)(result + TPMA_OBJECT_Marshal(
11                              (TPMA_OBJECT *)&(source->objectAttributes), buffer, size));
12
13       result = (UINT16)(result + TPM2B_DIGEST_Marshal(
14                                   (TPM2B_DIGEST *)&(source->authPolicy), buffer, size));
15
16       result = (UINT16)(result + TPMU_PUBLIC_PARMS_Marshal(
17                              (TPMU_PUBLIC_PARMS *)&(source->parameters), buffer, size,
18                                                                                      ));
19
20       result = (UINT16)(result + TPMU_PUBLIC_ID_Marshal(
21                                     (TPMU_PUBLIC_ID *)&(source->unique), buffer, size,
22                                                                                      ));
23
24       return result;
25   }




     Page 248                                 TCG Published                       Family "2.0"
     October 30, 2014                   Copyright © TCG 2006-2014     Level 00 Revision 01.16
     Part 4: Supporting Routines                                             Trusted Platform Module Library

     9.11.5       Unmarshal and Marshal an Array

     In TPM 2.0 Part 2, the TPML_DIGEST is defined by:

                               Table xxx — Definition of TPML_DIGEST Structure
     Parameter                           Type            Description

     count {2:}                          UINT32          number of digests in the list, minimum is two
     digests[count]{:8}                  TPM2B_DIGEST a list of digests
                                                      For TPM2_PolicyOR(), all digests will have been
                                                      computed using the digest of the policy session. For
                                                      TPM2_PCR_Read(), each digest will be the size of the
                                                      digest for the bank containing the PCR.
     #TPM_RC_SIZE                                        response code when count is not at least two or is
                                                         greater than 8
     The digests parameter is an array of up to count structures (TPM2B_DIGESTS). The auto-generated code
     to Unmarshal this structure is:

 1   TPM_RC
 2   TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size)
 3   {
 4       TPM_RC    result;
 5       result = UINT32_Unmarshal((UINT32 *)&(target->count), buffer, size);
 6       if(result != TPM_RC_SUCCESS)
 7           return result;
 8
 9       if( (target->count < 2))         // This check is triggered by the {2:} notation
10                                        // on ‘count’
11                return TPM_RC_SIZE;
12
13       if((target->count) > 8)          // This check is triggered by the {:8} notation
14                                        // on ‘digests’.
15                return TPM_RC_SIZE;
16
17       result = TPM2B_DIGEST_Array_Unmarshal((TPM2B_DIGEST *)(target->digests),
18                                             buffer, size,                                         );
19       if(result != TPM_RC_SUCCESS)
20           return result;
21
22       return TPM_RC_SUCCESS;
23   }

     The routine unmarshals a count value and passes that value to a routine that unmarshals an array of
     TPM2B_DIGEST values. The unmarshaling code for the array is:

 1   TPM_RC
 2   TPM2B_DIGEST_Array_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size,
 3                                       INT32 count)
 4   {
 5       TPM_RC    result;
 6       INT32 i;
 7       for(i = 0; i < count; i++) {
 8           result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size);
 9           if(result != TPM_RC_SUCCESS)
10               return result;
11       }
12       return TPM_RC_SUCCESS;
13   }
14


     Family "2.0"                               TCG Published                                        Page 249
     Level 00 Revision 01.16            Copyright © TCG 2006-2014                           October 30, 2014
     Trusted Platform Module Library                                     Part 4: Supporting Routines


     Marshaling of the TPML_DIGEST uses a similar scheme with a structure specifying the number of
     elements in an array and a subsequent call to a routine to marshal an array of that type.

 1   UINT16
 2   TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size)
 3   {
 4       UINT16    result = 0;
 5       result = (UINT16)(result + UINT32_Marshal((UINT32 *)&(source->count), buffer,
 6                                                                                  size));
 7       result = (UINT16)(result + TPM2B_DIGEST_Array_Marshal(
 8                                       (TPM2B_DIGEST *)(source->digests), buffer, size,
 9                                       (INT32)(source->count)));
10
11       return result;
12   }

     The marshaling code for the array is:

 1   TPM_RC
 2   TPM2B_DIGEST_Array_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size,
 3                                       INT32 count)
 4   {
 5       TPM_RC    result;
 6       INT32 i;
 7       for(i = 0; i < count; i++) {
 8           result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size);
 9           if(result != TPM_RC_SUCCESS)
10               return result;
11       }
12       return TPM_RC_SUCCESS;
13   }




     Page 250                                     TCG Published                        Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014     Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library

     9.11.6    TPM2B Handling

     A TPM2B structure is handled as a special case. The unmarshaling code is similar to what is shown in
     10.11.5 but the unmarshaling/marshaling is to a union element. Each TPM2B is a union of two sized
     buffers, one of which is type specific (the ‘t’ element) and the other is a generic value (the ‘b’ element).
     This allows each of the TPM2B structures to have some inheritance property with all other TPM2B. The
     purpose is to allow functions that have parameters that can be any TPM2B structure while allowing other
     functions to be specific about the type of the TPM2B that is used. When the generic structure is allowed,
     the input parameter would use the ‘b’ element and when the type-specific structure is required, the ‘t’
     element is used.

                                  Table xxx — Definition of TPM2B_EVENT Structure
     Parameter                                Type                   Description

     size                                     UINT16                 Size of the operand
     buffer [size] {:1024}                    BYTE                   The operand

 1   TPM_RC
 2   TPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size)
 3   {
 4          TPM_RC    result;
 5          result = UINT16_Unmarshal((UINT16 *)&(target->t.size), buffer, size);
 6          if(result != TPM_RC_SUCCESS)
 7              return result;
 8
 9       // if size equal to 0, the rest of the structure is a zero buffer.                   Stop
     processing
10       if(target->t.size == 0)
11           return TPM_RC_SUCCESS;
12
13          if((target->t.size) > 1024)         // This check is triggered by the {:1024} notation
14                                              // on ‘buffer’
15             return TPM_RC_SIZE;
16
17          result = BYTE_Array_Unmarshal((BYTE *)(target->t.buffer), buffer, size,
18                                        (INT32)(target->t.size));
19          if(result != TPM_RC_SUCCESS)
20              return result;
21
22          return TPM_RC_SUCCESS;
23   }

     Which use these structure definitions:

 1   typedef struct {
 2       UINT16              size;
 3       BYTE                buffer[1];
 4   } TPM2B;
 5
 6   typedef struct {
 7       UINT16              size;
 8       BYTE                buffer[1024];
 9   } EVENT_2B;
10
11   typedef union {
12       EVENT_2B            t;      // The type-specific union member
13       TPM2B               b;      // The generic union member
14   } TPM2B_EVENT;




     Family "2.0"                                 TCG Published                                       Page 251
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                        Part 4: Supporting Routines

     9.12     MemoryLib.c

     9.12.1     Description

     This file contains a set of miscellaneous memory manipulation routines. Many of the functions have the
     same semantics as functions defined in string.h. Those functions are not used in the TPM in order to
     avoid namespace contamination.

     9.12.2     Includes and Data Definitions

 1   #define MEMORY_LIB_C
 2   #include "InternalRoutines.h"

     These buffers are set aside to hold command and response values. In this implementation, it is not
     guaranteed that the code will stop accessing the s_actionInputBuffer before starting to put values in the
     s_actionOutputBuffer so different buffers are required. However, the s_actionInputBuffer and
     s_responseBuffer are not needed at the same time and they could be the same buffer.

     9.12.3     Functions on BYTE Arrays

     9.12.3.1     MemoryMove()

     This function moves data from one place in memory to another. No safety checks of any type are
     performed. If source and data buffer overlap, then the move is done as if an intermediate buffer were
     used.

     NOTE:           This function is used by MemoryCopy(), MemoryCopy2B(), and MemoryConcat2b() and requires that the caller
                     know the maximum size of the destination buffer so that there is no possibility of buffer overrun.

 3   LIB_EXPORT void
 4   MemoryMove(
 5          void              *destination,          //   OUT: move destination
 6          const void        *source,               //   IN: move source
 7          UINT32             size,                 //   IN: number of octets to moved
 8          UINT32             dSize                 //   IN: size of the receive buffer
 9          )
10   {
11          const BYTE *p = (BYTE *)source;
12          BYTE *q = (BYTE *)destination;
13
14          if(destination == NULL || source == NULL)
15              return;
16
17          pAssert(size <= dSize);
18          // if the destination buffer has a lower address than the
19          // source, then moving bytes in ascending order is safe.
20          dSize -= size;
21
22          if (p>q || (p+size <= q))
23          {
24              while(size--)
25                  *q++ = *p++;
26          }
27          // If the destination buffer has a higher address than the
28          // source, then move bytes from the end to the beginning.
29          else if (p < q)
30          {
31              p += size;
32              q += size;


     Page 252                                        TCG Published                                           Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014                        Level 00 Revision 01.16
     Part 4: Supporting Routines                                                   Trusted Platform Module Library

33              while (size--)
34                  *--q = *--p;
35          }
36
37          // If the source and destination address are the same, nothing to move.
38          return;
39   }


     9.12.3.2    MemoryCopy()

     This function moves data from one place in memory to another. No safety checks of any type are
     performed. If the destination and source overlap, then the results are unpredictable. void MemoryCopy(

     void                             *destination, // OUT: copy destination

     void                             *source, // IN: copy source
     UINT32                           size, // IN: number of octets being copied
     UINT32                           dSize // IN: size of the receive buffer

     MemoryMove(destination, source, size, dSize);

40   //%#define MemoryCopy(destination, source, size, destSize)                          \
41   //%    MemoryMove((destination), (source), (size), (destSize))


     9.12.3.3    MemoryEqual()

     This function indicates if two buffers have the same values in the indicated number of bytes.

     Return Value                     Meaning

     TRUE                             all octets are the same
     FALSE                            all octets are not the same

42   LIB_EXPORT BOOL
43   MemoryEqual(
44          const void       *buffer1,             // IN: compare buffer1
45          const void       *buffer2,             // IN: compare buffer2
46          UINT32            size                 // IN: size of bytes being compared
47          )
48   {
49          BOOL          equal = TRUE;
50          const BYTE   *b1, *b2;
51
52          b1 = (BYTE *)buffer1;
53          b2 = (BYTE *)buffer2;
54
55          // Compare all bytes so that there is no leakage of information
56          // due to timing differences.
57          for(; size > 0; size--)
58              equal = (*b1++ == *b2++) && equal;
59
60          return equal;
61   }


     9.12.3.4    MemoryCopy2B()

     This function copies a TPM2B. This can be used when the TPM2B types are the same or different. No
     size checking is done on the destination so the caller should make sure that the destination is large
     enough.

     Family "2.0"                                  TCG Published                                        Page 253
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines


      This function returns the number of octets in the data buffer of the TPM2B.

 62   LIB_EXPORT INT16
 63   MemoryCopy2B(
 64       TPM2B               *dest,                // OUT: receiving TPM2B
 65       const TPM2B         *source,              // IN: source TPM2B
 66       UINT16               dSize                // IN: size of the receiving buffer
 67       )
 68   {
 69
 70       if(dest == NULL)
 71           return 0;
 72       if(source == NULL)
 73           dest->size = 0;
 74       else
 75       {
 76           dest->size = source->size;
 77           MemoryMove(dest->buffer, source->buffer, dest->size, dSize);
 78       }
 79       return dest->size;
 80   }


      9.12.3.5    MemoryConcat2B()

      This function will concatenate the buffer contents of a TPM2B to an the buffer contents of another TPM2B
      and adjust the size accordingly (a := (a | b)).

 81   LIB_EXPORT void
 82   MemoryConcat2B(
 83       TPM2B               *aInOut,              // IN/OUT: destination 2B
 84       TPM2B               *bIn,                 // IN: second 2B
 85       UINT16               aSize                // IN: The size of aInOut.buffer (max values for
 86                                                 //     aInOut.size)
 87       )
 88   {
 89       MemoryMove(&aInOut->buffer[aInOut->size],
 90                  bIn->buffer,
 91                  bIn->size,
 92                  aSize - aInOut->size);
 93       aInOut->size = aInOut->size + bIn->size;
 94       return;
 95   }


      9.12.3.6    Memory2BEqual()

      This function will compare two TPM2B structures. To be equal, they need to be the same size and the
      buffer contexts need to be the same in all octets.

      Return Value                      Meaning

      TRUE                              size and buffer contents are the same
      FALSE                             size or buffer contents are not the same

 96   LIB_EXPORT BOOL
 97   Memory2BEqual(
 98       const TPM2B         *aIn,                 // IN: compare value
 99       const TPM2B         *bIn                  // IN: compare value
100       )
101   {
102       if(aIn->size != bIn->size)
103           return FALSE;

      Page 254                                       TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                                          Trusted Platform Module Library

104
105        return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size);
106   }


      9.12.3.7    MemorySet()

      This function will set all the octets in the specified memory range to the specified octet value.

      NOTE:            the dSize parameter forces the caller to know how big the receiving buffer is to make sure that there is no
                       possibility that the caller will inadvertently run over the end of the buffer.

107   LIB_EXPORT void
108   MemorySet(
109        void                 *destination,           // OUT: memory destination
110        char                  value,                 // IN: fill value
111        UINT32                size                   // IN: number of octets to fill
112        )
113   {
114        char *p = (char *)destination;
115        while (size--)
116            *p++ = value;
117        return;
118   }


      9.12.3.8    MemoryGetActionInputBuffer()

      This function returns the address of the buffer into which the command parameters will be unmarshaled in
      preparation for calling the command actions.

119   BYTE *
120   MemoryGetActionInputBuffer(
121        UINT32                 size                  // Size, in bytes, required for the input
122                                                     // unmarshaling
123        )
124   {
125        BYTE           *buf = NULL;
126
127        if(size > 0)
128        {
129            // In this implementation, a static buffer is set aside for action output.
130            // Other implementations may apply additional optimization based on command
131            // code or other factors.
132            UINT32      *p = s_actionInputBuffer;
133            buf = (BYTE *)p;
134            pAssert(size < sizeof(s_actionInputBuffer));
135
136           // size of an element in the buffer
137   #define SZ      sizeof(s_actionInputBuffer[0])
138
139           for(size = (size + SZ - 1) / SZ; size > 0; size--)
140               *p++ = 0;
141   #undef SZ
142       }
143       return buf;
144   }


      9.12.3.9    MemoryGetActionOutputBuffer()

      This function returns the address of the buffer into which the command action code places its output
      values.


      Family "2.0"                                      TCG Published                                                Page 255
      Level 00 Revision 01.16                  Copyright © TCG 2006-2014                                   October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

145   void *
146   MemoryGetActionOutputBuffer(
147          TPM_CC             command            // Command that requires the buffer
148          )
149   {
150          // In this implementation, a static buffer is set aside for action output.
151          // Other implementations may apply additional optimization based on the command
152          // code or other factors.
153          command = 0;        // Unreferenced parameter
154          return s_actionOutputBuffer;
155   }


      9.12.3.10 MemoryGetResponseBuffer()

      This function returns the address into which the command response is marshaled from values in the
      action output buffer.

156   BYTE *
157   MemoryGetResponseBuffer(
158          TPM_CC             command            // Command that requires the buffer
159          )
160   {
161          // In this implementation, a static buffer is set aside for responses.
162          // Other implementation may apply additional optimization based on the command
163          // code or other factors.
164          command = 0;        // Unreferenced parameter
165          return s_responseBuffer;
166   }


      9.12.3.11 MemoryRemoveTrailingZeros()

      This function is used to adjust the length of an authorization value. It adjusts the size of the TPM2B so
      that it does not include octets at the end of the buffer that contain zero. The function returns the number
      of non-zero octets in the buffer.

167   UINT16
168   MemoryRemoveTrailingZeros (
169          TPM2B_AUTH        *auth               // IN/OUT: value to adjust
170          )
171   {
172          BYTE         *a = &auth->t.buffer[auth->t.size-1];
173          for(; auth->t.size > 0; auth->t.size--)
174          {
175              if(*a--)
176                  break;
177          }
178          return auth->t.size;
179   }


      9.13     Power.c

      9.13.1     Description

      This file contains functions that receive the simulated power state transitions of the TPM.

      9.13.2     Includes and Data Definitions

  1   #define POWER_C
  2   #include "InternalRoutines.h"

      Page 256                                     TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                         Trusted Platform Module Library

     9.13.3     Functions

     9.13.3.1      TPMInit()

     This function is used to process a power on event.

 3   void
 4   TPMInit(
 5          void
 6          )
 7   {
 8          // Set state as not initialized. This means that Startup is required
 9          s_initialized = FALSE;
10
11          return;
12   }


     9.13.3.2      TPMRegisterStartup()

     This function registers the fact that the TPM has been initialized (a TPM2_Startup() has completed
     successfully).

13   void
14   TPMRegisterStartup(
15          void
16          )
17   {
18          s_initialized = TRUE;
19
20          return;
21   }


     9.13.3.3      TPMIsStarted()

     Indicates if the TPM has been initialized (a TPM2_Startup() has completed successfully after a
     _TPM_Init()).

     Return Value                    Meaning

     TRUE                            TPM has been initialized
     FALSE                           TPM has not been initialized

22   BOOL
23   TPMIsStarted(
24          void
25          )
26   {
27          return s_initialized;
28   }


     9.14     PropertyCap.c

     9.14.1     Description

     This file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values.




     Family "2.0"                                TCG Published                                Page 257
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                   October 30, 2014
     Trusted Platform Module Library                                                  Part 4: Supporting Routines

     9.14.2     Includes

 1   #include "InternalRoutines.h"


     9.14.3     Functions

     9.14.3.1    PCRGetProperty()

     This function accepts a property selection and, if so, sets value to the value of the property.
     All the fixed values are vendor dependent or determined by a platform-specific specification. The values
     in the table below are examples and should be changed by the vendor.

     Return Value                      Meaning

     TRUE                              referenced property exists and value set
     FALSE                             referenced property does not exist

 2   static BOOL
 3   TPMPropertyIsDefined(
 4        TPM_PT               property,           // IN: property
 5        UINT32              *value               // OUT: property value
 6        )
 7   {
 8       switch(property)
 9       {
10           case TPM_PT_FAMILY_INDICATOR:
11               // from the title page of the specification
12               // For this specification, the value is "2.0".
13               *value = TPM_SPEC_FAMILY;
14               break;
15           case TPM_PT_LEVEL:
16               // from the title page of the specification
17               *value = TPM_SPEC_LEVEL;
18               break;
19           case TPM_PT_REVISION:
20               // from the title page of the specification
21               *value = TPM_SPEC_VERSION;
22               break;
23           case TPM_PT_DAY_OF_YEAR:
24               // computed from the date value on the title page of the specification
25               *value = TPM_SPEC_DAY_OF_YEAR;
26               break;
27           case TPM_PT_YEAR:
28               // from the title page of the specification
29               *value = TPM_SPEC_YEAR;
30               break;
31           case TPM_PT_MANUFACTURER:
32               // vendor ID unique to each TPM manufacturer
33               *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER);
34               break;
35           case TPM_PT_VENDOR_STRING_1:
36               // first four characters of the vendor ID string
37               *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1);
38               break;
39           case TPM_PT_VENDOR_STRING_2:
40               // second four characters of the vendor ID string
41   #ifdef VENDOR_STRING_2
42               *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2);
43   #else
44               *value = 0;
45   #endif

     Page 258                                       TCG Published                                      Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

 46               break;
 47           case TPM_PT_VENDOR_STRING_3:
 48               // third four characters of the vendor ID string
 49   #ifdef VENDOR_STRING_3
 50               *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3);
 51   #else
 52               *value = 0;
 53   #endif
 54               break;
 55           case TPM_PT_VENDOR_STRING_4:
 56               // fourth four characters of the vendor ID string
 57   #ifdef VENDOR_STRING_4
 58               *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4);
 59   #else
 60               *value = 0;
 61   #endif
 62               break;
 63           case TPM_PT_VENDOR_TPM_TYPE:
 64               // vendor-defined value indicating the TPM model
 65               *value = 1;
 66               break;
 67           case TPM_PT_FIRMWARE_VERSION_1:
 68               // more significant 32-bits of a vendor-specific value
 69               *value = gp.firmwareV1;
 70               break;
 71           case TPM_PT_FIRMWARE_VERSION_2:
 72               // less significant 32-bits of a vendor-specific value
 73               *value = gp.firmwareV2;
 74               break;
 75           case TPM_PT_INPUT_BUFFER:
 76               // maximum size of TPM2B_MAX_BUFFER
 77               *value = MAX_DIGEST_BUFFER;
 78               break;
 79           case TPM_PT_HR_TRANSIENT_MIN:
 80               // minimum number of transient objects that can be held in TPM
 81               // RAM
 82               *value = MAX_LOADED_OBJECTS;
 83               break;
 84           case TPM_PT_HR_PERSISTENT_MIN:
 85               // minimum number of persistent objects that can be held in
 86               // TPM NV memory
 87               // In this implementation, there is no minimum number of
 88               // persistent objects.
 89               *value = MIN_EVICT_OBJECTS;
 90               break;
 91           case TPM_PT_HR_LOADED_MIN:
 92               // minimum number of authorization sessions that can be held in
 93               // TPM RAM
 94               *value = MAX_LOADED_SESSIONS;
 95               break;
 96           case TPM_PT_ACTIVE_SESSIONS_MAX:
 97               // number of authorization sessions that may be active at a time
 98               *value = MAX_ACTIVE_SESSIONS;
 99               break;
100           case TPM_PT_PCR_COUNT:
101               // number of PCR implemented
102               *value = IMPLEMENTATION_PCR;
103               break;
104           case TPM_PT_PCR_SELECT_MIN:
105               // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect
106               *value = PCR_SELECT_MIN;
107               break;
108           case TPM_PT_CONTEXT_GAP_MAX:
109               // maximum allowed difference (unsigned) between the contextID
110               // values of two saved session contexts
111               *value = (1 << (sizeof(CONTEXT_SLOT) * 8)) - 1;

      Family "2.0"                        TCG Published                                Page 259
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                  Part 4: Supporting Routines

112                break;
113            case TPM_PT_NV_COUNTERS_MAX:
114                // maximum number of NV indexes that are allowed to have the
115                // TPMA_NV_COUNTER attribute SET
116                // In this implementation, there is no limitation on the number
117                // of counters, except for the size of the NV Index memory.
118                *value = 0;
119                break;
120            case TPM_PT_NV_INDEX_MAX:
121                // maximum size of an NV index data area
122                *value = MAX_NV_INDEX_SIZE;
123                break;
124            case TPM_PT_MEMORY:
125                // a TPMA_MEMORY indicating the memory management method for the TPM
126            {
127                TPMA_MEMORY         attributes = {0};
128                attributes.sharedNV = SET;
129                attributes.objectCopiedToRam = SET;
130
131                 // Note: Different compilers may require a different method to cast
132                 // a bit field structure to a UINT32.
133                 *value = * (UINT32 *) &attributes;
134                 break;
135            }
136            case TPM_PT_CLOCK_UPDATE:
137                // interval, in seconds, between updates to the copy of
138                // TPMS_TIME_INFO .clock in NV
139                *value = (1 << NV_CLOCK_UPDATE_INTERVAL);
140                break;
141            case TPM_PT_CONTEXT_HASH:
142                // algorithm used for the integrity hash on saved contexts and
143                // for digesting the fuData of TPM2_FirmwareRead()
144                *value = CONTEXT_INTEGRITY_HASH_ALG;
145                break;
146            case TPM_PT_CONTEXT_SYM:
147                // algorithm used for encryption of saved contexts
148                *value = CONTEXT_ENCRYPT_ALG;
149                break;
150            case TPM_PT_CONTEXT_SYM_SIZE:
151                // size of the key used for encryption of saved contexts
152                *value = CONTEXT_ENCRYPT_KEY_BITS;
153                break;
154            case TPM_PT_ORDERLY_COUNT:
155                // maximum difference between the volatile and non-volatile
156                // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET
157                *value = MAX_ORDERLY_COUNT;
158                break;
159            case TPM_PT_MAX_COMMAND_SIZE:
160                // maximum value for 'commandSize'
161                *value = MAX_COMMAND_SIZE;
162                break;
163            case TPM_PT_MAX_RESPONSE_SIZE:
164                // maximum value for 'responseSize'
165                *value = MAX_RESPONSE_SIZE;
166                break;
167            case TPM_PT_MAX_DIGEST:
168                // maximum size of a digest that can be produced by the TPM
169                *value = sizeof(TPMU_HA);
170                break;
171            case TPM_PT_MAX_OBJECT_CONTEXT:
172                // maximum size of a TPMS_CONTEXT that will be returned by
173                // TPM2_ContextSave for object context
174                *value = 0;
175
176                 // adding sequence, saved handle and hierarchy
177                 *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +

      Page 260                               TCG Published                            Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014          Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

178                            sizeof(TPMI_RH_HIERARCHY);
179                  // add size field in TPM2B_CONTEXT
180                  *value += sizeof(UINT16);
181
182                  // add integrity hash size
183                  *value += sizeof(UINT16) +
184                            CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
185
186                  // Add fingerprint size, which is the same as sequence size
187                  *value += sizeof(UINT64);
188
189                // Add OBJECT structure size
190                *value += sizeof(OBJECT);
191                break;
192            case TPM_PT_MAX_SESSION_CONTEXT:
193                // the maximum size of a TPMS_CONTEXT that will be returned by
194                // TPM2_ContextSave for object context
195                *value = 0;
196
197                  // adding sequence, saved handle and hierarchy
198                  *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +
199                            sizeof(TPMI_RH_HIERARCHY);
200                  // Add size field in TPM2B_CONTEXT
201                  *value += sizeof(UINT16);
202
203                  // Add integrity hash size
204                  *value += sizeof(UINT16) +
205                            CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
206                  // Add fingerprint size, which is the same as sequence size
207                  *value += sizeof(UINT64);
208
209               // Add SESSION structure size
210               *value += sizeof(SESSION);
211               break;
212           case TPM_PT_PS_FAMILY_INDICATOR:
213               // platform specific values for the TPM_PT_PS parameters from
214               // the relevant platform-specific specification
215               // In this reference implementation, all of these values are 0.
216               *value = 0;
217               break;
218           case TPM_PT_PS_LEVEL:
219               // level of the platform-specific specification
220               *value = 0;
221               break;
222           case TPM_PT_PS_REVISION:
223               // specification Revision times 100 for the platform-specific
224               // specification
225               *value = 0;
226               break;
227           case TPM_PT_PS_DAY_OF_YEAR:
228               // platform-specific specification day of year using TCG calendar
229               *value = 0;
230               break;
231           case TPM_PT_PS_YEAR:
232               // platform-specific specification year using the CE
233               *value = 0;
234               break;
235           case TPM_PT_SPLIT_MAX:
236               // number of split signing operations supported by the TPM
237               *value = 0;
238       #ifdef TPM_ALG_ECC
239               *value = sizeof(gr.commitArray) * 8;
240       #endif
241               break;
242           case TPM_PT_TOTAL_COMMANDS:
243               // total number of commands implemented in the TPM

      Family "2.0"                           TCG Published                                Page 261
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                  Part 4: Supporting Routines

244                 // Since the reference implementation does not have any
245                 // vendor-defined commands, this will be the same as the
246                 // number of library commands.
247            {
248                 UINT32 i;
249                 *value = 0;
250
251                 // calculate implemented command numbers
252                 for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
253                 {
254                     if(CommandIsImplemented(i)) (*value)++;
255                 }
256                 break;
257            }
258            case TPM_PT_LIBRARY_COMMANDS:
259                // number of commands from the TPM library that are implemented
260            {
261                UINT32 i;
262                *value = 0;
263
264                 // calculate implemented command numbers
265                 for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
266                 {
267                     if(CommandIsImplemented(i)) (*value)++;
268                 }
269                 break;
270            }
271            case TPM_PT_VENDOR_COMMANDS:
272                // number of vendor commands that are implemented
273                *value = 0;
274                break;
275            case TPM_PT_PERMANENT:
276                // TPMA_PERMANENT
277            {
278                TPMA_PERMANENT           flags = {0};
279                if(gp.ownerAuth.t.size != 0)
280                    flags.ownerAuthSet = SET;
281                if(gp.endorsementAuth.t.size != 0)
282                    flags.endorsementAuthSet = SET;
283                if(gp.lockoutAuth.t.size != 0)
284                    flags.lockoutAuthSet = SET;
285                if(gp.disableClear)
286                    flags.disableClear = SET;
287                if(gp.failedTries >= gp.maxTries)
288                    flags.inLockout = SET;
289                // In this implementation, EPS is always generated by TPM
290                flags.tpmGeneratedEPS = SET;
291
292                 // Note: Different compilers may require a different method to cast
293                 // a bit field structure to a UINT32.
294                 *value = * (UINT32 *) &flags;
295                 break;
296            }
297            case TPM_PT_STARTUP_CLEAR:
298                // TPMA_STARTUP_CLEAR
299            {
300                TPMA_STARTUP_CLEAR      flags = {0};
301                if(g_phEnable)
302                    flags.phEnable = SET;
303                if(gc.shEnable)
304                    flags.shEnable = SET;
305                if(gc.ehEnable)
306                    flags.ehEnable = SET;
307                if(gc.phEnableNV)
308                    flags.phEnableNV = SET;
309                if(g_prevOrderlyState != SHUTDOWN_NONE)

      Page 262                               TCG Published                           Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014        Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

310                      flags.orderly = SET;
311
312                  // Note: Different compilers may require a different method to cast
313                  // a bit field structure to a UINT32.
314                  *value = * (UINT32 *) &flags;
315                  break;
316            }
317            case TPM_PT_HR_NV_INDEX:
318                // number of NV indexes currently defined
319                *value = NvCapGetIndexNumber();
320                break;
321            case TPM_PT_HR_LOADED:
322                // number of authorization sessions currently loaded into TPM
323                // RAM
324                *value = SessionCapGetLoadedNumber();
325                break;
326            case TPM_PT_HR_LOADED_AVAIL:
327                // number of additional authorization sessions, of any type,
328                // that could be loaded into TPM RAM
329                *value = SessionCapGetLoadedAvail();
330                break;
331            case TPM_PT_HR_ACTIVE:
332                // number of active authorization sessions currently being
333                // tracked by the TPM
334                *value = SessionCapGetActiveNumber();
335                break;
336            case TPM_PT_HR_ACTIVE_AVAIL:
337                // number of additional authorization sessions, of any type,
338                // that could be created
339                *value = SessionCapGetActiveAvail();
340                break;
341            case TPM_PT_HR_TRANSIENT_AVAIL:
342                // estimate of the number of additional transient objects that
343                // could be loaded into TPM RAM
344                *value = ObjectCapGetTransientAvail();
345                break;
346            case TPM_PT_HR_PERSISTENT:
347                // number of persistent objects currently loaded into TPM
348                // NV memory
349                *value = NvCapGetPersistentNumber();
350                break;
351            case TPM_PT_HR_PERSISTENT_AVAIL:
352                // number of additional persistent objects that could be loaded
353                // into NV memory
354                *value = NvCapGetPersistentAvail();
355                break;
356            case TPM_PT_NV_COUNTERS:
357                // number of defined NV indexes that have NV TPMA_NV_COUNTER
358                // attribute SET
359                *value = NvCapGetCounterNumber();
360                break;
361            case TPM_PT_NV_COUNTERS_AVAIL:
362                // number of additional NV indexes that can be defined with their
363                // TPMA_NV_COUNTER attribute SET
364                *value = NvCapGetCounterAvail();
365                break;
366            case TPM_PT_ALGORITHM_SET:
367                // region code for the TPM
368                *value = gp.algorithmSet;
369                break;
370
371           case TPM_PT_LOADED_CURVES:
372       #ifdef TPM_ALG_ECC
373               // number of loaded ECC curves
374               *value = CryptCapGetEccCurveNumber();
375       #else // TPM_ALG_ECC

      Family "2.0"                              TCG Published                             Page 263
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

376                 *value = 0;
377         #endif // TPM_ALG_ECC
378                 break;
379
380              case TPM_PT_LOCKOUT_COUNTER:
381                  // current value of the lockout counter
382                  *value = gp.failedTries;
383                  break;
384              case TPM_PT_MAX_AUTH_FAIL:
385                  // number of authorization failures before DA lockout is invoked
386                  *value = gp.maxTries;
387                  break;
388              case TPM_PT_LOCKOUT_INTERVAL:
389                  // number of seconds before the value reported by
390                  // TPM_PT_LOCKOUT_COUNTER is decremented
391                  *value = gp.recoveryTime;
392                  break;
393              case TPM_PT_LOCKOUT_RECOVERY:
394                  // number of seconds after a lockoutAuth failure before use of
395                  // lockoutAuth may be attempted again
396                  *value = gp.lockoutRecovery;
397                  break;
398              case TPM_PT_AUDIT_COUNTER_0:
399                  // high-order 32 bits of the command audit counter
400                  *value = (UINT32) (gp.auditCounter >> 32);
401                  break;
402              case TPM_PT_AUDIT_COUNTER_1:
403                  // low-order 32 bits of the command audit counter
404                  *value = (UINT32) (gp.auditCounter);
405                  break;
406              default:
407                  // property is not defined
408                  return FALSE;
409                  break;
410         }
411
412         return TRUE;
413   }


      9.14.3.2     TPMCapGetProperties()

      This function is used to get the TPM_PT values. The search of properties will start at property and
      continue until propertyList has as many values as will fit, or the last property has been reported, or the list
      has as many values as requested in count.

      Return Value                      Meaning

      YES                               more properties are available
      NO                                no more properties to be reported

414   TPMI_YES_NO
415   TPMCapGetProperties(
416         TPM_PT                              property,           // IN: the starting TPM property
417         UINT32                              count,              // IN: maximum number of returned
418                                                                 //     propertie
419         TPML_TAGGED_TPM_PROPERTY           *propertyList        // OUT: property list
420         )
421   {
422         TPMI_YES_NO        more = NO;
423         UINT32             i;
424
425         // initialize output property list
426         propertyList->count = 0;

      Page 264                                       TCG Published                                     Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library

427
428          // maximum count of properties we may return is MAX_PCR_PROPERTIES
429          if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES;
430
431          // If property is less than PT_FIXED, start from PT_FIXED.
432          if(property < PT_FIXED) property = PT_FIXED;
433
434          // Scan through the TPM properties of the requested group.
435          // The size of TPM property group is PT_GROUP * 2 for fix and
436          // variable groups.
437          for(i = property; i <= PT_FIXED + PT_GROUP * 2; i++)
438          {
439              UINT32          value;
440              if(TPMPropertyIsDefined((TPM_PT) i, &value))
441              {
442                  if(propertyList->count < count)
443                  {
444
445                        // If the list is not full, add this property
446                        propertyList->tpmProperty[propertyList->count].property =
447                            (TPM_PT) i;
448                        propertyList->tpmProperty[propertyList->count].value = value;
449                        propertyList->count++;
450                  }
451                  else
452                  {
453                      // If the return list is full but there are more properties
454                      // available, set the indication and exit the loop.
455                      more = YES;
456                      break;
457                  }
458              }
459          }
460          return more;
461   }


      9.15     TpmFail.c

      9.15.1    Includes, Defines, and Types

  1   #define        TPM_FAIL_C
  2   #include       "InternalRoutines.h"
  3   #include       <assert.h>

      On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of the
      TPM_Types.h include. This will avoid a lot of alignment warnings from the compiler for the unaligned
      structures. The alignment of the structures is not important as this function does not use any of the
      structures in TPM_Types.h and only include it for the #defines of the capabilities, properties, and
      command code values.

  4   #pragma pack(push, 1)
  5   #include "TPM_Types.h"
  6   #pragma pack (pop)
  7   #include "swap.h"


      9.15.2    Typedefs

      These defines are used primarily for sizing of the local response buffer.

  8   #pragma pack(push,1)
  9   typedef struct {

      Family "2.0"                                 TCG Published                                       Page 265
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                            Part 4: Supporting Routines

10       TPM_ST           tag;
11       UINT32           size;
12       TPM_RC           code;
13   } HEADER;
14   typedef struct {
15       UINT16       size;
16       struct {
17           UINT32       function;
18           UINT32       line;
19           UINT32       code;
20       } values;
21       TPM_RC       returnCode;
22   } GET_TEST_RESULT_PARAMETERS;
23   typedef struct {
24       TPMI_YES_NO                   moreData;
25       TPM_CAP                       capability; // Always TPM_CAP_TPM_PROPERTIES
26       TPML_TAGGED_TPM_PROPERTY      tpmProperty; // a single tagged property
27   } GET_CAPABILITY_PARAMETERS;
28   typedef struct {
29       HEADER header;
30       GET_TEST_RESULT_PARAMETERS getTestResult;
31   } TEST_RESPONSE;
32   typedef struct {
33       HEADER header;
34       GET_CAPABILITY_PARAMETERS     getCap;
35   } CAPABILITY_RESPONSE;
36   typedef union {
37       TEST_RESPONSE            test;
38       CAPABILITY_RESPONSE      cap;
39   } RESPONSES;
40   #pragma pack(pop)

     Buffer to hold the responses. This may be a little larger than required due to padding that a compiler
     might add.

     NOTE:           This is not in Global.c because of the specialized data definitions above. Since the data contained in this
                     structure is not relevant outside of the execution of a single command (when the TPM is in failure mode. There
                     is no compelling reason to move all the typedefs to Global.h and this structure to Global.c.

41   #ifndef __IGNORE_STATE__ // Don't define this value
42   static BYTE response[sizeof(RESPONSES)];
43   #endif


     9.15.3     Local Functions

     9.15.3.1    MarshalUint16()

     Function to marshal a 16 bit value to the output buffer.

44   static INT32
45   MarshalUint16(
46        UINT16               integer,
47        BYTE                 **buffer
48        )
49   {
50        return UINT16_Marshal(&integer, buffer, NULL);
51   }


     9.15.3.2    MarshalUint32()

     Function to marshal a 32 bit value to the output buffer.

     Page 266                                          TCG Published                                              Family "2.0"
     October 30, 2014                         Copyright © TCG 2006-2014                           Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library

52   static INT32
53   MarshalUint32(
54        UINT32               integer,
55        BYTE                **buffer
56        )
57   {
58        return UINT32_Marshal(&integer, buffer, NULL);
59   }


     9.15.3.3    UnmarshalHeader()

     Funtion to unmarshal the 10-byte command header.

60   static BOOL
61   UnmarshalHeader(
62        HEADER              *header,
63        BYTE                **buffer,
64        INT32               *size
65        )
66   {
67        UINT32 usize;
68        TPM_RC ucode;
69        if(     UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS
70            || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS
71            || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS
72            )
73            return FALSE;
74        header->size = usize;
75        header->code = ucode;
76        return TRUE;
77   }


     9.15.4     Public Functions

     9.15.4.1    SetForceFailureMode()

     This function is called by the simulator to enable failure mode testing.

78   LIB_EXPORT void
79   SetForceFailureMode(
80        void
81        )
82   {
83        g_forceFailureMode = TRUE;
84        return;
85   }


     9.15.4.2    TpmFail()

     This function is called by TPM.lib when a failure occurs. It will set up the failure values to be returned on
     TPM2_GetTestResult().

86   void
87   TpmFail(
88        const char                         *function,
89        int line,                 int       code
90        )
91   {
92        // Save the values that indicate where the error occurred.
93        // On a 64-bit machine, this may truncate the address of the string

     Family "2.0"                                  TCG Published                                       Page 267
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

 94        // of the function name where the error occurred.
 95        s_failFunction = *(UINT32*)&function;
 96        s_failLine = line;
 97        s_failCode = code;
 98
 99        // if asserts are enabled, then do an assert unless the failure mode code
100        // is being tested
101        assert(g_forceFailureMode);
102
103        // Clear this flag
104        g_forceFailureMode = FALSE;
105
106        // Jump to the failure mode code.
107        // Note: only get here if asserts are off or if we are testing failure mode
108        longjmp(&g_jumpBuffer[0], 1);
109   }


      9.15.5    TpmFailureMode

      This function is called by the interface code when the platform is in failure mode.

110   void
111   TpmFailureMode (
112        unsigned   int       inRequestSize,          //   IN: command buffer size
113        unsigned   char     *inRequest,              //   IN: command buffer
114        unsigned   int      *outResponseSize,        //   OUT: response buffer size
115        unsigned   char     **outResponse            //   OUT: response buffer
116        )
117   {
118        BYTE                *buffer;
119        UINT32               marshalSize;
120        UINT32               capability;
121        HEADER               header;     // unmarshaled command header
122        UINT32               pt;     // unmarshaled property type
123        UINT32               count; // unmarshaled property count
124
125        // If there is no command buffer, then just return TPM_RC_FAILURE
126        if(inRequestSize == 0 || inRequest == NULL)
127            goto FailureModeReturn;
128
129        // If the header is not correct for TPM2_GetCapability() or
130        // TPM2_GetTestResult() then just return the in failure mode response;
131        buffer = inRequest;
132        if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize))
133            goto FailureModeReturn;
134        if(   header.tag != TPM_ST_NO_SESSIONS
135           || header.size < 10)
136           goto FailureModeReturn;
137
138        switch (header.code) {
139        case TPM_CC_GetTestResult:
140
141             // make sure that the command size is correct
142             if(header.size != 10)
143                  goto FailureModeReturn;
144             buffer = &response[10];
145             marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer);
146             marshalSize += MarshalUint32(s_failFunction, &buffer);
147             marshalSize += MarshalUint32(s_failLine, &buffer);
148             marshalSize += MarshalUint32(s_failCode, &buffer);
149             if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
150                  marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer);
151             else
152                  marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);


      Page 268                                      TCG Published                                   Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                      Trusted Platform Module Library

153            break;
154
155       case TPM_CC_GetCapability:
156           // make sure that the size of the command is exactly the size
157           // returned for the capability, property, and count
158           if(     header.size!= (10 + (3 * sizeof(UINT32)))
159                   // also verify that this is requesting TPM properties
160               ||      (UINT32_Unmarshal(&capability, &inRequest,
161                                         (INT32 *)&inRequestSize)
162                   != TPM_RC_SUCCESS)
163               || (capability != TPM_CAP_TPM_PROPERTIES)
164               ||      (UINT32_Unmarshal(&pt, &inRequest, (INT32 *)&inRequestSize)
165                   != TPM_RC_SUCCESS)
166               ||      (UINT32_Unmarshal(&count, &inRequest, (INT32 *)&inRequestSize)
167                   != TPM_RC_SUCCESS)
168               )
169
170                  goto FailureModeReturn;
171
172            // If in failure mode because of an unrecoverable read error, and the
173            // property is 0 and the count is 0, then this is an indication to
174            // re-manufacture the TPM. Do the re-manufacture but stay in failure
175            // mode until the TPM is reset.
176            // Note: this behavior is not required by the specification and it is
177            // OK to leave the TPM permanently bricked due to an unrecoverable NV
178            // error.
179            if( count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
180            {
181                g_manufactured = FALSE;
182                TPM_Manufacture(0);
183            }
184
185            if(count > 0)
186                count = 1;
187            else if(pt > TPM_PT_FIRMWARE_VERSION_2)
188                count = 0;
189            if(pt < TPM_PT_MANUFACTURER)
190                pt = TPM_PT_MANUFACTURER;
191
192            // set up for return
193            buffer = &response[10];
194            // if the request was for a PT less than the last one
195            // then we indicate more, otherwise, not.
196            if(pt < TPM_PT_FIRMWARE_VERSION_2)
197                 *buffer++ = YES;
198            else
199                 *buffer++ = NO;
200
201            marshalSize = 1;
202
203            // indicate     the capability type
204            marshalSize     += MarshalUint32(capability, &buffer);
205            // indicate     the number of values that are being returned (0 or 1)
206            marshalSize     += MarshalUint32(count, &buffer);
207            // indicate     the property
208            marshalSize     += MarshalUint32(pt, &buffer);
209
210            if(count > 0)
211                switch (pt) {
212                case TPM_PT_MANUFACTURER:
213                // the vendor ID unique to each TPM manufacturer
214   #ifdef   MANUFACTURER
215                pt = *(UINT32*)MANUFACTURER;
216   #else
217                  pt = 0;
218   #endif

      Family "2.0"                             TCG Published                                Page 269
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                 Part 4: Supporting Routines

219                break;
220            case TPM_PT_VENDOR_STRING_1:
221                // the first four characters of the vendor ID string
222   #ifdef   VENDOR_STRING_1
223                pt = *(UINT32*)VENDOR_STRING_1;
224   #else
225                 pt = 0;
226   #endif
227                break;
228            case TPM_PT_VENDOR_STRING_2:
229                // the second four characters of the vendor ID string
230   #ifdef   VENDOR_STRING_2
231                pt = *(UINT32*)VENDOR_STRING_2;
232   #else
233                 pt = 0;
234   #endif
235                break;
236            case TPM_PT_VENDOR_STRING_3:
237                // the third four characters of the vendor ID string
238   #ifdef   VENDOR_STRING_3
239                pt = *(UINT32*)VENDOR_STRING_3;
240   #else
241                 pt = 0;
242   #endif
243                break;
244            case TPM_PT_VENDOR_STRING_4:
245                // the fourth four characters of the vendor ID string
246   #ifdef   VENDOR_STRING_4
247                pt = *(UINT32*)VENDOR_STRING_4;
248   #else
249                 pt = 0;
250   #endif
251
252                break;
253            case TPM_PT_VENDOR_TPM_TYPE:
254                // vendor-defined value indicating the TPM model
255                // We just make up a number here
256                pt = 1;
257                break;
258            case TPM_PT_FIRMWARE_VERSION_1:
259                // the more significant 32-bits of a vendor-specific value
260                // indicating the version of the firmware
261   #ifdef   FIRMWARE_V1
262                pt = FIRMWARE_V1;
263   #else
264                 pt = 0;
265   #endif
266                break;
267            default: // TPM_PT_FIRMWARE_VERSION_2:
268                // the less significant 32-bits of a vendor-specific value
269                // indicating the version of the firmware
270   #ifdef   FIRMWARE_V2
271                pt = FIRMWARE_V2;
272   #else
273                 pt = 0;
274   #endif
275               break;
276           }
277           marshalSize += MarshalUint32(pt, &buffer);
278           break;
279       default: // default for switch (cc)
280           goto FailureModeReturn;
281       }
282       // Now do the header
283       buffer = response;
284       marshalSize = marshalSize + 10; // Add the header size to the

      Page 270                               TCG Published                            Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014          Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

285                                       // stuff already marshaled
286       MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag
287       MarshalUint32(marshalSize, &buffer); // responseSize
288       MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code
289
290       *outResponseSize = marshalSize;
291       *outResponse = (unsigned char *)&response;
292       return;
293
294   FailureModeReturn:
295
296       buffer = response;
297
298       marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer);
299       marshalSize += MarshalUint32(10, &buffer);
300       marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);
301
302       *outResponseSize = marshalSize;
303       *outResponse = (unsigned char *)response;
304       return;
305   }




      Family "2.0"                        TCG Published                                Page 271
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                                Part 4: Supporting Routines


     10 Cryptographic Functions

     10.1     Introduction

     The files in this section provide cryptographic support for the other functions in the TPM and the interface
     to the Crypto Engine.

     10.2     CryptUtil.c

     10.2.1     Includes

 1   #include        "TPM_Types.h"
 2   #include        "CryptoEngine.h"        // types shared by CryptUtil and CryptoEngine.
 3                                           // Includes the function prototypes for the
 4                                           // CryptoEngine functions.
 5   #include        "Global.h"
 6   #include        "InternalRoutines.h"
 7   #include        "MemoryLib_fp.h"
 8   //#include        "CryptSelfTest_fp.h"


     10.2.2     TranslateCryptErrors()

     This function converts errors from the cryptographic library into TPM_RC_VALUES.

     Error Returns                     Meaning

     TPM_RC_VALUE                      CRYPT_FAIL
     TPM_RC_NO_RESULT                  CRYPT_NO_RESULT
     TPM_RC_SCHEME                     CRYPT_SCHEME
     TPM_RC_VALUE                      CRYPT_PARAMETER
     TPM_RC_SIZE                       CRYPT_UNDERFLOW
     TPM_RC_ECC_POINT                  CRYPT_POINT
     TPM_RC_CANCELLED                  CRYPT_CANCEL

 9   static TPM_RC
10   TranslateCryptErrors (
11          CRYPT_RESULT            retVal                 // IN: crypt error to evaluate
12   )
13   {
14          switch (retVal)
15          {
16          case CRYPT_SUCCESS:
17              return TPM_RC_SUCCESS;
18          case CRYPT_FAIL:
19              return TPM_RC_VALUE;
20          case CRYPT_NO_RESULT:
21              return TPM_RC_NO_RESULT;
22          case CRYPT_SCHEME:
23              return TPM_RC_SCHEME;
24          case CRYPT_PARAMETER:
25              return TPM_RC_VALUE;
26          case CRYPT_UNDERFLOW:
27              return TPM_RC_SIZE;
28          case CRYPT_POINT:
29              return TPM_RC_ECC_POINT;
30          case CRYPT_CANCEL:

     Page 272                                     TCG Published                                    Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                           Trusted Platform Module Library

31           return TPM_RC_CANCELED;
32       default: // Other unknown warnings
33           return TPM_RC_FAILURE;
34       }
35   }


     10.2.3     Random Number Generation Functions

36   #ifdef TPM_ALG_NULL //%
37   #ifdef _DRBG_STATE_SAVE //%


     10.2.3.1    CryptDrbgGetPutState()

     Read or write the current state from the DRBG in the cryptoEngine.

38   void
39   CryptDrbgGetPutState(
40       GET_PUT              direction         // IN: Get from or put to DRBG
41       )
42   {
43       _cpri__DrbgGetPutState(direction,
44                              sizeof(go.drbgState),
45                              (BYTE *)&go.drbgState);
46   }
47   #else   //% 00
48   //%#define CryptDrbgGetPutState(ignored)            // If not doing state save, turn this
49   //%                                                  // into a null macro
50   #endif //%


     10.2.3.2    CryptStirRandom()

     Stir random entropy

51   void
52   CryptStirRandom(
53       UINT32               entropySize,      // IN: size of entropy buffer
54       BYTE                *buffer            // IN: entropy buffer
55       )
56   {
57       // RNG self testing code may be inserted here
58
59       // Call crypto engine random number stirring function
60       _cpri__StirRandom(entropySize, buffer);
61
62       return;
63   }


     10.2.3.3    CryptGenerateRandom()

     This is the interface to _cpri__GenerateRandom().

64   UINT16
65   CryptGenerateRandom(
66       UINT16               randomSize,       // IN: size of random number
67       BYTE                *buffer            // OUT: buffer of random number
68       )
69   {
70       UINT16               result;
71       pAssert(randomSize <= MAX_RSA_KEY_BYTES || randomSize <= PRIMARY_SEED_SIZE);
72       if(randomSize == 0)

     Family "2.0"                               TCG Published                                   Page 273
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

 73              return 0;
 74
 75        // Call crypto engine random number generation
 76        result = _cpri__GenerateRandom(randomSize, buffer);
 77        if(result != randomSize)
 78            FAIL(FATAL_ERROR_INTERNAL);
 79
 80       return result;
 81   }
 82   #endif //TPM_ALG_NULL //%


      10.2.4     Hash/HMAC Functions

      10.2.4.1    CryptGetContextAlg()

      This function returns the hash algorithm associated with a hash context.

 83   #ifdef TPM_ALG_KEYEDHASH                 //% 1
 84   TPM_ALG_ID
 85   CryptGetContextAlg(
 86        void                *state                // IN: the context to check
 87        )
 88   {
 89        HASH_STATE *context = (HASH_STATE *)state;
 90        return _cpri__GetContextAlg(&context->state);
 91   }


      10.2.4.2    CryptStartHash()

      This function starts a hash and return the size, in bytes, of the digest.

      Return Value                      Meaning

      >0                                the digest size of the algorithm
      =0                                the hashAlg was TPM_ALG_NULL

 92   UINT16
 93   CryptStartHash(
 94        TPMI_ALG_HASH        hashAlg,             // IN: hash algorithm
 95        HASH_STATE          *hashState            // OUT: the state of hash stack. It will be used
 96                                                  //     in hash update and completion
 97        )
 98   {
 99        CRYPT_RESULT            retVal = 0;
100
101        pAssert(hashState != NULL);
102
103        TEST_HASH(hashAlg);
104
105        hashState->type = HASH_STATE_EMPTY;
106
107        // Call crypto engine start hash function
108        if((retVal = _cpri__StartHash(hashAlg, FALSE, &hashState->state)) > 0)
109            hashState->type = HASH_STATE_HASH;
110
111        return retVal;
112   }




      Page 274                                        TCG Published                              Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library

      10.2.4.3    CryptStartHashSequence()

      Start a hash stack for a sequence object and return the size, in bytes, of the digest. This call uses the
      form of the hash state that requires context save and restored.

      Return Value                    Meaning

      >0                              the digest size of the algorithm
      =0                              the hashAlg was TPM_ALG_NULL

113   UINT16
114   CryptStartHashSequence(
115        TPMI_ALG_HASH       hashAlg,            // IN: hash algorithm
116        HASH_STATE         *hashState           // OUT: the state of hash stack. It will be used
117                                                //     in hash update and completion
118        )
119   {
120        CRYPT_RESULT      retVal = 0;
121
122        pAssert(hashState != NULL);
123
124        TEST_HASH(hashAlg);
125
126        hashState->type = HASH_STATE_EMPTY;
127
128        // Call crypto engine start hash function
129        if((retVal = _cpri__StartHash(hashAlg, TRUE, &hashState->state)) > 0)
130            hashState->type = HASH_STATE_HASH;
131
132        return retVal;
133
134   }


      10.2.4.4    CryptStartHMAC()

      This function starts an HMAC sequence and returns the size of the digest that will be produced.
      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
      not alter the contents of this buffer until the hash sequence is completed or abandoned.

      Return Value                    Meaning

      >0                              the digest size of the algorithm
      =0                              the hashAlg was TPM_ALG_NULL

135   UINT16
136   CryptStartHMAC(
137        TPMI_ALG_HASH       hashAlg,            //   IN: hash algorithm
138        UINT16              keySize,            //   IN: the size of HMAC key in byte
139        BYTE               *key,                //   IN: HMAC key
140        HMAC_STATE         *hmacState           //   OUT: the state of HMAC stack. It will be used
141                                                //       in HMAC update and completion
142        )
143   {
144        HASH_STATE         *hashState = (HASH_STATE *)hmacState;
145        CRYPT_RESULT       retVal;
146
147        // This has to come before the pAssert in case we             all calling this function
148        // during testing. If so, the first instance will             have no arguments but the
149        // hash algorithm. The call from the test routine             will have arguments. When
150        // the second call is done, then we return to the             test dispatcher.
151        TEST_HASH(hashAlg);

      Family "2.0"                                 TCG Published                                        Page 275
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                        October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

152
153        pAssert(hashState != NULL);
154
155        hashState->type = HASH_STATE_EMPTY;
156
157        if((retVal =    _cpri__StartHMAC(hashAlg, FALSE, &hashState->state, keySize, key,
158                                         &hmacState->hmacKey.b)) > 0)
159              hashState->type = HASH_STATE_HMAC;
160
161        return retVal;
162   }


      10.2.4.5    CryptStartHMACSequence()

      This function starts an HMAC sequence and returns the size of the digest that will be produced.
      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
      not alter the contents of this buffer until the hash sequence is completed or abandoned.
      This call is used to start a sequence HMAC that spans multiple TPM commands.

      Return Value                      Meaning

      >0                                the digest size of the algorithm
      =0                                the hashAlg was TPM_ALG_NULL

163   UINT16
164   CryptStartHMACSequence(
165        TPMI_ALG_HASH       hashAlg,              //   IN: hash algorithm
166        UINT16              keySize,              //   IN: the size of HMAC key in byte
167        BYTE               *key,                  //   IN: HMAC key
168        HMAC_STATE         *hmacState             //   OUT: the state of HMAC stack. It will be used
169                                                  //       in HMAC update and completion
170        )
171   {
172        HASH_STATE         *hashState = (HASH_STATE *)hmacState;
173        CRYPT_RESULT       retVal;
174
175        TEST_HASH(hashAlg);
176
177        hashState->type = HASH_STATE_EMPTY;
178
179        if((retVal =    _cpri__StartHMAC(hashAlg, TRUE, &hashState->state,
180                                         keySize, key, &hmacState->hmacKey.b)) > 0)
181              hashState->type = HASH_STATE_HMAC;
182
183        return retVal;
184   }


      10.2.4.6    CryptStartHMAC2B()

      This function starts an HMAC and returns the size of the digest that will be produced.
      This function is provided to support the most common use of starting an HMAC with a TPM2B key.
      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
      not alter the contents of this buffer until the hash sequence is completed or abandoned.




      Page 276                                        TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library


      Return Value                    Meaning

      >0                              the digest size of the algorithm
      =0                              the hashAlg was TPM_ALG_NULL

185   LIB_EXPORT UINT16
186   CryptStartHMAC2B(
187        TPMI_ALG_HASH       hashAlg,            // IN: hash algorithm
188        TPM2B              *key,                // IN: HMAC key
189        HMAC_STATE         *hmacState           // OUT: the state of HMAC stack. It will be used
190                                                //     in HMAC update and completion
191        )
192   {
193        return CryptStartHMAC(hashAlg, key->size, key->buffer, hmacState);
194   }


      10.2.4.7    CryptStartHMACSequence2B()

      This function starts an HMAC sequence and returns the size of the digest that will be produced.
      This function is provided to support the most common use of starting an HMAC with a TPM2B key.
      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
      not alter the contents of this buffer until the hash sequence is completed or abandoned.

      Return Value                    Meaning

      >0                              the digest size of the algorithm
      =0                              the hashAlg was TPM_ALG_NULL

195   UINT16
196   CryptStartHMACSequence2B(
197        TPMI_ALG_HASH       hashAlg,            // IN: hash algorithm
198        TPM2B              *key,                // IN: HMAC key
199        HMAC_STATE         *hmacState           // OUT: the state of HMAC stack. It will be used
200                                                //     in HMAC update and completion
201        )
202   {
203        return CryptStartHMACSequence(hashAlg, key->size, key->buffer, hmacState);
204   }


      10.2.4.8    CryptUpdateDigest()

      This function updates a digest (hash or HMAC) with an array of octets.
      This function can be used for both HMAC and hash functions so the digestState is void so that either
      state type can be passed.

205   LIB_EXPORT void
206   CryptUpdateDigest(
207        void               *digestState,        // IN: the state of hash stack
208        UINT32              dataSize,           // IN: the size of data
209        BYTE               *data                // IN: data to be hashed
210        )
211   {
212        HASH_STATE         *hashState = (HASH_STATE *)digestState;
213
214        pAssert(digestState != NULL);
215
216        if(hashState->type != HASH_STATE_EMPTY && data != NULL && dataSize != 0)
217        {

      Family "2.0"                                 TCG Published                                        Page 277
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                        October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

218              // Call crypto engine update hash function
219              _cpri__UpdateHash(&hashState->state, dataSize, data);
220        }
221        return;
222   }


      10.2.4.9     CryptUpdateDigest2B()

      This function updates a digest (hash or HMAC) with a TPM2B.
      This function can be used for both HMAC and hash functions so the digestState is void so that either
      state type can be passed.

223   LIB_EXPORT void
224   CryptUpdateDigest2B(
225        void                *digestState,       // IN: the digest state
226        TPM2B               *bIn                // IN: 2B containing the data
227        )
228   {
229        // Only compute the digest if a pointer to the 2B is provided.
230        // In CryptUpdateDigest(), if size is zero or buffer is NULL, then no change
231        // to the digest occurs. This function should not provide a buffer if bIn is
232        // not provided.
233        if(bIn != NULL)
234            CryptUpdateDigest(digestState, bIn->size, bIn->buffer);
235        return;
236   }


      10.2.4.10 CryptUpdateDigestInt()

      This function is used to include an integer value to a hash stack. The function marshals the integer into its
      canonical form before calling CryptUpdateHash().

237   LIB_EXPORT void
238   CryptUpdateDigestInt(
239        void                *state,             // IN: the state of hash stack
240        UINT32               intSize,           // IN: the size of 'intValue' in byte
241        void                *intValue           // IN: integer value to be hashed
242        )
243   {
244
245   #if BIG_ENDIAN_TPM == YES
246       pAssert(    intValue != NULL && (intSize == 1 || intSize == 2
247               || intSize == 4 || intSize == 8));
248       CryptUpdateHash(state, inSize, (BYTE *)intValue);
249   #else
250
251        BYTE        marshalBuffer[8];
252        // Point to the big end of an little-endian value
253        BYTE        *p = &((BYTE *)intValue)[intSize - 1];
254        // Point to the big end of an big-endian value
255        BYTE        *q = marshalBuffer;
256
257        pAssert(intValue != NULL);
258        switch (intSize)
259        {
260        case 8:
261            *q++ = *p--;
262            *q++ = *p--;
263            *q++ = *p--;
264            *q++ = *p--;
265        case 4:
266            *q++ = *p--;

      Page 278                                      TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

267             *q++ = *p--;
268         case 2:
269             *q++ = *p--;
270         case 1:
271             *q = *p;
272             // Call update the hash
273             CryptUpdateDigest(state, intSize, marshalBuffer);
274             break;
275         default:
276             FAIL(0);
277         }
278
279   #endif
280       return;
281   }


      10.2.4.11 CryptCompleteHash()

      This function completes a hash sequence and returns the digest.
      This function can be called to complete either an HMAC or hash sequence. The state type determines if
      the context type is a hash or HMAC. If an HMAC, then the call is forwarded to CryptCompleteHash().
      If digestSize is smaller than the digest size of hash/HMAC algorithm, the most significant bytes of
      required size will be returned

      Return Value                     Meaning

      >=0                              the number of bytes placed in digest

282   LIB_EXPORT UINT16
283   CryptCompleteHash(
284         void               *state,             // IN: the state of hash stack
285         UINT16              digestSize,        // IN: size of digest buffer
286         BYTE               *digest             // OUT: hash digest
287         )
288   {
289         HASH_STATE         *hashState = (HASH_STATE *)state;              // local value
290
291         // If the session type is HMAC, then could forward this to
292         // the HMAC processing and not cause an error. However, if no
293         // function calls this routine to forward it, then we can't get
294         // test coverage. The decision is to assert if this is called with
295         // the type == HMAC and fix anything that makes the wrong call.
296         pAssert(hashState->type == HASH_STATE_HASH);
297
298         // Set the state to empty so that it doesn't get used again
299         hashState->type = HASH_STATE_EMPTY;
300
301         // Call crypto engine complete hash function
302         return     _cpri__CompleteHash(&hashState->state, digestSize, digest);
303   }


      10.2.4.12 CryptCompleteHash2B()

      This function is the same as CypteCompleteHash() but the digest is placed in a TPM2B. This is the most
      common use and this is provided for specification clarity. 'digest.size' should be set to indicate the number
      of bytes to place in the buffer




      Family "2.0"                                 TCG Published                                        Page 279
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                   Part 4: Supporting Routines


      Return Value                      Meaning

      >=0                               the number of bytes placed in 'digest.buffer'

304   LIB_EXPORT UINT16
305   CryptCompleteHash2B(
306         void               *state,               // IN: the state of hash stack
307         TPM2B              *digest               // IN: the size of the buffer Out: requested
308                                                  //     number of byte
309         )
310   {
311         UINT16                  retVal = 0;
312
313         if(digest != NULL)
314             retVal = CryptCompleteHash(state, digest->size, digest->buffer);
315
316         return retVal;
317   }


      10.2.4.13 CryptHashBlock()

      Hash a block of data and return the results. If the digest is larger than retSize, it is truncated and with the
      least significant octets dropped.

      Return Value                      Meaning

      >=0                               the number of bytes placed in ret

318   LIB_EXPORT UINT16
319   CryptHashBlock(
320         TPM_ALG_ID          algId,               //   IN: the hash algorithm to use
321         UINT16              blockSize,           //   IN: size of the data block
322         BYTE               *block,               //   IN: address of the block to hash
323         UINT16              retSize,             //   IN: size of the return buffer
324         BYTE               *ret                  //   OUT: address of the buffer
325         )
326   {
327         TEST_HASH(algId);
328
329         return _cpri__HashBlock(algId, blockSize, block, retSize, ret);
330   }


      10.2.4.14 CryptCompleteHMAC()

      This function completes a HMAC sequence and returns the digest. If digestSize is smaller than the digest
      size of the HMAC algorithm, the most significant bytes of required size will be returned.

      Return Value                      Meaning

      >=0                               the number of bytes placed in digest

331   LIB_EXPORT UINT16
332   CryptCompleteHMAC(
333         HMAC_STATE         *hmacState,           // IN: the state of HMAC stack
334         UINT32              digestSize,          // IN: size of digest buffer
335         BYTE               *digest               // OUT: HMAC digest
336         )
337   {
338         HASH_STATE         *hashState;
339
340         pAssert(hmacState != NULL);

      Page 280                                       TCG Published                                     Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

341         hashState = &hmacState->hashState;
342
343         pAssert(hashState->type == HASH_STATE_HMAC);
344
345         hashState->type = HASH_STATE_EMPTY;
346
347         return _cpri__CompleteHMAC(&hashState->state, &hmacState->hmacKey.b,
348                                    digestSize, digest);
349
350   }


      10.2.4.15 CryptCompleteHMAC2B()

      This function is the same as CryptCompleteHMAC() but the HMAC result is returned in a TPM2B which is
      the most common use.

      Return Value                     Meaning

      >=0                              the number of bytes placed in digest

351   LIB_EXPORT UINT16
352   CryptCompleteHMAC2B(
353         HMAC_STATE         *hmacState,           // IN: the state of HMAC stack
354         TPM2B              *digest               // OUT: HMAC
355         )
356   {
357         UINT16               retVal = 0;
358         if(digest != NULL)
359             retVal = CryptCompleteHMAC(hmacState, digest->size, digest->buffer);
360         return retVal;
361   }


      10.2.4.16 CryptHashStateImportExport()

      This function is used to prepare a hash state context for LIB_EXPORT or to import it into the internal
      format. It is used by TPM2_ContextSave() and TPM2_ContextLoad() via SequenceDataImportExport().
      This is just a pass-through function to the crypto library.

362   void
363   CryptHashStateImportExport(
364         HASH_STATE         *internalFmt,         // IN: state to LIB_EXPORT
365         HASH_STATE         *externalFmt,         // OUT: exported state
366         IMPORT_EXPORT       direction
367         )
368   {
369         _cpri__ImportExportHashState(&internalFmt->state,
370                                      (EXPORT_HASH_STATE *)&externalFmt->state,
371                                      direction);
372   }


      10.2.4.17 CryptGetHashDigestSize()

      This function returns the digest size in bytes for a hash algorithm.

      Return Value                     Meaning

      0                                digest size for TPM_ALG_NULL
      >0                               digest size

373   LIB_EXPORT UINT16

      Family "2.0"                                   TCG Published                                 Page 281
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                     October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

374   CryptGetHashDigestSize(
375        TPM_ALG_ID           hashAlg              // IN: hash algorithm
376        )
377   {
378        return _cpri__GetDigestSize(hashAlg);
379   }


      10.2.4.18 CryptGetHashBlockSize()

      Get the digest size in byte of a hash algorithm.

      Return Value                      Meaning

      0                                 block size for TPM_ALG_NULL
      >0                                block size

380   LIB_EXPORT UINT16
381   CryptGetHashBlockSize(
382        TPM_ALG_ID           hash                 // IN: hash algorithm to look up
383        )
384   {
385        return _cpri__GetHashBlockSize(hash);
386   }


      10.2.4.19 CryptGetHashAlgByIndex()

      This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are
      not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first
      implemented hash and an index value of 2 will return the last implemented hash. All other index values
      will return TPM_ALG_NULL.

      Return Value                      Meaning

      TPM_ALG_xxx()                     a hash algorithm
      TPM_ALG_NULL                      this can be used as a stop value

387   LIB_EXPORT TPM_ALG_ID
388   CryptGetHashAlgByIndex(
389        UINT32               index                // IN: the index
390        )
391   {
392        return _cpri__GetHashAlgByIndex(index);
393   }


      10.2.4.20 CryptSignHMAC()

      Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message.

      Error Returns                     Meaning

394   static TPM_RC
395   CryptSignHMAC(
396        OBJECT                   *signKey,              //   IN: HMAC key sign the hash
397        TPMT_SIG_SCHEME          *scheme,               //   IN: signing scheme
398        TPM2B_DIGEST             *hashData,             //   IN: hash to be signed
399        TPMT_SIGNATURE           *signature             //   OUT: signature
400        )
401   {


      Page 282                                       TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library

402       HMAC_STATE           hmacState;
403       UINT32               digestSize;
404
405       // HMAC algorithm self testing code may be inserted here
406
407       digestSize = CryptStartHMAC2B(scheme->details.hmac.hashAlg,
408                                     &signKey->sensitive.sensitive.bits.b,
409                                     &hmacState);
410
411       // The hash algorithm must be a valid one.
412       pAssert(digestSize > 0);
413
414       CryptUpdateDigest2B(&hmacState, &hashData->b);
415
416       CryptCompleteHMAC(&hmacState, digestSize,
417                         (BYTE *) &signature->signature.hmac.digest);
418
419       // Set HMAC algorithm
420       signature->signature.hmac.hashAlg = scheme->details.hmac.hashAlg;
421
422       return TPM_RC_SUCCESS;
423   }


      10.2.4.21 CryptHMACVerifySignature()

      This function will verify a signature signed by a HMAC key.

      Error Returns                   Meaning

      TPM_RC_SIGNATURE                if invalid input or signature is not genuine

424   static TPM_RC
425   CryptHMACVerifySignature(
426       OBJECT              *signKey,            // IN: HMAC key signed the hash
427       TPM2B_DIGEST        *hashData,           // IN: digest being verified
428       TPMT_SIGNATURE      *signature           // IN: signature to be verified
429       )
430   {
431       HMAC_STATE                hmacState;
432       TPM2B_DIGEST              digestToCompare;
433
434       digestToCompare.t.size = CryptStartHMAC2B(signature->signature.hmac.hashAlg,
435                                &signKey->sensitive.sensitive.bits.b, &hmacState);
436
437       CryptUpdateDigest2B(&hmacState, &hashData->b);
438
439       CryptCompleteHMAC2B(&hmacState, &digestToCompare.b);
440
441       // Compare digest
442       if(MemoryEqual(digestToCompare.t.buffer,
443                      (BYTE *) &signature->signature.hmac.digest,
444                      digestToCompare.t.size))
445           return TPM_RC_SUCCESS;
446       else
447           return TPM_RC_SIGNATURE;
448
449   }


      10.2.4.22 CryptGenerateKeyedHash()

      This function creates a keyedHash object.



      Family "2.0"                                 TCG Published                                          Page 283
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                                      Part 4: Supporting Routines


      Error Returns                     Meaning

      TPM_RC_SIZE                       sensitive data size is larger than allowed for the scheme

450   static TPM_RC
451   CryptGenerateKeyedHash(
452       TPMT_PUBLIC                    *publicArea,                //   IN/OUT: the public area template
453                                                                  //       for the new key.
454       TPMS_SENSITIVE_CREATE          *sensitiveCreate,           //   IN: sensitive creation data
455       TPMT_SENSITIVE                 *sensitive,                 //   OUT: sensitive area
456       TPM_ALG_ID                      kdfHashAlg,                //   IN: algorithm for the KDF
457       TPM2B_SEED                     *seed,                      //   IN: the seed
458       TPM2B_NAME                     *name                       //   IN: name of the object
459       )
460   {
461       TPMT_KEYEDHASH_SCHEME          *scheme;
462       TPM_ALG_ID                      hashAlg;
463       UINT16                          hashBlockSize;
464
465       scheme = &publicArea->parameters.keyedHashDetail.scheme;
466
467       pAssert(publicArea->type == TPM_ALG_KEYEDHASH);
468
469       // Pick the limiting hash algorithm
470       if(scheme->scheme == TPM_ALG_NULL)
471           hashAlg = publicArea->nameAlg;
472       else if(scheme->scheme == TPM_ALG_XOR)
473           hashAlg = scheme->details.xor.hashAlg;
474       else
475           hashAlg = scheme->details.hmac.hashAlg;
476       hashBlockSize = CryptGetHashBlockSize(hashAlg);
477
478       // if this is a signing or a decryption key, then then the limit
479       // for the data size is the block size of the hash. This limit
480       // is set because larger values have lower entropy because of the
481       // HMAC function.
482       if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)
483       {
484           if(    (    publicArea->objectAttributes.decrypt
485                    || publicArea->objectAttributes.sign)
486               && sensitiveCreate->data.t.size > hashBlockSize)
487
488               return TPM_RC_SIZE;
489       }
490       else
491       {
492           // If the TPM is going to generate the data, then set the size to be the
493           // size of the digest of the algorithm
494           sensitive->sensitive.sym.t.size = CryptGetHashDigestSize(hashAlg);
495           sensitiveCreate->data.t.size = 0;
496       }
497
498       // Fill in the sensitive area
499       CryptGenerateNewSymmetric(sensitiveCreate, sensitive, kdfHashAlg,
500                                 seed, name);
501
502       // Create unique area in public
503       CryptComputeSymmetricUnique(publicArea->nameAlg,
504                                   sensitive, &publicArea->unique.sym);
505
506       return TPM_RC_SUCCESS;
507   }




      Page 284                                       TCG Published                                       Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      10.2.4.23 CryptKDFa()

      This function generates a key using the KDFa() formulation in Part 1 of the TPM specification. In this
      implementation, this is a macro invocation of _cpri__KDFa() in the hash module of the CryptoEngine().
      This macro sets once to FALSE so that KDFa() will iterate as many times as necessary to generate
      sizeInBits number of bits.

508   //%#define CryptKDFa(hashAlg, key, label, contextU, contextV,                  \
509   //%                  sizeInBits, keyStream, counterInOut)                      \
510   //%         TEST_HASH(hashAlg);                                                \
511   //%        _cpri__KDFa(                                                        \
512   //%                       ((TPM_ALG_ID)hashAlg),                               \
513   //%                       ((TPM2B *)key),                                      \
514   //%                       ((const char *)label),                               \
515   //%                       ((TPM2B *)contextU),                                 \
516   //%                       ((TPM2B *)contextV),                                 \
517   //%                       ((UINT32)sizeInBits),                                \
518   //%                       ((BYTE *)keyStream),                                 \
519   //%                       ((UINT32 *)counterInOut),                            \
520   //%                       ((BOOL) FALSE)                                       \
521   //%                     )
522   //%


      10.2.4.24 CryptKDFaOnce()

      This function generates a key using the KDFa() formulation in Part 1 of the TPM specification. In this
      implementation, this is a macro invocation of _cpri__KDFa() in the hash module of the CryptoEngine().
      This macro will call _cpri__KDFa() with once TRUE so that only one iteration is performed, regardless of
      sizeInBits.

523   //%#define CryptKDFaOnce(hashAlg, key, label, contextU, contextV,                   \
524   //%                        sizeInBits, keyStream, counterInOut)                     \
525   //%         TEST_HASH(hashAlg);                                                     \
526   //%        _cpri__KDFa(                                                             \
527   //%                       ((TPM_ALG_ID)hashAlg),                                    \
528   //%                       ((TPM2B *)key),                                           \
529   //%                       ((const char *)label),                                    \
530   //%                       ((TPM2B *)contextU),                                      \
531   //%                       ((TPM2B *)contextV),                                      \
532   //%                       ((UINT32)sizeInBits),                                     \
533   //%                      ((BYTE *)keyStream),                                       \
534   //%                       ((UINT32 *)counterInOut),                                 \
535   //%                       ((BOOL) TRUE)                                             \
536   //%                     )
537   //%


      10.2.4.25 KDFa()

      This function is used by functions outside of CryptUtil() to access _cpri_KDFa().

538   void
539   KDFa(
540       TPM_ALG_ID           hash,              //   IN: hash algorithm used in HMAC
541       TPM2B               *key,               //   IN: HMAC key
542       const char          *label,             //   IN: a null-terminated label for KDF
543       TPM2B               *contextU,          //   IN: context U
544       TPM2B               *contextV,          //   IN: context V
545       UINT32               sizeInBits,        //   IN: size of generated key in bit
546       BYTE                *keyStream,         //   OUT: key buffer
547       UINT32              *counterInOut       //   IN/OUT: caller may provide the iteration
548                                               //       counter for incremental operations to

      Family "2.0"                                 TCG Published                                      Page 285
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

549                                               //       avoid large intermediate buffers.
550       )
551   {
552       CryptKDFa(hash, key, label, contextU, contextV, sizeInBits,
553                 keyStream, counterInOut);
554   }


      10.2.4.26 CryptKDFe()

      This function generates a key using the KDFa() formulation in Part 1 of the TPM specification. In this
      implementation, this is a macro invocation of _cpri__KDFe() in the hash module of the CryptoEngine().

555   //%#define CryptKDFe(hashAlg, Z, label, partyUInfo, partyVInfo,                         \
556   //%                   sizeInBits, keyStream)                                            \
557   //% TEST_HASH(hashAlg);                                                                 \
558   //% _cpri__KDFe(                                                                        \
559   //%              ((TPM_ALG_ID)hashAlg),                                                 \
560   //%              ((TPM2B *)Z),                                                          \
561   //%             ((const char *)label),                                                  \
562   //%              ((TPM2B *)partyUInfo),                                                 \
563   //%              ((TPM2B *)partyVInfo),                                                 \
564   //%              ((UINT32)sizeInBits),                                                  \
565   //%              ((BYTE *)keyStream)                                                    \
566   //%              )
567   //%
568   #endif //TPM_ALG_KEYEDHASH     //% 1


      10.2.5     RSA Functions

      10.2.5.1    BuildRSA()

      Function to set the cryptographic elements of an RSA key into a structure to simplify the interface to
      _cpri__ RSA function. This can/should be eliminated by building this structure into the object structure.

569   #ifdef TPM_ALG_RSA                 //% 2
570   static void
571   BuildRSA(
572       OBJECT              *rsaKey,
573       RSA_KEY             *key
574       )
575   {
576       key->exponent = rsaKey->publicArea.parameters.rsaDetail.exponent;
577       if(key->exponent == 0)
578           key->exponent = RSA_DEFAULT_PUBLIC_EXPONENT;
579       key->publicKey = &rsaKey->publicArea.unique.rsa.b;
580
581       if(rsaKey->attributes.publicOnly || rsaKey->privateExponent.t.size == 0)
582           key->privateKey = NULL;
583       else
584           key->privateKey = &(rsaKey->privateExponent.b);
585   }


      10.2.5.2    CryptTestKeyRSA()

      This function provides the interface to _cpri__TestKeyRSA(). If both p and q are provided, n will be set to
      p*q.
      If only p is provided, q is computed by q = n/p. If n mod p != 0, TPM_RC_BINDING is returned.
      The key is validated by checking that a d can be found such that e d mod ((p-1)*(q-1)) = 1. If d is found
      that satisfies this requirement, it will be placed in d.
      Page 286                                     TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library


      Error Returns                   Meaning

      TPM_RC_BINDING                  the public and private portions of the key are not matched

586   TPM_RC
587   CryptTestKeyRSA(
588       TPM2B              *d,                   //   OUT: receives the private exponent
589       UINT32              e,                   //   IN: public exponent
590       TPM2B              *n,                   //   IN/OUT: public modulu
591       TPM2B              *p,                   //   IN: a first prime
592       TPM2B              *q                    //   IN: an optional second prime
593       )
594   {
595       CRYPT_RESULT       retVal;
596
597       TEST(ALG_NULL_VALUE);
598
599       pAssert(d != NULL && n != NULL && p != NULL);
600       // Set the exponent
601       if(e == 0)
602           e = RSA_DEFAULT_PUBLIC_EXPONENT;
603       // CRYPT_PARAMETER
604       retVal =_cpri__TestKeyRSA(d, e, n, p, q);
605       if(retVal == CRYPT_SUCCESS)
606           return TPM_RC_SUCCESS;
607       else
608           return TPM_RC_BINDING; // convert CRYPT_PARAMETER
609   }


      10.2.5.3   CryptGenerateKeyRSA()

      This function is called to generate an RSA key from a provided seed. It calls _cpri__GenerateKeyRSA()
      to perform the computations. The implementation is vendor specific.

      Error Returns                   Meaning

      TPM_RC_RANGE                    the exponent value is not supported
      TPM_RC_CANCELLED                key generation has been canceled
      TPM_RC_VALUE                    exponent is not prime or is less than 3; or could not find a prime using
                                      the provided parameters

610   static TPM_RC
611   CryptGenerateKeyRSA(
612       TPMT_PUBLIC               *publicArea,              //   IN/OUT: The public area template for
613                                                           //        the new key. The public key
614                                                           //        area will be replaced by the
615                                                           //        product of two primes found by
616                                                           //        this function
617       TPMT_SENSITIVE            *sensitive,               //   OUT: the sensitive area will be
618                                                           //        updated to contain the first
619                                                           //        prime and the symmetric
620                                                           //        encryption key
621       TPM_ALG_ID                 hashAlg,                 //   IN: the hash algorithm for the KDF
622       TPM2B_SEED                *seed,                    //   IN: Seed for the creation
623       TPM2B_NAME                *name,                    //   IN: Object name
624       UINT32                    *counter                  //   OUT: last iteration of the counter
625   )
626   {
627       CRYPT_RESULT       retVal;
628       UINT32             exponent = publicArea->parameters.rsaDetail.exponent;
629
630       TEST_HASH(hashAlg);

      Family "2.0"                                 TCG Published                                                 Page 287
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                                 October 30, 2014
      Trusted Platform Module Library                                                    Part 4: Supporting Routines

631       TEST(ALG_NULL_VALUE);
632
633       // In this implementation, only the default exponent is allowed
634       if(exponent != 0 && exponent != RSA_DEFAULT_PUBLIC_EXPONENT)
635           return TPM_RC_RANGE;
636       exponent = RSA_DEFAULT_PUBLIC_EXPONENT;
637
638       *counter = 0;
639
640       // _cpri_GenerateKeyRSA can return CRYPT_CANCEL or CRYPT_FAIL
641       retVal = _cpri__GenerateKeyRSA(&publicArea->unique.rsa.b,
642                                      &sensitive->sensitive.rsa.b,
643                                      publicArea->parameters.rsaDetail.keyBits,
644                                      exponent,
645                                      hashAlg,
646                                      &seed->b,
647                                      "RSA key by vendor",
648                                      &name->b,
649                                      counter);
650
651       // CRYPT_CANCEL -> TPM_RC_CANCELLED; CRYPT_FAIL -> TPM_RC_VALUE
652       return TranslateCryptErrors(retVal);
653
654   }


      10.2.5.4    CryptLoadPrivateRSA()

      This function is called to generate the private exponent of an RSA key. It uses CryptTestKeyRSA().

      Error Returns                     Meaning

      TPM_RC_BINDING                    public and private parts of rsaKey are not matched

655   TPM_RC
656   CryptLoadPrivateRSA(
657       OBJECT              *rsaKey               // IN: the RSA key object
658       )
659   {
660       TPM_RC               result;
661       TPMT_PUBLIC         *publicArea = &rsaKey->publicArea;
662       TPMT_SENSITIVE      *sensitive = &rsaKey->sensitive;
663
664       // Load key by computing the private exponent
665       // TPM_RC_BINDING
666       result = CryptTestKeyRSA(&(rsaKey->privateExponent.b),
667                                publicArea->parameters.rsaDetail.exponent,
668                                &(publicArea->unique.rsa.b),
669                                &(sensitive->sensitive.rsa.b),
670                                NULL);
671       if(result == TPM_RC_SUCCESS)
672           rsaKey->attributes.privateExp = SET;
673
674       return result;
675   }


      10.2.5.5    CryptSelectRSAScheme()

      This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select a
      scheme between input and object default. This function assume the RSA object is loaded. If a default
      scheme is defined in object, the default scheme should be chosen, otherwise, the input scheme should
      be chosen. In the case that both the object and scheme are not TPM_ALG_NULL, then if the schemes


      Page 288                                       TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library


      are the same, the input scheme will be chosen. if the scheme are not compatible, a NULL pointer will be
      returned.
      The return pointer may point to a TPM_ALG_NULL scheme.

676   TPMT_RSA_DECRYPT*
677   CryptSelectRSAScheme(
678       TPMI_DH_OBJECT             rsaHandle,         // IN: handle of sign key
679       TPMT_RSA_DECRYPT          *scheme             // IN: a sign or decrypt scheme
680       )
681   {
682       OBJECT                    *rsaObject;
683       TPMT_ASYM_SCHEME          *keyScheme;
684       TPMT_RSA_DECRYPT          *retVal = NULL;
685
686       // Get sign object pointer
687       rsaObject = ObjectGet(rsaHandle);
688       keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme;
689
690       // if the default scheme of the object is TPM_ALG_NULL, then select the
691       // input scheme
692       if(keyScheme->scheme == TPM_ALG_NULL)
693       {
694           retVal = scheme;
695       }
696       // if the object scheme is not TPM_ALG_NULL and the input scheme is
697       // TPM_ALG_NULL, then select the default scheme of the object.
698       else if(scheme->scheme == TPM_ALG_NULL)
699       {
700           // if input scheme is NULL
701           retVal = (TPMT_RSA_DECRYPT *)keyScheme;
702       }
703       // get here if both the object scheme and the input scheme are
704       // not TPM_ALG_NULL. Need to insure that they are the same.
705       // IMPLEMENTATION NOTE: This could cause problems if future versions have
706       // schemes that have more values than just a hash algorithm. A new function
707       // (IsSchemeSame()) might be needed then.
708       else if(    keyScheme->scheme == scheme->scheme
709                && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg)
710       {
711           retVal = scheme;
712       }
713       // two different, incompatible schemes specified will return NULL
714       return retVal;
715   }


      10.2.5.6    CryptDecryptRSA()

      This function is the interface to _cpri__DecryptRSA(). It handles the return codes from that function and
      converts them from CRYPT_RESULT to TPM_RC values. The rsaKey parameter must reference an RSA
      decryption key

      Error Returns                   Meaning

      TPM_RC_BINDING                  Public and private parts of the key are not cryptographically bound.
      TPM_RC_SIZE                     Size of data to decrypt is not the same as the key size.
      TPM_RC_VALUE                    Numeric value of the encrypted data is greater than the public
                                      exponent, or output buffer is too small for the decrypted message.

716   TPM_RC
717   CryptDecryptRSA(
718       UINT16                    *dataOutSize,       // OUT: size of plain text in byte

      Family "2.0"                                 TCG Published                                             Page 289
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                                October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

719       BYTE                    *dataOut,        //   OUT: plain text
720       OBJECT                  *rsaKey,         //   IN: internal RSA key
721       TPMT_RSA_DECRYPT        *scheme,         //   IN: selects the padding scheme
722       UINT16                   cipherInSize,   //   IN: size of cipher text in byte
723       BYTE                    *cipherIn,       //   IN: cipher text
724       const char              *label           //   IN: a label, when needed
725       )
726   {
727       RSA_KEY            key;
728       CRYPT_RESULT       retVal = CRYPT_SUCCESS;
729       UINT32             dSize;                   //   Place to put temporary value for the
730                                                   //   returned data size
731       TPMI_ALG_HASH      hashAlg = TPM_ALG_NULL; //    hash algorithm in the selected
732                                                   //   padding scheme
733       TPM_RC             result = TPM_RC_SUCCESS;
734
735       // pointer checks
736       pAssert(    (dataOutSize != NULL) && (dataOut != NULL)
737               && (rsaKey != NULL) && (cipherIn != NULL));
738
739       // The public type is a RSA decrypt key
740       pAssert(    (rsaKey->publicArea.type == TPM_ALG_RSA
741               && rsaKey->publicArea.objectAttributes.decrypt == SET));
742
743       // Must have the private portion loaded. This check is made before this
744       // function is called.
745       pAssert(rsaKey->attributes.publicOnly == CLEAR);
746
747       // decryption requires that the private modulus be present
748       if(rsaKey->attributes.privateExp == CLEAR)
749       {
750
751            // Load key by computing the private exponent
752            // CryptLoadPrivateRSA may return TPM_RC_BINDING
753            result = CryptLoadPrivateRSA(rsaKey);
754       }
755
756       // the input buffer must be the size of the key
757       if(result == TPM_RC_SUCCESS)
758       {
759           if(cipherInSize != rsaKey->publicArea.unique.rsa.t.size)
760                result = TPM_RC_SIZE;
761           else
762           {
763                BuildRSA(rsaKey, &key);
764
765                 // Initialize the dOutSize parameter
766                 dSize = *dataOutSize;
767
768                 // For OAEP scheme, initialize the hash algorithm for padding
769                 if(scheme->scheme == TPM_ALG_OAEP)
770                 {
771                     hashAlg = scheme->details.oaep.hashAlg;
772                     TEST_HASH(hashAlg);
773                 }
774                 // See if the padding mode needs to be tested
775                 TEST(scheme->scheme);
776
777                 // _cpri__DecryptRSA may return CRYPT_PARAMETER CRYPT_FAIL CRYPT_SCHEME
778                 retVal = _cpri__DecryptRSA(&dSize, dataOut, &key, scheme->scheme,
779                                            cipherInSize, cipherIn, hashAlg, label);
780
781                 // Scheme must have been validated when the key was loaded/imported
782                 pAssert(retVal != CRYPT_SCHEME);
783
784                 // Set the return size

      Page 290                                TCG Published                               Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library

785                   pAssert(dSize <= UINT16_MAX);
786                   *dataOutSize = (UINT16)dSize;
787
788                   // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_FAIL -> TPM_RC_VALUE
789                   result = TranslateCryptErrors(retVal);
790           }
791       }
792       return result;
793   }


      10.2.5.7   CryptEncryptRSA()

      This function provides the interface to _cpri__EncryptRSA(). The object referenced by rsaKey is required
      to be an RSA decryption key.

      Error Returns                   Meaning

      TPM_RC_SCHEME                   scheme is not supported
      TPM_RC_VALUE                    numeric value of dataIn is greater than the key modulus

794   TPM_RC
795   CryptEncryptRSA(
796       UINT16                    *cipherOutSize,    //   OUT: size of cipher text in byte
797       BYTE                      *cipherOut,        //   OUT: cipher text
798       OBJECT                    *rsaKey,           //   IN: internal RSA key
799       TPMT_RSA_DECRYPT          *scheme,           //   IN: selects the padding scheme
800       UINT16                     dataInSize,       //   IN: size of plain text in byte
801       BYTE                      *dataIn,           //   IN: plain text
802       const char                *label             //   IN: an optional label
803       )
804   {
805       RSA_KEY                    key;
806       CRYPT_RESULT               retVal;
807       UINT32                     cOutSize;                         // Conversion variable
808       TPMI_ALG_HASH              hashAlg = TPM_ALG_NULL;           // hash algorithm in selected
809                                                                    // padding scheme
810
811       // must have a pointer to a key and some data to encrypt
812       pAssert(rsaKey != NULL && dataIn != NULL);
813
814       // The public type is a RSA decryption key
815       pAssert(   rsaKey->publicArea.type == TPM_ALG_RSA
816               && rsaKey->publicArea.objectAttributes.decrypt == SET);
817
818       // If the cipher buffer must be provided and it must be large enough
819       // for the result
820       pAssert(   cipherOut != NULL
821               && cipherOutSize != NULL
822               && *cipherOutSize >= rsaKey->publicArea.unique.rsa.t.size);
823
824       // Only need the public key and exponent for encryption
825       BuildRSA(rsaKey, &key);
826
827       // Copy the size to the conversion buffer
828       cOutSize = *cipherOutSize;
829
830       // For OAEP scheme, initialize the hash algorithm for padding
831       if(scheme->scheme == TPM_ALG_OAEP)
832       {
833           hashAlg = scheme->details.oaep.hashAlg;
834           TEST_HASH(hashAlg);
835       }
836

      Family "2.0"                                TCG Published                                        Page 291
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                                     Part 4: Supporting Routines

837       // This is a public key operation and does not require that the private key
838       // be loaded. To verify this, need to do the full algorithm
839       TEST(scheme->scheme);
840
841       // Encrypt the data with the public exponent
842       // _cpri__EncryptRSA may return CRYPT_PARAMETER or CRYPT_SCHEME
843       retVal = _cpri__EncryptRSA(&cOutSize,cipherOut, &key, scheme->scheme,
844                                  dataInSize, dataIn, hashAlg, label);
845
846       pAssert (cOutSize <= UINT16_MAX);
847       *cipherOutSize = (UINT16)cOutSize;
848       // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_SCHEME -> TPM_RC_SCHEME
849       return TranslateCryptErrors(retVal);
850   }


      10.2.5.8     CryptSignRSA()

      This function is used to sign a digest with an RSA signing key.

      Error Returns                     Meaning

      TPM_RC_BINDING                    public and private part of signKey are not properly bound
      TPM_RC_SCHEME                     scheme is not supported
      TPM_RC_VALUE                      hashData is larger than the modulus of signKey, or the size of
                                        hashData does not match hash algorithm in scheme

851   static TPM_RC
852   CryptSignRSA(
853       OBJECT                   *signKey,              //   IN: RSA key signs the hash
854       TPMT_SIG_SCHEME          *scheme,               //   IN: sign scheme
855       TPM2B_DIGEST             *hashData,             //   IN: hash to be signed
856       TPMT_SIGNATURE           *sig                   //   OUT: signature
857       )
858   {
859       UINT32                     signSize;
860       RSA_KEY                    key;
861       CRYPT_RESULT               retVal;
862       TPM_RC                     result = TPM_RC_SUCCESS;
863
864       pAssert(       (signKey != NULL) && (scheme != NULL)
865                      && (hashData != NULL) && (sig != NULL));
866
867       // assume that the key has private part loaded and that it is a signing key.
868       pAssert(   (signKey->attributes.publicOnly == CLEAR)
869               && (signKey->publicArea.objectAttributes.sign == SET));
870
871       // check if the private exponent has been computed
872       if(signKey->attributes.privateExp == CLEAR)
873           // May return TPM_RC_BINDING
874           result = CryptLoadPrivateRSA(signKey);
875
876       if(result == TPM_RC_SUCCESS)
877       {
878           BuildRSA(signKey, &key);
879
880              // Make sure that the hash is tested
881              TEST_HASH(sig->signature.any.hashAlg);
882
883              // Run a test of the RSA sign
884              TEST(scheme->scheme);
885
886              // _crypi__SignRSA can return CRYPT_SCHEME and CRYPT_PARAMETER
887              retVal = _cpri__SignRSA(&signSize,

      Page 292                                       TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                      Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

888                                      sig->signature.rsassa.sig.t.buffer,
889                                      &key,
890                                      sig->sigAlg,
891                                      sig->signature.any.hashAlg,
892                                      hashData->t.size, hashData->t.buffer);
893              pAssert(signSize <= UINT16_MAX);
894              sig->signature.rsassa.sig.t.size = (UINT16)signSize;
895
896              // CRYPT_SCHEME -> TPM_RC_SCHEME; CRYPT_PARAMTER -> TPM_RC_VALUE
897              result = TranslateCryptErrors(retVal);
898       }
899       return result;
900   }


      10.2.5.9    CryptRSAVerifySignature()

      This function is used to verify signature signed by a RSA key.

      Error Returns                   Meaning

      TPM_RC_SIGNATURE                if signature is not genuine
      TPM_RC_SCHEME                   signature scheme not supported

901   static TPM_RC
902   CryptRSAVerifySignature(
903       OBJECT              *signKey,            // IN: RSA key signed the hash
904       TPM2B_DIGEST        *digestData,         // IN: digest being signed
905       TPMT_SIGNATURE      *sig                 // IN: signature to be verified
906       )
907   {
908       RSA_KEY                   key;
909       CRYPT_RESULT              retVal;
910       TPM_RC                    result;
911
912       // Validate parameter assumptions
913       pAssert((signKey != NULL) && (digestData != NULL) && (sig != NULL));
914
915       TEST_HASH(sig->signature.any.hashAlg);
916       TEST(sig->sigAlg);
917
918       // This is a public-key-only operation
919       BuildRSA(signKey, &key);
920
921       // Call crypto engine to verify signature
922       // _cpri_ValidateSignaturRSA may return CRYPT_FAIL or CRYPT_SCHEME
923       retVal = _cpri__ValidateSignatureRSA(&key,
924                                            sig->sigAlg,
925                                            sig->signature.any.hashAlg,
926                                            digestData->t.size,
927                                            digestData->t.buffer,
928                                            sig->signature.rsassa.sig.t.size,
929                                            sig->signature.rsassa.sig.t.buffer,
930                                            0);
931       // _cpri__ValidateSignatureRSA can return CRYPT_SUCCESS, CRYPT_FAIL, or
932       // CRYPT_SCHEME. Translate CRYPT_FAIL to TPM_RC_SIGNATURE
933       if(retVal == CRYPT_FAIL)
934           result = TPM_RC_SIGNATURE;
935       else
936           // CRYPT_SCHEME -> TPM_RC_SCHEME
937           result = TranslateCryptErrors(retVal);
938
939       return result;
940   }


      Family "2.0"                                 TCG Published                                Page 293
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

941   #endif //TPM_ALG_RSA             //% 2


      10.2.6     ECC Functions

      10.2.6.1    CryptEccGetCurveDataPointer()

      This function returns a pointer to an ECC_CURVE_VALUES structure that contains the parameters for
      the key size and schemes for a given curve.

942   #ifdef TPM_ALG_ECC //% 3
943   static const ECC_CURVE    *
944   CryptEccGetCurveDataPointer(
945        TPM_ECC_CURVE        curveID             // IN: id of the curve
946        )
947   {
948        return _cpri__EccGetParametersByCurveId(curveID);
949   }


      10.2.6.2    CryptEccGetKeySizeInBits()

      This function returns the size in bits of the key associated with a curve.

950   UINT16
951   CryptEccGetKeySizeInBits(
952        TPM_ECC_CURVE        curveID             // IN: id of the curve
953        )
954   {
955        const ECC_CURVE               *curve = CryptEccGetCurveDataPointer(curveID);
956        UINT16                         keySizeInBits = 0;
957
958        if(curve != NULL)
959            keySizeInBits = curve->keySizeBits;
960
961        return keySizeInBits;
962   }


      10.2.6.3    CryptEccGetKeySizeBytes()

      This macro returns the size of the ECC key in bytes. It uses CryptEccGetKeySizeInBits().

963   // The next lines will be placed in CyrptUtil_fp.h with the //% removed
964   //% #define CryptEccGetKeySizeInBytes(curve)            \
965   //%             ((CryptEccGetKeySizeInBits(curve)+7)/8)


      10.2.6.4    CryptEccGetParameter()

      This function returns a pointer to an ECC curve parameter. The parameter is selected by a single
      character designator from the set of {pnabxyh}.

966   LIB_EXPORT const TPM2B *
967   CryptEccGetParameter(
968        char                 p,                  // IN: the parameter selector
969        TPM_ECC_CURVE        curveId             // IN: the curve id
970        )
971   {
972        const ECC_CURVE          *curve = _cpri__EccGetParametersByCurveId(curveId);
973        const TPM2B              *parameter = NULL;
974
975        if(curve != NULL)

      Page 294                                      TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
       Part 4: Supporting Routines                                                 Trusted Platform Module Library

 976        {
 977              switch (p)
 978              {
 979              case 'p':
 980                  parameter    = curve->curveData->p;
 981                  break;
 982              case 'n':
 983                  parameter    =   curve->curveData->n;
 984                  break;
 985              case 'a':
 986                  parameter    =   curve->curveData->a;
 987                  break;
 988              case 'b':
 989                  parameter    =   curve->curveData->b;
 990                  break;
 991              case 'x':
 992                  parameter    =   curve->curveData->x;
 993                  break;
 994              case 'y':
 995                  parameter    =   curve->curveData->y;
 996                  break;
 997              case 'h':
 998                  parameter    =   curve->curveData->h;
 999                  break;
1000              default:
1001                  break;
1002              }
1003        }
1004        return parameter;
1005   }


       10.2.6.5    CryptGetCurveSignScheme()

       This function will return a pointer to the scheme of the curve.

1006   const TPMT_ECC_SCHEME *
1007   CryptGetCurveSignScheme(
1008        TPM_ECC_CURVE         curveId            // IN: The curve selector
1009        )
1010   {
1011        const ECC_CURVE               *curve = _cpri__EccGetParametersByCurveId(curveId);
1012        const TPMT_ECC_SCHEME         *scheme = NULL;
1013
1014        if(curve != NULL)
1015            scheme = &(curve->sign);
1016        return scheme;
1017   }


       10.2.6.6    CryptEccIsPointOnCurve()

       This function will validate that an ECC point is on the curve of given curveID.

       Return Value                     Meaning

       TRUE                             if the point is on curve
       FALSE                            if the point is not on curve

1018   BOOL
1019   CryptEccIsPointOnCurve(
1020        TPM_ECC_CURVE        curveID,            // IN: ECC curve ID
1021        TPMS_ECC_POINT      *Q                   // IN: ECC point
1022        )

       Family "2.0"                                   TCG Published                                     Page 295
       Level 00 Revision 01.16               Copyright © TCG 2006-2014                         October 30, 2014
       Trusted Platform Module Library                                                         Part 4: Supporting Routines

1023   {
1024       // Make sure that point multiply is working
1025       TEST(TPM_ALG_ECC);
1026       // Check point on curve logic by seeing if the test key is on the curve
1027
1028       // Call crypto engine function to check if a ECC public point is on the
1029       // given curve
1030       if(_cpri__EccIsPointOnCurve(curveID, Q))
1031           return TRUE;
1032       else
1033           return FALSE;
1034   }


       10.2.6.7    CryptNewEccKey()

       This function creates a random ECC key that is not derived from other parameters as is a Primary Key.

1035   TPM_RC
1036   CryptNewEccKey(
1037       TPM_ECC_CURVE                    curveID,               // IN: ECC curve
1038       TPMS_ECC_POINT                  *publicPoint,           // OUT: public point
1039       TPM2B_ECC_PARAMETER             *sensitive              // OUT: private area
1040       )
1041   {
1042       TPM_RC               result = TPM_RC_SUCCESS;
1043       // _cpri__GetEphemeralECC may return CRYPT_PARAMETER
1044       if(_cpri__GetEphemeralEcc(publicPoint, sensitive, curveID) != CRYPT_SUCCESS)
1045           // Something is wrong with the key.
1046           result = TPM_RC_KEY;
1047
1048       return result;
1049   }


       10.2.6.8    CryptEccPointMultiply()

       This function is used to perform a point multiply R = [d]Q. If Q is not provided, the multiplication is
       performed using the generator point of the curve.

       Error Returns                     Meaning

       TPM_RC_ECC_POINT                  invalid optional ECC point pIn
       TPM_RC_NO_RESULT                  multiplication resulted in a point at infinity
       TPM_RC_CANCELED                   if a self-test was done, it might have been aborted

1050   TPM_RC
1051   CryptEccPointMultiply(
1052       TPMS_ECC_POINT                  *pOut,                  //   OUT: output point
1053       TPM_ECC_CURVE                    curveId,               //   IN: curve selector
1054       TPM2B_ECC_PARAMETER             *dIn,                   //   IN: public scalar
1055       TPMS_ECC_POINT                  *pIn                    //   IN: optional point
1056       )
1057   {
1058       TPM2B_ECC_PARAMETER             *n = NULL;
1059       CRYPT_RESULT                    retVal;
1060
1061       pAssert(pOut != NULL && dIn != NULL);
1062
1063       if(pIn != NULL)
1064       {
1065           n = dIn;
1066           dIn = NULL;

       Page 296                                         TCG Published                                        Family "2.0"
       October 30, 2014                        Copyright © TCG 2006-2014                        Level 00 Revision 01.16
       Part 4: Supporting Routines                                              Trusted Platform Module Library

1067       }
1068       // Do a test of point multiply
1069       TEST(TPM_ALG_ECC);
1070
1071       // _cpri__EccPointMultiply may return CRYPT_POINT or CRYPT_NO_RESULT
1072       retVal = _cpri__EccPointMultiply(pOut, curveId, dIn, pIn, n);
1073
1074       // CRYPT_POINT->TPM_RC_ECC_POINT and CRYPT_NO_RESULT->TPM_RC_NO_RESULT
1075       return TranslateCryptErrors(retVal);
1076   }


       10.2.6.9    CryptGenerateKeyECC()

       This function generates an ECC key from a seed value.
       The method here may not work for objects that have an order (G) that with a different size than a private
       key.

       Error Returns                   Meaning

       TPM_RC_VALUE                    hash algorithm is not supported

1077   static TPM_RC
1078   CryptGenerateKeyECC(
1079       TPMT_PUBLIC         *publicArea,        //   IN/OUT: The public area template for the new
1080                                               //       key.
1081       TPMT_SENSITIVE      *sensitive,         //   IN/OUT: the sensitive area
1082       TPM_ALG_ID           hashAlg,           //   IN: algorithm for the KDF
1083       TPM2B_SEED          *seed,              //   IN: the seed value
1084       TPM2B_NAME          *name,              //   IN: the name of the object
1085       UINT32              *counter            //   OUT: the iteration counter
1086       )
1087   {
1088       CRYPT_RESULT              retVal;
1089
1090       TEST_HASH(hashAlg);
1091       TEST(ALG_ECDSA_VALUE); // ECDSA is used to verify each key
1092
1093       // The iteration counter has no meaning for ECC key generation. The parameter
1094       // will be overloaded for those implementations that have a requirement for
1095       // doing pair-wise consistency checks on signing keys. If the counter parameter
1096       // is 0 or NULL, then no consistency check is done. If it is other than 0, then
1097       // a consistency check is run. This modification allow this code to work with
1098       // the existing versions of the CrytpoEngine and with FIPS-compliant versions
1099       // as well.
1100       *counter = (UINT32)(publicArea->objectAttributes.sign == SET);
1101
1102       // _cpri__GenerateKeyEcc only has one error return (CRYPT_PARAMETER) which means
1103       // that the hash algorithm is not supported. This should not be possible
1104       retVal = _cpri__GenerateKeyEcc(&publicArea->unique.ecc,
1105                                      &sensitive->sensitive.ecc,
1106                                      publicArea->parameters.eccDetail.curveID,
1107                                      hashAlg, &seed->b, "ECC key by vendor",
1108                                      &name->b, counter);
1109       // This will only be useful if _cpri__GenerateKeyEcc return CRYPT_CANCEL
1110       return TranslateCryptErrors(retVal);
1111   }


       10.2.6.10 CryptSignECC()

       This function is used for ECC signing operations. If the signing scheme is a split scheme, and the signing
       operation is successful, the commit value is retired.


       Family "2.0"                                TCG Published                                      Page 297
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                          October 30, 2014
       Trusted Platform Module Library                                                      Part 4: Supporting Routines


       Error Returns                     Meaning

       TPM_RC_SCHEME                     unsupported scheme
       TPM_RC_VALUE                      invalid commit status (in case of a split scheme) or failed to generate
                                         r value.

1112   static TPM_RC
1113   CryptSignECC(
1114       OBJECT                   *signKey,                //   IN: ECC key to sign the hash
1115       TPMT_SIG_SCHEME          *scheme,                 //   IN: sign scheme
1116       TPM2B_DIGEST             *hashData,               //   IN: hash to be signed
1117       TPMT_SIGNATURE           *signature               //   OUT: signature
1118       )
1119   {
1120       TPM2B_ECC_PARAMETER              r;
1121       TPM2B_ECC_PARAMETER             *pr = NULL;
1122       CRYPT_RESULT                     retVal;
1123
1124       // Run a test of the ECC sign and verify if it has not already been run
1125       TEST_HASH(scheme->details.any.hashAlg);
1126       TEST(scheme->scheme);
1127
1128       if(CryptIsSplitSign(scheme->scheme))
1129       {
1130           // When this code was written, the only split scheme was ECDAA
1131           // (which can also be used for U-Prove).
1132           if(!CryptGenerateR(&r,
1133                              &scheme->details.ecdaa.count,
1134                              signKey->publicArea.parameters.eccDetail.curveID,
1135                              &signKey->name))
1136               return TPM_RC_VALUE;
1137           pr = &r;
1138       }
1139       // Call crypto engine function to sign
1140       // _cpri__SignEcc may return CRYPT_SCHEME
1141       retVal = _cpri__SignEcc(&signature->signature.ecdsa.signatureR,
1142                               &signature->signature.ecdsa.signatureS,
1143                               scheme->scheme,
1144                               scheme->details.any.hashAlg,
1145                               signKey->publicArea.parameters.eccDetail.curveID,
1146                               &signKey->sensitive.sensitive.ecc,
1147                               &hashData->b,
1148                               pr
1149                               );
1150       if(CryptIsSplitSign(scheme->scheme) && retVal == CRYPT_SUCCESS)
1151           CryptEndCommit(scheme->details.ecdaa.count);
1152       // CRYPT_SCHEME->TPM_RC_SCHEME
1153       return TranslateCryptErrors(retVal);
1154   }


       10.2.6.11 CryptECCVerifySignature()

       This function is used to verify a signature created with an ECC key.

       Error Returns                     Meaning

       TPM_RC_SIGNATURE                  if signature is not valid
       TPM_RC_SCHEME                     the signing scheme or hashAlg is not supported

1155   static TPM_RC
1156   CryptECCVerifySignature(
1157       OBJECT              *signKey,               // IN: ECC key signed the hash

       Page 298                                         TCG Published                                        Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

1158       TPM2B_DIGEST        *digestData,       // IN: digest being signed
1159       TPMT_SIGNATURE      *signature         // IN: signature to be verified
1160       )
1161   {
1162       CRYPT_RESULT              retVal;
1163
1164       TEST_HASH(signature->signature.any.hashAlg);
1165       TEST(signature->sigAlg);
1166
1167       // This implementation uses the fact that all the defined ECC signing
1168       // schemes have the hash as the first parameter.
1169       // _cpriValidateSignatureEcc may return CRYPT_FAIL or CRYP_SCHEME
1170       retVal = _cpri__ValidateSignatureEcc(&signature->signature.ecdsa.signatureR,
1171                                      &signature->signature.ecdsa.signatureS,
1172                                      signature->sigAlg,
1173                                      signature->signature.any.hashAlg,
1174                                      signKey->publicArea.parameters.eccDetail.curveID,
1175                                      &signKey->publicArea.unique.ecc,
1176                                      &digestData->b);
1177       if(retVal == CRYPT_FAIL)
1178           return TPM_RC_SIGNATURE;
1179       // CRYPT_SCHEME->TPM_RC_SCHEME
1180       return TranslateCryptErrors(retVal);
1181   }


       10.2.6.12 CryptGenerateR()

       This function computes the commit random value for a split signing scheme.
       If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM will
       validate that the gr.commitArray bit associated with the input value of c is SET. If not, the TPM returns
       FALSE and no r value is generated.

       Return Value                    Meaning

       TRUE                            r value computed
       FALSE                           no r value computed

1182   BOOL
1183   CryptGenerateR(
1184       TPM2B_ECC_PARAMETER           *r,                 //   OUT: the generated random value
1185       UINT16                        *c,                 //   IN/OUT: count value.
1186       TPMI_ECC_CURVE                 curveID,           //   IN: the curve for the value
1187       TPM2B_NAME                    *name               //   IN: optional name of a key to
1188                                                         //       associate with 'r'
1189       )
1190   {
1191       // This holds the marshaled g_commitCounter.
1192       TPM2B_TYPE(8B, 8);
1193       TPM2B_8B                cntr = {8,{0}};
1194
1195       UINT32                   iterations;
1196       const TPM2B             *n;
1197       UINT64                   currentCount = gr.commitCounter;
1198       // This is just to suppress a compiler warning about a conditional expression
1199       // being a constant. This is because of the macro expansion of ryptKDFa
1200       TPMI_ALG_HASH            hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
1201
1202       n = CryptEccGetParameter('n', curveID);
1203       pAssert(r != NULL && n != NULL);
1204
1205       // If this is the commit phase, use the current value of the commit counter
1206       if(c != NULL)


       Family "2.0"                                TCG Published                                     Page 299
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                         October 30, 2014
       Trusted Platform Module Library                                   Part 4: Supporting Routines

1207       {
1208
1209            UINT16      t1;
1210            // if the array bit is not set, can't use the value.
1211            if(!BitIsSet((*c & COMMIT_INDEX_MASK), gr.commitArray,
1212                         sizeof(gr.commitArray)))
1213                return FALSE;
1214
1215            //   If it is the sign phase, figure out what the counter value was
1216            //   when the commitment was made.
1217            //
1218            //   When gr.commitArray has less than 64K bits, the extra
1219            //   bits of 'c' are used as a check to make sure that the
1220            //   signing operation is not using an out of range count value
1221            t1   = (UINT16)currentCount;
1222
1223            // If the lower bits of c are greater or equal to the lower bits of t1
1224            // then the upper bits of t1 must be one more than the upper bits
1225            // of c
1226            if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK))
1227                // Since the counter is behind, reduce the current count
1228                currentCount = currentCount - (COMMIT_INDEX_MASK + 1);
1229
1230            t1 = (UINT16)currentCount;
1231            if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK))
1232                return FALSE;
1233            // set the counter to the value that was
1234            // present when the commitment was made
1235            currentCount = (currentCount & 0xffffffffffff0000) | *c;
1236
1237       }
1238       // Marshal the count value to a TPM2B buffer for the KDF
1239       cntr.t.size = sizeof(currentCount);
1240       UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer);
1241
1242       //   Now can do the KDF to create the random value for the signing operation
1243       //   During the creation process, we may generate an r that does not meet the
1244       //   requirements of the random value.
1245       //   want to generate a new r.
1246
1247       r->t.size = n->size;
1248
1249       // Arbitrary upper limit on the number of times that we can look for
1250       // a suitable random value. The normally number of tries will be 1.
1251       for(iterations = 1; iterations < 1000000;)
1252       {
1253           BYTE    *pr = &r->b.buffer[0];
1254           int     i;
1255           CryptKDFa(hashAlg, &gr.commitNonce.b, "ECDAA Commit",
1256                     name, &cntr.b, n->size * 8, r->t.buffer, &iterations);
1257
1258            // random value must be less than the prime
1259            if(CryptCompare(r->b.size, r->b.buffer, n->size, n->buffer) >= 0)
1260                continue;
1261
1262            // in this implementation it is required that at least bit
1263            // in the upper half of the number be set
1264            for(i = n->size/2; i > 0; i--)
1265                if(*pr++ != 0)
1266                    return TRUE;
1267       }
1268       return FALSE;
1269   }




       Page 300                               TCG Published                            Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                                 Trusted Platform Module Library

       10.2.6.13 CryptCommit()

       This function is called when the count value is committed. The gr.commitArray value associated with the
       current count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of the
       counter is returned.

1270   UINT16
1271   CryptCommit(
1272       void
1273       )
1274   {
1275       UINT16      oldCount = (UINT16)gr.commitCounter;
1276       gr.commitCounter++;
1277       BitSet(oldCount & COMMIT_INDEX_MASK, gr.commitArray, sizeof(gr.commitArray));
1278       return oldCount;
1279   }


       10.2.6.14 CryptEndCommit()

       This function is called when the signing operation using the committed value is completed. It clears the
       gr.commitArray bit associated with the count value so that it can't be used again.

1280   void
1281   CryptEndCommit(
1282       UINT16               c                    // IN: the counter value of the commitment
1283       )
1284   {
1285       BitClear((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray));
1286   }


       10.2.6.15 CryptCommitCompute()

       This function performs the computations for the TPM2_Commit() command. This could be a macro.

       Error Returns                   Meaning

       TPM_RC_NO_RESULT                K, L, or E is the point at infinity
       TPM_RC_CANCELLED                command was canceled

1287   TPM_RC
1288   CryptCommitCompute(
1289       TPMS_ECC_POINT                *K,                     //   OUT: [d]B
1290       TPMS_ECC_POINT                *L,                     //   OUT: [r]B
1291       TPMS_ECC_POINT                *E,                     //   OUT: [r]M
1292       TPM_ECC_CURVE                  curveID,               //   IN: The curve for the computation
1293       TPMS_ECC_POINT                *M,                     //   IN: M (P1)
1294       TPMS_ECC_POINT                *B,                     //   IN: B (x2, y2)
1295       TPM2B_ECC_PARAMETER           *d,                     //   IN: the private scalar
1296       TPM2B_ECC_PARAMETER           *r                      //   IN: the computed r value
1297       )
1298   {
1299       TEST(ALG_ECDH_VALUE);
1300       // CRYPT_NO_RESULT->TPM_RC_NO_RESULT CRYPT_CANCEL->TPM_RC_CANCELLED
1301       return TranslateCryptErrors(
1302                  _cpri__EccCommitCompute(K, L , E, curveID, M, B, d, r));
1303   }




       Family "2.0"                                  TCG Published                                      Page 301
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
       Trusted Platform Module Library                                             Part 4: Supporting Routines

       10.2.6.16 CryptEccGetParameters()

       This function returns the ECC parameter details of the given curve

       Return Value                      Meaning

       TRUE                              Get parameters success
       FALSE                             Unsupported ECC curve ID

1304   BOOL
1305   CryptEccGetParameters(
1306       TPM_ECC_CURVE                        curveId,            // IN: ECC curve ID
1307       TPMS_ALGORITHM_DETAIL_ECC           *parameters          // OUT: ECC parameter
1308       )
1309   {
1310       const ECC_CURVE                     *curve = _cpri__EccGetParametersByCurveId(curveId);
1311       const ECC_CURVE_DATA                *data;
1312       BOOL                                 found = curve != NULL;
1313
1314       if(found)
1315       {
1316
1317            data = curve->curveData;
1318
1319            parameters->curveID = curve->curveId;
1320
1321            // Key size in bit
1322            parameters->keySize = curve->keySizeBits;
1323
1324            // KDF
1325            parameters->kdf = curve->kdf;
1326
1327            // Sign
1328            parameters->sign = curve->sign;
1329
1330            // Copy p value
1331            MemoryCopy2B(&parameters->p.b, data->p, sizeof(parameters->p.t.buffer));
1332
1333            // Copy a value
1334            MemoryCopy2B(&parameters->a.b, data->a, sizeof(parameters->a.t.buffer));
1335
1336            // Copy b value
1337            MemoryCopy2B(&parameters->b.b, data->b, sizeof(parameters->b.t.buffer));
1338
1339            // Copy Gx value
1340            MemoryCopy2B(&parameters->gX.b, data->x, sizeof(parameters->gX.t.buffer));
1341
1342            // Copy Gy value
1343            MemoryCopy2B(&parameters->gY.b, data->y, sizeof(parameters->gY.t.buffer));
1344
1345            // Copy n value
1346            MemoryCopy2B(&parameters->n.b, data->n, sizeof(parameters->n.t.buffer));
1347
1348            // Copy h value
1349            MemoryCopy2B(&parameters->h.b, data->h, sizeof(parameters->h.t.buffer));
1350       }
1351       return found;
1352   }
1353   #if CC_ZGen_2Phase == YES

       CryptEcc2PhaseKeyExchange() This is the interface to the key exchange function.

1354   TPM_RC
1355   CryptEcc2PhaseKeyExchange(

       Page 302                                      TCG Published                               Family "2.0"
       October 30, 2014                      Copyright © TCG 2006-2014               Level 00 Revision 01.16
       Part 4: Supporting Routines                                            Trusted Platform Module Library

1356       TPMS_ECC_POINT                *outZ1,            //   OUT: the computed point
1357       TPMS_ECC_POINT                *outZ2,            //   OUT: optional second point
1358       TPM_ALG_ID                     scheme,           //   IN: the key exchange scheme
1359       TPM_ECC_CURVE                  curveId,          //   IN: the curve for the computation
1360       TPM2B_ECC_PARAMETER           *dsA,              //   IN: static private TPM key
1361       TPM2B_ECC_PARAMETER           *deA,              //   IN: ephemeral private TPM key
1362       TPMS_ECC_POINT                *QsB,              //   IN: static public party B key
1363       TPMS_ECC_POINT                *QeB               //   IN: ephemeral public party B key
1364       )
1365   {
1366       return (TranslateCryptErrors(_cpri__C_2_2_KeyExchange(outZ1,
1367                                                             outZ2,
1368                                                             scheme,
1369                                                             curveId,
1370                                                             dsA,
1371                                                             deA,
1372                                                             QsB,
1373                                                             QeB)));
1374   }
1375   #endif // CC_ZGen_2Phase
1376   #endif //TPM_ALG_ECC //% 3


       10.2.6.17 CryptIsSchemeAnonymous()

       This function is used to test a scheme to see if it is an anonymous scheme The only anonymous scheme
       is ECDAA. ECDAA can be used to do things like U-Prove.

1377   BOOL
1378   CryptIsSchemeAnonymous(
1379       TPM_ALG_ID           scheme            // IN: the scheme algorithm to test
1380       )
1381   {
1382   #ifdef TPM_ALG_ECDAA
1383       return (scheme == TPM_ALG_ECDAA);
1384   #else
1385       UNREFERENCED(scheme);
1386       return 0;
1387   #endif
1388   }


       10.2.7     Symmetric Functions

       10.2.7.1    ParmDecryptSym()

       This function performs parameter decryption using symmetric block cipher.

1389   void
1390   ParmDecryptSym(
1391       TPM_ALG_ID          symAlg,            //   IN: the symmetric algorithm
1392       TPM_ALG_ID          hash,              //   IN: hash algorithm for KDFa
1393       UINT16              keySizeInBits,     //   IN: key key size in bit
1394       TPM2B              *key,               //   IN: KDF HMAC key
1395       TPM2B              *nonceCaller,       //   IN: nonce caller
1396       TPM2B              *nonceTpm,          //   IN: nonce TPM
1397       UINT32              dataSize,          //   IN: size of parameter buffer
1398       BYTE               *data               //   OUT: buffer to be decrypted
1399       )
1400   {
1401       // KDF output buffer
1402       // It contains parameters for the CFB encryption
1403       // From MSB to LSB, they are the key and iv
1404       BYTE             symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];

       Family "2.0"                               TCG Published                                    Page 303
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                      October 30, 2014
       Trusted Platform Module Library                                             Part 4: Supporting Routines

1405       // Symmetric key size in byte
1406       UINT16           keySize = (keySizeInBits + 7) / 8;
1407       TPM2B_IV         iv;
1408
1409       iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
1410       // If there is decryption to do...
1411       if(iv.t.size > 0)
1412       {
1413           // Generate key and iv
1414           CryptKDFa(hash, key, "CFB", nonceCaller, nonceTpm,
1415                     keySizeInBits + (iv.t.size * 8), symParmString, NULL);
1416           MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size,
1417                      sizeof(iv.t.buffer));
1418
1419              CryptSymmetricDecrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB,
1420                                    symParmString, &iv, dataSize, data);
1421       }
1422       return;
1423   }


       10.2.7.2     ParmEncryptSym()

       This function performs parameter encryption using symmetric block cipher.

1424   void
1425   ParmEncryptSym(
1426       TPM_ALG_ID          symAlg,            //   IN: symmetric algorithm
1427       TPM_ALG_ID          hash,              //   IN: hash algorithm for KDFa
1428       UINT16              keySizeInBits,     //   IN: AES key size in bit
1429       TPM2B              *key,               //   IN: KDF HMAC key
1430       TPM2B              *nonceCaller,       //   IN: nonce caller
1431       TPM2B              *nonceTpm,          //   IN: nonce TPM
1432       UINT32              dataSize,          //   IN: size of parameter buffer
1433       BYTE               *data               //   OUT: buffer to be encrypted
1434       )
1435   {
1436       // KDF output buffer
1437       // It contains parameters for the CFB encryption
1438       BYTE             symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
1439
1440       // Symmetric key size in bytes
1441       UINT16           keySize = (keySizeInBits + 7) / 8;
1442
1443       TPM2B_IV             iv;
1444
1445       iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
1446       // See if there is any encryption to do
1447       if(iv.t.size > 0)
1448       {
1449           // Generate key and iv
1450           CryptKDFa(hash, key, "CFB", nonceTpm, nonceCaller,
1451                     keySizeInBits + (iv.t.size * 8), symParmString, NULL);
1452
1453              MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size,
1454                         sizeof(iv.t.buffer));
1455
1456              CryptSymmetricEncrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB,
1457                                    symParmString, &iv, dataSize, data);
1458       }
1459       return;
1460   }




       Page 304                                   TCG Published                                  Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014                Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

       10.2.7.3     CryptGenerateNewSymmetric()

       This function creates the sensitive symmetric values for an HMAC or symmetric key. If the sensitive area
       is zero, then the sensitive creation key data is copied. If it is not zero, then the TPM will generate a
       random value of the selected size.

1461   void
1462   CryptGenerateNewSymmetric(
1463       TPMS_SENSITIVE_CREATE        *sensitiveCreate,       //   IN: sensitive creation data
1464       TPMT_SENSITIVE               *sensitive,             //   OUT: sensitive area
1465       TPM_ALG_ID                    hashAlg,               //   IN: hash algorithm for the KDF
1466       TPM2B_SEED                   *seed,                  //   IN: seed used in creation
1467       TPM2B_NAME                   *name                   //   IN: name of the object
1468       )
1469   {
1470       // This function is called to create a key and obfuscation value for a
1471       // symmetric key that can either be a block cipher or an XOR key. The buffer
1472       // in sensitive->sensitive will hold either. When we call the function
1473       // to copy the input value or generated value to the sensitive->sensitive
1474       // buffer we will need to have a size for the output buffer. This define
1475       // computes the maximum that it might need to be and uses that. It will always
1476       // be smaller than the largest value that will fit.
1477       #define MAX_SENSITIVE_SIZE                                                   \
1478           (MAX(sizeof(sensitive->sensitive.bits.t.buffer),                         \
1479               sizeof(sensitive->sensitive.sym.t.buffer)))
1480
1481       // set the size of the obfuscation value
1482       sensitive->seedValue.t.size = CryptGetHashDigestSize(hashAlg);
1483
1484       // If the input sensitive size is zero, then create both the sensitive data
1485       // and the obfuscation value
1486       if(sensitiveCreate->data.t.size == 0)
1487       {
1488           BYTE                     symValues[MAX(MAX_DIGEST_SIZE, MAX_SYM_KEY_BYTES)
1489                                              + MAX_DIGEST_SIZE];
1490           UINT16                  requestSize;
1491
1492              // Set the size of the request to be the size of the key and the
1493              // obfuscation value
1494              requestSize =   sensitive->sensitive.sym.t.size
1495                            + sensitive->seedValue.t.size;
1496              pAssert(requestSize <= sizeof(symValues));
1497
1498              requestSize = _cpri__GenerateSeededRandom(requestSize, symValues, hashAlg,
1499                                                        &seed->b,
1500                                                        "symmetric sensitive", &name->b,
1501                                                        NULL);
1502              pAssert(requestSize != 0);
1503
1504              // Copy the new key
1505              MemoryCopy(sensitive->sensitive.sym.t.buffer,
1506                         symValues, sensitive->sensitive.sym.t.size,
1507                         MAX_SENSITIVE_SIZE);
1508
1509              // copy the obfuscation value
1510              MemoryCopy(sensitive->seedValue.t.buffer,
1511                         &symValues[sensitive->sensitive.sym.t.size],
1512                         sensitive->seedValue.t.size,
1513                         sizeof(sensitive->seedValue.t.buffer));
1514       }
1515       else
1516       {
1517           // Copy input symmetric key to sensitive area as long as it will fit
1518           MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b,
1519                        MAX_SENSITIVE_SIZE);

       Family "2.0"                               TCG Published                                     Page 305
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                        October 30, 2014
       Trusted Platform Module Library                                                    Part 4: Supporting Routines

1520
1521              // Create the obfuscation value
1522              _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
1523                                          sensitive->seedValue.t.buffer,
1524                                          hashAlg, &seed->b,
1525                                          "symmetric obfuscation", &name->b, NULL);
1526       }
1527       return;
1528   }


       10.2.7.4    CryptGenerateKeySymmetric()

       This function derives a symmetric cipher key from the provided seed.

       Error Returns                     Meaning

       TPM_RC_KEY_SIZE                   key size in the public area does not match the size in the sensitive
                                         creation area

1529   static TPM_RC
1530   CryptGenerateKeySymmetric(
1531       TPMT_PUBLIC                    *publicArea,               //   IN/OUT: The public area template
1532                                                                 //       for the new key.
1533       TPMS_SENSITIVE_CREATE          *sensitiveCreate,          //   IN: sensitive creation data
1534       TPMT_SENSITIVE                 *sensitive,                //   OUT: sensitive area
1535       TPM_ALG_ID                      hashAlg,                  //   IN: hash algorithm for the KDF
1536       TPM2B_SEED                     *seed,                     //   IN: seed used in creation
1537       TPM2B_NAME                     *name                      //   IN: name of the object
1538       )
1539   {
1540       // If this is not a new key, then the provided key data must be the right size
1541       if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)
1542       {
1543           if(     (sensitiveCreate->data.t.size * 8)
1544               != publicArea->parameters.symDetail.sym.keyBits.sym)
1545               return TPM_RC_KEY_SIZE;
1546           // Make sure that the key size is OK.
1547           // This implementation only supports symmetric key sizes that are
1548           // multiples of 8
1549           if(publicArea->parameters.symDetail.sym.keyBits.sym % 8 != 0)
1550               return TPM_RC_KEY_SIZE;
1551       }
1552       else
1553       {
1554           // TPM is going to generate the key so set the size
1555           sensitive->sensitive.sym.t.size
1556               = publicArea->parameters.symDetail.sym.keyBits.sym / 8;
1557           sensitiveCreate->data.t.size = 0;
1558       }
1559       // Fill in the sensitive area
1560       CryptGenerateNewSymmetric(sensitiveCreate, sensitive, hashAlg,
1561                                 seed, name);
1562
1563       // Create unique area in public
1564       CryptComputeSymmetricUnique(publicArea->nameAlg,
1565                                   sensitive, &publicArea->unique.sym);
1566
1567       return TPM_RC_SUCCESS;
1568   }




       Page 306                                       TCG Published                                       Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
       Part 4: Supporting Routines                                                            Trusted Platform Module Library

       10.2.7.5     CryptXORObfuscation()

       This function implements XOR obfuscation. It should not be called if the hash algorithm is not
       implemented. The only return value from this function is TPM_RC_SUCCESS.

1569   #ifdef TPM_ALG_KEYEDHASH //% 5
1570   void
1571   CryptXORObfuscation(
1572       TPM_ALG_ID             hash,                  //   IN: hash algorithm for KDF
1573       TPM2B                 *key,                   //   IN: KDF key
1574       TPM2B                 *contextU,              //   IN: contextU
1575       TPM2B                 *contextV,              //   IN: contextV
1576       UINT32                 dataSize,              //   IN: size of data buffer
1577       BYTE                  *data                   //   IN/OUT: data to be XORed in place
1578       )
1579   {
1580       BYTE                   mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer
1581       BYTE                  *pm;
1582       UINT32                 i;
1583       UINT32                 counter = 0;
1584       UINT16                 hLen = CryptGetHashDigestSize(hash);
1585       UINT32                 requestSize = dataSize * 8;
1586       INT32                  remainBytes = (INT32) dataSize;
1587
1588       pAssert((key != NULL) && (data != NULL) && (hLen != 0));
1589
1590       // Call KDFa to generate XOR mask
1591       for(; remainBytes > 0; remainBytes -= hLen)
1592       {
1593           // Make a call to KDFa to get next iteration
1594           CryptKDFaOnce(hash, key, "XOR", contextU, contextV,
1595                         requestSize, mask, &counter);
1596
1597              // XOR next piece of the data
1598              pm = mask;
1599              for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)
1600                  *data++ ^= *pm++;
1601       }
1602       return;
1603   }
1604   #endif //TPM_ALG_KEYED_HASH //%5


       10.2.8     Initialization and shut down

       10.2.8.1     CryptInitUnits()

       This function is called when the TPM receives a _TPM_Init() indication. After function returns, the hash
       algorithms should be available.

       NOTE:           The hash algorithms do not have to be tested, they just need to be available. They have to be tested before the
                       TPM can accept HMAC authorization or return any result that relies on a hash algorithm.

1605   void
1606   CryptInitUnits(
1607       void
1608       )
1609   {
1610       // Initialize the vector of implemented algorithms
1611       AlgorithmGetImplementedVector(&g_implementedAlgorithms);
1612
1613       // Indicate that all test are necessary
1614       CryptInitializeToTest();


       Family "2.0"                                      TCG Published                                                   Page 307
       Level 00 Revision 01.16                  Copyright © TCG 2006-2014                                     October 30, 2014
       Trusted Platform Module Library                                               Part 4: Supporting Routines

1615
1616       // Call crypto engine unit initialization
1617       // It is assumed that crypt engine initialization should always succeed.
1618       // Otherwise, TPM should go to failure mode.
1619       if(_cpri__InitCryptoUnits(&TpmFail) != CRYPT_SUCCESS)
1620           FAIL(FATAL_ERROR_INTERNAL);
1621       return;
1622   }


       10.2.8.2    CryptStopUnits()

       This function is only used in a simulated environment. There should be no reason to shut down the
       cryptography on an actual TPM other than loss of power. After receiving TPM2_Startup(), the TPM should
       be able to accept commands until it loses power and, unless the TPM is in Failure Mode, the
       cryptographic algorithms should be available.

1623   void
1624   CryptStopUnits(
1625       void
1626       )
1627   {
1628       // Call crypto engine unit stopping
1629       _cpri__StopCryptoUnits();
1630
1631       return;
1632   }


       10.2.8.3    CryptUtilStartup()

       This function is called by TPM2_Startup() to initialize the functions in this crypto library and in the
       provided CryptoEngine(). In this implementation, the only initialization required in this library is
       initialization of the Commit nonce on TPM Reset.
       This function returns false if some problem prevents the functions from starting correctly. The TPM should
       go into failure mode.

1633   BOOL
1634   CryptUtilStartup(
1635       STARTUP_TYPE         type               // IN: the startup type
1636       )
1637   {
1638       // Make sure that the crypto library functions are ready.
1639       // NOTE: need to initialize the crypto before loading
1640       // the RND state may trigger a self-test which
1641       // uses the
1642       if( !_cpri__Startup())
1643           return FALSE;
1644
1645       // Initialize the state of the RNG.
1646       CryptDrbgGetPutState(PUT_STATE);
1647
1648       if(type == SU_RESET)
1649       {
1650   #ifdef TPM_ALG_ECC
1651           // Get a new random commit nonce
1652           gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
1653           _cpri__GenerateRandom(gr.commitNonce.t.size, gr.commitNonce.t.buffer);
1654           // Reset the counter and commit array
1655           gr.commitCounter = 0;
1656           MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));
1657   #endif // TPM_ALG_ECC
1658       }

       Page 308                                    TCG Published                                   Family "2.0"
       October 30, 2014                     Copyright © TCG 2006-2014                 Level 00 Revision 01.16
       Part 4: Supporting Routines                                              Trusted Platform Module Library

1659
1660        // If the shutdown was orderly, then the values recovered from NV will
1661        // be OK to use. If the shutdown was not orderly, then a TPM Reset was required
1662        // and we would have initialized in the code above.
1663
1664        return TRUE;
1665   }


       10.2.9     Algorithm-Independent Functions

       10.2.9.1    Introduction

       These functions are used generically when a function of a general type (e.g., symmetric encryption) is
       required. The functions will modify the parameters as required to interface to the indicated algorithms.

       10.2.9.2    CryptIsAsymAlgorithm()

       This function indicates if an algorithm is an asymmetric algorithm.

       Return Value                      Meaning

       TRUE                              if it is an asymmetric algorithm
       FALSE                             if it is not an asymmetric algorithm

1666   BOOL
1667   CryptIsAsymAlgorithm(
1668        TPM_ALG_ID           algID                // IN: algorithm ID
1669        )
1670   {
1671       return (
1672   #ifdef TPM_ALG_RSA
1673                algID == TPM_ALG_RSA
1674   #endif
1675   #if defined TPM_ALG_RSA && defined TPM_ALG_ECC
1676                ||
1677   #endif
1678   #ifdef TPM_ALG_ECC
1679                algID == TPM_ALG_ECC
1680   #endif
1681              );
1682   }


       10.2.9.3    CryptGetSymmetricBlockSize()

       This function returns the size in octets of the symmetric encryption block used by an algorithm and key
       size combination.

1683   INT16
1684   CryptGetSymmetricBlockSize(
1685        TPMI_ALG_SYM         algorithm,           // IN: symmetric algorithm
1686        UINT16               keySize              // IN: key size in bit
1687        )
1688   {
1689        return _cpri__GetSymmetricBlockSize(algorithm, keySize);
1690   }




       Family "2.0"                                   TCG Published                                  Page 309
       Level 00 Revision 01.16                Copyright © TCG 2006-2014                     October 30, 2014
       Trusted Platform Module Library                                             Part 4: Supporting Routines

       10.2.9.4    CryptSymmetricEncrypt()

       This function does in-place encryption of a buffer using the indicated symmetric algorithm, key, IV, and
       mode. If the symmetric algorithm and mode are not defined, the TPM will fail.

1691   void
1692   CryptSymmetricEncrypt(
1693       BYTE                    *encrypted,         //   OUT: the encrypted data
1694       TPM_ALG_ID               algorithm,         //   IN: algorithm for encryption
1695       UINT16                   keySizeInBits,     //   IN: key size in bit
1696       TPMI_ALG_SYM_MODE        mode,              //   IN: symmetric encryption mode
1697       BYTE                    *key,               //   IN: encryption key
1698       TPM2B_IV                *ivIn,              //   IN/OUT: Input IV and output chaining
1699                                                   //       value for the next block
1700       UINT32                   dataSize,          //   IN: data size in byte
1701       BYTE                    *data               //   IN/OUT: data buffer
1702       )
1703   {
1704
1705       TPM2B_IV                 defaultIv = {0};
1706       TPM2B_IV                *iv = (ivIn != NULL) ? ivIn : &defaultIv;
1707
1708       TEST(algorithm);
1709
1710       pAssert(encrypted != NULL && key != NULL);
1711
1712       // this check can pass but the case below can fail. ALG_xx_VALUE values are
1713       // defined for all algorithms but the TPM_ALG_xx might not be.
1714       if(algorithm == ALG_AES_VALUE || algorithm == ALG_SM4_VALUE)
1715       {
1716           if(mode != TPM_ALG_ECB)
1717               defaultIv.t.size = 16;
1718           // A provided IV has to be the right size
1719           pAssert(mode == TPM_ALG_ECB || iv->t.size == 16);
1720       }
1721       switch(algorithm)
1722       {
1723   #ifdef TPM_ALG_AES
1724           case TPM_ALG_AES:
1725           {
1726               switch (mode)
1727               {
1728                   case TPM_ALG_CTR:
1729                       _cpri__AESEncryptCTR(encrypted, keySizeInBits, key,
1730                                            iv->t.buffer, dataSize, data);
1731                       break;
1732                   case TPM_ALG_OFB:
1733                       _cpri__AESEncryptOFB(encrypted, keySizeInBits, key,
1734                                            iv->t.buffer, dataSize, data);
1735                       break;
1736                   case TPM_ALG_CBC:
1737                       _cpri__AESEncryptCBC(encrypted, keySizeInBits, key,
1738                                            iv->t.buffer, dataSize, data);
1739                       break;
1740                   case TPM_ALG_CFB:
1741                       _cpri__AESEncryptCFB(encrypted, keySizeInBits, key,
1742                                            iv->t.buffer, dataSize, data);
1743                       break;
1744                   case TPM_ALG_ECB:
1745                       _cpri__AESEncryptECB(encrypted, keySizeInBits, key,
1746                                            dataSize, data);
1747                       break;
1748                   default:
1749                       pAssert(0);
1750               }

       Page 310                                   TCG Published                                   Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014                 Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

1751              }
1752              break;
1753   #endif
1754   #ifdef TPM_ALG_SM4
1755           case TPM_ALG_SM4:
1756           {
1757               switch (mode)
1758               {
1759                   case TPM_ALG_CTR:
1760                       _cpri__SM4EncryptCTR(encrypted, keySizeInBits, key,
1761                                            iv->t.buffer, dataSize, data);
1762                       break;
1763                   case TPM_ALG_OFB:
1764                       _cpri__SM4EncryptOFB(encrypted, keySizeInBits, key,
1765                                            iv->t.buffer, dataSize, data);
1766                       break;
1767                   case TPM_ALG_CBC:
1768                       _cpri__SM4EncryptCBC(encrypted, keySizeInBits, key,
1769                                            iv->t.buffer, dataSize, data);
1770                       break;
1771
1772                       case TPM_ALG_CFB:
1773                           _cpri__SM4EncryptCFB(encrypted, keySizeInBits, key,
1774                                                iv->t.buffer, dataSize, data);
1775                           break;
1776                       case TPM_ALG_ECB:
1777                           _cpri__SM4EncryptECB(encrypted, keySizeInBits, key,
1778                                                dataSize, data);
1779                           break;
1780                       default:
1781                           pAssert(0);
1782                  }
1783              }
1784              break;
1785
1786   #endif
1787              default:
1788                  pAssert(FALSE);
1789                  break;
1790       }
1791
1792       return;
1793
1794   }


       10.2.9.5    CryptSymmetricDecrypt()

       This function does in-place decryption of a buffer using the indicated symmetric algorithm, key, IV, and
       mode. If the symmetric algorithm and mode are not defined, the TPM will fail.

1795   void
1796   CryptSymmetricDecrypt(
1797       BYTE                      *decrypted,
1798       TPM_ALG_ID                 algorithm,       //   IN: algorithm for encryption
1799       UINT16                     keySizeInBits,   //   IN: key size in bit
1800       TPMI_ALG_SYM_MODE          mode,            //   IN: symmetric encryption mode
1801       BYTE                      *key,             //   IN: encryption key
1802       TPM2B_IV                  *ivIn,            //   IN/OUT: IV for next block
1803       UINT32                     dataSize,        //   IN: data size in byte
1804       BYTE                      *data             //   IN/OUT: data buffer
1805       )
1806   {
1807       BYTE                      *iv = NULL;
1808       BYTE                       defaultIV[sizeof(TPMT_HA)];

       Family "2.0"                               TCG Published                                     Page 311
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                        October 30, 2014
       Trusted Platform Module Library                                    Part 4: Supporting Routines

1809
1810       TEST(algorithm);
1811
1812       if(
1813   #ifdef TPM_ALG_AES
1814             algorithm == TPM_ALG_AES
1815   #endif
1816   #if defined TPM_ALG_AES && defined TPM_ALG_SM4
1817          ||
1818   #endif
1819   #ifdef TPM_ALG_SM4
1820             algorithm == TPM_ALG_SM4
1821   #endif
1822         )
1823       {
1824           // Both SM4 and AES have block size of 128 bits
1825           // If the iv is not provided, create a default of 0
1826           if(ivIn == NULL)
1827           {
1828                // Initialize the default IV
1829                iv = defaultIV;
1830                MemorySet(defaultIV, 0, 16);
1831           }
1832           else
1833           {
1834                // A provided IV has to be the right size
1835                pAssert(mode == TPM_ALG_ECB || ivIn->t.size == 16);
1836                iv = &(ivIn->t.buffer[0]);
1837           }
1838       }
1839
1840       switch(algorithm)
1841       {
1842   #ifdef TPM_ALG_AES
1843       case TPM_ALG_AES:
1844       {
1845
1846            switch (mode)
1847            {
1848                case TPM_ALG_CTR:
1849                    _cpri__AESDecryptCTR(decrypted, keySizeInBits,   key, iv,
1850                                         dataSize, data);
1851                    break;
1852                case TPM_ALG_OFB:
1853                    _cpri__AESDecryptOFB(decrypted, keySizeInBits,   key, iv,
1854                                         dataSize, data);
1855                    break;
1856                case TPM_ALG_CBC:
1857                    _cpri__AESDecryptCBC(decrypted, keySizeInBits,   key, iv,
1858                                         dataSize, data);
1859                    break;
1860                case TPM_ALG_CFB:
1861                    _cpri__AESDecryptCFB(decrypted, keySizeInBits,   key, iv,
1862                                         dataSize, data);
1863                    break;
1864                case TPM_ALG_ECB:
1865                    _cpri__AESDecryptECB(decrypted, keySizeInBits,   key,
1866                                         dataSize, data);
1867                    break;
1868                default:
1869                    pAssert(0);
1870            }
1871            break;
1872       }
1873   #endif //TPM_ALG_AES
1874   #ifdef TPM_ALG_SM4

       Page 312                               TCG Published                             Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                                   Trusted Platform Module Library

1875       case TPM_ALG_SM4 :
1876           switch (mode)
1877           {
1878               case TPM_ALG_CTR:
1879                   _cpri__SM4DecryptCTR(decrypted, keySizeInBits,                       key, iv,
1880                                        dataSize, data);
1881                   break;
1882               case TPM_ALG_OFB:
1883                   _cpri__SM4DecryptOFB(decrypted, keySizeInBits,                       key, iv,
1884                                        dataSize, data);
1885                   break;
1886               case TPM_ALG_CBC:
1887                   _cpri__SM4DecryptCBC(decrypted, keySizeInBits,                       key, iv,
1888                                        dataSize, data);
1889                   break;
1890               case TPM_ALG_CFB:
1891                   _cpri__SM4DecryptCFB(decrypted, keySizeInBits,                       key, iv,
1892                                        dataSize, data);
1893                   break;
1894               case TPM_ALG_ECB:
1895                   _cpri__SM4DecryptECB(decrypted, keySizeInBits,                       key,
1896                                        dataSize, data);
1897                   break;
1898               default:
1899                   pAssert(0);
1900           }
1901           break;
1902   #endif //TPM_ALG_SM4
1903
1904       default:
1905           pAssert(FALSE);
1906           break;
1907       }
1908       return;
1909   }


       10.2.9.6    CryptSecretEncrypt()

       This function creates a secret value and its associated secret structure using an asymmetric algorithm.
       This function is used by TPM2_Rewrap() TPM2_MakeCredential(), and TPM2_Duplicate().

       Error Returns                   Meaning

       TPM_RC_ATTRIBUTES               keyHandle does not reference a valid decryption key
       TPM_RC_KEY                      invalid ECC key (public point is not on the curve)
       TPM_RC_SCHEME                   RSA key with an unsupported padding scheme
       TPM_RC_VALUE                    numeric value of the data to be decrypted is greater than the RSA
                                       key modulus

1910   TPM_RC
1911   CryptSecretEncrypt(
1912       TPMI_DH_OBJECT                 keyHandle,           //   IN: encryption key handle
1913       const char                    *label,               //   IN: a null-terminated string as L
1914       TPM2B_DATA                    *data,                //   OUT: secret value
1915       TPM2B_ENCRYPTED_SECRET        *secret               //   OUT: secret structure
1916       )
1917   {
1918       TPM_RC          result = TPM_RC_SUCCESS;
1919       OBJECT         *encryptKey = ObjectGet(keyHandle);              // TPM key used for encrypt
1920
1921       pAssert(data != NULL && secret != NULL);

       Family "2.0"                                 TCG Published                                             Page 313
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                                  October 30, 2014
       Trusted Platform Module Library                                    Part 4: Supporting Routines

1922
1923       // The output secret value has the size of the digest produced by the nameAlg.
1924       data->t.size = CryptGetHashDigestSize(encryptKey->publicArea.nameAlg);
1925
1926       pAssert(encryptKey->publicArea.objectAttributes.decrypt == SET);
1927
1928       switch(encryptKey->publicArea.type)
1929       {
1930   #ifdef TPM_ALG_RSA
1931           case TPM_ALG_RSA:
1932           {
1933               TPMT_RSA_DECRYPT            scheme;
1934
1935                 // Use OAEP scheme
1936                 scheme.scheme = TPM_ALG_OAEP;
1937                 scheme.details.oaep.hashAlg = encryptKey->publicArea.nameAlg;
1938
1939                 // Create secret data from RNG
1940                 CryptGenerateRandom(data->t.size, data->t.buffer);
1941
1942                 // Encrypt the data by RSA OAEP into encrypted secret
1943                 result = CryptEncryptRSA(&secret->t.size, secret->t.secret,
1944                                          encryptKey, &scheme,
1945                                          data->t.size, data->t.buffer, label);
1946           }
1947           break;
1948   #endif //TPM_ALG_RSA
1949
1950   #ifdef TPM_ALG_ECC
1951           case TPM_ALG_ECC:
1952           {
1953               TPMS_ECC_POINT         eccPublic;
1954               TPM2B_ECC_PARAMETER    eccPrivate;
1955               TPMS_ECC_POINT         eccSecret;
1956               BYTE                   *buffer = secret->t.secret;
1957
1958                 // Need to make sure that the public point of the key is on the
1959                 // curve defined by the key.
1960                 if(!_cpri__EccIsPointOnCurve(
1961                             encryptKey->publicArea.parameters.eccDetail.curveID,
1962                             &encryptKey->publicArea.unique.ecc))
1963                     result = TPM_RC_KEY;
1964                 else
1965                 {
1966
1967                      // Call crypto engine to create an auxiliary ECC key
1968                      // We assume crypt engine initialization should always success.
1969                      // Otherwise, TPM should go to failure mode.
1970                      CryptNewEccKey(encryptKey->publicArea.parameters.eccDetail.curveID,
1971                                     &eccPublic, &eccPrivate);
1972
1973                      // Marshal ECC public to secret structure. This will be used by the
1974                      // recipient to decrypt the secret with their private key.
1975                      secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL);
1976
1977                      // Compute ECDH shared secret which is R = [d]Q where d is the
1978                      // private part of the ephemeral key and Q is the public part of a
1979                      // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret
1980                      // because the auxiliary ECC key is just created according to the
1981                      // parameters of input ECC encrypt key.
1982                      if(     CryptEccPointMultiply(&eccSecret,
1983                                      encryptKey->publicArea.parameters.eccDetail.curveID,
1984                                      &eccPrivate,
1985                                      &encryptKey->publicArea.unique.ecc)
1986                          != CRYPT_SUCCESS)
1987                           result = TPM_RC_KEY;

       Page 314                               TCG Published                             Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                                         Trusted Platform Module Library

1988                      else
1989
1990                          //     The secret value is computed from Z using KDFe as:
1991                          //     secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
1992                          //     Where:
1993                          //      HashID the nameAlg of the decrypt key
1994                          //      Z    the x coordinate (Px) of the product (P) of the point
1995                          //           (Q) of the secret and the private x coordinate (de,V)
1996                          //           of the decryption key
1997                          //      Use a null-terminated string containing "SECRET"
1998                          //      PartyUInfo the x coordinate of the point in the secret
1999                          //                   (Qe,U )
2000                          //      PartyVInfo the x coordinate of the public key (Qs,V )
2001                          //      bits     the number of bits in the digest of HashID
2002                          //     Retrieve seed from KDFe
2003
2004                          CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b,
2005                                    label, &eccPublic.x.b,
2006                                    &encryptKey->publicArea.unique.ecc.x.b,
2007                                    data->t.size * 8, data->t.buffer);
2008               }
2009           }
2010           break;
2011   #endif //TPM_ALG_ECC
2012
2013       default:
2014           FAIL(FATAL_ERROR_INTERNAL);
2015           break;
2016       }
2017
2018       return result;
2019   }


       10.2.9.7   CryptSecretDecrypt()

       Decrypt a secret value by asymmetric (or symmetric) algorithm This function is used for
       ActivateCredential() and Import for asymmetric decryption, and StartAuthSession() for both asymmetric
       and symmetric decryption process

       Error Returns                    Meaning

       TPM_RC_ATTRIBUTES                RSA key is not a decryption key
       TPM_RC_BINDING                   Invalid RSA key (public and private parts are not cryptographically
                                        bound.
       TPM_RC_ECC_POINT                 ECC point in the secret is not on the curve
       TPM_RC_INSUFFICIENT              failed to retrieve ECC point from the secret
       TPM_RC_NO_RESULT                 multiplication resulted in ECC point at infinity
       TPM_RC_SIZE                      data to decrypt is not of the same size as RSA key
       TPM_RC_VALUE                     For RSA key, numeric value of the encrypted data is greater than the
                                        modulus, or the recovered data is larger than the output buffer. For
                                        keyedHash or symmetric key, the secret is larger than the size of the
                                        digest produced by the name algorithm.
       TPM_RC_FAILURE                   internal error

2020   TPM_RC
2021   CryptSecretDecrypt(
2022       TPM_HANDLE                      tpmKey,               // IN: decrypt key
2023       TPM2B_NONCE                    *nonceCaller,          // IN: nonceCaller. It is needed for
2024                                                             //     symmetric decryption. For

       Family "2.0"                                      TCG Published                                          Page 315
       Level 00 Revision 01.16               Copyright © TCG 2006-2014                                 October 30, 2014
       Trusted Platform Module Library                                          Part 4: Supporting Routines

2025                                                       //     asymmetric decryption, this
2026                                                       //     parameter is NULL
2027       const char                    *label,           // IN: a null-terminated string as L
2028       TPM2B_ENCRYPTED_SECRET        *secret,          // IN: input secret
2029       TPM2B_DATA                    *data             // OUT: decrypted secret value
2030       )
2031   {
2032       TPM_RC         result = TPM_RC_SUCCESS;
2033       OBJECT         *decryptKey = ObjectGet(tpmKey);          //TPM key used for decrypting
2034
2035       // Decryption for secret
2036       switch(decryptKey->publicArea.type)
2037       {
2038
2039   #ifdef TPM_ALG_RSA
2040           case TPM_ALG_RSA:
2041           {
2042               TPMT_RSA_DECRYPT             scheme;
2043
2044                 // Use OAEP scheme
2045                 scheme.scheme = TPM_ALG_OAEP;
2046                 scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;
2047
2048                 // Set the output buffer capacity
2049                 data->t.size = sizeof(data->t.buffer);
2050
2051                 // Decrypt seed by RSA OAEP
2052                 result = CryptDecryptRSA(&data->t.size, data->t.buffer, decryptKey,
2053                                           &scheme,
2054                                           secret->t.size, secret->t.secret,label);
2055                 if(    (result == TPM_RC_SUCCESS)
2056                     && (data->t.size
2057                          > CryptGetHashDigestSize(decryptKey->publicArea.nameAlg)))
2058                      result = TPM_RC_VALUE;
2059           }
2060           break;
2061   #endif //TPM_ALG_RSA
2062
2063   #ifdef TPM_ALG_ECC
2064           case TPM_ALG_ECC:
2065           {
2066               TPMS_ECC_POINT            eccPublic;
2067               TPMS_ECC_POINT            eccSecret;
2068               BYTE                     *buffer = secret->t.secret;
2069               INT32                     size = secret->t.size;
2070
2071                 // Retrieve ECC point from secret buffer
2072                 result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);
2073                 if(result == TPM_RC_SUCCESS)
2074                 {
2075                     result = CryptEccPointMultiply(&eccSecret,
2076                                    decryptKey->publicArea.parameters.eccDetail.curveID,
2077                                    &decryptKey->sensitive.sensitive.ecc,
2078                                    &eccPublic);
2079
2080                      if(result == TPM_RC_SUCCESS)
2081                      {
2082
2083                          // Set the size of the "recovered" secret value to be the size
2084                          // of the digest produced by the nameAlg.
2085                          data->t.size =
2086                                  CryptGetHashDigestSize(decryptKey->publicArea.nameAlg);
2087
2088                          // The secret value is computed from Z using KDFe as:
2089                          // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
2090                          // Where:

       Page 316                                     TCG Published                             Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014              Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

2091                          // HashID -- the nameAlg of the decrypt key
2092                          // Z -- the x coordinate (Px) of the product (P) of the point
2093                          //        (Q) of the secret and the private x coordinate (de,V)
2094                          //        of the decryption key
2095                          // Use -- a null-terminated string containing "SECRET"
2096                          // PartyUInfo -- the x coordinate of the point in the secret
2097                          //              (Qe,U )
2098                          // PartyVInfo -- the x coordinate of the public key (Qs,V )
2099                          // bits -- the number of bits in the digest of HashID
2100                          // Retrieve seed from KDFe
2101                          CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label,
2102                                    &eccPublic.x.b,
2103                                    &decryptKey->publicArea.unique.ecc.x.b,
2104                                    data->t.size * 8, data->t.buffer);
2105                      }
2106                  }
2107           }
2108           break;
2109   #endif //TPM_ALG_ECC
2110
2111            case TPM_ALG_KEYEDHASH:
2112                // The seed size can not be bigger than the digest size of nameAlg
2113                if(secret->t.size >
2114                        CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))
2115                    result = TPM_RC_VALUE;
2116                else
2117                {
2118                    // Retrieve seed by XOR Obfuscation:
2119                    //    seed = XOR(secret, hash, key, nonceCaller, nullNonce)
2120                    //    where:
2121                    //    secret the secret parameter from the TPM2_StartAuthHMAC
2122                    //             command
2123                    //             which contains the seed value
2124                    //    hash     nameAlg of tpmKey
2125                    //    key      the key or data value in the object referenced by
2126                    //             entityHandle in the TPM2_StartAuthHMAC command
2127                    //    nonceCaller the parameter from the TPM2_StartAuthHMAC command
2128                    //    nullNonce    a zero-length nonce
2129                    // XOR Obfuscation in place
2130                    CryptXORObfuscation(decryptKey->publicArea.nameAlg,
2131                                         &decryptKey->sensitive.sensitive.bits.b,
2132                                         &nonceCaller->b, NULL,
2133                                         secret->t.size, secret->t.secret);
2134                    // Copy decrypted seed
2135                    MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2136                }
2137                break;
2138            case TPM_ALG_SYMCIPHER:
2139                {
2140                    TPM2B_IV                 iv = {0};
2141                    TPMT_SYM_DEF_OBJECT      *symDef;
2142                    // The seed size can not be bigger than the digest size of nameAlg
2143                    if(secret->t.size >
2144                             CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))
2145                        result = TPM_RC_VALUE;
2146                    else
2147                    {
2148                        symDef = &decryptKey->publicArea.parameters.symDetail.sym;
2149                        iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
2150                                                                 symDef->keyBits.sym);
2151                        pAssert(iv.t.size != 0);
2152                        if(nonceCaller->t.size >= iv.t.size)
2153                             MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size,
2154                                         sizeof(iv.t.buffer));
2155                        else
2156                             MemoryCopy(iv.b.buffer, nonceCaller->t.buffer,

       Family "2.0"                           TCG Published                                Page 317
       Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
       Trusted Platform Module Library                                    Part 4: Supporting Routines

2157                                          nonceCaller->t.size, sizeof(iv.t.buffer));
2158                           // CFB decrypt in place, using nonceCaller as iv
2159                           CryptSymmetricDecrypt(secret->t.secret, symDef->algorithm,
2160                                              symDef->keyBits.sym, TPM_ALG_CFB,
2161                                              decryptKey->sensitive.sensitive.sym.t.buffer,
2162                                              &iv, secret->t.size, secret->t.secret);
2163
2164                           // Copy decrypted seed
2165                           MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2166                       }
2167                  }
2168                  break;
2169              default:
2170                  pAssert(0);
2171                  break;
2172       }
2173       return result;
2174   }


       10.2.9.8    CryptParameterEncryption()

       This function does in-place encryption of a response parameter.

2175   void
2176   CryptParameterEncryption(
2177       TPM_HANDLE           handle,            // IN: encrypt session handle
2178       TPM2B               *nonceCaller,       // IN: nonce caller
2179       UINT16               leadingSizeInByte, // IN: the size of the leading size field in
2180                                               //     byte
2181       TPM2B_AUTH          *extraKey,          // IN: additional key material other than
2182                                               //     session auth
2183       BYTE                *buffer             // IN/OUT: parameter buffer to be encrypted
2184       )
2185   {
2186       SESSION     *session = SessionGet(handle); // encrypt session
2187       TPM2B_TYPE(SYM_KEY, ( sizeof(extraKey->t.buffer)
2188                            + sizeof(session->sessionKey.t.buffer)));
2189       TPM2B_SYM_KEY        key;               // encryption key
2190       UINT32               cipherSize = 0;    // size of cipher text
2191
2192       pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer));
2193
2194       // Retrieve encrypted data size.
2195       if(leadingSizeInByte == 2)
2196       {
2197           // Extract the first two bytes as the size field as the data size
2198           // encrypt
2199           cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
2200           // advance the buffer
2201           buffer = &buffer[2];
2202       }
2203   #ifdef      TPM4B
2204       else if(leadingSizeInByte == 4)
2205       {
2206           // use the first four bytes to indicate the number of bytes to encrypt
2207           cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
2208           //advance pointer
2209           buffer = &buffer[4];
2210       }
2211   #endif
2212       else
2213       {
2214           pAssert(FALSE);
2215       }


       Page 318                                    TCG Published                        Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014        Level 00 Revision 01.16
       Part 4: Supporting Routines                                               Trusted Platform Module Library

2216
2217       // Compute encryption key by concatenating sessionAuth with extra key
2218       MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
2219       MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
2220
2221       if (session->symmetric.algorithm == TPM_ALG_XOR)
2222
2223           // XOR parameter encryption formulation:
2224           //    XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
2225           CryptXORObfuscation(session->authHashAlg, &(key.b),
2226                                      &(session->nonceTPM.b),
2227                                      nonceCaller, cipherSize, buffer);
2228       else
2229           ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
2230                                 session->symmetric.keyBits.aes, &(key.b),
2231                                 nonceCaller, &(session->nonceTPM.b),
2232                                 cipherSize, buffer);
2233       return;
2234   }


       10.2.9.9   CryptParameterDecryption()

       This function does in-place decryption of a command parameter.

       Error Returns                  Meaning

       TPM_RC_SIZE                    The number of bytes in the input buffer is less than the number of
                                      bytes to be decrypted.

2235   TPM_RC
2236   CryptParameterDecryption(
2237       TPM_HANDLE          handle,                 //   IN: encrypted session handle
2238       TPM2B              *nonceCaller,            //   IN: nonce caller
2239       UINT32              bufferSize,             //   IN: size of parameter buffer
2240       UINT16              leadingSizeInByte,      //   IN: the size of the leading size field in
2241                                                   //       byte
2242       TPM2B_AUTH         *extraKey,               //   IN: the authValue
2243       BYTE               *buffer                  //   IN/OUT: parameter buffer to be decrypted
2244       )
2245   {
2246       SESSION         *session = SessionGet(handle); // encrypt session
2247       // The HMAC key is going to be the concatenation of the session key and any
2248       // additional key material (like the authValue). The size of both of these
2249       // is the size of the buffer which can contain a TPMT_HA.
2250       TPM2B_TYPE(HMAC_KEY, ( sizeof(extraKey->t.buffer)
2251                             + sizeof(session->sessionKey.t.buffer)));
2252       TPM2B_HMAC_KEY          key;            // decryption key
2253       UINT32                  cipherSize = 0; // size of cipher text
2254
2255       pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer));
2256
2257       // Retrieve encrypted data size.
2258       if(leadingSizeInByte == 2)
2259       {
2260           // The first two bytes of the buffer are the size of the
2261           // data to be decrypted
2262           cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
2263           buffer = &buffer[2];    // advance the buffer
2264       }
2265   #ifdef TPM4B
2266       else if(leadingSizeInByte == 4)
2267       {
2268           // the leading size is four bytes so get the four byte size field
2269           cipherSize = BYTE_ARRAY_TO_UINT32(buffer);

       Family "2.0"                               TCG Published                                            Page 319
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                           October 30, 2014
       Trusted Platform Module Library                                                 Part 4: Supporting Routines

2270           buffer = &buffer[4];    //advance pointer
2271       }
2272   #endif
2273       else
2274       {
2275           pAssert(FALSE);
2276       }
2277       if(cipherSize > bufferSize)
2278           return TPM_RC_SIZE;
2279
2280       // Compute decryption key by concatenating sessionAuth with extra input key
2281       MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
2282       MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
2283
2284       if(session->symmetric.algorithm == TPM_ALG_XOR)
2285           // XOR parameter decryption formulation:
2286           //    XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
2287           // Call XOR obfuscation function
2288           CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller,
2289                                      &(session->nonceTPM.b), cipherSize, buffer);
2290       else
2291           // Assume that it is one of the symmetric block ciphers.
2292           ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg,
2293                                 session->symmetric.keyBits.sym,
2294                                 &key.b, nonceCaller, &session->nonceTPM.b,
2295                                 cipherSize, buffer);
2296
2297       return TPM_RC_SUCCESS;
2298
2299   }


       10.2.9.10 CryptComputeSymmetricUnique()

       This function computes the unique field in public area for symmetric objects.

2300   void
2301   CryptComputeSymmetricUnique(
2302       TPMI_ALG_HASH        nameAlg,           // IN: object name algorithm
2303       TPMT_SENSITIVE      *sensitive,         // IN: sensitive area
2304       TPM2B_DIGEST        *unique             // OUT: unique buffer
2305       )
2306   {
2307       HASH_STATE     hashState;
2308
2309       pAssert(sensitive != NULL && unique != NULL);
2310
2311       // Compute the public value as the hash of sensitive.symkey || unique.buffer
2312       unique->t.size = CryptGetHashDigestSize(nameAlg);
2313       CryptStartHash(nameAlg, &hashState);
2314
2315       // Add obfuscation value
2316       CryptUpdateDigest2B(&hashState, &sensitive->seedValue.b);
2317
2318       // Add sensitive value
2319       CryptUpdateDigest2B(&hashState, &sensitive->sensitive.any.b);
2320
2321       CryptCompleteHash2B(&hashState, &unique->b);
2322
2323       return;
2324   }
2325   #if 0 //%




       Page 320                                     TCG Published                                    Family "2.0"
       October 30, 2014                     Copyright © TCG 2006-2014                   Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

       10.2.9.11 CryptComputeSymValue()

       This function computes the seedValue field in asymmetric sensitive areas.

2326   void
2327   CryptComputeSymValue(
2328        TPM_HANDLE            parentHandle,      //   IN: parent handle of the object to be created
2329        TPMT_PUBLIC          *publicArea,        //   IN/OUT: the public area template
2330        TPMT_SENSITIVE       *sensitive,         //   IN: sensitive area
2331        TPM2B_SEED           *seed,              //   IN: the seed
2332        TPMI_ALG_HASH         hashAlg,           //   IN: hash algorithm for KDFa
2333        TPM2B_NAME           *name               //   IN: object name
2334        )
2335   {
2336        TPM2B_AUTH       *proof = NULL;
2337
2338        if(CryptIsAsymAlgorithm(publicArea->type))
2339        {
2340            // Generate seedValue only when an asymmetric key is a storage key
2341            if(publicArea->objectAttributes.decrypt == SET
2342                      && publicArea->objectAttributes.restricted == SET)
2343            {
2344                 // If this is a primary object in the endorsement hierarchy, use
2345                 // ehProof in the creation of the symmetric seed so that child
2346                 // objects in the endorsement hierarchy are voided on TPM2_Clear()
2347                 // or TPM2_ChangeEPS()
2348                 if(    parentHandle == TPM_RH_ENDORSEMENT
2349                     && publicArea->objectAttributes.fixedTPM == SET)
2350                      proof = &gp.ehProof;
2351            }
2352            else
2353            {
2354                 sensitive->seedValue.t.size = 0;
2355                 return;
2356            }
2357        }
2358
2359        // For all object types, the size of seedValue is the digest size of nameAlg
2360        sensitive->seedValue.t.size = CryptGetHashDigestSize(publicArea->nameAlg);
2361
2362        // Compute seedValue using implementation-dependent method
2363        _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
2364                                    sensitive->seedValue.t.buffer,
2365                                    hashAlg,
2366                                    &seed->b,
2367                                    "seedValue",
2368                                    &name->b,
2369                                    (TPM2B *)proof);
2370        return;
2371   }
2372   #endif //%


       10.2.9.12 CryptCreateObject()

       This function creates an object. It:
       a) fills in the created key in public and sensitive area;
       b) creates a random number in sensitive area for symmetric keys; and
       c) compute the unique id in public area for symmetric keys.




       Family "2.0"                                  TCG Published                                 Page 321
       Level 00 Revision 01.16                Copyright © TCG 2006-2014                    October 30, 2014
       Trusted Platform Module Library                                                     Part 4: Supporting Routines


       Error Returns                     Meaning

       TPM_RC_KEY_SIZE                   key size in the public area does not match the size in the sensitive
                                         creation area for a symmetric key
       TPM_RC_RANGE                      for an RSA key, the exponent is not supported
       TPM_RC_SIZE                       sensitive data size is larger than allowed for the scheme for a keyed
                                         hash object
       TPM_RC_VALUE                      exponent is not prime or could not find a prime using the provided
                                         parameters for an RSA key; unsupported name algorithm for an ECC
                                         key

2373   TPM_RC
2374   CryptCreateObject(
2375       TPM_HANDLE                       parentHandle,            //   IN/OUT: indication of the seed
2376                                                                 //       source
2377       TPMT_PUBLIC                    *publicArea,               //   IN/OUT: public area
2378       TPMS_SENSITIVE_CREATE          *sensitiveCreate,          //   IN: sensitive creation
2379       TPMT_SENSITIVE                 *sensitive                 //   OUT: sensitive area
2380       )
2381   {
2382       // Next value is a placeholder for a random seed that is used in
2383       // key creation when the parent is not a primary seed. It has the same
2384       // size as the primary seed.
2385
2386       TPM2B_SEED          localSeed;            // data to seed key creation if this
2387                                                 // is not a primary seed
2388
2389       TPM2B_SEED         *seed = NULL;
2390       TPM_RC              result = TPM_RC_SUCCESS;
2391
2392       TPM2B_NAME          name;
2393       TPM_ALG_ID          hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
2394       OBJECT             *parent;
2395       UINT32              counter;
2396
2397       // Set the sensitive type for the object
2398       sensitive->sensitiveType = publicArea->type;
2399       ObjectComputeName(publicArea, &name);
2400
2401       // For all objects, copy the initial auth data
2402       sensitive->authValue = sensitiveCreate->userAuth;
2403
2404       // If this is a permanent handle assume that it is a hierarchy
2405       if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
2406       {
2407           seed = HierarchyGetPrimarySeed(parentHandle);
2408       }
2409       else
2410       {
2411           // If not hierarchy handle, get parent
2412           parent = ObjectGet(parentHandle);
2413           hashAlg = parent->publicArea.nameAlg;
2414
2415            // Use random value as seed for non-primary objects
2416            localSeed.t.size = PRIMARY_SEED_SIZE;
2417            CryptGenerateRandom(PRIMARY_SEED_SIZE, localSeed.t.buffer);
2418            seed = &localSeed;
2419       }
2420
2421       switch(publicArea->type)
2422       {
2423   #ifdef TPM_ALG_RSA
2424           // Create RSA key

       Page 322                                       TCG Published                                        Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

2425       case TPM_ALG_RSA:
2426           result = CryptGenerateKeyRSA(publicArea, sensitive,
2427                                        hashAlg, seed, &name, &counter);
2428           break;
2429   #endif // TPM_ALG_RSA
2430
2431   #ifdef TPM_ALG_ECC
2432           // Create ECC key
2433       case TPM_ALG_ECC:
2434           result = CryptGenerateKeyECC(publicArea, sensitive,
2435                                            hashAlg, seed, &name, &counter);
2436           break;
2437   #endif // TPM_ALG_ECC
2438
2439           // Collect symmetric key information
2440       case TPM_ALG_SYMCIPHER:
2441           return CryptGenerateKeySymmetric(publicArea, sensitiveCreate,
2442                                            sensitive, hashAlg, seed, &name);
2443           break;
2444       case TPM_ALG_KEYEDHASH:
2445           return CryptGenerateKeyedHash(publicArea, sensitiveCreate,
2446                                         sensitive, hashAlg, seed, &name);
2447           break;
2448       default:
2449           pAssert(0);
2450           break;
2451       }
2452       if(result == TPM_RC_SUCCESS)
2453       {
2454           TPM2B_AUTH          *proof = NULL;
2455
2456            if(publicArea->objectAttributes.decrypt == SET
2457                     && publicArea->objectAttributes.restricted == SET)
2458            {
2459                // If this is a primary object in the endorsement hierarchy, use
2460                // ehProof in the creation of the symmetric seed so that child
2461                // objects in the endorsement hierarchy are voided on TPM2_Clear()
2462                // or TPM2_ChangeEPS()
2463                if(    parentHandle == TPM_RH_ENDORSEMENT
2464                    && publicArea->objectAttributes.fixedTPM == SET)
2465                     proof = &gp.ehProof;
2466
2467                  // For all object types, the size of seedValue is the digest size
2468                  // of its nameAlg
2469                  sensitive->seedValue.t.size
2470                      = CryptGetHashDigestSize(publicArea->nameAlg);
2471
2472                  // Compute seedValue using implementation-dependent method
2473                  _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
2474                                              sensitive->seedValue.t.buffer,
2475                                              hashAlg,
2476                                              &seed->b,
2477                                              "seedValuea",
2478                                              &name.b,
2479                                              (TPM2B *)proof);
2480            }
2481            else
2482            {
2483                  sensitive->seedValue.t.size = 0;
2484            }
2485       }
2486
2487       return result;
2488
2489   }


       Family "2.0"                           TCG Published                                Page 323
       Level 00 Revision 01.16          Copyright © TCG 2006-2014                  October 30, 2014
       Trusted Platform Module Library                                               Part 4: Supporting Routines

       10.2.9.13 CryptObjectIsPublicConsistent()

       This function checks that the key sizes in the public area are consistent. For an asymmetric key, the size
       of the public key must match the size indicated by the public->parameters.
       Checks for the algorithm types matching the key type are handled by the unmarshaling operation.

       Return Value                      Meaning

       TRUE                              sizes are consistent
       FALSE                             sizes are not consistent

2490   BOOL
2491   CryptObjectIsPublicConsistent(
2492       TPMT_PUBLIC         *publicArea           // IN: public area
2493       )
2494   {
2495       BOOL                  OK = TRUE;
2496       switch (publicArea->type)
2497       {
2498   #ifdef TPM_ALG_RSA
2499           case TPM_ALG_RSA:
2500               OK = CryptAreKeySizesConsistent(publicArea);
2501               break;
2502   #endif //TPM_ALG_RSA
2503
2504   #ifdef TPM_ALG_ECC
2505           case TPM_ALG_ECC:
2506               {
2507                   const ECC_CURVE                              *curveValue;
2508
2509                      // Check that the public point is on the indicated curve.
2510                      OK = CryptEccIsPointOnCurve(
2511                                      publicArea->parameters.eccDetail.curveID,
2512                                      &publicArea->unique.ecc);
2513                      if(OK)
2514                      {
2515                          curveValue = CryptEccGetCurveDataPointer(
2516                                               publicArea->parameters.eccDetail.curveID);
2517                          pAssert(curveValue != NULL);
2518
2519                           // The input ECC curve must be a supported curve
2520                           // IF a scheme is defined for the curve, then that scheme must
2521                           // be used.
2522                           OK =    (curveValue->sign.scheme == TPM_ALG_NULL
2523                                || (   publicArea->parameters.eccDetail.scheme.scheme
2524                                    == curveValue->sign.scheme));
2525                           OK = OK && CryptAreKeySizesConsistent(publicArea);
2526                   }
2527               }
2528               break;
2529   #endif //TPM_ALG_ECC
2530
2531            default:
2532                // Symmetric object common checks
2533                // There is noting to check with a symmetric key that is public only.
2534                // Also not sure that there is anything useful to be done with it
2535                // either.
2536                break;
2537       }
2538       return OK;
2539   }




       Page 324                                       TCG Published                                Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
       Part 4: Supporting Routines                                                  Trusted Platform Module Library

       10.2.9.14 CryptObjectPublicPrivateMatch()

       This function checks the cryptographic binding between the public and sensitive areas.

       Error Returns                   Meaning

       TPM_RC_TYPE                     the type of the public and private areas are not the same
       TPM_RC_FAILURE                  crypto error
       TPM_RC_BINDING                  the public and private areas are not cryptographically matched.

2540   TPM_RC
2541   CryptObjectPublicPrivateMatch(
2542       OBJECT              *object                // IN: the object to check
2543       )
2544   {
2545       TPMT_PUBLIC               *publicArea;
2546       TPMT_SENSITIVE            *sensitive;
2547       TPM_RC                     result = TPM_RC_SUCCESS;
2548       BOOL                       isAsymmetric = FALSE;
2549
2550       pAssert(object != NULL);
2551       publicArea = &object->publicArea;
2552       sensitive = &object->sensitive;
2553       if(publicArea->type != sensitive->sensitiveType)
2554           return TPM_RC_TYPE;
2555
2556       switch(publicArea->type)
2557       {
2558   #ifdef TPM_ALG_RSA
2559       case TPM_ALG_RSA:
2560           isAsymmetric = TRUE;
2561           // The public and private key sizes need to be consistent
2562           if(sensitive->sensitive.rsa.t.size != publicArea->unique.rsa.t.size/2)
2563                result = TPM_RC_BINDING;
2564           else
2565           // Load key by computing the private exponent
2566                result = CryptLoadPrivateRSA(object);
2567           break;
2568   #endif
2569   #ifdef TPM_ALG_ECC
2570           // This function is called from ObjectLoad() which has already checked to
2571           // see that the public point is on the curve so no need to repeat that
2572           // check.
2573       case TPM_ALG_ECC:
2574           isAsymmetric = TRUE;
2575           if(    publicArea->unique.ecc.x.t.size
2576                     != sensitive->sensitive.ecc.t.size)
2577                result = TPM_RC_BINDING;
2578           else if(publicArea->nameAlg != TPM_ALG_NULL)
2579           {
2580                TPMS_ECC_POINT           publicToCompare;
2581                // Compute ECC public key
2582                CryptEccPointMultiply(&publicToCompare,
2583                                       publicArea->parameters.eccDetail.curveID,
2584                                       &sensitive->sensitive.ecc, NULL);
2585                // Compare ECC public key
2586                if(    (!Memory2BEqual(&publicArea->unique.ecc.x.b,
2587                                       &publicToCompare.x.b))
2588                    || (!Memory2BEqual(&publicArea->unique.ecc.y.b,
2589                                       &publicToCompare.y.b)))
2590                     result = TPM_RC_BINDING;
2591           }
2592           break;


       Family "2.0"                                   TCG Published                                       Page 325
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                               October 30, 2014
       Trusted Platform Module Library                                          Part 4: Supporting Routines

2593   #endif
2594       case TPM_ALG_KEYEDHASH:
2595           break;
2596       case TPM_ALG_SYMCIPHER:
2597           if(    (publicArea->parameters.symDetail.sym.keyBits.sym + 7)/8
2598               != sensitive->sensitive.sym.t.size)
2599                result = TPM_RC_BINDING;
2600           break;
2601       default:
2602           // The choice here is an assert or a return of a bad type for the object
2603           pAssert(0);
2604           break;
2605       }
2606
2607       // For asymmetric keys, the algorithm for validating the linkage between
2608       // the public and private areas is algorithm dependent. For symmetric keys
2609       // the linkage is based on hashing the symKey and obfuscation values.
2610       if(   result == TPM_RC_SUCCESS && !isAsymmetric
2611          && publicArea->nameAlg != TPM_ALG_NULL)
2612       {
2613           TPM2B_DIGEST    uniqueToCompare;
2614
2615            // Compute unique for symmetric key
2616            CryptComputeSymmetricUnique(publicArea->nameAlg, sensitive,
2617                                         &uniqueToCompare);
2618            // Compare unique
2619            if(!Memory2BEqual(&publicArea->unique.sym.b,
2620                              &uniqueToCompare.b))
2621                result = TPM_RC_BINDING;
2622       }
2623       return result;
2624
2625   }


       10.2.9.15 CryptGetSignHashAlg()

       Get the hash algorithm of signature from a TPMT_SIGNATURE structure. It assumes the signature is not
       NULL This is a function for easy access

2626   TPMI_ALG_HASH
2627   CryptGetSignHashAlg(
2628       TPMT_SIGNATURE     *auth             // IN: signature
2629       )
2630   {
2631       pAssert(auth->sigAlg != TPM_ALG_NULL);
2632
2633       // Get authHash algorithm based on signing scheme
2634       switch(auth->sigAlg)
2635       {
2636
2637   #ifdef   TPM_ALG_RSA
2638            case TPM_ALG_RSASSA:
2639                return auth->signature.rsassa.hash;
2640
2641            case TPM_ALG_RSAPSS:
2642                return auth->signature.rsapss.hash;
2643
2644       #endif //TPM_ALG_RSA
2645
2646       #ifdef TPM_ALG_ECC
2647           case TPM_ALG_ECDSA:
2648               return auth->signature.ecdsa.hash;
2649
2650       #endif //TPM_ALG_ECC

       Page 326                                  TCG Published                                Family "2.0"
       October 30, 2014                   Copyright © TCG 2006-2014               Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

2651
2652                case TPM_ALG_HMAC:
2653                    return auth->signature.hmac.hashAlg;
2654
2655                default:
2656                    return TPM_ALG_NULL;
2657        }
2658   }


       10.2.9.16 CryptIsSplitSign()

       This function us used to determine if the signing operation is a split signing operation that required a
       TPM2_Commit().

2659   BOOL
2660   CryptIsSplitSign(
2661        TPM_ALG_ID           scheme             // IN: the algorithm selector
2662        )
2663   {
2664        if(   scheme != scheme
2665   #    ifdef   TPM_ALG_ECDAA
2666           || scheme == TPM_ALG_ECDAA
2667   #    endif   // TPM_ALG_ECDAA
2668
2669            )
2670            return TRUE;
2671        return FALSE;
2672   }


       10.2.9.17 CryptIsSignScheme()

       This function indicates if a scheme algorithm is a sign algorithm.

2673   BOOL
2674   CryptIsSignScheme(
2675        TPMI_ALG_ASYM_SCHEME           scheme
2676        )
2677   {
2678        BOOL                isSignScheme = FALSE;
2679
2680       switch(scheme)
2681       {
2682   #ifdef TPM_ALG_RSA
2683           // If RSA is implemented, then both signing schemes are required
2684       case TPM_ALG_RSASSA:
2685       case TPM_ALG_RSAPSS:
2686           isSignScheme = TRUE;
2687           break;
2688   #endif //TPM_ALG_RSA
2689
2690   #ifdef TPM_ALG_ECC
2691           // If ECC is implemented ECDSA is required
2692       case TPM_ALG_ECDSA:
2693   #ifdef TPM_ALG_ECDAA
2694           // ECDAA is optional
2695       case TPM_ALG_ECDAA:
2696   #endif
2697   #ifdef   TPM_ALG_ECSCHNORR
2698           // Schnorr is also optional
2699       case TPM_ALG_ECSCHNORR:
2700   #endif
2701   #ifdef TPM_ALG_SM2
2702       case TPM_ALG_SM2:

       Family "2.0"                                 TCG Published                                   Page 327
       Level 00 Revision 01.16               Copyright © TCG 2006-2014                      October 30, 2014
       Trusted Platform Module Library                                             Part 4: Supporting Routines

2703   #endif
2704           isSignScheme = TRUE;
2705           break;
2706   #endif //TPM_ALG_ECC
2707       default:
2708           break;
2709       }
2710       return isSignScheme;
2711   }


       10.2.9.18 CryptIsDecryptScheme()

       This function indicate if a scheme algorithm is a decrypt algorithm.

2712   BOOL
2713   CryptIsDecryptScheme(
2714        TPMI_ALG_ASYM_SCHEME           scheme
2715        )
2716   {
2717        BOOL           isDecryptScheme = FALSE;
2718
2719       switch(scheme)
2720       {
2721   #ifdef TPM_ALG_RSA
2722           // If RSA is implemented, then both decrypt schemes are required
2723       case TPM_ALG_RSAES:
2724       case TPM_ALG_OAEP:
2725            isDecryptScheme = TRUE;
2726           break;
2727   #endif //TPM_ALG_RSA
2728
2729   #ifdef TPM_ALG_ECC
2730           // If ECC is implemented ECDH is required
2731       case TPM_ALG_ECDH:
2732   #ifdef TPM_ALG_SM2
2733       case TPM_ALG_SM2:
2734   #endif
2735   #ifdef TPM_ALG_ECMQV
2736       case TPM_ALG_ECMQV:
2737   #endif
2738           isDecryptScheme = TRUE;
2739           break;
2740   #endif //TPM_ALG_ECC
2741       default:
2742           break;
2743       }
2744       return isDecryptScheme;
2745   }


       10.2.9.19 CryptSelectSignScheme()

       This function is used by the attestation and signing commands. It implements the rules for selecting the
       signature scheme to use in signing. This function requires that the signing key either be TPM_RH_NULL
       or be loaded.
       If a default scheme is defined in object, the default scheme should be chosen, otherwise, the input
       scheme should be chosen. In the case that both object and input scheme has a non-NULL scheme
       algorithm, if the schemes are compatible, the input scheme will be chosen.




       Page 328                                     TCG Published                                 Family "2.0"
       October 30, 2014                      Copyright © TCG 2006-2014               Level 00 Revision 01.16
       Part 4: Supporting Routines                                                  Trusted Platform Module Library


       Error Returns                   Meaning

       TPM_RC_KEY                      key referenced by signHandle is not a signing key
       TPM_RC_SCHEME                   both scheme and key's default scheme are empty; or scheme is
                                       empty while key's default scheme requires explicit input scheme (split
                                       signing); or non-empty default key scheme differs from scheme

2746   TPM_RC
2747   CryptSelectSignScheme(
2748       TPMI_DH_OBJECT             signHandle,        // IN: handle of signing key
2749       TPMT_SIG_SCHEME           *scheme             // IN/OUT: signing scheme
2750       )
2751   {
2752       OBJECT                    *signObject;
2753       TPMT_SIG_SCHEME           *objectScheme;
2754       TPMT_PUBLIC               *publicArea;
2755       TPM_RC                     result = TPM_RC_SUCCESS;
2756
2757       // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless
2758       // of the setting of scheme
2759       if(signHandle == TPM_RH_NULL)
2760       {
2761           scheme->scheme = TPM_ALG_NULL;
2762           scheme->details.any.hashAlg = TPM_ALG_NULL;
2763       }
2764       else
2765       {
2766           // sign handle is not NULL so...
2767           // Get sign object pointer
2768           signObject = ObjectGet(signHandle);
2769           publicArea = &signObject->publicArea;
2770
2771            // is this a signing key?
2772            if(!publicArea->objectAttributes.sign)
2773                 result = TPM_RC_KEY;
2774            else
2775            {
2776                 // "parms" defined to avoid long code lines.
2777                 TPMU_PUBLIC_PARMS    *parms = &publicArea->parameters;
2778                 if(CryptIsAsymAlgorithm(publicArea->type))
2779                     objectScheme = (TPMT_SIG_SCHEME *)&parms->asymDetail.scheme;
2780                 else
2781                     objectScheme = (TPMT_SIG_SCHEME *)&parms->keyedHashDetail.scheme;
2782
2783                   // If the object doesn't have a default scheme, then use the
2784                   // input scheme.
2785                   if(objectScheme->scheme == TPM_ALG_NULL)
2786                   {
2787                       // Input and default can't both be NULL
2788                       if(scheme->scheme == TPM_ALG_NULL)
2789                           result = TPM_RC_SCHEME;
2790
2791                       // Assume that the scheme is compatible with the key. If not,
2792                       // we will generate an error in the signing operation.
2793
2794                   }
2795                   else if(scheme->scheme == TPM_ALG_NULL)
2796                   {
2797                       // input scheme is NULL so use default
2798
2799                       // First, check to see if the default requires that the caller
2800                       // provided scheme data
2801                       if(CryptIsSplitSign(objectScheme->scheme))
2802                           result = TPM_RC_SCHEME;

       Family "2.0"                                 TCG Published                                               Page 329
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                               October 30, 2014
       Trusted Platform Module Library                                                     Part 4: Supporting Routines

2803                       else
2804                       {
2805                           scheme->scheme = objectScheme->scheme;
2806                           scheme->details.any.hashAlg
2807                                       = objectScheme->details.any.hashAlg;
2808                       }
2809                   }
2810                   else
2811                   {
2812                       // Both input and object have scheme selectors
2813                       // If the scheme and the hash are not the same then...
2814                       if(    objectScheme->scheme != scheme->scheme
2815                           || (   objectScheme->details.any.hashAlg
2816                               != scheme->details.any.hashAlg))
2817                            result = TPM_RC_SCHEME;
2818                   }
2819            }
2820
2821       }
2822       return result;
2823   }


       10.2.9.20 CryptSign()

       Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and the
       generic TPM2_Sign() command. This function checks the key scheme and digest size. It does not check
       if the sign operation is allowed for restricted key. It should be checked before the function is called. The
       function will assert if the key is not a signing key.

       Error Returns                     Meaning

       TPM_RC_SCHEME                     signScheme is not compatible with the signing key type
       TPM_RC_VALUE                      digest value is greater than the modulus of signHandle or size of
                                         hashData does not match hash algorithm insignScheme (for an RSA
                                         key); invalid commit status or failed to generate r value (for an ECC
                                         key)

2824   TPM_RC
2825   CryptSign(
2826       TPMI_DH_OBJECT            signHandle,          //   IN: The handle of sign key
2827       TPMT_SIG_SCHEME          *signScheme,          //   IN: sign scheme.
2828       TPM2B_DIGEST             *digest,              //   IN: The digest being signed
2829       TPMT_SIGNATURE           *signature            //   OUT: signature
2830       )
2831   {
2832       OBJECT                   *signKey = ObjectGet(signHandle);
2833       TPM_RC                    result = TPM_RC_SCHEME;
2834
2835       // check if input handle is a sign key
2836       pAssert(signKey->publicArea.objectAttributes.sign == SET);
2837
2838       // Must have the private portion loaded. This check is made during
2839       // authorization.
2840       pAssert(signKey->attributes.publicOnly == CLEAR);
2841
2842       // Initialize signature scheme
2843       signature->sigAlg = signScheme->scheme;
2844
2845       // If the signature algorithm is TPM_ALG_NULL, then we are done
2846       if(signature->sigAlg == TPM_ALG_NULL)
2847           return TPM_RC_SUCCESS;
2848
2849       // All the schemes other than TPM_ALG_NULL have a hash algorithm

       Page 330                                       TCG Published                                        Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
       Part 4: Supporting Routines                                               Trusted Platform Module Library

2850        TEST_HASH(signScheme->details.any.hashAlg);
2851
2852        // Initialize signature hash
2853        // Note: need to do the check for alg null first because the null scheme
2854        // doesn't have a hashAlg member.
2855        signature->signature.any.hashAlg = signScheme->details.any.hashAlg;
2856
2857        // perform sign operation based on different key type
2858        switch (signKey->publicArea.type)
2859        {
2860
2861   #ifdef TPM_ALG_RSA
2862           case TPM_ALG_RSA:
2863               result = CryptSignRSA(signKey, signScheme, digest, signature);
2864               break;
2865   #endif //TPM_ALG_RSA
2866
2867   #ifdef TPM_ALG_ECC
2868           case TPM_ALG_ECC:
2869               result = CryptSignECC(signKey, signScheme, digest, signature);
2870               break;
2871   #endif //TPM_ALG_ECC
2872           case TPM_ALG_KEYEDHASH:
2873               result = CryptSignHMAC(signKey, signScheme, digest, signature);
2874               break;
2875           default:
2876               break;
2877       }
2878
2879        return result;
2880   }


       10.2.9.21 CryptVerifySignature()

       This function is used to verify a signature.               It is called by TPM2_VerifySignature() and
       TPM2_PolicySigned().
       Since this operation only requires use of a public key, no consistency checks are necessary for the key to
       signature type because a caller can load any public key that they like with any scheme that they like. This
       routine simply makes sure that the signature is correct, whatever the type.
       This function requires that auth is not a NULL pointer.

       Error Returns                    Meaning

       TPM_RC_SIGNATURE                 the signature is not genuine
       TPM_RC_SCHEME                    the scheme is not supported
       TPM_RC_HANDLE                    an HMAC key was selected but the private part of the key is not
                                        loaded

2881   TPM_RC
2882   CryptVerifySignature(
2883        TPMI_DH_OBJECT       keyHandle,         // IN: The handle of sign key
2884        TPM2B_DIGEST        *digest,            // IN: The digest being validated
2885        TPMT_SIGNATURE      *signature          // IN: signature
2886        )
2887   {
2888        // NOTE: ObjectGet will either return a pointer to a loaded object or
2889        // will assert. It will never return a non-valid value. This makes it save
2890        // to initialize 'publicArea' with the return value from ObjectGet() without
2891        // checking it first.
2892        OBJECT              *authObject = ObjectGet(keyHandle);
2893        TPMT_PUBLIC         *publicArea = &authObject->publicArea;

       Family "2.0"                                  TCG Published                                        Page 331
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
       Trusted Platform Module Library                                                       Part 4: Supporting Routines

2894        TPM_RC                    result = TPM_RC_SCHEME;
2895
2896        // The input unmarshaling should prevent any input signature from being
2897        // a NULL signature, but just in case
2898        if(signature->sigAlg == TPM_ALG_NULL)
2899            return TPM_RC_SIGNATURE;
2900
2901        switch (publicArea->type)
2902        {
2903
2904   #ifdef TPM_ALG_RSA
2905       case TPM_ALG_RSA:
2906           result = CryptRSAVerifySignature(authObject, digest, signature);
2907           break;
2908   #endif //TPM_ALG_RSA
2909
2910   #ifdef TPM_ALG_ECC
2911       case TPM_ALG_ECC:
2912           result = CryptECCVerifySignature(authObject, digest, signature);
2913           break;
2914
2915   #endif // TPM_ALG_ECC
2916
2917        case TPM_ALG_KEYEDHASH:
2918            if(authObject->attributes.publicOnly)
2919                 result = TPM_RCS_HANDLE;
2920            else
2921                 result = CryptHMACVerifySignature(authObject, digest, signature);
2922            break;
2923
2924        default:
2925            break;
2926        }
2927        return result;
2928
2929   }


       10.2.10 Math functions

       10.2.10.1 CryptDivide()

       This function interfaces to the math library for large number divide.

       Error Returns                     Meaning

       TPM_RC_SIZE                       quotient or remainder is too small to receive the result

2930   TPM_RC
2931   CryptDivide(
2932        TPM2B               *numerator,           //   IN: numerator
2933        TPM2B               *denominator,         //   IN: denominator
2934        TPM2B               *quotient,            //   OUT: quotient = numerator / denominator.
2935        TPM2B               *remainder            //   OUT: numerator mod denominator.
2936        )
2937   {
2938        pAssert(   numerator != NULL         && denominator!= NULL
2939                && (quotient != NULL         || remainder != NULL)
2940               );
2941        // assume denominator is not         0
2942        pAssert(denominator->size !=         0);
2943
2944        return TranslateCryptErrors(_math__Div(numerator,
2945                                               denominator,

       Page 332                                        TCG Published                                       Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                        Level 00 Revision 01.16
       Part 4: Supporting Routines                                                              Trusted Platform Module Library

2946                                                                  quotient,
2947                                                                  remainder)
2948                                               );
2949   }


       10.2.10.2 CryptCompare()

       This function interfaces to the math library for large number, unsigned compare.

       Return Value                         Meaning

       1                                    if a > b
       0                                    if a = b
       -1                                   if a < b

2950   LIB_EXPORT int
2951   CryptCompare(
2952        const   UINT32         aSize,                  //   IN:   size of a
2953        const   BYTE          *a,                      //   IN:   a buffer
2954        const   UINT32         bSize,                  //   IN:   size of b
2955        const   BYTE          *b                       //   IN:   b buffer
2956        )
2957   {
2958        return _math__uComp(aSize, a, bSize, b);
2959   }


       10.2.10.3 CryptCompareSigned()

       This function interfaces to the math library for large number, signed compare.

       Return Value                         Meaning

       1                                    if a > b
       0                                    if a = b
       -1                                   if a < b

2960   int
2961   CryptCompareSigned(
2962        UINT32                 aSize,                  //   IN:   size of a
2963        BYTE                  *a,                      //   IN:   a buffer
2964        UINT32                 bSize,                  //   IN:   size of b
2965        BYTE                  *b                       //   IN:   b buffer
2966        )
2967   {
2968        return _math__Comp(aSize, a, bSize, b);
2969   }


       10.2.10.4 CryptGetTestResult

       This function returns the results of a self-test function.

       NOTE:            the behavior in this function is NOT the correct behavior for a real TPM implementation. An artificial behavior is
                        placed here due to the limitation of a software simulation environment. For the correct behavior, consult the
                        part 3 specification for TPM2_GetTestResult().

2970   TPM_RC
2971   CryptGetTestResult(
2972        TPM2B_MAX_BUFFER            *outData                 // OUT: test result data

       Family "2.0"                                        TCG Published                                                    Page 333
       Level 00 Revision 01.16                    Copyright © TCG 2006-2014                                      October 30, 2014
       Trusted Platform Module Library                                               Part 4: Supporting Routines

2973         )
2974   {
2975         outData->t.size = 0;
2976         return TPM_RC_SUCCESS;
2977   }


       10.2.11 Capability Support

       10.2.11.1 CryptCapGetECCCurve()

       This function returns the list of implemented ECC curves.

       Return Value                      Meaning

       YES                               if no more ECC curve is available
       NO                                if there are more ECC curves not reported

2978   #ifdef TPM_ALG_ECC //% 5
2979   TPMI_YES_NO
2980   CryptCapGetECCCurve(
2981         TPM_ECC_CURVE      curveID,             // IN: the starting ECC curve
2982         UINT32             maxCount,            // IN: count of returned curve
2983         TPML_ECC_CURVE    *curveList            // OUT: ECC curve list
2984         )
2985   {
2986         TPMI_YES_NO         more = NO;
2987         UINT16              i;
2988         UINT32              count = _cpri__EccGetCurveCount();
2989         TPM_ECC_CURVE       curve;
2990
2991         // Initialize output property list
2992         curveList->count = 0;
2993
2994         // The maximum count of curves we may return is MAX_ECC_CURVES
2995         if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES;
2996
2997         // Scan the eccCurveValues array
2998         for(i = 0; i < count; i++)
2999         {
3000             curve = _cpri__GetCurveIdByIndex(i);
3001             // If curveID is less than the starting curveID, skip it
3002             if(curve < curveID)
3003                 continue;
3004
3005             if(curveList->count < maxCount)
3006             {
3007                  // If we have not filled up the return list, add more curves to
3008                  // it
3009                  curveList->eccCurves[curveList->count] = curve;
3010                  curveList->count++;
3011             }
3012             else
3013             {
3014                  // If the return list is full but we still have curves
3015                  // available, report this and stop iterating
3016                  more = YES;
3017                  break;
3018             }
3019
3020         }
3021
3022         return more;
3023

       Page 334                                       TCG Published                                Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
       Part 4: Supporting Routines                                                Trusted Platform Module Library

3024   }


       10.2.11.2 CryptCapGetEccCurveNumber()

       This function returns the number of ECC curves supported by the TPM.

3025   UINT32
3026   CryptCapGetEccCurveNumber(
3027       void
3028       )
3029   {
3030       // There is an array that holds the curve data. Its size divided by the
3031       // size of an entry is the number of values in the table.
3032       return _cpri__EccGetCurveCount();
3033   }
3034   #endif //TPM_ALG_ECC //% 5


       10.2.11.3 CryptAreKeySizesConsistent()

       This function validates that the public key size values are consistent for an asymmetric key.

       NOTE:           This is not a comprehensive test of the public key.


       Return Value                        Meaning

       TRUE                                sizes are consistent
       FALSE                               sizes are not consistent

3035   BOOL
3036   CryptAreKeySizesConsistent(
3037       TPMT_PUBLIC           *publicArea              // IN: the public area to check
3038       )
3039   {
3040       BOOL                  consistent = FALSE;
3041
3042       switch (publicArea->type)
3043       {
3044   #ifdef TPM_ALG_RSA
3045           case TPM_ALG_RSA:
3046               // The key size in bits is filtered by the unmarshaling
3047               consistent = (     ((publicArea->parameters.rsaDetail.keyBits+7)/8)
3048                               == publicArea->unique.rsa.t.size);
3049               break;
3050   #endif //TPM_ALG_RSA
3051
3052   #ifdef TPM_ALG_ECC
3053           case TPM_ALG_ECC:
3054               {
3055                   UINT16                        keySizeInBytes;
3056                   TPM_ECC_CURVE                 curveId = publicArea->parameters.eccDetail.curveID;
3057
3058                       keySizeInBytes = CryptEccGetKeySizeInBytes(curveId);
3059
3060                       consistent =         keySizeInBytes > 0
3061                                         && publicArea->unique.ecc.x.t.size <= keySizeInBytes
3062                                         && publicArea->unique.ecc.y.t.size <= keySizeInBytes;
3063               }
3064               break;
3065   #endif //TPM_ALG_ECC
3066           default:
3067               break;

       Family "2.0"                                       TCG Published                                Page 335
       Level 00 Revision 01.16                   Copyright © TCG 2006-2014                     October 30, 2014
       Trusted Platform Module Library                                                 Part 4: Supporting Routines

3068          }
3069
3070          return consistent;
3071   }


       10.2.11.4 CryptAlgSetImplemented()

       This function initializes the bit vector with one bit for each implemented algorithm. This function is called
       from _TPM_Init(). The vector of implemented algorithms should be generated by the part 2 parser so that
       the g_implementedAlgorithms vector can be a const. That's not how it is now

3072   void
3073   CryptAlgsSetImplemented(
3074          void
3075          )
3076   {
3077          AlgorithmGetImplementedVector(&g_implementedAlgorithms);
3078   }


       10.3       Ticket.c

       10.3.1       Introduction

       This clause contains the functions used for ticket computations.

       10.3.2       Includes

   1   #include "InternalRoutines.h"


       10.3.3       Functions

       10.3.3.1       TicketIsSafe()

       This function indicates if producing a ticket is safe. It checks if the leading bytes of an input buffer is
       TPM_GENERATED_VALUE or its substring of canonical form. If so, it is not safe to produce ticket for an
       input buffer claiming to be TPM generated buffer

       Return Value                      Meaning

       TRUE                              It is safe to produce ticket
       FALSE                             It is not safe to produce ticket

   2   BOOL
   3   TicketIsSafe(
   4          TPM2B                *buffer
   5          )
   6   {
   7          TPM_GENERATED        valueToCompare = TPM_GENERATED_VALUE;
   8          BYTE                 bufferToCompare[sizeof(valueToCompare)];
   9          BYTE                 *marshalBuffer;
  10
  11          // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume
  12          // it is not safe to generate a ticket
  13          if(buffer->size < sizeof(valueToCompare))
  14              return FALSE;
  15
  16          marshalBuffer = bufferToCompare;

       Page 336                                        TCG Published                                  Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                           Trusted Platform Module Library

17       TPM_GENERATED_Marshal(&valueToCompare, &marshalBuffer, NULL);
18       if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare)))
19           return FALSE;
20       else
21           return TRUE;
22   }


     10.3.3.2   TicketComputeVerified()

     This function creates a TPMT_TK_VERIFIED ticket.

23   void
24   TicketComputeVerified(
25       TPMI_RH_HIERARCHY          hierarchy,       //   IN: hierarchy constant for ticket
26       TPM2B_DIGEST              *digest,          //   IN: digest
27       TPM2B_NAME                *keyName,         //   IN: name of key that signed the value
28       TPMT_TK_VERIFIED          *ticket           //   OUT: verified ticket
29       )
30   {
31       TPM2B_AUTH                *proof;
32       HMAC_STATE                 hmacState;
33
34       // Fill in ticket fields
35       ticket->tag = TPM_ST_VERIFIED;
36       ticket->hierarchy = hierarchy;
37
38       // Use the proof value of the hierarchy
39       proof = HierarchyGetProof(hierarchy);
40
41       // Start HMAC
42       ticket->digest.t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG,
43                                                &proof->b, &hmacState);
44
45       // add TPM_ST_VERIFIED
46       CryptUpdateDigestInt(&hmacState, sizeof(TPM_ST), &ticket->tag);
47
48       // add digest
49       CryptUpdateDigest2B(&hmacState, &digest->b);
50
51       // add key name
52       CryptUpdateDigest2B(&hmacState, &keyName->b);
53
54       // complete HMAC
55       CryptCompleteHMAC2B(&hmacState, &ticket->digest.b);
56
57       return;
58   }


     10.3.3.3   TicketComputeAuth()

     This function creates a TPMT_TK_AUTH ticket.

59   void
60   TicketComputeAuth(
61       TPM_ST                     type,            //   IN: the type of ticket.
62       TPMI_RH_HIERARCHY          hierarchy,       //   IN: hierarchy constant for ticket
63       UINT64                     timeout,         //   IN: timeout
64       TPM2B_DIGEST              *cpHashA,         //   IN: input cpHashA
65       TPM2B_NONCE               *policyRef,       //   IN: input policyRef
66       TPM2B_NAME                *entityName,      //   IN: name of entity
67       TPMT_TK_AUTH              *ticket           //   OUT: Created ticket
68       )
69   {

     Family "2.0"                                 TCG Published                                 Page 337
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                     October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

 70       TPM2B_AUTH              *proof;
 71       HMAC_STATE               hmacState;
 72
 73       // Get proper proof
 74       proof = HierarchyGetProof(hierarchy);
 75
 76       // Fill in ticket fields
 77       ticket->tag = type;
 78       ticket->hierarchy = hierarchy;
 79
 80       // Start HMAC
 81       ticket->digest.t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG,
 82                                                &proof->b, &hmacState);
 83
 84       // Adding TPM_ST_AUTH
 85       CryptUpdateDigestInt(&hmacState, sizeof(UINT16), &ticket->tag);
 86
 87       // Adding timeout
 88       CryptUpdateDigestInt(&hmacState, sizeof(UINT64), &timeout);
 89
 90       // Adding cpHash
 91       CryptUpdateDigest2B(&hmacState, &cpHashA->b);
 92
 93       // Adding policyRef
 94       CryptUpdateDigest2B(&hmacState, &policyRef->b);
 95
 96       // Adding keyName
 97       CryptUpdateDigest2B(&hmacState, &entityName->b);
 98
 99       // Compute HMAC
100       CryptCompleteHMAC2B(&hmacState, &ticket->digest.b);
101
102       return;
103   }


      10.3.3.4   TicketComputeHashCheck()

      This function creates a TPMT_TK_HASHCHECK ticket.

104   void
105   TicketComputeHashCheck(
106       TPMI_RH_HIERARCHY        hierarchy,      //   IN: hierarchy constant for ticket
107       TPM_ALG_ID               hashAlg,        //   IN: the hash algorithm used to create
108                                                //       'digest'
109       TPM2B_DIGEST            *digest,         //   IN: input digest
110       TPMT_TK_HASHCHECK       *ticket          //   OUT: Created ticket
111       )
112   {
113       TPM2B_AUTH              *proof;
114       HMAC_STATE               hmacState;
115
116       // Get proper proof
117       proof = HierarchyGetProof(hierarchy);
118
119       // Fill in ticket fields
120       ticket->tag = TPM_ST_HASHCHECK;
121       ticket->hierarchy = hierarchy;
122
123       ticket->digest.t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG,
124                                                &proof->b, &hmacState);
125
126       // Add TPM_ST_HASHCHECK
127       CryptUpdateDigestInt(&hmacState, sizeof(TPM_ST), &ticket->tag);
128


      Page 338                                  TCG Published                             Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014             Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library

129          // Add hash algorithm
130          CryptUpdateDigestInt(&hmacState, sizeof(hashAlg), &hashAlg);
131
132          // Add digest
133          CryptUpdateDigest2B(&hmacState, &digest->b);
134
135          // Compute HMAC
136          CryptCompleteHMAC2B(&hmacState, &ticket->digest.b);
137
138          return;
139   }


      10.3.3.5     TicketComputeCreation()

      This function creates a TPMT_TK_CREATION ticket.

140   void
141   TicketComputeCreation(
142          TPMI_RH_HIERARCHY       hierarchy,        //   IN: hierarchy for ticket
143          TPM2B_NAME             *name,             //   IN: object name
144          TPM2B_DIGEST           *creation,         //   IN: creation hash
145          TPMT_TK_CREATION       *ticket            //   OUT: created ticket
146          )
147   {
148          TPM2B_AUTH             *proof;
149          HMAC_STATE              hmacState;
150
151          // Get proper proof
152          proof = HierarchyGetProof(hierarchy);
153
154          // Fill in ticket fields
155          ticket->tag = TPM_ST_CREATION;
156          ticket->hierarchy = hierarchy;
157
158          ticket->digest.t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG,
159                                                   &proof->b, &hmacState);
160
161          // Add TPM_ST_CREATION
162          CryptUpdateDigestInt(&hmacState, sizeof(TPM_ST), &ticket->tag);
163
164          // Add name
165          CryptUpdateDigest2B(&hmacState, &name->b);
166
167          // Add creation hash
168          CryptUpdateDigest2B(&hmacState, &creation->b);
169
170          // Compute HMAC
171          CryptCompleteHMAC2B(&hmacState, &ticket->digest.b);
172
173          return;
174   }


      10.4     CryptSelfTest.c

      10.4.1     Introduction

      The functions in this file are designed to support self-test of cryptographic functions in the TPM. The TPM
      allows the user to decide whether to run self-test on a demand basis or to run all the self-tests before
      proceeding.
      The self-tests are controlled by a set of bit vectors. The g_untestedDecryptionAlgorithms vector has a bit
      for each decryption algorithm that needs to be tested and g_untestedEncryptionAlgorithms has a bit for

      Family "2.0"                                TCG Published                                       Page 339
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                   Part 4: Supporting Routines


     each encryption algorithm that needs to be tested. Before an algorithm is used, the appropriate vector is
     checked (indexed using the algorithm ID). If the bit is SET, then the test function should be called.

 1   #include        "Global.h"
 2   #include        "CryptoEngine.h"
 3   #include        "InternalRoutines.h"
 4   #include        "AlgorithmCap_fp.h"


     10.4.2     Functions

     10.4.2.1     RunSelfTest()

     Local function to run self-test

 5   static TPM_RC
 6   CryptRunSelfTests(
 7        ALGORITHM_VECTOR             *toTest            // IN: the vector of the algorithms to test
 8        )
 9   {
10        TPM_ALG_ID                    alg;
11
12        // For each of the algorithms that are in the toTestVecor, need to run a
13        // test
14        for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++)
15        {
16            if(TEST_BIT(alg, *toTest))
17            {
18                TPM_RC          result = CryptTestAlgorithm(alg, toTest);
19                if(result != TPM_RC_SUCCESS)
20                    return result;
21            }
22        }
23        return TPM_RC_SUCCESS;
24   }


     10.4.2.2     CryptSelfTest()

     This function is called to start/complete a full self-test. If fullTest is NO, then only the untested algorithms
     will be run. If fullTest is YES, then g_untestedDecryptionAlgorithms is reinitialized and then all tests are
     run. This implementation of the reference design does not support processing outside the framework of a
     TPM command. As a consequence, this command does not complete until all tests are done. Since this
     can take a long time, the TPM will check after each test to see if the command is canceled. If so, then the
     TPM will returned TPM_RC_CANCELLED. To continue with the self-tests, call TPM2_SelfTest(fullTest ==
     No) and the TPM will complete the testing.

     Error Returns                       Meaning

     TPM_RC_CANCELED                     if the command is canceled

25   LIB_EXPORT
26   TPM_RC
27   CryptSelfTest(
28        TPMI_YES_NO           fullTest             // IN: if full test is required
29        )
30   {
31        if(g_forceFailureMode)
32            FAIL(FATAL_ERROR_FORCED);
33
34        // If the caller requested a full test, then reset the to test vector so that
35        // all the tests will be run

     Page 340                                        TCG Published                                     Family "2.0"
     October 30, 2014                          Copyright © TCG 2006-2014                 Level 00 Revision 01.16
     Part 4: Supporting Routines                                                   Trusted Platform Module Library

36       if(fullTest == YES)
37       {
38           MemoryCopy(g_toTest,
39                      g_implementedAlgorithms,
40                      sizeof(g_toTest), sizeof(g_toTest));
41       }
42       return CryptRunSelfTests(&g_toTest);
43   }


     10.4.2.3     CryptIncrementalSelfTest()

     This function is used to perform an incremental self-test. This implementation will perform the toTest
     values before returning. That is, it assumes that the TPM cannot perform background tasks between
     commands.
     This command may be canceled. If it is, then there is no return result. However, this command can be run
     again and the incremental progress will not be lost.

     Error Returns                   Meaning

     TPM_RC_CANCELED                 processing of this command was canceled
     TPM_RC_TESTING                  if toTest list is not empty
     TPM_RC_VALUE                    an algorithm in the toTest list is not implemented

44   TPM_RC
45   CryptIncrementalSelfTest(
46       TPML_ALG            *toTest,              // IN: list of algorithms to be tested
47       TPML_ALG            *toDoList             // OUT: list of algorithms needing test
48       )
49   {
50       ALGORITHM_VECTOR          toTestVector = {0};
51       TPM_ALG_ID                alg;
52       UINT32                       i;
53
54       pAssert(toTest != NULL && toDoList != NULL);
55       if(toTest->count > 0)
56       {
57           // Transcribe the toTest list into the toTestVector
58           for(i = 0; i < toTest->count; i++)
59           {
60               TPM_ALG_ID      alg = toTest->algorithms[i];
61
62                   // make sure that the algorithm value is not out of range
63                   if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms))
64                       return TPM_RC_VALUE;
65                   SET_BIT(alg, toTestVector);
66              }
67              // Run the test
68              if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED)
69                  return TPM_RC_CANCELED;
70       }
71       // Fill in the toDoList with the algorithms that are still untested
72       toDoList->count = 0;
73
74       for(alg = TPM_ALG_FIRST;
75           toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST;
76           alg++)
77       {
78           if(TEST_BIT(alg, g_toTest))
79               toDoList->algorithms[toDoList->count++] = alg;
80       }
81       return TPM_RC_SUCCESS;


     Family "2.0"                                  TCG Published                                        Page 341
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                   Part 4: Supporting Routines

 82   }


      10.4.2.4    CryptInitializeToTest()

      This function will initialize the data structures for testing all the algorithms. This should not be called
      unless CryptAlgsSetImplemented() has been called

 83   void
 84   CryptInitializeToTest(
 85        void
 86        )
 87   {
 88        MemoryCopy(g_toTest,
 89                   g_implementedAlgorithms,
 90                   sizeof(g_toTest),
 91                   sizeof(g_toTest));
 92        // Setting the algorithm to null causes the test function to just clear
 93        // out any algorithms for which there is no test.
 94        CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest);
 95
 96        return;
 97   }


      10.4.2.5    CryptTestAlgorithm()

      Only point of contact with the actual self tests. If a self-test fails, there is no return and the TPM goes into
      failure mode. The call to TestAlgorithm() uses an algorithms selector and a bit vector. When the test is
      run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest is NULL, then only the bit in
      g_toTest is CLEAR. There is a special case for the call to TestAlgorithm(). When alg is
      TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for which it has no test. This allows the
      knowledge about which algorithms have test to be accessed through the interface that provides the test.

      Error Returns                     Meaning

      TPM_RC_SUCCESS                    test complete
      TPM_RC_CANCELED                   test was canceled

 98   LIB_EXPORT
 99   TPM_RC
100   CryptTestAlgorithm(
101        TPM_ALG_ID                 alg,
102        ALGORITHM_VECTOR          *toTest
103        )
104   {
105       TPM_RC                   result = TPM_RC_SUCCESS;
106   #ifdef SELF_TEST
107       // This is the function prototype for TestAlgorithms(). It is here and not
108       // in a _fp.h file to avoid a compiler error when SELF_TEST is not defined and
109       // AlgorithmTexts.c is not part of the build.
110       TPM_RC TestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest);
111       result = TestAlgorithm(alg, toTest);
112   #else
113       // If this is an attempt to determine the algorithms for which there is a
114       // self test, pretend that all of them do. We do that by not clearing any
115       // of the algorithm bits. When/if this function is called to run tests, it
116       // will over report. This can be changed so that any call to check on which
117       // algorithms have tests, 'toTest' can be cleared.
118       if(alg != TPM_ALG_ERROR)
119       {
120           CLEAR_BIT(alg, g_toTest);
121           if(toTest != NULL)

      Page 342                                       TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                    Level 00 Revision 01.16
      Part 4: Supporting Routines                               Trusted Platform Module Library

122               CLEAR_BIT(alg, *toTest);
123       }
124   #endif
125       return result;
126   }




      Family "2.0"                           TCG Published                           Page 343
      Level 00 Revision 01.16       Copyright © TCG 2006-2014               October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines


                                                   Annex A
                                                 (informative)
                                           Implementation Dependent

     A.1   Introduction

     This header file contains definitions that are derived from the values in the annexes of TPM 2.0 Part 2.
     This file would change based on the implementation.
     The values shown in this version of the file reflect the example settings in TPM 2.0 Part 2.

     A.2   Implementation.h

 1   #ifndef _IMPLEMENTATION_H_
 2   #define _IMPLEMENTATION_H_
 3   #include     "BaseTypes.h"
 4   #include     "TPMB.h"
 5   #undef TRUE
 6   #undef FALSE

     This table is built in to TpmStructures() Change these definitions to turn all algorithms or commands on or
     off

 7   #define         ALG_YES         YES
 8   #define         ALG_NO          NO
 9   #define         CC_YES          YES
10   #define         CC_NO           NO

     From TPM 2.0 Part 2: Table 4 - Defines for Logic Values

11   #define    TRUE       1
12   #define    FALSE      0
13   #define    YES        1
14   #define    NO         0
15   #define    SET        1
16   #define    CLEAR      0

     From Vendor-Specific: Table 1 - Defines for Processor Values

17   #define    BIG_ENDIAN_TPM             NO
18   #define    LITTLE_ENDIAN_TPM          YES
19   #define    NO_AUTO_ALIGN              NO

     From Vendor-Specific: Table 2 - Defines for Implemented Algorithms

20   #define    ALG_RSA                     ALG_YES
21   #define    ALG_SHA1                    ALG_YES
22   #define    ALG_HMAC                    ALG_YES
23   #define    ALG_AES                     ALG_YES
24   #define    ALG_MGF1                    ALG_YES
25   #define    ALG_XOR                     ALG_YES
26   #define    ALG_KEYEDHASH               ALG_YES
27   #define    ALG_SHA256                  ALG_YES
28   #define    ALG_SHA384                  ALG_YES
29   #define    ALG_SHA512                  ALG_NO
30   #define    ALG_SM3_256                 ALG_NO
31   #define    ALG_SM4                     ALG_NO
32   #define    ALG_RSASSA                  (ALG_YES*ALG_RSA)
33   #define    ALG_RSAES                   (ALG_YES*ALG_RSA)
34   #define    ALG_RSAPSS                  (ALG_YES*ALG_RSA)

     Page 344                                     TCG Published                                     Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
     Part 4: Supporting Routines                                        Trusted Platform Module Library

35   #define   ALG_OAEP                  (ALG_YES*ALG_RSA)
36   #define   ALG_ECC                   ALG_YES
37   #define   ALG_ECDH                  (ALG_YES*ALG_ECC)
38   #define   ALG_ECDSA                 (ALG_YES*ALG_ECC)
39   #define   ALG_ECDAA                 (ALG_YES*ALG_ECC)
40   #define   ALG_SM2                   (ALG_YES*ALG_ECC)
41   #define   ALG_ECSCHNORR             (ALG_YES*ALG_ECC)
42   #define   ALG_ECMQV                 (ALG_NO*ALG_ECC)
43   #define   ALG_SYMCIPHER             ALG_YES
44   #define   ALG_KDF1_SP800_56A        (ALG_YES*ALG_ECC)
45   #define   ALG_KDF2                  ALG_NO
46   #define   ALG_KDF1_SP800_108        ALG_YES
47   #define   ALG_CTR                   ALG_YES
48   #define   ALG_OFB                   ALG_YES
49   #define   ALG_CBC                   ALG_YES
50   #define   ALG_CFB                   ALG_YES
51   #define   ALG_ECB                   ALG_YES

     From Vendor-Specific: Table 4 - Defines for Key Size Constants

52   #define RSA_KEY_SIZES_BITS          {1024,2048}
53   #define RSA_KEY_SIZE_BITS_1024      RSA_ALLOWED_KEY_SIZE_1024
54   #define RSA_KEY_SIZE_BITS_2048      RSA_ALLOWED_KEY_SIZE_2048
55   #define MAX_RSA_KEY_BITS            2048
56   #define MAX_RSA_KEY_BYTES           256
57   #define AES_KEY_SIZES_BITS          {128,256}
58   #define AES_KEY_SIZE_BITS_128       AES_ALLOWED_KEY_SIZE_128
59   #define AES_KEY_SIZE_BITS_256       AES_ALLOWED_KEY_SIZE_256
60   #define MAX_AES_KEY_BITS            256
61   #define MAX_AES_KEY_BYTES           32
62   #define MAX_AES_BLOCK_SIZE_BYTES                               \
63               MAX(AES_128_BLOCK_SIZE_BYTES,                      \
64               MAX(AES_256_BLOCK_SIZE_BYTES, 0))
65   #define SM4_KEY_SIZES_BITS          {128}
66   #define SM4_KEY_SIZE_BITS_128       SM4_ALLOWED_KEY_SIZE_128
67   #define MAX_SM4_KEY_BITS            128
68   #define MAX_SM4_KEY_BYTES           16
69   #define MAX_SM4_BLOCK_SIZE_BYTES                               \
70               MAX(SM4_128_BLOCK_SIZE_BYTES, 0)
71   #define CAMELLIA_KEY_SIZES_BITS     {128}
72   #define CAMELLIA_KEY_SIZE_BITS_128      CAMELLIA_ALLOWED_KEY_SIZE_128
73   #define MAX_CAMELLIA_KEY_BITS       128
74   #define MAX_CAMELLIA_KEY_BYTES      16
75   #define MAX_CAMELLIA_BLOCK_SIZE_BYTES                          \
76               MAX(CAMELLIA_128_BLOCK_SIZE_BYTES, 0)

     From Vendor-Specific: Table 5 - Defines for Implemented Curves

77   #define ECC_NIST_P256          YES
78   #define ECC_NIST_P384          YES
79   #define ECC_BN_P256            YES
80   #define ECC_CURVES             {\
81       TPM_ECC_BN_P256, TPM_ECC_NIST_P256, TPM_ECC_NIST_P384}
82   #define ECC_KEY_SIZES_BITS     {256, 384}
83   #define ECC_KEY_SIZE_BITS_256
84   #define ECC_KEY_SIZE_BITS_384
85   #define MAX_ECC_KEY_BITS       384
86   #define MAX_ECC_KEY_BYTES      48

     From Vendor-Specific: Table 6 - Defines for Implemented Commands

87   #define   CC_ActivateCredential                  CC_YES
88   #define   CC_Certify                             CC_YES
89   #define   CC_CertifyCreation                     CC_YES


     Family "2.0"                              TCG Published                                 Page 345
     Level 00 Revision 01.16            Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                 Part 4: Supporting Routines

 90   #define    CC_ChangeEPS                      CC_YES
 91   #define    CC_ChangePPS                      CC_YES
 92   #define    CC_Clear                          CC_YES
 93   #define    CC_ClearControl                   CC_YES
 94   #define    CC_ClockRateAdjust                CC_YES
 95   #define    CC_ClockSet                       CC_YES
 96   #define    CC_Commit                         (CC_YES*ALG_ECC)
 97   #define    CC_ContextLoad                    CC_YES
 98   #define    CC_ContextSave                    CC_YES
 99   #define    CC_Create                         CC_YES
100   #define    CC_CreatePrimary                  CC_YES
101   #define    CC_DictionaryAttackLockReset      CC_YES
102   #define    CC_DictionaryAttackParameters     CC_YES
103   #define    CC_Duplicate                      CC_YES
104   #define    CC_ECC_Parameters                 (CC_YES*ALG_ECC)
105   #define    CC_ECDH_KeyGen                    (CC_YES*ALG_ECC)
106   #define    CC_ECDH_ZGen                      (CC_YES*ALG_ECC)
107   #define    CC_EncryptDecrypt                 CC_YES
108   #define    CC_EventSequenceComplete          CC_YES
109   #define    CC_EvictControl                   CC_YES
110   #define    CC_FieldUpgradeData               CC_NO
111   #define    CC_FieldUpgradeStart              CC_NO
112   #define    CC_FirmwareRead                   CC_NO
113   #define    CC_FlushContext                   CC_YES
114   #define    CC_GetCapability                  CC_YES
115   #define    CC_GetCommandAuditDigest          CC_YES
116   #define    CC_GetRandom                      CC_YES
117   #define    CC_GetSessionAuditDigest          CC_YES
118   #define    CC_GetTestResult                  CC_YES
119   #define    CC_GetTime                        CC_YES
120   #define    CC_Hash                           CC_YES
121   #define    CC_HashSequenceStart              CC_YES
122   #define    CC_HierarchyChangeAuth            CC_YES
123   #define    CC_HierarchyControl               CC_YES
124   #define    CC_HMAC                           CC_YES
125   #define    CC_HMAC_Start                     CC_YES
126   #define    CC_Import                         CC_YES
127   #define    CC_IncrementalSelfTest            CC_YES
128   #define    CC_Load                           CC_YES
129   #define    CC_LoadExternal                   CC_YES
130   #define    CC_MakeCredential                 CC_YES
131   #define    CC_NV_Certify                     CC_YES
132   #define    CC_NV_ChangeAuth                  CC_YES
133   #define    CC_NV_DefineSpace                 CC_YES
134   #define    CC_NV_Extend                      CC_YES
135   #define    CC_NV_GlobalWriteLock             CC_YES
136   #define    CC_NV_Increment                   CC_YES
137   #define    CC_NV_Read                        CC_YES
138   #define    CC_NV_ReadLock                    CC_YES
139   #define    CC_NV_ReadPublic                  CC_YES
140   #define    CC_NV_SetBits                     CC_YES
141   #define    CC_NV_UndefineSpace               CC_YES
142   #define    CC_NV_UndefineSpaceSpecial        CC_YES
143   #define    CC_NV_Write                       CC_YES
144   #define    CC_NV_WriteLock                   CC_YES
145   #define    CC_ObjectChangeAuth               CC_YES
146   #define    CC_PCR_Allocate                   CC_YES
147   #define    CC_PCR_Event                      CC_YES
148   #define    CC_PCR_Extend                     CC_YES
149   #define    CC_PCR_Read                       CC_YES
150   #define    CC_PCR_Reset                      CC_YES
151   #define    CC_PCR_SetAuthPolicy              CC_YES
152   #define    CC_PCR_SetAuthValue               CC_YES
153   #define    CC_PolicyAuthorize                CC_YES
154   #define    CC_PolicyAuthValue                CC_YES
155   #define    CC_PolicyCommandCode              CC_YES

      Page 346                               TCG Published                          Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                         Trusted Platform Module Library

156   #define   CC_PolicyCounterTimer                  CC_YES
157   #define   CC_PolicyCpHash                        CC_YES
158   #define   CC_PolicyDuplicationSelect             CC_YES
159   #define   CC_PolicyGetDigest                     CC_YES
160   #define   CC_PolicyLocality                      CC_YES
161   #define   CC_PolicyNameHash                      CC_YES
162   #define   CC_PolicyNV                            CC_YES
163   #define   CC_PolicyOR                            CC_YES
164   #define   CC_PolicyPassword                      CC_YES
165   #define   CC_PolicyPCR                           CC_YES
166   #define   CC_PolicyPhysicalPresence              CC_YES
167   #define   CC_PolicyRestart                       CC_YES
168   #define   CC_PolicySecret                        CC_YES
169   #define   CC_PolicySigned                        CC_YES
170   #define   CC_PolicyTicket                        CC_YES
171   #define   CC_PP_Commands                         CC_YES
172   #define   CC_Quote                               CC_YES
173   #define   CC_ReadClock                           CC_YES
174   #define   CC_ReadPublic                          CC_YES
175   #define   CC_Rewrap                              CC_YES
176   #define   CC_RSA_Decrypt                         (CC_YES*ALG_RSA)
177   #define   CC_RSA_Encrypt                         (CC_YES*ALG_RSA)
178   #define   CC_SelfTest                            CC_YES
179   #define   CC_SequenceComplete                    CC_YES
180   #define   CC_SequenceUpdate                      CC_YES
181   #define   CC_SetAlgorithmSet                     CC_YES
182   #define   CC_SetCommandCodeAuditStatus           CC_YES
183   #define   CC_SetPrimaryPolicy                    CC_YES
184   #define   CC_Shutdown                            CC_YES
185   #define   CC_Sign                                CC_YES
186   #define   CC_StartAuthSession                    CC_YES
187   #define   CC_Startup                             CC_YES
188   #define   CC_StirRandom                          CC_YES
189   #define   CC_TestParms                           CC_YES
190   #define   CC_Unseal                              CC_YES
191   #define   CC_VerifySignature                     CC_YES
192   #define   CC_ZGen_2Phase                         (CC_YES*ALG_ECC)
193   #define   CC_EC_Ephemeral                        (CC_YES*ALG_ECC)
194   #define   CC_PolicyNvWritten                     CC_YES

      From Vendor-Specific: Table 7 - Defines for Implementation Values

195   #define   FIELD_UPGRADE_IMPLEMENTED              NO
196   #define   BSIZE                                  UINT16
197   #define   BUFFER_ALIGNMENT                       4
198   #define   IMPLEMENTATION_PCR                     24
199   #define   PLATFORM_PCR                           24
200   #define   DRTM_PCR                               17
201   #define   HCRTM_PCR                              0
202   #define   NUM_LOCALITIES                         5
203   #define   MAX_HANDLE_NUM                         3
204   #define   MAX_ACTIVE_SESSIONS                    64
205   #define   CONTEXT_SLOT                           UINT16
206   #define   CONTEXT_COUNTER                        UINT64
207   #define   MAX_LOADED_SESSIONS                    3
208   #define   MAX_SESSION_NUM                        3
209   #define   MAX_LOADED_OBJECTS                     3
210   #define   MIN_EVICT_OBJECTS                      2
211   #define   PCR_SELECT_MIN                         ((PLATFORM_PCR+7)/8)
212   #define   PCR_SELECT_MAX                         ((IMPLEMENTATION_PCR+7)/8)
213   #define   NUM_POLICY_PCR_GROUP                   1
214   #define   NUM_AUTHVALUE_PCR_GROUP                1
215   #define   MAX_CONTEXT_SIZE                       2048
216   #define   MAX_DIGEST_BUFFER                      1024
217   #define   MAX_NV_INDEX_SIZE                      2048


      Family "2.0"                              TCG Published                                  Page 347
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines

218   #define MAX_NV_BUFFER_SIZE                1024
219   #define MAX_CAP_BUFFER                    1024
220   #define NV_MEMORY_SIZE                    16384
221   #define NUM_STATIC_PCR                    16
222   #define MAX_ALG_LIST_SIZE                 64
223   #define TIMER_PRESCALE                    100000
224   #define PRIMARY_SEED_SIZE                 32
225   #define CONTEXT_ENCRYPT_ALG               TPM_ALG_AES
226   #define CONTEXT_ENCRYPT_KEY_BITS          MAX_SYM_KEY_BITS
227   #define CONTEXT_ENCRYPT_KEY_BYTES         ((CONTEXT_ENCRYPT_KEY_BITS+7)/8)
228   #define CONTEXT_INTEGRITY_HASH_ALG        TPM_ALG_SHA256
229   #define CONTEXT_INTEGRITY_HASH_SIZE       SHA256_DIGEST_SIZE
230   #define PROOF_SIZE                        CONTEXT_INTEGRITY_HASH_SIZE
231   #define NV_CLOCK_UPDATE_INTERVAL          12
232   #define NUM_POLICY_PCR                    1
233   #define MAX_COMMAND_SIZE                  4096
234   #define MAX_RESPONSE_SIZE                 4096
235   #define ORDERLY_BITS                      8
236   #define MAX_ORDERLY_COUNT                 ((1<<ORDERLY_BITS)-1)
237   #define ALG_ID_FIRST                      TPM_ALG_FIRST
238   #define ALG_ID_LAST                       TPM_ALG_LAST
239   #define MAX_SYM_DATA                      128
240   #define MAX_RNG_ENTROPY_SIZE              64
241   #define RAM_INDEX_SPACE                   512
242   #define RSA_DEFAULT_PUBLIC_EXPONENT       0x00010001
243   #define ENABLE_PCR_NO_INCREMENT           YES
244   #define CRT_FORMAT_RSA                    YES
245   #define PRIVATE_VENDOR_SPECIFIC_BYTES     \
246       ((MAX_RSA_KEY_BYTES/2)*(3+CRT_FORMAT_RSA*2))

      From TCG Algorithm Registry: Table 2 - Definition of TPM_ALG_ID Constants

247   typedef UINT16              TPM_ALG_ID;
248   #define TPM_ALG_ERROR                (TPM_ALG_ID)(0x0000)
249   #define ALG_ERROR_VALUE              0x0000
250   #if defined ALG_RSA && ALG_RSA == YES
251   #define TPM_ALG_RSA                  (TPM_ALG_ID)(0x0001)
252   #endif
253   #define ALG_RSA_VALUE                0x0001
254   #if defined ALG_SHA && ALG_SHA == YES
255   #define TPM_ALG_SHA                  (TPM_ALG_ID)(0x0004)
256   #endif
257   #define ALG_SHA_VALUE                0x0004
258   #if defined ALG_SHA1 && ALG_SHA1 == YES
259   #define TPM_ALG_SHA1                 (TPM_ALG_ID)(0x0004)
260   #endif
261   #define ALG_SHA1_VALUE               0x0004
262   #if defined ALG_HMAC && ALG_HMAC == YES
263   #define TPM_ALG_HMAC                  (TPM_ALG_ID)(0x0005)
264   #endif
265   #define ALG_HMAC_VALUE               0x0005
266   #if defined ALG_AES && ALG_AES == YES
267   #define TPM_ALG_AES                  (TPM_ALG_ID)(0x0006)
268   #endif
269   #define ALG_AES_VALUE                0x0006
270   #if defined ALG_MGF1 && ALG_MGF1 == YES
271   #define TPM_ALG_MGF1                 (TPM_ALG_ID)(0x0007)
272   #endif
273   #define ALG_MGF1_VALUE               0x0007
274   #if defined ALG_KEYEDHASH && ALG_KEYEDHASH == YES
275   #define TPM_ALG_KEYEDHASH            (TPM_ALG_ID)(0x0008)
276   #endif
277   #define ALG_KEYEDHASH_VALUE          0x0008
278   #if defined ALG_XOR && ALG_XOR == YES
279   #define TPM_ALG_XOR                  (TPM_ALG_ID)(0x000A)


      Page 348                                 TCG Published                                    Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                   Trusted Platform Module Library

280   #endif
281   #define ALG_XOR_VALUE                0x000A
282   #if defined ALG_SHA256 && ALG_SHA256 == YES
283   #define TPM_ALG_SHA256               (TPM_ALG_ID)(0x000B)
284   #endif
285   #define ALG_SHA256_VALUE             0x000B
286   #if defined ALG_SHA384 && ALG_SHA384 == YES
287   #define TPM_ALG_SHA384               (TPM_ALG_ID)(0x000C)
288   #endif
289   #define ALG_SHA384_VALUE             0x000C
290   #if defined ALG_SHA512 && ALG_SHA512 == YES
291   #define TPM_ALG_SHA512               (TPM_ALG_ID)(0x000D)
292   #endif
293   #define ALG_SHA512_VALUE             0x000D
294   #define TPM_ALG_NULL                 (TPM_ALG_ID)(0x0010)
295   #define ALG_NULL_VALUE               0x0010
296   #if defined ALG_SM3_256 && ALG_SM3_256 == YES
297   #define TPM_ALG_SM3_256              (TPM_ALG_ID)(0x0012)
298   #endif
299   #define ALG_SM3_256_VALUE            0x0012
300   #if defined ALG_SM4 && ALG_SM4 == YES
301   #define TPM_ALG_SM4                  (TPM_ALG_ID)(0x0013)
302   #endif
303   #define ALG_SM4_VALUE                0x0013
304   #if defined ALG_RSASSA && ALG_RSASSA == YES
305   #define TPM_ALG_RSASSA               (TPM_ALG_ID)(0x0014)
306   #endif
307   #define ALG_RSASSA_VALUE             0x0014
308   #if defined ALG_RSAES && ALG_RSAES == YES
309   #define TPM_ALG_RSAES                (TPM_ALG_ID)(0x0015)
310   #endif
311   #define ALG_RSAES_VALUE              0x0015
312   #if defined ALG_RSAPSS && ALG_RSAPSS == YES
313   #define TPM_ALG_RSAPSS               (TPM_ALG_ID)(0x0016)
314   #endif
315   #define ALG_RSAPSS_VALUE             0x0016
316   #if defined ALG_OAEP && ALG_OAEP == YES
317   #define TPM_ALG_OAEP                 (TPM_ALG_ID)(0x0017)
318   #endif
319   #define ALG_OAEP_VALUE               0x0017
320   #if defined ALG_ECDSA && ALG_ECDSA == YES
321   #define TPM_ALG_ECDSA                (TPM_ALG_ID)(0x0018)
322   #endif
323   #define ALG_ECDSA_VALUE              0x0018
324   #if defined ALG_ECDH && ALG_ECDH == YES
325   #define TPM_ALG_ECDH                 (TPM_ALG_ID)(0x0019)
326   #endif
327   #define ALG_ECDH_VALUE               0x0019
328   #if defined ALG_ECDAA && ALG_ECDAA == YES
329   #define TPM_ALG_ECDAA                (TPM_ALG_ID)(0x001A)
330   #endif
331   #define ALG_ECDAA_VALUE              0x001A
332   #if defined ALG_SM2 && ALG_SM2 == YES
333   #define TPM_ALG_SM2                  (TPM_ALG_ID)(0x001B)
334   #endif
335   #define ALG_SM2_VALUE                0x001B
336   #if defined ALG_ECSCHNORR && ALG_ECSCHNORR == YES
337   #define TPM_ALG_ECSCHNORR            (TPM_ALG_ID)(0x001C)
338   #endif
339   #define ALG_ECSCHNORR_VALUE          0x001C
340   #if defined ALG_ECMQV && ALG_ECMQV == YES
341   #define TPM_ALG_ECMQV                (TPM_ALG_ID)(0x001D)
342   #endif
343   #define ALG_ECMQV_VALUE              0x001D
344   #if defined ALG_KDF1_SP800_56A && ALG_KDF1_SP800_56A == YES
345   #define TPM_ALG_KDF1_SP800_56A       (TPM_ALG_ID)(0x0020)

      Family "2.0"                        TCG Published                                  Page 349
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                         Part 4: Supporting Routines

346   #endif
347   #define ALG_KDF1_SP800_56A_VALUE     0x0020
348   #if defined ALG_KDF2 && ALG_KDF2 == YES
349   #define TPM_ALG_KDF2                 (TPM_ALG_ID)(0x0021)
350   #endif
351   #define ALG_KDF2_VALUE               0x0021
352   #if defined ALG_KDF1_SP800_108 && ALG_KDF1_SP800_108 == YES
353   #define TPM_ALG_KDF1_SP800_108       (TPM_ALG_ID)(0x0022)
354   #endif
355   #define ALG_KDF1_SP800_108_VALUE     0x0022
356   #if defined ALG_ECC && ALG_ECC == YES
357   #define TPM_ALG_ECC                  (TPM_ALG_ID)(0x0023)
358   #endif
359   #define ALG_ECC_VALUE                0x0023
360   #if defined ALG_SYMCIPHER && ALG_SYMCIPHER == YES
361   #define TPM_ALG_SYMCIPHER            (TPM_ALG_ID)(0x0025)
362   #endif
363   #define ALG_SYMCIPHER_VALUE          0x0025
364   #if defined ALG_CAMELLIA && ALG_CAMELLIA == YES
365   #define TPM_ALG_CAMELLIA             (TPM_ALG_ID)(0x0026)
366   #endif
367   #define ALG_CAMELLIA_VALUE           0x0026
368   #if defined ALG_CTR && ALG_CTR == YES
369   #define TPM_ALG_CTR                  (TPM_ALG_ID)(0x0040)
370   #endif
371   #define ALG_CTR_VALUE                0x0040
372   #if defined ALG_OFB && ALG_OFB == YES
373   #define TPM_ALG_OFB                   (TPM_ALG_ID)(0x0041)
374   #endif
375   #define ALG_OFB_VALUE                0x0041
376   #if defined ALG_CBC && ALG_CBC == YES
377   #define TPM_ALG_CBC                  (TPM_ALG_ID)(0x0042)
378   #endif
379   #define ALG_CBC_VALUE                0x0042
380   #if defined ALG_CFB && ALG_CFB == YES
381   #define TPM_ALG_CFB                  (TPM_ALG_ID)(0x0043)
382   #endif
383   #define ALG_CFB_VALUE                0x0043
384   #if defined ALG_ECB && ALG_ECB == YES
385   #define TPM_ALG_ECB                  (TPM_ALG_ID)(0x0044)
386   #endif
387   #define ALG_ECB_VALUE                0x0044
388   #define TPM_ALG_FIRST                (TPM_ALG_ID)(0x0001)
389   #define ALG_FIRST_VALUE              0x0001
390   #define TPM_ALG_LAST                 (TPM_ALG_ID)(0x0044)
391   #define ALG_LAST_VALUE               0x0044

      From TCG Algorithm Registry: Table 3 - Definition of TPM_ECC_CURVE Constants

392   typedef    UINT16                 TPM_ECC_CURVE;
393   #define    TPM_ECC_NONE             (TPM_ECC_CURVE)(0x0000)
394   #define    TPM_ECC_NIST_P192        (TPM_ECC_CURVE)(0x0001)
395   #define    TPM_ECC_NIST_P224        (TPM_ECC_CURVE)(0x0002)
396   #define    TPM_ECC_NIST_P256        (TPM_ECC_CURVE)(0x0003)
397   #define    TPM_ECC_NIST_P384        (TPM_ECC_CURVE)(0x0004)
398   #define    TPM_ECC_NIST_P521        (TPM_ECC_CURVE)(0x0005)
399   #define    TPM_ECC_BN_P256          (TPM_ECC_CURVE)(0x0010)
400   #define    TPM_ECC_BN_P638          (TPM_ECC_CURVE)(0x0011)
401   #define    TPM_ECC_SM2_P256         (TPM_ECC_CURVE)(0x0020)

      From TCG Algorithm Registry: Table 4 - Defines for NIST_P192 ECC Values Data in CrpiEccData.c From
      TCG Algorithm Registry: Table 5 - Defines for NIST_P224 ECC Values Data in CrpiEccData.c From TCG
      Algorithm Registry: Table 6 - Defines for NIST_P256 ECC Values Data in CrpiEccData.c From TCG
      Algorithm Registry: Table 7 - Defines for NIST_P384 ECC Values Data in CrpiEccData.c From TCG

      Page 350                                  TCG Published                               Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014            Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library


      Algorithm Registry: Table 8 - Defines for NIST_P521 ECC Values Data in CrpiEccData.c     From   TCG
      Algorithm Registry: Table 9 - Defines for BN_P256 ECC Values Data in CrpiEccData.c       From   TCG
      Algorithm Registry: Table 10 - Defines for BN_P638 ECC Values Data in CrpiEccData.c      From   TCG
      Algorithm Registry: Table 11 - Defines for SM2_P256 ECC Values Data in CrpiEccData.c     From   TCG
      Algorithm Registry: Table 12 - Defines for SHA1 Hash Values

402   #define SHA1_DIGEST_SIZE     20
403   #define SHA1_BLOCK_SIZE      64
404   #define SHA1_DER_SIZE        15
405   #define SHA1_DER             \
406       0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14

      From TCG Algorithm Registry: Table 13 - Defines for SHA256 Hash Values

407   #define   SHA256_DIGEST_SIZE       32
408   #define   SHA256_BLOCK_SIZE        64
409   #define   SHA256_DER_SIZE          19
410   #define   SHA256_DER               \
411
      0x30,0x31,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0
      x04,0x20

      From TCG Algorithm Registry: Table 14 - Defines for SHA384 Hash Values

412   #define   SHA384_DIGEST_SIZE       48
413   #define   SHA384_BLOCK_SIZE        128
414   #define   SHA384_DER_SIZE          19
415   #define   SHA384_DER               \
416
      0x30,0x41,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0
      x04,0x30

      From TCG Algorithm Registry: Table 15 - Defines for SHA512 Hash Values

417   #define   SHA512_DIGEST_SIZE       64
418   #define   SHA512_BLOCK_SIZE        128
419   #define   SHA512_DER_SIZE          19
420   #define   SHA512_DER               \
421
      0x30,0x51,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0
      x04,0x40

      From TCG Algorithm Registry: Table 16 - Defines for SM3_256 Hash Values

422   #define   SM3_256_DIGEST_SIZE       32
423   #define   SM3_256_BLOCK_SIZE        64
424   #define   SM3_256_DER_SIZE          18
425   #define   SM3_256_DER               \
426
      0x30,0x30,0x30,0x0C,0x06,0x08,0x2A,0x81,0x1C,0x81,0x45,0x01,0x83,0x11,0x05,0x00,0x04,0
      x20

      From TCG Algorithm Registry: Table 17 - Defines for AES Symmetric Cipher Algorithm Constants

427   #define   AES_ALLOWED_KEY_SIZE_128        YES
428   #define   AES_ALLOWED_KEY_SIZE_192        YES
429   #define   AES_ALLOWED_KEY_SIZE_256        YES
430   #define   AES_128_BLOCK_SIZE_BYTES        16
431   #define   AES_192_BLOCK_SIZE_BYTES        16
432   #define   AES_256_BLOCK_SIZE_BYTES        16

      From TCG Algorithm Registry: Table 18 - Defines for SM4 Symmetric Cipher Algorithm Constants

      Family "2.0"                             TCG Published                                    Page 351
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                         Part 4: Supporting Routines

433   #define    SM4_ALLOWED_KEY_SIZE_128       YES
434   #define    SM4_128_BLOCK_SIZE_BYTES       16

      From TCG Algorithm Registry: Table 19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants

435   #define    CAMELLIA_ALLOWED_KEY_SIZE_128        YES
436   #define    CAMELLIA_ALLOWED_KEY_SIZE_192        YES
437   #define    CAMELLIA_ALLOWED_KEY_SIZE_256        YES
438   #define    CAMELLIA_128_BLOCK_SIZE_BYTES        16
439   #define    CAMELLIA_192_BLOCK_SIZE_BYTES        16
440   #define    CAMELLIA_256_BLOCK_SIZE_BYTES        16

      From TPM 2.0 Part 2: Table 13 - Definition of TPM_CC Constants

441   typedef UINT32              TPM_CC;
442   #define TPM_CC_FIRST                          (TPM_CC)(0x0000011F)
443   #define TPM_CC_PP_FIRST                       (TPM_CC)(0x0000011F)
444   #if defined CC_NV_UndefineSpaceSpecial && CC_NV_UndefineSpaceSpecial == YES
445   #define TPM_CC_NV_UndefineSpaceSpecial        (TPM_CC)(0x0000011F)
446   #endif
447   #if defined CC_EvictControl && CC_EvictControl == YES
448   #define TPM_CC_EvictControl                   (TPM_CC)(0x00000120)
449   #endif
450   #if defined CC_HierarchyControl && CC_HierarchyControl == YES
451   #define TPM_CC_HierarchyControl               (TPM_CC)(0x00000121)
452   #endif
453   #if defined CC_NV_UndefineSpace && CC_NV_UndefineSpace == YES
454   #define TPM_CC_NV_UndefineSpace               (TPM_CC)(0x00000122)
455   #endif
456   #if defined CC_ChangeEPS && CC_ChangeEPS == YES
457   #define TPM_CC_ChangeEPS                      (TPM_CC)(0x00000124)
458   #endif
459   #if defined CC_ChangePPS && CC_ChangePPS == YES
460   #define TPM_CC_ChangePPS                      (TPM_CC)(0x00000125)
461   #endif
462   #if defined CC_Clear && CC_Clear == YES
463   #define TPM_CC_Clear                          (TPM_CC)(0x00000126)
464   #endif
465   #if defined CC_ClearControl && CC_ClearControl == YES
466   #define TPM_CC_ClearControl                   (TPM_CC)(0x00000127)
467   #endif
468   #if defined CC_ClockSet && CC_ClockSet == YES
469   #define TPM_CC_ClockSet                       (TPM_CC)(0x00000128)
470   #endif
471   #if defined CC_HierarchyChangeAuth && CC_HierarchyChangeAuth == YES
472   #define TPM_CC_HierarchyChangeAuth            (TPM_CC)(0x00000129)
473   #endif
474   #if defined CC_NV_DefineSpace && CC_NV_DefineSpace == YES
475   #define TPM_CC_NV_DefineSpace                 (TPM_CC)(0x0000012A)
476   #endif
477   #if defined CC_PCR_Allocate && CC_PCR_Allocate == YES
478   #define TPM_CC_PCR_Allocate                   (TPM_CC)(0x0000012B)
479   #endif
480   #if defined CC_PCR_SetAuthPolicy && CC_PCR_SetAuthPolicy == YES
481   #define TPM_CC_PCR_SetAuthPolicy              (TPM_CC)(0x0000012C)
482   #endif
483   #if defined CC_PP_Commands && CC_PP_Commands == YES
484   #define TPM_CC_PP_Commands                    (TPM_CC)(0x0000012D)
485   #endif
486   #if defined CC_SetPrimaryPolicy && CC_SetPrimaryPolicy == YES
487   #define TPM_CC_SetPrimaryPolicy               (TPM_CC)(0x0000012E)
488   #endif
489   #if defined CC_FieldUpgradeStart && CC_FieldUpgradeStart == YES
490   #define TPM_CC_FieldUpgradeStart              (TPM_CC)(0x0000012F)
491   #endif

      Page 352                                  TCG Published                               Family "2.0"
      October 30, 2014                   Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

492   #if defined CC_ClockRateAdjust && CC_ClockRateAdjust == YES
493   #define TPM_CC_ClockRateAdjust                (TPM_CC)(0x00000130)
494   #endif
495   #if defined CC_CreatePrimary && CC_CreatePrimary == YES
496   #define TPM_CC_CreatePrimary                  (TPM_CC)(0x00000131)
497   #endif
498   #if defined CC_NV_GlobalWriteLock && CC_NV_GlobalWriteLock == YES
499   #define TPM_CC_NV_GlobalWriteLock             (TPM_CC)(0x00000132)
500   #endif
501   #define TPM_CC_PP_LAST                        (TPM_CC)(0x00000132)
502   #if defined CC_GetCommandAuditDigest && CC_GetCommandAuditDigest == YES
503   #define TPM_CC_GetCommandAuditDigest          (TPM_CC)(0x00000133)
504   #endif
505   #if defined CC_NV_Increment && CC_NV_Increment == YES
506   #define TPM_CC_NV_Increment                   (TPM_CC)(0x00000134)
507   #endif
508   #if defined CC_NV_SetBits && CC_NV_SetBits == YES
509   #define TPM_CC_NV_SetBits                     (TPM_CC)(0x00000135)
510   #endif
511   #if defined CC_NV_Extend && CC_NV_Extend == YES
512   #define TPM_CC_NV_Extend                      (TPM_CC)(0x00000136)
513   #endif
514   #if defined CC_NV_Write && CC_NV_Write == YES
515   #define TPM_CC_NV_Write                       (TPM_CC)(0x00000137)
516   #endif
517   #if defined CC_NV_WriteLock && CC_NV_WriteLock == YES
518   #define TPM_CC_NV_WriteLock                   (TPM_CC)(0x00000138)
519   #endif
520   #if defined CC_DictionaryAttackLockReset && CC_DictionaryAttackLockReset == YES
521   #define TPM_CC_DictionaryAttackLockReset      (TPM_CC)(0x00000139)
522   #endif
523   #if defined CC_DictionaryAttackParameters && CC_DictionaryAttackParameters == YES
524   #define TPM_CC_DictionaryAttackParameters     (TPM_CC)(0x0000013A)
525   #endif
526   #if defined CC_NV_ChangeAuth && CC_NV_ChangeAuth == YES
527   #define TPM_CC_NV_ChangeAuth                  (TPM_CC)(0x0000013B)
528   #endif
529   #if defined CC_PCR_Event && CC_PCR_Event == YES
530   #define TPM_CC_PCR_Event                      (TPM_CC)(0x0000013C)
531   #endif
532   #if defined CC_PCR_Reset && CC_PCR_Reset == YES
533   #define TPM_CC_PCR_Reset                      (TPM_CC)(0x0000013D)
534   #endif
535   #if defined CC_SequenceComplete && CC_SequenceComplete == YES
536   #define TPM_CC_SequenceComplete               (TPM_CC)(0x0000013E)
537   #endif
538   #if defined CC_SetAlgorithmSet && CC_SetAlgorithmSet == YES
539   #define TPM_CC_SetAlgorithmSet                (TPM_CC)(0x0000013F)
540   #endif
541   #if defined CC_SetCommandCodeAuditStatus && CC_SetCommandCodeAuditStatus == YES
542   #define TPM_CC_SetCommandCodeAuditStatus      (TPM_CC)(0x00000140)
543   #endif
544   #if defined CC_FieldUpgradeData && CC_FieldUpgradeData == YES
545   #define TPM_CC_FieldUpgradeData               (TPM_CC)(0x00000141)
546   #endif
547   #if defined CC_IncrementalSelfTest && CC_IncrementalSelfTest == YES
548   #define TPM_CC_IncrementalSelfTest            (TPM_CC)(0x00000142)
549   #endif
550   #if defined CC_SelfTest && CC_SelfTest == YES
551   #define TPM_CC_SelfTest                       (TPM_CC)(0x00000143)
552   #endif
553   #if defined CC_Startup && CC_Startup == YES
554   #define TPM_CC_Startup                        (TPM_CC)(0x00000144)
555   #endif
556   #if defined CC_Shutdown && CC_Shutdown == YES
557   #define TPM_CC_Shutdown                       (TPM_CC)(0x00000145)

      Family "2.0"                        TCG Published                                Page 353
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

558   #endif
559   #if defined CC_StirRandom && CC_StirRandom == YES
560   #define TPM_CC_StirRandom                     (TPM_CC)(0x00000146)
561   #endif
562   #if defined CC_ActivateCredential && CC_ActivateCredential == YES
563   #define TPM_CC_ActivateCredential             (TPM_CC)(0x00000147)
564   #endif
565   #if defined CC_Certify && CC_Certify == YES
566   #define TPM_CC_Certify                        (TPM_CC)(0x00000148)
567   #endif
568   #if defined CC_PolicyNV && CC_PolicyNV == YES
569   #define TPM_CC_PolicyNV                       (TPM_CC)(0x00000149)
570   #endif
571   #if defined CC_CertifyCreation && CC_CertifyCreation == YES
572   #define TPM_CC_CertifyCreation                (TPM_CC)(0x0000014A)
573   #endif
574   #if defined CC_Duplicate && CC_Duplicate == YES
575   #define TPM_CC_Duplicate                      (TPM_CC)(0x0000014B)
576   #endif
577   #if defined CC_GetTime && CC_GetTime == YES
578   #define TPM_CC_GetTime                        (TPM_CC)(0x0000014C)
579   #endif
580   #if defined CC_GetSessionAuditDigest && CC_GetSessionAuditDigest == YES
581   #define TPM_CC_GetSessionAuditDigest          (TPM_CC)(0x0000014D)
582   #endif
583   #if defined CC_NV_Read && CC_NV_Read == YES
584   #define TPM_CC_NV_Read                        (TPM_CC)(0x0000014E)
585   #endif
586   #if defined CC_NV_ReadLock && CC_NV_ReadLock == YES
587   #define TPM_CC_NV_ReadLock                    (TPM_CC)(0x0000014F)
588   #endif
589   #if defined CC_ObjectChangeAuth && CC_ObjectChangeAuth == YES
590   #define TPM_CC_ObjectChangeAuth               (TPM_CC)(0x00000150)
591   #endif
592   #if defined CC_PolicySecret && CC_PolicySecret == YES
593   #define TPM_CC_PolicySecret                   (TPM_CC)(0x00000151)
594   #endif
595   #if defined CC_Rewrap && CC_Rewrap == YES
596   #define TPM_CC_Rewrap                         (TPM_CC)(0x00000152)
597   #endif
598   #if defined CC_Create && CC_Create == YES
599   #define TPM_CC_Create                         (TPM_CC)(0x00000153)
600   #endif
601   #if defined CC_ECDH_ZGen && CC_ECDH_ZGen == YES
602   #define TPM_CC_ECDH_ZGen                      (TPM_CC)(0x00000154)
603   #endif
604   #if defined CC_HMAC && CC_HMAC == YES
605   #define TPM_CC_HMAC                           (TPM_CC)(0x00000155)
606   #endif
607   #if defined CC_Import && CC_Import == YES
608   #define TPM_CC_Import                         (TPM_CC)(0x00000156)
609   #endif
610   #if defined CC_Load && CC_Load == YES
611   #define TPM_CC_Load                           (TPM_CC)(0x00000157)
612   #endif
613   #if defined CC_Quote && CC_Quote == YES
614   #define TPM_CC_Quote                          (TPM_CC)(0x00000158)
615   #endif
616   #if defined CC_RSA_Decrypt && CC_RSA_Decrypt == YES
617   #define TPM_CC_RSA_Decrypt                    (TPM_CC)(0x00000159)
618   #endif
619   #if defined CC_HMAC_Start && CC_HMAC_Start == YES
620   #define TPM_CC_HMAC_Start                     (TPM_CC)(0x0000015B)
621   #endif
622   #if defined CC_SequenceUpdate && CC_SequenceUpdate == YES
623   #define TPM_CC_SequenceUpdate                 (TPM_CC)(0x0000015C)

      Page 354                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

624   #endif
625   #if defined CC_Sign && CC_Sign == YES
626   #define TPM_CC_Sign                           (TPM_CC)(0x0000015D)
627   #endif
628   #if defined CC_Unseal && CC_Unseal == YES
629   #define TPM_CC_Unseal                         (TPM_CC)(0x0000015E)
630   #endif
631   #if defined CC_PolicySigned && CC_PolicySigned == YES
632   #define TPM_CC_PolicySigned                   (TPM_CC)(0x00000160)
633   #endif
634   #if defined CC_ContextLoad && CC_ContextLoad == YES
635   #define TPM_CC_ContextLoad                    (TPM_CC)(0x00000161)
636   #endif
637   #if defined CC_ContextSave && CC_ContextSave == YES
638   #define TPM_CC_ContextSave                    (TPM_CC)(0x00000162)
639   #endif
640   #if defined CC_ECDH_KeyGen && CC_ECDH_KeyGen == YES
641   #define TPM_CC_ECDH_KeyGen                    (TPM_CC)(0x00000163)
642   #endif
643   #if defined CC_EncryptDecrypt && CC_EncryptDecrypt == YES
644   #define TPM_CC_EncryptDecrypt                 (TPM_CC)(0x00000164)
645   #endif
646   #if defined CC_FlushContext && CC_FlushContext == YES
647   #define TPM_CC_FlushContext                   (TPM_CC)(0x00000165)
648   #endif
649   #if defined CC_LoadExternal && CC_LoadExternal == YES
650   #define TPM_CC_LoadExternal                   (TPM_CC)(0x00000167)
651   #endif
652   #if defined CC_MakeCredential && CC_MakeCredential == YES
653   #define TPM_CC_MakeCredential                 (TPM_CC)(0x00000168)
654   #endif
655   #if defined CC_NV_ReadPublic && CC_NV_ReadPublic == YES
656   #define TPM_CC_NV_ReadPublic                  (TPM_CC)(0x00000169)
657   #endif
658   #if defined CC_PolicyAuthorize && CC_PolicyAuthorize == YES
659   #define TPM_CC_PolicyAuthorize                (TPM_CC)(0x0000016A)
660   #endif
661   #if defined CC_PolicyAuthValue && CC_PolicyAuthValue == YES
662   #define TPM_CC_PolicyAuthValue                (TPM_CC)(0x0000016B)
663   #endif
664   #if defined CC_PolicyCommandCode && CC_PolicyCommandCode == YES
665   #define TPM_CC_PolicyCommandCode              (TPM_CC)(0x0000016C)
666   #endif
667   #if defined CC_PolicyCounterTimer && CC_PolicyCounterTimer == YES
668   #define TPM_CC_PolicyCounterTimer             (TPM_CC)(0x0000016D)
669   #endif
670   #if defined CC_PolicyCpHash && CC_PolicyCpHash == YES
671   #define TPM_CC_PolicyCpHash                   (TPM_CC)(0x0000016E)
672   #endif
673   #if defined CC_PolicyLocality && CC_PolicyLocality == YES
674   #define TPM_CC_PolicyLocality                 (TPM_CC)(0x0000016F)
675   #endif
676   #if defined CC_PolicyNameHash && CC_PolicyNameHash == YES
677   #define TPM_CC_PolicyNameHash                 (TPM_CC)(0x00000170)
678   #endif
679   #if defined CC_PolicyOR && CC_PolicyOR == YES
680   #define TPM_CC_PolicyOR                       (TPM_CC)(0x00000171)
681   #endif
682   #if defined CC_PolicyTicket && CC_PolicyTicket == YES
683   #define TPM_CC_PolicyTicket                   (TPM_CC)(0x00000172)
684   #endif
685   #if defined CC_ReadPublic && CC_ReadPublic == YES
686   #define TPM_CC_ReadPublic                     (TPM_CC)(0x00000173)
687   #endif
688   #if defined CC_RSA_Encrypt && CC_RSA_Encrypt == YES
689   #define TPM_CC_RSA_Encrypt                    (TPM_CC)(0x00000174)

      Family "2.0"                        TCG Published                                Page 355
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

690   #endif
691   #if defined CC_StartAuthSession && CC_StartAuthSession == YES
692   #define TPM_CC_StartAuthSession               (TPM_CC)(0x00000176)
693   #endif
694   #if defined CC_VerifySignature && CC_VerifySignature == YES
695   #define TPM_CC_VerifySignature                (TPM_CC)(0x00000177)
696   #endif
697   #if defined CC_ECC_Parameters && CC_ECC_Parameters == YES
698   #define TPM_CC_ECC_Parameters                 (TPM_CC)(0x00000178)
699   #endif
700   #if defined CC_FirmwareRead && CC_FirmwareRead == YES
701   #define TPM_CC_FirmwareRead                   (TPM_CC)(0x00000179)
702   #endif
703   #if defined CC_GetCapability && CC_GetCapability == YES
704   #define TPM_CC_GetCapability                  (TPM_CC)(0x0000017A)
705   #endif
706   #if defined CC_GetRandom && CC_GetRandom == YES
707   #define TPM_CC_GetRandom                      (TPM_CC)(0x0000017B)
708   #endif
709   #if defined CC_GetTestResult && CC_GetTestResult == YES
710   #define TPM_CC_GetTestResult                  (TPM_CC)(0x0000017C)
711   #endif
712   #if defined CC_Hash && CC_Hash == YES
713   #define TPM_CC_Hash                           (TPM_CC)(0x0000017D)
714   #endif
715   #if defined CC_PCR_Read && CC_PCR_Read == YES
716   #define TPM_CC_PCR_Read                       (TPM_CC)(0x0000017E)
717   #endif
718   #if defined CC_PolicyPCR && CC_PolicyPCR == YES
719   #define TPM_CC_PolicyPCR                      (TPM_CC)(0x0000017F)
720   #endif
721   #if defined CC_PolicyRestart && CC_PolicyRestart == YES
722   #define TPM_CC_PolicyRestart                  (TPM_CC)(0x00000180)
723   #endif
724   #if defined CC_ReadClock && CC_ReadClock == YES
725   #define TPM_CC_ReadClock                      (TPM_CC)(0x00000181)
726   #endif
727   #if defined CC_PCR_Extend && CC_PCR_Extend == YES
728   #define TPM_CC_PCR_Extend                     (TPM_CC)(0x00000182)
729   #endif
730   #if defined CC_PCR_SetAuthValue && CC_PCR_SetAuthValue == YES
731   #define TPM_CC_PCR_SetAuthValue               (TPM_CC)(0x00000183)
732   #endif
733   #if defined CC_NV_Certify && CC_NV_Certify == YES
734   #define TPM_CC_NV_Certify                     (TPM_CC)(0x00000184)
735   #endif
736   #if defined CC_EventSequenceComplete && CC_EventSequenceComplete == YES
737   #define TPM_CC_EventSequenceComplete          (TPM_CC)(0x00000185)
738   #endif
739   #if defined CC_HashSequenceStart && CC_HashSequenceStart == YES
740   #define TPM_CC_HashSequenceStart              (TPM_CC)(0x00000186)
741   #endif
742   #if defined CC_PolicyPhysicalPresence && CC_PolicyPhysicalPresence == YES
743   #define TPM_CC_PolicyPhysicalPresence         (TPM_CC)(0x00000187)
744   #endif
745   #if defined CC_PolicyDuplicationSelect && CC_PolicyDuplicationSelect == YES
746   #define TPM_CC_PolicyDuplicationSelect        (TPM_CC)(0x00000188)
747   #endif
748   #if defined CC_PolicyGetDigest && CC_PolicyGetDigest == YES
749   #define TPM_CC_PolicyGetDigest                (TPM_CC)(0x00000189)
750   #endif
751   #if defined CC_TestParms && CC_TestParms == YES
752   #define TPM_CC_TestParms                      (TPM_CC)(0x0000018A)
753   #endif
754   #if defined CC_Commit && CC_Commit == YES
755   #define TPM_CC_Commit                         (TPM_CC)(0x0000018B)

      Page 356                               TCG Published                          Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                         Trusted Platform Module Library

756   #endif
757   #if defined CC_PolicyPassword && CC_PolicyPassword == YES
758   #define TPM_CC_PolicyPassword                 (TPM_CC)(0x0000018C)
759   #endif
760   #if defined CC_ZGen_2Phase && CC_ZGen_2Phase == YES
761   #define TPM_CC_ZGen_2Phase                    (TPM_CC)(0x0000018D)
762   #endif
763   #if defined CC_EC_Ephemeral && CC_EC_Ephemeral == YES
764   #define TPM_CC_EC_Ephemeral                   (TPM_CC)(0x0000018E)
765   #endif
766   #if defined CC_PolicyNvWritten && CC_PolicyNvWritten == YES
767   #define TPM_CC_PolicyNvWritten                (TPM_CC)(0x0000018F)
768   #endif
769   #define TPM_CC_LAST                           (TPM_CC)(0x0000018F)
770   #ifndef MAX
771   #define MAX(a, b) ((a) > (b) ? (a) : (b))
772   #endif
773   #define MAX_HASH_BLOCK_SIZE (                    \
774       MAX(ALG_SHA1 * SHA1_BLOCK_SIZE,              \
775       MAX(ALG_SHA256 * SHA256_BLOCK_SIZE,          \
776       MAX(ALG_SHA384 * SHA384_BLOCK_SIZE,          \
777       MAX(ALG_SM3_256 * SM3_256_BLOCK_SIZE,        \
778       MAX(ALG_SHA512 * SHA512_BLOCK_SIZE,          \
779       0 ))))))
780   #define MAX_DIGEST_SIZE      (                   \
781       MAX(ALG_SHA1 * SHA1_DIGEST_SIZE,             \
782       MAX(ALG_SHA256 * SHA256_DIGEST_SIZE,         \
783       MAX(ALG_SHA384 * SHA384_DIGEST_SIZE,         \
784       MAX(ALG_SM3_256 * SM3_256_DIGEST_SIZE,       \
785       MAX(ALG_SHA512 * SHA512_DIGEST_SIZE,         \
786       0 ))))))
787   #if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0
788   #error "Hash data not valid"
789   #endif
790   #define HASH_COUNT (ALG_SHA1+ALG_SHA256+ALG_SHA384+ALG_SM3_256+ALG_SHA512)

      Define the 2B structure that would hold any hash block

791   TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE);

      Folloing typedef is for some old code

792   typedef TPM2B_MAX_HASH_BLOCK    TPM2B_HASH_BLOCK;
793   #ifndef MAX
794   #define MAX(a, b) ((a) > (b) ? (a) : (b))
795   #endif
796   #ifndef ALG_CAMELLIA
797   #   define ALG_CAMELLIA         NO
798   #endif
799   #ifndef MAX_CAMELLIA_KEY_BITS
800   #   define      MAX_CAMELLIA_KEY_BITS 0
801   #   define      MAX_CAMELLIA_BLOCK_SIZE_BYTES 0
802   #endif
803   #ifndef ALG_SM4
804   #   define ALG_SM4         NO
805   #endif
806   #ifndef MAX_SM4_KEY_BITS
807   #   define      MAX_SM4_KEY_BITS 0
808   #   define      MAX_SM4_BLOCK_SIZE_BYTES 0
809   #endif
810   #ifndef ALG_AES
811   #   define ALG_AES         NO
812   #endif
813   #ifndef MAX_AES_KEY_BITS
814   #   define      MAX_AES_KEY_BITS 0

      Family "2.0"                                 TCG Published                               Page 357
      Level 00 Revision 01.16                 Copyright © TCG 2006-2014               October 30, 2014
      Trusted Platform Module Library                                  Part 4: Supporting Routines

815   #   define      MAX_AES_BLOCK_SIZE_BYTES 0
816   #endif
817   #define MAX_SYM_KEY_BITS (                                \
818               MAX(MAX_CAMELLIA_KEY_BITS * ALG_CAMELLIA,            \
819               MAX(MAX_SM4_KEY_BITS * ALG_SM4,           \
820               MAX(MAX_AES_KEY_BITS * ALG_AES,           \
821               0))))
822   #define MAX_SYM_KEY_BYTES ((MAX_SYM_KEY_BITS + 7) / 8)
823   #define MAX_SYM_BLOCK_SIZE (                              \
824               MAX(MAX_CAMELLIA_BLOCK_SIZE_BYTES * ALG_CAMELLIA,    \
825               MAX(MAX_SM4_BLOCK_SIZE_BYTES * ALG_SM4,   \
826               MAX(MAX_AES_BLOCK_SIZE_BYTES * ALG_AES,   \
827               0))))
828   #if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0
829   #   error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK_SIZE
830   #endif

      Define the 2B structure for a seed

831   TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE);
832   #endif // _IMPLEMENTATION_H_




      Page 358                                  TCG Published                         Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014       Level 00 Revision 01.16
     Part 4: Supporting Routines                                                 Trusted Platform Module Library


                                                  Annex B
                                                (informative)
                                       Cryptographic Library Interface

     B.1      Introduction

     The files in this annex provide cryptographic support functions for the TPM.
     When possible, the functions in these files make calls to functions that are provided by a cryptographic
     library (for this annex, it is OpenSSL). In many cases, there is a mismatch between the function
     performed by the cryptographic library and the function needed by the TPM. In those cases, a function is
     provided in the code in this clause.
     There are cases where the cryptographic library could have been used for a specific function but not all
     functions of the same group. An example is that the OpenSSL version of CFB was not suitable for the
     requirements of the TPM. Rather than have one symmetric mode be provided in this code with the
     remaining modes provided by OpenSSL, all the symmetric modes are provided in this code.
     The provided cryptographic code is believed to be functionally correct but it might not be conformant with
     all applicable standards. For example, the RSA key generation schemes produces serviceable RSA keys
     but the method is not compliant with FIPS 186-3. Still, the implementation meets the major objective of
     the implementation, which is to demonstrate proper TPM behavior. It is not an objective of this
     implementation to be submitted for certification.

     B.2      Integer Format

     The big integers passed to/from the function interfaces in the crypto engine are in BYTE buffers that have
     the same format used in the TPM 2.0 specification that states:
     "Integer values are considered to be an array of one or more bytes. The byte at offset zero within the
     array is the most significant byte of the integer."




     B.3      CryptoEngine.h

     B.3.1.     Introduction

     This file contains constant definition shared by CryptUtil() and the parts of the Crypto Engine.

 1   #ifndef _CRYPT_PRI_H
 2   #define _CRYPT_PRI_H
 3   #include     <stddef.h>
 4   #include     "TpmBuildSwitches.h"
 5   #include     "BaseTypes.h"
 6   #include     "TpmError.h"
 7   #include     "swap.h"
 8   #include     "Implementation.h"
 9   #include     "TPM_types.h"
10   //#include     "TPMB.h"
11   #include     "bool.h"
12   #include     "Platform.h"
13   #ifndef NULL
14   #define NULL     0
15   #endif
16   typedef UINT16 NUMBYTES;          // When a size is a number of bytes
17   typedef UINT32 NUMDIGITS;         // When a size is a number of "digits"

     Family "2.0"                                 TCG Published                                         Page 359
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
     Trusted Platform Module Library                                               Part 4: Supporting Routines

     B.3.2.   General Purpose Macros

18   #ifndef MAX
19   #   define MAX(a, b) ((a) > (b) ? (a) : b)
20   #endif

     This is the definition of a bit array with one bit per algorithm

21   typedef BYTE         ALGORITHM_VECTOR[(ALG_LAST_VALUE + 7) / 8];


     B.3.3.   Self-test

     This structure is used to contain self-test tracking information for the crypto engine. Each of the major
     modules is given a 32-bit value in which it may maintain its own self test information. The convention for
     this state is that when all of the bits in this structure are 0, all functions need to be tested.

22   typedef struct {
23       UINT32       rng;
24       UINT32       hash;
25       UINT32       sym;
26   #ifdef TPM_ALG_RSA
27       UINT32       rsa;
28   #endif
29   #ifdef TPM_ALG_ECC
30       UINT32       ecc;
31   #endif
32   } CRYPTO_SELF_TEST_STATE;


     B.3.4.   Hash-related Structures

33   typedef struct {
34       const TPM_ALG_ID              alg;
35       const NUMBYTES                digestSize;
36       const NUMBYTES                blockSize;
37       const NUMBYTES                derSize;
38       const BYTE                    der[20];
39   } HASH_INFO;

     This value will change with each implementation. The value of 16 is used to account for any slop in the
     context values. The overall size needs to be as large as any of the hash contexts. The structure needs to
     start on an alignment boundary and be an even multiple of the alignment

40   #define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b))
41   #define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16)
42   #define MAX_HASH_STATE_SIZE_ALIGNED                                                              \
43                       ALIGNED_SIZE(MAX_HASH_STATE_SIZE, CRYPTO_ALIGNMENT)

     This is an byte array that will hold any of the hash contexts.

44   typedef CRYPTO_ALIGNED BYTE ALIGNED_HASH_STATE[MAX_HASH_STATE_SIZE_ALIGNED];

     Macro to align an address to the next higher size

45   #define AlignPointer(address, align)                                                             \
46      ((((intptr_t)&(address)) + (align - 1)) & ~(align - 1))

     Macro to test alignment

47   #define IsAddressAligned(address, align)                                                         \
48                       (((intptr_t)(address) & (align - 1)) == 0)

     Page 360                                        TCG Published                               Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014              Level 00 Revision 01.16
     Part 4: Supporting Routines                                                  Trusted Platform Module Library


     This is the structure that is used for passing a context into the hashing functions. It should be the same
     size as the function context used within the hashing functions. This is checked when the hash function is
     initialized. This version uses a new layout for the contexts and a different definition. The state buffer is an
     array of HASH_UNIT values so that a decent compiler will put the structure on a HASH_UNIT boundary.
     If the structure is not properly aligned, the code that manipulates the structure will copy to a properly
     aligned structure before it is used and copy the result back. This just makes things slower.

49   typedef struct _HASH_STATE
50   {
51       ALIGNED_HASH_STATE       state;
52       TPM_ALG_ID               hashAlg;
53   } CPRI_HASH_STATE, *PCPRI_HASH_STATE;
54   extern const HASH_INFO   g_hashData[HASH_COUNT + 1];

     This is for the external hash state. This implementation assumes that the size of the exported hash state
     is no larger than the internal hash state. There is a compile-time check to make sure that this is true.

55   typedef struct {
56       ALIGNED_HASH_STATE             buffer;
57       TPM_ALG_ID                     hashAlg;
58   } EXPORT_HASH_STATE;
59   typedef enum {
60       IMPORT_STATE,             // Converts externally formatted state to internal
61       EXPORT_STATE              // Converts internal formatted state to external
62   } IMPORT_EXPORT;

     Values and structures for the random number generator. These values are defined in this header file so
     that the size of the RNG state can be known to TPM.lib. This allows the allocation of some space in NV
     memory for the state to be stored on an orderly shutdown. The GET_PUT enum is used by
     _cpri__DrbgGetPutState() to indicate the direction of data flow.

63   typedef enum {
64       GET_STATE,           // Get the state to save to NV
65       PUT_STATE            // Restore the state from NV
66   } GET_PUT;

     The DRBG based on a symmetric block cipher is defined by three values,
     a) the key size
     b) the block size (the IV size)
     c) the symmetric algorithm

67   #define DRBG_KEY_SIZE_BITS       MAX_AES_KEY_BITS
68   #define DRBG_IV_SIZE_BITS        (MAX_AES_BLOCK_SIZE_BYTES * 8)
69   #define DRBG_ALGORITHM           TPM_ALG_AES
70   #if ((DRBG_KEY_SIZE_BITS % 8) != 0) || ((DRBG_IV_SIZE_BITS % 8) != 0)
71   #error "Key size and IV for DRBG must be even multiples of 8"
72   #endif
73   #if (DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0
74   #error "Key size for DRBG must be even multiple of the cypher block size"
75   #endif
76   typedef UINT32     DRBG_SEED[(DRBG_KEY_SIZE_BITS + DRBG_IV_SIZE_BITS) / 32];
77   typedef struct {
78       UINT64       reseedCounter;
79       UINT32       magic;
80       DRBG_SEED    seed; // contains the key and IV for the counter mode DRBG
81       UINT32       lastValue[4];   // used when the TPM does continuous self-test
82                                    // for FIPS compliance of DRBG
83   } DRBG_STATE, *pDRBG_STATE;



     Family "2.0"                                  TCG Published                                         Page 361
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                     Part 4: Supporting Routines

      B.3.5.     Asymmetric Structures and Values

 84   #ifdef TPM_ALG_ECC


      B.3.5.1.    ECC-related Structures

      This structure replicates the structure definition in TPM_Types.h. It is duplicated to avoid inclusion of all of
      TPM_Types.h This structure is similar to the RSA_KEY structure below. The purpose of these structures
      is to reduce the overhead of a function call and to make the code less dependent on key types as much
      as possible.

 85   typedef struct {
 86       UINT32                        curveID;            // The curve identifier
 87       TPMS_ECC_POINT               *publicPoint;        // Pointer to the public point
 88       TPM2B_ECC_PARAMETER          *privateKey;         // Pointer to the private key
 89   } ECC_KEY;
 90   #endif // TPM_ALG_ECC
 91   #ifdef TPM_ALG_RSA


      B.3.5.2.    RSA-related Structures

      This structure is a succinct representation of the cryptographic components of an RSA key.

 92   typedef struct {
 93       UINT32        exponent;                 // The public exponent pointer
 94       TPM2B        *publicKey;                // Pointer to the public modulus
 95       TPM2B        *privateKey;               // The private exponent (not a prime)
 96   } RSA_KEY;
 97   #endif // TPM_ALG_RSA


      B.3.6.     Miscelaneous

 98   #ifdef TPM_ALG_RSA
 99   #   ifdef TPM_ALG_ECC
100   #       if    MAX_RSA_KEY_BYTES > MAX_ECC_KEY_BYTES
101   #            define MAX_NUMBER_SIZE          MAX_RSA_KEY_BYTES
102   #       else
103   #            define MAX_NUMBER_SIZE          MAX_ECC_KEY_BYTES
104   #       endif
105   #   else // RSA but no ECC
106   #       define MAX_NUMBER_SIZE               MAX_RSA_KEY_BYTES
107   #   endif
108   #elif defined TPM_ALG_ECC
109   #   define MAX_NUMBER_SIZE                  MAX_ECC_KEY_BYTES
110   #else
111   #   error No assymmetric algorithm implemented.
112   #endif
113   typedef INT16      CRYPT_RESULT;
114   #define CRYPT_RESULT_MIN     INT16_MIN
115   #define CRYPT_RESULT_MAX     INT16_MAX


      <0                                recoverable error

      0                                 success
      >0                                command specific return value (generally a digest size)

116   #define CRYPT_FAIL                  ((CRYPT_RESULT) 1)
117   #define CRYPT_SUCCESS               ((CRYPT_RESULT) 0)
118   #define CRYPT_NO_RESULT             ((CRYPT_RESULT) -1)


      Page 362                                       TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                      Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

119   #define CRYPT_SCHEME        ((CRYPT_RESULT) -2)
120   #define CRYPT_PARAMETER     ((CRYPT_RESULT) -3)
121   #define CRYPT_UNDERFLOW     ((CRYPT_RESULT) -4)
122   #define CRYPT_POINT         ((CRYPT_RESULT) -5)
123   #define CRYPT_CANCEL        ((CRYPT_RESULT) -6)
124   typedef UINT64              HASH_CONTEXT[MAX_HASH_STATE_SIZE/sizeof(UINT64)];
125   #include    "CpriCryptPri_fp.h"
126   #ifdef TPM_ALG_ECC
127   #   include "CpriDataEcc.h"
128   #   include "CpriECC_fp.h"
129   #endif
130   #include    "MathFunctions_fp.h"
131   #include    "CpriRNG_fp.h"
132   #include    "CpriHash_fp.h"
133   #include    "CpriSym_fp.h"
134   #ifdef TPM_ALG_RSA
135   #   include    "CpriRSA_fp.h"
136   #endif
137   #endif // !_CRYPT_PRI_H




      Family "2.0"                        TCG Published                                Page 363
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines



     B.4      OsslCryptoEngine.h

     B.4.1.    Introduction

     This is the header file used by the components of the CryptoEngine(). This file should not be included in
     any file other than the files in the crypto engine.
     Vendors may replace the implementation in this file by a local crypto engine. The implementation in this
     file is based on OpenSSL() library. Integer format: the big integers passed in/out the function interfaces in
     this library by a byte buffer (BYTE *) adopt the same format used in TPM 2.0 specification: Integer values
     are considered to be an array of one or more bytes. The byte at offset zero within the array is the most
     significant byte of the integer.

     B.4.2.    Defines

 1   #ifndef _OSSL_CRYPTO_ENGINE_H
 2   #define _OSSL_CRYPTO_ENGINE_H
 3   #include <openssl/aes.h>
 4   #include <openssl/evp.h>
 5   #include <openssl/sha.h>
 6   #include <openssl/ec.h>
 7   #include <openssl/rand.h>
 8   #include <openssl/bn.h>
 9   #include <openSSL/ec_lcl.h>
10   #define     CRYPTO_ENGINE
11   #include "CryptoEngine.h"
12   #include "CpriMisc_fp.h"
13   #define MAX_ECC_PARAMETER_BYTES 32
14   #define MAX_2B_BYTES MAX((MAX_RSA_KEY_BYTES * ALG_RSA),                              \
15                             MAX((MAX_ECC_PARAMETER_BYTES * ALG_ECC),                   \
16                                 MAX_DIGEST_SIZE))
17   #define assert2Bsize(a) pAssert((a).size <= sizeof((a).buffer))
18   #ifdef TPM_ALG_RSA
19   #   ifdef   RSA_KEY_SIEVE
20   #       include     "RsaKeySieve.h"
21   #       include     "RsaKeySieve_fp.h"
22   #   endif
23   #   include    "CpriRSA_fp.h"
24   #endif

     This is a structure to hold the parameters for the version of KDFa() used by the CryptoEngine(). This
     structure allows the state to be passed between multiple functions that use the same pseudo-random
     sequence.

25   typedef struct {
26       CPRI_HASH_STATE          iPadCtx;
27       CPRI_HASH_STATE          oPadCtx;
28       TPM2B                   *extra;
29       UINT32                  *outer;
30       TPM_ALG_ID               hashAlg;
31       UINT16                   keySizeInBits;
32   } KDFa_CONTEXT;
33   #endif // _OSSL_CRYPTO_ENGINE_H




     Page 364                                      TCG Published                                    Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library


     B.5      MathFunctions.c

     B.5.1.     Introduction

     This file contains implementation of some of the big number primitives. This is used in order to reduce the
     overhead in dealing with data conversions to standard big number format.
     The simulator code uses the canonical form whenever possible in order to make the code in Part 3 more
     accessible. The canonical data formats are simple and not well suited for complex big number
     computations. This library provides functions that are found in typical big number libraries but they are
     written to handle the canonical data format of the reference TPM.
     In some cases, data is converted to a big number format used by a standard library, such as OpenSSL().
     This is done when the computations are complex enough warrant conversion. Vendors may replace the
     implementation in this file with a library that provides equivalent functions. A vendor may also rewrite the
     TPM code so that it uses a standard big number format instead of the canonical form and use the
     standard libraries instead of the code in this file.
     The implementation in this file makes use of the OpenSSL() library.
     Integer format: integers passed through the function interfaces in this library adopt the same format used
     in TPM 2.0 specification. It defines an integer as "an array of one or more octets with the most significant
     octet at the lowest index of the array." An additional value is needed to indicate the number of significant
     bytes.

 1   #include "OsslCryptoEngine.h"


     B.5.2.     Externally Accessible Functions

     B.5.2.1.      _math__Normalize2B()

     This function will normalize the value in a TPM2B. If there are leading bytes of zero, the first non-zero
     byte is shifted up.

     Return Value                     Meaning

     0                                no significant bytes, value is zero
     >0                               number of significant bytes

 2   LIB_EXPORT UINT16
 3   _math__Normalize2B(
 4         TPM2B               *b                  // IN/OUT: number to normalize
 5         )
 6   {
 7         UINT16        from;
 8         UINT16        to;
 9         UINT16        size = b->size;
10
11         for(from = 0; b->buffer[from] == 0 && from < size; from++);
12         b->size -= from;
13         for(to = 0; from < size; to++, from++ )
14             b->buffer[to] = b->buffer[from];
15         return b->size;
16   }




     Family "2.0"                                  TCG Published                                      Page 365
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines

     B.5.2.2.   _math__Denormalize2B()

     This function is used to adjust a TPM2B so that the number has the desired number of bytes. This is
     accomplished by adding bytes of zero at the start of the number.

     Return Value                      Meaning

     TRUE                              number de-normalized
     FALSE                             number already larger than the desired size

17   LIB_EXPORT BOOL
18   _math__Denormalize2B(
19        TPM2B              *in,                   // IN:OUT TPM2B number to de-normalize
20        UINT32              size                  // IN: the desired size
21        )
22   {
23        UINT32       to;
24        UINT32       from;
25        // If the current size is greater than the requested size, see if this can be
26        // normalized to a value smaller than the requested size and then de-normalize
27        if(in->size > size)
28        {
29            _math__Normalize2B(in);
30            if(in->size > size)
31                return FALSE;
32        }
33        // If the size is already what is requested, leave
34        if(in->size == size)
35            return TRUE;
36
37        // move the bytes to the 'right'
38        for(from = in->size, to = size; from > 0;)
39            in->buffer[--to] = in->buffer[--from];
40
41        // 'to' will always be greater than 0 because we checked for equal above.
42        for(; to > 0;)
43            in->buffer[--to] = 0;
44
45        in->size = (UINT16)size;
46        return TRUE;
47   }


     B.5.2.3.   _math__sub()

     This function to subtract one unsigned value from another c = a - b. c may be the same as a or b.

     Return Value                      Meaning

     1                                 if (a > b) so no borrow
     0                                 if (a = b) so no borrow and b == a
     -1                                if (a < b) so there was a borrow

48   LIB_EXPORT int
49   _math__sub(
50        const UINT32        aSize,                //   IN: size   of a
51        const BYTE         *a,                    //   IN: a
52        const UINT32        bSize,                //   IN: size   of b
53        const BYTE         *b,                    //   IN: b
54        UINT16             *cSize,                //   OUT: set   to MAX(aSize, bSize)
55        BYTE               *c                     //   OUT: the   difference
56        )

     Page 366                                        TCG Published                                 Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                         Trusted Platform Module Library

 57   {
 58        int               borrow = 0;
 59        int               notZero = 0;
 60        int               i;
 61        int               i2;
 62
 63        // set c to the longer of a or b
 64        *cSize = (UINT16)((aSize > bSize) ? aSize : bSize);
 65        // pick the shorter of a and b
 66        i = (aSize > bSize) ? bSize : aSize;
 67        i2 = *cSize - i;
 68        a = &a[aSize - 1];
 69        b = &b[bSize - 1];
 70        c = &c[*cSize - 1];
 71        for(; i > 0; i--)
 72        {
 73            borrow = *a-- - *b-- + borrow;
 74            *c-- = (BYTE)borrow;
 75            notZero = notZero || borrow;
 76            borrow >>= 8;
 77        }
 78        if(aSize > bSize)
 79        {
 80            for(;i2 > 0; i2--)
 81            {
 82                borrow = *a-- + borrow;
 83                *c-- = (BYTE)borrow;
 84                notZero = notZero || borrow;
 85                borrow >>= 8;
 86            }
 87        }
 88        else if(aSize < bSize)
 89        {
 90            for(;i2 > 0; i2--)
 91            {
 92                borrow = 0 - *b-- + borrow;
 93                *c-- = (BYTE)borrow;
 94                notZero = notZero || borrow;
 95                borrow >>= 8;
 96            }
 97        }
 98        // if there is a borrow, then b > a
 99        if(borrow)
100            return -1;
101        // either a > b or they are the same
102        return notZero;
103   }


      B.5.2.4.   _math__Inc()

      This function increments a large, big-endian number value by one.

      Return Value                   Meaning

      0                              result is zero
      !0                             result is not zero

104   LIB_EXPORT int
105   _math__Inc(
106        UINT32             aSize,              // IN: size of a
107        BYTE              *a                   // IN: a
108        )
109   {


      Family "2.0"                                    TCG Published                            Page 367
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

110
111          for(a = &a[aSize-1];aSize > 0; aSize--)
112          {
113              if((*a-- += 1) != 0)
114                  return 1;
115          }
116          return 0;
117   }


      B.5.2.5.    _math__Dec()

      This function decrements a large, ENDIAN value by one.

118   LIB_EXPORT void
119   _math__Dec(
120          UINT32            aSize,                // IN: size of a
121          BYTE             *a                     // IN: a
122          )
123   {
124          for(a = &a[aSize-1]; aSize > 0; aSize--)
125          {
126              if((*a-- -= 1) != 0xff)
127                  return;
128          }
129          return;
130   }


      B.5.2.6.    _math__Mul()

      This function is used to multiply two large integers: p = a* b. If the size of p is not specified (pSize ==
      NULL), the size of the results p is assumed to be aSize + bSize and the results are de-normalized so that
      the resulting size is exactly aSize + bSize. If pSize is provided, then the actual size of the result is
      returned. The initial value for pSize must be at least aSize + pSize.

      Return Value                      Meaning

      <0                                indicates an error
      >= 0                              the size of the product

131   LIB_EXPORT int
132   _math__Mul(
133          const UINT32      aSize,                //   IN: size of a
134          const BYTE       *a,                    //   IN: a
135          const UINT32      bSize,                //   IN: size of b
136          const BYTE       *b,                    //   IN: b
137          UINT32           *pSize,                //   IN/OUT: size of the product
138          BYTE             *p                     //   OUT: product. length of product = aSize +
139                                                  //       bSize
140          )
141   {
142          BIGNUM           *bnA;
143          BIGNUM           *bnB;
144          BIGNUM           *bnP;
145          BN_CTX           *context;
146          int              retVal = 0;
147
148          // First check that pSize is large enough if present
149          if((pSize != NULL) && (*pSize < (aSize + bSize)))
150              return CRYPT_PARAMETER;
151          pAssert(pSize == NULL || *pSize <= MAX_2B_BYTES);
152          //


      Page 368                                       TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

153        // Allocate space for BIGNUM context
154        //
155        context = BN_CTX_new();
156        if(context == NULL)
157            FAIL(FATAL_ERROR_ALLOCATION);
158        bnA = BN_CTX_get(context);
159        bnB = BN_CTX_get(context);
160        bnP = BN_CTX_get(context);
161        if (bnP == NULL)
162            FAIL(FATAL_ERROR_ALLOCATION);
163
164        // Convert the inputs to BIGNUMs
165        //
166        if (BN_bin2bn(a, aSize, bnA) == NULL || BN_bin2bn(b, bSize, bnB) == NULL)
167            FAIL(FATAL_ERROR_INTERNAL);
168
169        // Perform the multiplication
170        //
171        if (BN_mul(bnP, bnA, bnB, context) != 1)
172            FAIL(FATAL_ERROR_INTERNAL);
173
174        // If the size of the results is allowed to float, then set the return
175        // size. Otherwise, it might be necessary to de-normalize the results
176        retVal = BN_num_bytes(bnP);
177        if(pSize == NULL)
178        {
179            BN_bn2bin(bnP, &p[aSize + bSize - retVal]);
180            memset(p, 0, aSize + bSize - retVal);
181            retVal = aSize + bSize;
182        }
183        else
184        {
185            BN_bn2bin(bnP, p);
186            *pSize = retVal;
187        }
188
189        BN_CTX_end(context);
190        BN_CTX_free(context);
191        return retVal;
192   }


      B.5.2.7.   _math__Div()

      Divide an integer (n) by an integer (d) producing a quotient (q) and a remainder (r). If q or r is not needed,
      then the pointer to them may be set to NULL.

      Return Value                     Meaning

      CRYPT_SUCCESS                    operation complete
      CRYPT_UNDERFLOW                  q or r is too small to receive the result

193   LIB_EXPORT CRYPT_RESULT
194   _math__Div(
195        const TPM2B         *n,                  //   IN: numerator
196        const TPM2B         *d,                  //   IN: denominator
197        TPM2B               *q,                  //   OUT: quotient
198        TPM2B               *r                   //   OUT: remainder
199        )
200   {
201        BIGNUM              *bnN;
202        BIGNUM              *bnD;
203        BIGNUM              *bnQ;
204        BIGNUM              *bnR;

      Family "2.0"                                   TCG Published                                       Page 369
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                     Part 4: Supporting Routines

205        BN_CTX            *context;
206        CRYPT_RESULT       retVal = CRYPT_SUCCESS;
207
208        // Get structures for the big number representations
209        context = BN_CTX_new();
210        if(context == NULL)
211            FAIL(FATAL_ERROR_ALLOCATION);
212        BN_CTX_start(context);
213        bnN = BN_CTX_get(context);
214        bnD = BN_CTX_get(context);
215        bnQ = BN_CTX_get(context);
216        bnR = BN_CTX_get(context);
217
218        // Errors in BN_CTX_get() are sticky so only need to check the last allocation
219        if (    bnR == NULL
220             || BN_bin2bn(n->buffer, n->size, bnN) == NULL
221             || BN_bin2bn(d->buffer, d->size, bnD) == NULL)
222                 FAIL(FATAL_ERROR_INTERNAL);
223
224        // Check for divide by zero.
225        if(BN_num_bits(bnD) == 0)
226            FAIL(FATAL_ERROR_DIVIDE_ZERO);
227
228        // Perform the division
229        if (BN_div(bnQ, bnR, bnN, bnD, context) != 1)
230            FAIL(FATAL_ERROR_INTERNAL);
231
232        // Convert the BIGNUM result back to our format
233        if(q != NULL)   // If the quotient is being returned
234        {
235            if(!BnTo2B(q, bnQ, q->size))
236            {
237                retVal = CRYPT_UNDERFLOW;
238                goto Done;
239            }
240          }
241        if(r != NULL)   // If the remainder is being returned
242        {
243            if(!BnTo2B(r, bnR, r->size))
244                retVal = CRYPT_UNDERFLOW;
245        }
246
247   Done:
248       BN_CTX_end(context);
249       BN_CTX_free(context);
250
251        return retVal;
252   }


      B.5.2.8.   _math__uComp()

      This function compare two unsigned values.

      Return Value                      Meaning

      1                                 if (a > b)
      0                                 if (a = b)
      -1                                if (a < b)

253   LIB_EXPORT int
254   _math__uComp(
255        const UINT32       aSize,                 // IN: size of a
256        const BYTE        *a,                     // IN: a

      Page 370                                       TCG Published                      Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014    Level 00 Revision 01.16
      Part 4: Supporting Routines                                          Trusted Platform Module Library

257        const UINT32       bSize,                // IN: size of b
258        const BYTE        *b                     // IN: b
259        )
260   {
261        int              borrow = 0;
262        int              notZero = 0;
263        int              i;
264        // If a has more digits than b, then a is greater than b if
265        // any of the more significant bytes is non zero
266        if((i = (int)aSize - (int)bSize) > 0)
267            for(; i > 0; i--)
268                if(*a++) // means a > b
269                     return 1;
270        // If b has more digits than a, then b is greater if any of the
271        // more significant bytes is non zero
272        if(i < 0) // Means that b is longer than a
273            for(; i < 0; i++)
274                if(*b++) // means that b > a
275                     return -1;
276        // Either the vales are the same size or the upper bytes of a or b are
277        // all zero, so compare the rest
278        i = (aSize > bSize) ? bSize : aSize;
279        a = &a[i-1];
280        b = &b[i-1];
281        for(; i > 0; i--)
282        {
283            borrow = *a-- - *b-- + borrow;
284            notZero = notZero || borrow;
285            borrow >>= 8;
286        }
287        // if there is a borrow, then b > a
288        if(borrow)
289            return -1;
290        // either a > b or they are the same
291        return notZero;
292   }


      B.5.2.9.     _math__Comp()

      Compare two signed integers:

      Return Value                    Meaning

      1                               if a > b
      0                               if a = b
      -1                              if a < b

293   LIB_EXPORT int
294   _math__Comp(
295        const   UINT32     aSize,                //   IN:   size of a
296        const   BYTE      *a,                    //   IN:   a buffer
297        const   UINT32     bSize,                //   IN:   size of b
298        const   BYTE      *b                     //   IN:   b buffer
299        )
300   {
301        int        signA, signB;              // sign of a and b
302
303        // For positive or 0, sign_a is 1
304        // for negative, sign_a is 0
305        signA = ((a[0] & 0x80) == 0) ? 1 : 0;
306
307        // For positive or 0, sign_b is 1
308        // for negative, sign_b is 0

      Family "2.0"                                  TCG Published                               Page 371
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                                       Part 4: Supporting Routines

309       signB = ((b[0] & 0x80) == 0) ? 1 : 0;
310
311       if(signA != signB)
312       {
313           return signA - signB;
314       }
315
316       if(signA == 1)
317           // do unsigned compare function
318           return _math__uComp(aSize, a, bSize, b);
319       else
320           // do unsigned compare the other way
321           return 0 - _math__uComp(aSize, a, bSize, b);
322   }


      B.5.2.10. _math__ModExp

      This function is used to do modular exponentiation in support of RSA. The most typical uses are: c = m^e
      mod n (RSA encrypt) and m = c^d mod n (RSA decrypt). When doing decryption, the e parameter of the
      function will contain the private exponent d instead of the public exponent e.
      If the results will not fit in the provided buffer, an error is returned (CRYPT_ERROR_UNDERFLOW). If
      the results is smaller than the buffer, the results is de-normalized.
      This version is intended for use with RSA and requires that m be less than n.

      Return Value                      Meaning

      CRYPT_SUCCESS                     exponentiation succeeded
      CRYPT_PARAMETER                   number to exponentiate is larger than the modulus
      CRYPT_UNDERFLOW                   result will not fit into the provided buffer

323   LIB_EXPORT CRYPT_RESULT
324   _math__ModExp(
325       UINT32               cSize,                 //   IN: size of the result
326       BYTE                *c,                     //   OUT: results buffer
327       const UINT32         mSize,                 //   IN: size of number to be exponentiated
328       const BYTE          *m,                     //   IN: number to be exponentiated
329       const UINT32         eSize,                 //   IN: size of power
330       const BYTE          *e,                     //   IN: power
331       const UINT32         nSize,                 //   IN: modulus size
332       const BYTE          *n                      //   IN: modulu
333       )
334   {
335       CRYPT_RESULT         retVal = CRYPT_SUCCESS;
336       BN_CTX              *context;
337       BIGNUM              *bnC;
338       BIGNUM              *bnM;
339       BIGNUM              *bnE;
340       BIGNUM              *bnN;
341       INT32                i;
342
343       context = BN_CTX_new();
344       if(context == NULL)
345           FAIL(FATAL_ERROR_ALLOCATION);
346       BN_CTX_start(context);
347       bnC = BN_CTX_get(context);
348       bnM = BN_CTX_get(context);
349       bnE = BN_CTX_get(context);
350       bnN = BN_CTX_get(context);
351
352       // Errors for BN_CTX_get are sticky so only need to check last allocation
353       if(bnN == NULL)

      Page 372                                         TCG Published                                      Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014                      Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

354             FAIL(FATAL_ERROR_ALLOCATION);
355
356        //convert arguments
357        if (    BN_bin2bn(m, mSize, bnM) == NULL
358             || BN_bin2bn(e, eSize, bnE) == NULL
359             || BN_bin2bn(n, nSize, bnN) == NULL)
360                 FAIL(FATAL_ERROR_INTERNAL);
361
362        // Don't do exponentiation if the number being exponentiated is
363        // larger than the modulus.
364        if(BN_ucmp(bnM, bnN) >= 0)
365        {
366            retVal = CRYPT_PARAMETER;
367            goto Cleanup;
368        }
369        // Perform the exponentiation
370        if(!(BN_mod_exp(bnC, bnM, bnE, bnN, context)))
371            FAIL(FATAL_ERROR_INTERNAL);
372
373        // Convert the results
374        // Make sure that the results will fit in the provided buffer.
375        if((unsigned)BN_num_bytes(bnC) > cSize)
376        {
377            retVal = CRYPT_UNDERFLOW;
378            goto Cleanup;
379        }
380        i = cSize - BN_num_bytes(bnC);
381        BN_bn2bin(bnC, &c[i]);
382        memset(c, 0, i);
383
384   Cleanup:
385       // Free up allocated BN values
386       BN_CTX_end(context);
387       BN_CTX_free(context);
388       return retVal;
389   }


      B.5.2.11. _math__IsPrime()

      Check if an 32-bit integer is a prime.

      Return Value                      Meaning

      TRUE                              if the integer is probably a prime
      FALSE                             if the integer is definitely not a prime

390   LIB_EXPORT BOOL
391   _math__IsPrime(
392        const UINT32         prime
393        )
394   {
395        int       isPrime;
396        BIGNUM    *p;
397
398        // Assume the size variables are not overflow, which should not happen in
399        // the contexts that this function will be called.
400        if((p = BN_new()) == NULL)
401            FAIL(FATAL_ERROR_ALLOCATION);
402        if(!BN_set_word(p, prime))
403            FAIL(FATAL_ERROR_INTERNAL);
404
405        //
406        // BN_is_prime returning -1 means that it ran into an error.


      Family "2.0"                                    TCG Published                                     Page 373
      Level 00 Revision 01.16                  Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

407       // It should only return 0 or 1
408       //
409       if((isPrime = BN_is_prime_ex(p, BN_prime_checks, NULL, NULL)) < 0)
410           FAIL(FATAL_ERROR_INTERNAL);
411
412       if(p != NULL)
413           BN_clear_free(p);
414       return (isPrime == 1);
415   }




      Page 374                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
     Part 4: Supporting Routines                                                    Trusted Platform Module Library


     B.6      CpriCryptPri.c

     B.6.1.     Introduction

     This file contains the interface to the initialization, startup and shutdown functions of the crypto library.

     B.6.2.     Includes and Locals

 1    #include "OsslCryptoEngine.h"
 2   static void Trap(const char *function, int line, int code);
 3   FAIL_FUNCTION       TpmFailFunction = (FAIL_FUNCTION)&Trap;


     B.6.3.     Functions

     B.6.3.1.     TpmFail()

     This is a shim function that is called when a failure occurs. It simply relays the call to the callback pointed
     to by TpmFailFunction(). It is only defined for the sake of NO_RETURN specifier that cannot be added to
     a function pointer with some compilers.

 4   void
 5   TpmFail(
 6         const char               *function,
 7         int                       line,
 8         int                       code)
 9   {
10         TpmFailFunction(function, line, code);
11   }


     B.6.3.2.     FAILURE_TRAP()

     This function is called if the caller to _cpri__InitCryptoUnits() doesn't provide a call back address.

12   static void
13   Trap(
14         const char          *function,
15         int                  line,
16         int                  code
17         )
18   {
19         UNREFERENCED(function);
20         UNREFERENCED(line);
21         UNREFERENCED(code);
22         abort();
23   }


     B.6.3.3.     _cpri__InitCryptoUnits()

     This function calls the initialization functions of the other crypto modules that are part of the crypto engine
     for this implementation. This function should be called as a result of _TPM_Init(). The parameter to this
     function is a call back function it TPM.lib that is called when the crypto engine has a failure.

24   LIB_EXPORT CRYPT_RESULT
25   _cpri__InitCryptoUnits(
26         FAIL_FUNCTION        failFunction
27         )
28   {

     Family "2.0"                                   TCG Published                                          Page 375
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                             October 30, 2014
     Trusted Platform Module Library                                                Part 4: Supporting Routines

29       TpmFailFunction = failFunction;
30
31       _cpri__RngStartup();
32       _cpri__HashStartup();
33       _cpri__SymStartup();
34
35   #ifdef TPM_ALG_RSA
36       _cpri__RsaStartup();
37   #endif
38
39   #ifdef TPM_ALG_ECC
40       _cpri__EccStartup();
41   #endif
42
43       return CRYPT_SUCCESS;
44   }


     B.6.3.4.     _cpri__StopCryptoUnits()

     This function calls the shutdown functions of the other crypto modules that are part of the crypto engine
     for this implementation.

45   LIB_EXPORT void
46   _cpri__StopCryptoUnits(
47       void
48       )
49   {
50       return;
51   }


     B.6.3.5.     _cpri__Startup()

     This function calls the startup functions of the other crypto modules that are part of the crypto engine for
     this implementation. This function should be called during processing of TPM2_Startup().

52   LIB_EXPORT BOOL
53   _cpri__Startup(
54       void
55       )
56   {
57
58       return(       _cpri__HashStartup()
59                  && _cpri__RngStartup()
60   #ifdef     TPM_ALG_RSA
61                  && _cpri__RsaStartup()
62   #endif     // TPM_ALG_RSA
63   #ifdef     TPM_ALG_ECC
64                  && _cpri__EccStartup()
65   #endif     // TPM_ALG_ECC
66                  && _cpri__SymStartup());
67   }




     Page 376                                     TCG Published                                    Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                               Trusted Platform Module Library


     B.7      CpriRNG.c

 1   //#define __TPM_RNG_FOR_DEBUG__


     B.7.1.     Introduction

     This file contains the interface to the OpenSSL() random number functions.

     B.7.2.     Includes

 2   #include "OsslCryptoEngine.h"
 3   int         s_entropyFailure;


     B.7.3.     Functions

     B.7.3.1.     _cpri__RngStartup()

     This function is called to initialize the random number generator. It collects entropy from the platform to
     seed the OpenSSL() random number generator.

 4   LIB_EXPORT BOOL
 5   _cpri__RngStartup(void)
 6   {
 7         UINT32           entropySize;
 8         BYTE             entropy[MAX_RNG_ENTROPY_SIZE];
 9         INT32            returnedSize = 0;
10
11         // Initialize the entropy source
12         s_entropyFailure = FALSE;
13         _plat__GetEntropy(NULL, 0);
14
15         // Collect entropy until we have enough
16         for(entropySize = 0;
17             entropySize < MAX_RNG_ENTROPY_SIZE && returnedSize >= 0;
18             entropySize += returnedSize)
19         {
20             returnedSize = _plat__GetEntropy(&entropy[entropySize],
21                                                 MAX_RNG_ENTROPY_SIZE - entropySize);
22         }
23         // Got some entropy on the last call and did not get an error
24         if(returnedSize > 0)
25         {
26             // Seed OpenSSL with entropy
27             RAND_seed(entropy, entropySize);
28         }
29         else
30         {
31             s_entropyFailure = TRUE;
32         }
33         return s_entropyFailure == FALSE;
34   }


     B.7.3.2.     _cpri__DrbgGetPutState()

     This function is used to set the state of the RNG (direction == PUT_STATE) or to recover the state of the
     RNG (direction == GET_STATE).




     Family "2.0"                                TCG Published                                       Page 377
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines

     NOTE:           This not currently supported on OpenSSL() version.

35   LIB_EXPORT CRYPT_RESULT
36   _cpri__DrbgGetPutState(
37        GET_PUT              direction,
38        int                  bufferSize,
39        BYTE                *buffer
40        )
41   {
42        UNREFERENCED_PARAMETER(direction);
43        UNREFERENCED_PARAMETER(bufferSize);
44        UNREFERENCED_PARAMETER(buffer);
45
46        return CRYPT_SUCCESS;                 // Function is not implemented
47   }


     B.7.3.3.     _cpri__StirRandom()

     This function is called to add external entropy to the OpenSSL() random number generator.

48   LIB_EXPORT CRYPT_RESULT
49   _cpri__StirRandom(
50        INT32                entropySize,
51        BYTE                *entropy
52        )
53   {
54        if (entropySize >= 0)
55        {
56            RAND_add((const void *)entropy, (int) entropySize, 0.0);
57
58        }
59        return CRYPT_SUCCESS;
60   }


     B.7.3.4.     _cpri__GenerateRandom()

     This function is called to get a string of random bytes from the OpenSSL() random number generator. The
     return value is the number of bytes placed in the buffer. If the number of bytes returned is not equal to the
     number of bytes requested (randomSize) it is indicative of a failure of the OpenSSL() random number
     generator and is probably fatal.

61   LIB_EXPORT UINT16
62   _cpri__GenerateRandom(
63        INT32                randomSize,
64        BYTE                *buffer
65        )
66   {
67        //
68        // We don't do negative sizes or ones that are too large
69        if (randomSize < 0 || randomSize > UINT16_MAX)
70            return 0;
71        // RAND_bytes uses 1 for success and we use 0
72        if(RAND_bytes(buffer, randomSize) == 1)
73            return (UINT16)randomSize;
74        else
75            return 0;
76   }




     Page 378                                          TCG Published                                Family "2.0"
     October 30, 2014                         Copyright © TCG 2006-2014                Level 00 Revision 01.16
     Part 4: Supporting Routines                                          Trusted Platform Module Library

     B.7.3.4.1.     _cpri__GenerateSeededRandom()

     This funciton is used to generate a pseudo-random number from some seed values This funciton returns
     the same result each time it is called with the same parameters

77   LIB_EXPORT UINT16
78   _cpri__GenerateSeededRandom(
79       INT32               randomSize,      //   IN: the size of the request
80       BYTE               *random,          //   OUT: receives the data
81       TPM_ALG_ID          hashAlg,         //   IN: used by KDF version but not here
82       TPM2B              *seed,            //   IN: the seed value
83       const char         *label,           //   IN: a label string (optional)
84       TPM2B              *partyU,          //   IN: other data (oprtional)
85       TPM2B              *partyV           //   IN: still more (optional)
86       )
87   {
88
89       return (_cpri__KDFa(hashAlg, seed, label, partyU, partyV,
90                           randomSize * 8, random, NULL, FALSE));
91   }
92   #endif   //%




     Family "2.0"                             TCG Published                                    Page 379
     Level 00 Revision 01.16           Copyright © TCG 2006-2014                       October 30, 2014
     Trusted Platform Module Library                                             Part 4: Supporting Routines


     B.8      CpriHash.c

     B.8.1.     Description

     This file contains implementation of cryptographic functions for hashing.

     B.8.2.     Includes, Defines, and Types

 1   #include     "OsslCryptoEngine.h"
 2   #include     "CpriHashData.c"
 3   #define OSSL_HASH_STATE_DATA_SIZE     (MAX_HASH_STATE_SIZE - 8)
 4   typedef struct {
 5       union    {
 6           EVP_MD_CTX context;
 7           BYTE         data[OSSL_HASH_STATE_DATA_SIZE];
 8       } u;
 9       INT16            copySize;
10   } OSSL_HASH_STATE;

     Temporary aliasing of SM3 to SHA256 until SM3 is available

11   #define EVP_sm3_256 EVP_sha256


     B.8.3.     Static Functions

     B.8.3.1.     GetHashServer()

     This function returns the address of the hash server function

12   static EVP_MD *
13   GetHashServer(
14         TPM_ALG_ID      hashAlg
15   )
16   {
17       switch (hashAlg)
18       {
19   #ifdef TPM_ALG_SHA1
20       case TPM_ALG_SHA1:
21           return (EVP_MD *)EVP_sha1();
22           break;
23   #endif
24   #ifdef TPM_ALG_SHA256
25       case TPM_ALG_SHA256:
26           return (EVP_MD *)EVP_sha256();
27           break;
28   #endif
29   #ifdef TPM_ALG_SHA384
30       case TPM_ALG_SHA384:
31           return (EVP_MD *)EVP_sha384();
32           break;
33   #endif
34   #ifdef TPM_ALG_SHA512
35       case TPM_ALG_SHA512:
36           return (EVP_MD *)EVP_sha512();
37           break;
38   #endif
39   #ifdef TPM_ALG_SM3_256
40       case TPM_ALG_SM3_256:
41           return (EVP_MD *)EVP_sm3_256();
42           break;

     Page 380                                     TCG Published                                Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014              Level 00 Revision 01.16
     Part 4: Supporting Routines                                              Trusted Platform Module Library

43   #endif
44       case TPM_ALG_NULL:
45           return NULL;
46       default:
47           FAIL(FATAL_ERROR_INTERNAL);
48       }
49   }


     B.8.3.2.   MarshalHashState()

     This function copies an OpenSSL() hash context into a caller provided buffer.

     Return Value                     Meaning

     >0                               the number of bytes of buf used.

50   static UINT16
51   MarshalHashState(
52        EVP_MD_CTX         *ctxt,               // IN: Context to marshal
53        BYTE               *buf                 // OUT: The buffer that will receive the
54                                                //     context. This buffer is at least
55                                                //     MAX_HASH_STATE_SIZE byte
56        )
57   {
58        // make sure everything will fit
59        pAssert(ctxt->digest->ctx_size <= OSSL_HASH_STATE_DATA_SIZE);
60
61        // Copy the context data
62        memcpy(buf, (void*) ctxt->md_data, ctxt->digest->ctx_size);
63
64        return (UINT16)ctxt->digest->ctx_size;
65   }


     B.8.3.3.   GetHashState()

     This function will unmarshal a caller provided buffer into an OpenSSL() hash context. The function returns
     the number of bytes copied (which may be zero).

66   static UINT16
67   GetHashState(
68        EVP_MD_CTX         *ctxt,               // OUT: The context structure to receive the
69                                                //     result of unmarshaling.
70        TPM_ALG_ID          algType,            // IN: The hash algorithm selector
71        BYTE               *buf                 // IN: Buffer containing marshaled hash data
72        )
73   {
74        EVP_MD             *evpmdAlgorithm = NULL;
75
76        pAssert(ctxt != NULL);
77
78        EVP_MD_CTX_init(ctxt);
79
80        evpmdAlgorithm = GetHashServer(algType);
81        if(evpmdAlgorithm == NULL)
82            return 0;
83
84        // This also allocates the ctxt->md_data
85        if((EVP_DigestInit_ex(ctxt, evpmdAlgorithm, NULL)) != 1)
86            FAIL(FATAL_ERROR_INTERNAL);
87
88        pAssert(ctxt->digest->ctx_size < sizeof(ALIGNED_HASH_STATE));
89        memcpy(ctxt->md_data, buf, ctxt->digest->ctx_size);


     Family "2.0"                                 TCG Published                                     Page 381
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

 90        return (UINT16)ctxt->digest->ctx_size;
 91   }


      B.8.3.4.    GetHashInfoPointer()

      This function returns a pointer to the hash info for the algorithm. If the algorithm is not supported, function
      returns a pointer to the data block associated with TPM_ALG_NULL.

 92   static const HASH_INFO *
 93   GetHashInfoPointer(
 94        TPM_ALG_ID           hashAlg
 95        )
 96   {
 97        UINT32 i, tableSize;
 98
 99        // Get the table size of g_hashData
100        tableSize = sizeof(g_hashData) / sizeof(g_hashData[0]);
101
102        for(i = 0; i < tableSize - 1; i++)
103        {
104            if(g_hashData[i].alg == hashAlg)
105                return &g_hashData[i];
106        }
107        return &g_hashData[tableSize-1];
108   }


      B.8.4.     Hash Functions

      B.8.4.1.    _cpri__HashStartup()

      Function that is called to initialize the hash service. In this implementation, this function does nothing but
      it is called by the CryptUtilStartup() function and must be present.

109   LIB_EXPORT BOOL
110   _cpri__HashStartup(
111        void
112        )
113   {
114        // On startup, make sure that the structure sizes are compatible. It would
115        // be nice if this could be done at compile time but I couldn't figure it out.
116        CPRI_HASH_STATE *cpriState = NULL;
117   //     NUMBYTES        evpCtxSize = sizeof(EVP_MD_CTX);
118        NUMBYTES        cpriStateSize = sizeof(cpriState->state);
119   //     OSSL_HASH_STATE *osslState;
120        NUMBYTES        osslStateSize = sizeof(OSSL_HASH_STATE);
121   //     int             dataSize = sizeof(osslState->u.data);
122        pAssert(cpriStateSize >= osslStateSize);
123
124        return TRUE;
125   }


      B.8.4.2.    _cpri__GetHashAlgByIndex()

      This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are
      not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first
      implemented hash and and index of 2 will return the last. All other index values will return
      TPM_ALG_NULL.




      Page 382                                      TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library


      Return Value                      Meaning

      TPM_ALG_xxx()                     a hash algorithm
      TPM_ALG_NULL                      this can be used as a stop value

126   LIB_EXPORT TPM_ALG_ID
127   _cpri__GetHashAlgByIndex(
128        UINT32               index               // IN: the index
129        )
130   {
131        if(index >= HASH_COUNT)
132            return TPM_ALG_NULL;
133        return g_hashData[index].alg;
134   }


      B.8.4.3.   _cpri__GetHashBlockSize()

      Returns the size of the block used for the hash

      Return Value                      Meaning

      <0                                the algorithm is not a supported hash
      >=                                the digest size (0 for TPM_ALG_NULL)

135   LIB_EXPORT UINT16
136   _cpri__GetHashBlockSize(
137        TPM_ALG_ID           hashAlg             // IN: hash algorithm to look up
138        )
139   {
140        return GetHashInfoPointer(hashAlg)->blockSize;
141   }


      B.8.4.4.   _cpri__GetHashDER

      This function returns a pointer to the DER string for the algorithm and indicates its size.

142   LIB_EXPORT UINT16
143   _cpri__GetHashDER(
144        TPM_ALG_ID           hashAlg,            // IN: the algorithm to look up
145        const BYTE          **p
146        )
147   {
148        const HASH_INFO       *q;
149        q = GetHashInfoPointer(hashAlg);
150        *p = &q->der[0];
151        return q->derSize;
152   }


      B.8.4.5.   _cpri__GetDigestSize()

      Gets the digest size of the algorithm. The algorithm is required to be supported.

      Return Value                      Meaning

      =0                                the digest size for TPM_ALG_NULL
      >0                                the digest size of a hash algorithm

153   LIB_EXPORT UINT16

      Family "2.0"                                   TCG Published                                         Page 383
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                               October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

154   _cpri__GetDigestSize(
155        TPM_ALG_ID           hashAlg               // IN: hash algorithm to look up
156        )
157   {
158        return GetHashInfoPointer(hashAlg)->digestSize;
159   }


      B.8.4.6.   _cpri__GetContextAlg()

      This function returns the algorithm associated with a hash context

160   LIB_EXPORT TPM_ALG_ID
161   _cpri__GetContextAlg(
162        CPRI_HASH_STATE         *hashState             // IN: the hash context
163        )
164   {
165        return hashState->hashAlg;
166   }


      B.8.4.7.   _cpri__CopyHashState

      This function is used to clone a CPRI_HASH_STATE. The return value is the size of the state.

167   LIB_EXPORT UINT16
168   _cpri__CopyHashState (
169        CPRI_HASH_STATE         *out,                  // OUT: destination of the state
170        CPRI_HASH_STATE         *in                    // IN: source of the state
171        )
172   {
173        OSSL_HASH_STATE    *i = (OSSL_HASH_STATE *)&in->state;
174        OSSL_HASH_STATE    *o = (OSSL_HASH_STATE *)&out->state;
175        pAssert(sizeof(i) <= sizeof(in->state));
176
177        EVP_MD_CTX_init(&o->u.context);
178        EVP_MD_CTX_copy_ex(&o->u.context, &i->u.context);
179        o->copySize = i->copySize;
180        out->hashAlg = in->hashAlg;
181        return sizeof(CPRI_HASH_STATE);
182   }


      B.8.4.8.   _cpri__StartHash()

      Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, the value of
      stateSize in hashState is updated to indicate the number of bytes of state that were saved. This function
      calls GetHashServer() and that function will put the TPM into failure mode if the hash algorithm is not
      supported.

      Return Value                      Meaning

      0                                 hash is TPM_ALG_NULL
      >0                                digest size

183   LIB_EXPORT UINT16
184   _cpri__StartHash(
185        TPM_ALG_ID               hashAlg,              // IN: hash algorithm
186        BOOL                     sequence,             // IN: TRUE if the state should be saved
187        CPRI_HASH_STATE         *hashState             // OUT: the state of hash stack.
188        )
189   {
190        EVP_MD_CTX           localState;

      Page 384                                        TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                        Trusted Platform Module Library

191       OSSL_HASH_STATE    *state = (OSSL_HASH_STATE *)&hashState->state;
192       BYTE               *stateData = state->u.data;
193       EVP_MD_CTX         *context;
194       EVP_MD             *evpmdAlgorithm = NULL;
195       UINT16              retVal = 0;
196
197       if(sequence)
198           context = &localState;
199       else
200           context = &state->u.context;
201
202       hashState->hashAlg = hashAlg;
203
204       EVP_MD_CTX_init(context);
205       evpmdAlgorithm = GetHashServer(hashAlg);
206       if(evpmdAlgorithm == NULL)
207           goto Cleanup;
208
209       if(EVP_DigestInit_ex(context, evpmdAlgorithm, NULL) != 1)
210           FAIL(FATAL_ERROR_INTERNAL);
211       retVal = (CRYPT_RESULT)EVP_MD_CTX_size(context);
212
213   Cleanup:
214       if(retVal > 0)
215       {
216           if (sequence)
217           {
218                if((state->copySize = MarshalHashState(context, stateData)) == 0)
219                {
220                    // If MarshalHashState returns a negative number, it is an error
221                    // code and not a hash size so copy the error code to be the return
222                    // from this function and set the actual stateSize to zero.
223                    retVal = state->copySize;
224                    state->copySize = 0;
225                }
226                // Do the cleanup
227                EVP_MD_CTX_cleanup(context);
228           }
229           else
230                state->copySize = -1;
231       }
232       else
233           state->copySize = 0;
234       return retVal;
235   }


      B.8.4.9.   _cpri__UpdateHash()

      Add data to a hash or HMAC stack.

236   LIB_EXPORT void
237   _cpri__UpdateHash(
238       CPRI_HASH_STATE           *hashState,      // IN: the hash context information
239       UINT32                     dataSize,       // IN: the size of data to be added to the
240                                                  //     digest
241       BYTE                      *data            // IN: data to be hashed
242       )
243   {
244       EVP_MD_CTX       localContext;
245       OSSL_HASH_STATE *state = (OSSL_HASH_STATE *)&hashState->state;
246       BYTE            *stateData = state->u.data;
247       EVP_MD_CTX      *context;
248       CRYPT_RESULT     retVal = CRYPT_SUCCESS;
249


      Family "2.0"                                TCG Published                               Page 385
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

250        // If there is no context, return
251        if(state->copySize == 0)
252            return;
253        if(state->copySize > 0)
254        {
255            context = &localContext;
256            if((retVal = GetHashState(context, hashState->hashAlg, stateData)) <= 0)
257                return;
258        }
259        else
260            context = &state->u.context;
261
262        if(EVP_DigestUpdate(context, data, dataSize) != 1)
263            FAIL(FATAL_ERROR_INTERNAL);
264        else if(    state->copySize > 0
265                    && (retVal= MarshalHashState(context, stateData)) >= 0)
266        {
267            // retVal is the size of the marshaled data. Make sure that it is consistent
268            // by ensuring that we didn't get more than allowed
269            if(retVal < state->copySize)
270                 FAIL(FATAL_ERROR_INTERNAL);
271            else
272                 EVP_MD_CTX_cleanup(context);
273        }
274        return;
275   }


      B.8.4.10. _cpri__CompleteHash()

      Complete a hash or HMAC computation. This function will place the smaller of digestSize or the size of
      the digest in dOut. The number of bytes in the placed in the buffer is returned. If there is a failure, the
      returned value is <= 0.

      Return Value                      Meaning

      0                                 no data returned
      >0                                the number of bytes in the digest

276   LIB_EXPORT UINT16
277   _cpri__CompleteHash(
278        CPRI_HASH_STATE         *hashState,             // IN: the state of hash stack
279        UINT32                   dOutSize,              // IN: size of digest buffer
280        BYTE                    *dOut                   // OUT: hash digest
281        )
282   {
283        EVP_MD_CTX          localState;
284        OSSL_HASH_STATE    *state = (OSSL_HASH_STATE *)&hashState->state;
285        BYTE               *stateData = state->u.data;
286        EVP_MD_CTX         *context;
287        UINT16              retVal;
288        int                 hLen;
289        BYTE                temp[MAX_DIGEST_SIZE];
290        BYTE               *rBuffer = dOut;
291
292        if(state->copySize == 0)
293            return 0;
294        if(state->copySize > 0)
295        {
296            context = &localState;
297            if((retVal = GetHashState(context, hashState->hashAlg, stateData)) <= 0)
298                goto Cleanup;
299        }
300        else

      Page 386                                       TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

301            context = &state->u.context;
302
303       hLen = EVP_MD_CTX_size(context);
304       if((unsigned)hLen > dOutSize)
305           rBuffer = temp;
306       if(EVP_DigestFinal_ex(context, rBuffer, NULL) == 1)
307       {
308           if(rBuffer != dOut)
309           {
310                if(dOut != NULL)
311                {
312                    memcpy(dOut, temp, dOutSize);
313                }
314                retVal = (UINT16)dOutSize;
315           }
316           else
317           {
318                retVal = (UINT16)hLen;
319           }
320           state->copySize = 0;
321       }
322       else
323       {
324           retVal = 0; // Indicate that no data is returned
325       }
326   Cleanup:
327       EVP_MD_CTX_cleanup(context);
328       return retVal;
329   }


      B.8.4.11. _cpri__ImportExportHashState()

      This function is used to import or export the hash state. This function would be called to export state when
      a sequence object was being prepared for export

330   LIB_EXPORT void
331   _cpri__ImportExportHashState(
332       CPRI_HASH_STATE           *osslFmt,          // IN/OUT: the hash state formated for use
333                                                    //     by openSSL
334       EXPORT_HASH_STATE         *externalFmt,      // IN/OUT: the exported hash state
335       IMPORT_EXPORT              direction         //
336       )
337   {
338       UNREFERENCED_PARAMETER(direction);
339       UNREFERENCED_PARAMETER(externalFmt);
340       UNREFERENCED_PARAMETER(osslFmt);
341       return;
342
343   #if 0
344       if(direction == IMPORT_STATE)
345       {
346           // don't have the import export functions yet so just copy
347           _cpri__CopyHashState(osslFmt, (CPRI_HASH_STATE *)externalFmt);
348       }
349       else
350       {
351           _cpri__CopyHashState((CPRI_HASH_STATE *)externalFmt, osslFmt);
352       }
353   #endif
354   }




      Family "2.0"                                 TCG Published                                       Page 387
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

      B.8.4.12. _cpri__HashBlock()

      Start a hash, hash a single block, update digest and return the size of the results.
      The digestSize parameter can be smaller than the digest. If so, only the more significant bytes are
      returned.

      Return Value                      Meaning

      >= 0                              number of bytes in digest (may be zero)

355   LIB_EXPORT UINT16
356   _cpri__HashBlock(
357          TPM_ALG_ID         hashAlg,            //   IN: The hash algorithm
358          UINT32             dataSize,           //   IN: size of buffer to hash
359          BYTE              *data,               //   IN: the buffer to hash
360          UINT32             digestSize,         //   IN: size of the digest buffer
361          BYTE              *digest              //   OUT: hash digest
362          )
363   {
364          EVP_MD_CTX        hashContext;
365          EVP_MD           *hashServer = NULL;
366          UINT16            retVal = 0;
367          BYTE              b[MAX_DIGEST_SIZE]; // temp buffer in case digestSize not
368          // a full digest
369          unsigned int      dSize = _cpri__GetDigestSize(hashAlg);
370
371          // If there is no digest to compute return
372          if(dSize == 0)
373              return 0;
374
375          // After the call to EVP_MD_CTX_init(), will need to call EVP_MD_CTX_cleanup()
376          EVP_MD_CTX_init(&hashContext);     // Initialize the local hash context
377          hashServer = GetHashServer(hashAlg); // Find the hash server
378
379          // It is an error if the digest size is non-zero but there is no                server
380          if(   (hashServer == NULL)
381             || (EVP_DigestInit_ex(&hashContext, hashServer, NULL) != 1)
382             || (EVP_DigestUpdate(&hashContext, data, dataSize) != 1))
383              FAIL(FATAL_ERROR_INTERNAL);
384          else
385          {
386              // If the size of the digest produced (dSize) is larger than                the available
387              // buffer (digestSize), then put the digest in a temp buffer                and only copy
388              // the most significant part into the available buffer.
389              if(dSize > digestSize)
390              {
391                   if(EVP_DigestFinal_ex(&hashContext, b, &dSize) != 1)
392                       FAIL(FATAL_ERROR_INTERNAL);
393                   memcpy(digest, b, digestSize);
394                   retVal = (UINT16)digestSize;
395              }
396              else
397              {
398                   if((EVP_DigestFinal_ex(&hashContext, digest, &dSize)) !=               1)
399                       FAIL(FATAL_ERROR_INTERNAL);
400                   retVal = (UINT16) dSize;
401              }
402          }
403          EVP_MD_CTX_cleanup(&hashContext);
404          return retVal;
405   }




      Page 388                                       TCG Published                                    Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      B.8.5.     HMAC Functions

      B.8.5.1.    _cpri__StartHMAC

      This function is used to start an HMAC using a temp hash context. The function does the initialization of
      the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad.
      The function returns the number of bytes in a digest produced by hashAlg.

      Return Value                    Meaning

      >= 0                            number of bytes in digest produced by hashAlg (may be zero)

406   LIB_EXPORT UINT16
407   _cpri__StartHMAC(
408          TPM_ALG_ID              hashAlg,          //   IN: the algorithm to use
409          BOOL                    sequence,         //   IN: indicates if the state should be
410                                                    //       saved
411          CPRI_HASH_STATE        *state,            //   IN/OUT: the state buffer
412          UINT16                  keySize,          //   IN: the size of the HMAC key
413          BYTE                   *key,              //   IN: the HMAC key
414          TPM2B                  *oPadKey           //   OUT: the key prepared for the oPad round
415          )
416   {
417          CPRI_HASH_STATE localState;
418          UINT16           blockSize = _cpri__GetHashBlockSize(hashAlg);
419          UINT16           digestSize;
420          BYTE            *pb;         // temp pointer
421          UINT32           i;
422
423          // If the key size is larger than the block size, then the hash of the key
424          // is used as the key
425          if(keySize > blockSize)
426          {
427              // large key so digest
428              if((digestSize = _cpri__StartHash(hashAlg, FALSE, &localState)) == 0)
429                  return 0;
430              _cpri__UpdateHash(&localState, keySize, key);
431              _cpri__CompleteHash(&localState, digestSize, oPadKey->buffer);
432              oPadKey->size = digestSize;
433          }
434          else
435          {
436              // key size is ok
437              memcpy(oPadKey->buffer, key, keySize);
438              oPadKey->size = keySize;
439          }
440          // XOR the key with iPad (0x36)
441          pb = oPadKey->buffer;
442          for(i = oPadKey->size; i > 0; i--)
443              *pb++ ^= 0x36;
444
445          // if the keySize is smaller than a block, fill the rest with 0x36
446          for(i = blockSize - oPadKey->size; i > 0; i--)
447              *pb++ = 0x36;
448
449          // Increase the oPadSize to a full block
450          oPadKey->size = blockSize;
451
452          // Start a new hash with the HMAC key
453          // This will go in the caller's state structure and may be a sequence or not
454
455          if((digestSize = _cpri__StartHash(hashAlg, sequence, state)) > 0)
456          {

      Family "2.0"                                TCG Published                                       Page 389
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

457
458              _cpri__UpdateHash(state, oPadKey->size, oPadKey->buffer);
459
460              // XOR the key block with 0x5c ^ 0x36
461              for(pb = oPadKey->buffer, i = blockSize; i > 0; i--)
462                  *pb++ ^= (0x5c ^ 0x36);
463          }
464
465          return digestSize;
466   }


      B.8.5.2.    _cpri_CompleteHMAC()

      This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will
      then add the oPadKey and the completed digest and return the results in dOut. It will not return more than
      dOutSize bytes.

      Return Value                      Meaning

      >= 0                              number of bytes in dOut (may be zero)

467   LIB_EXPORT UINT16
468   _cpri__CompleteHMAC(
469          CPRI_HASH_STATE        *hashState,          //   IN: the state of hash stack
470          TPM2B                  *oPadKey,            //   IN: the HMAC key in oPad format
471          UINT32                  dOutSize,           //   IN: size of digest buffer
472          BYTE                   *dOut                //   OUT: hash digest
473          )
474   {
475          BYTE             digest[MAX_DIGEST_SIZE];
476          CPRI_HASH_STATE *state = (CPRI_HASH_STATE *)hashState;
477          CPRI_HASH_STATE localState;
478          UINT16           digestSize = _cpri__GetDigestSize(state->hashAlg);
479
480          _cpri__CompleteHash(hashState, digestSize, digest);
481
482          // Using the local hash state, do a hash with the oPad
483          if(_cpri__StartHash(state->hashAlg, FALSE, &localState) != digestSize)
484              return 0;
485
486          _cpri__UpdateHash(&localState, oPadKey->size, oPadKey->buffer);
487          _cpri__UpdateHash(&localState, digestSize, digest);
488          return _cpri__CompleteHash(&localState, dOutSize, dOut);
489   }


      B.8.6.     Mask and Key Generation Functions

      B.8.6.1.    _crypi_MGF1()

      This function performs MGF1 using the selected hash. MGF1 is T(n) = T(n-1) || H(seed || counter). This
      function returns the length of the mask produced which could be zero if the digest algorithm is not
      supported

      Return Value                      Meaning

      0                                 hash algorithm not supported
      >0                                should be the same as mSize

490   LIB_EXPORT CRYPT_RESULT
491   _cpri__MGF1(

      Page 390                                      TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                       Trusted Platform Module Library

492       UINT32              mSize,          //   IN: length of the mask to be produced
493       BYTE               *mask,           //   OUT: buffer to receive the mask
494       TPM_ALG_ID          hashAlg,        //   IN: hash to use
495       UINT32              sSize,          //   IN: size of the seed
496       BYTE               *seed            //   IN: seed size
497       )
498   {
499       EVP_MD_CTX           hashContext;
500       EVP_MD              *hashServer = NULL;
501       CRYPT_RESULT         retVal = 0;
502       BYTE                 b[MAX_DIGEST_SIZE]; // temp buffer in case mask is not an
503       // even multiple of a full digest
504       CRYPT_RESULT         dSize = _cpri__GetDigestSize(hashAlg);
505       unsigned int         digestSize = (UINT32)dSize;
506       UINT32               remaining;
507       UINT32               counter;
508       BYTE                 swappedCounter[4];
509
510       // Parameter check
511       if(mSize > (1024*16)) // Semi-arbitrary maximum
512           FAIL(FATAL_ERROR_INTERNAL);
513
514       // If there is no digest to compute return
515       if(dSize <= 0)
516           return 0;
517
518       EVP_MD_CTX_init(&hashContext);     // Initialize the local hash context
519       hashServer = GetHashServer(hashAlg); // Find the hash server
520       if(hashServer == NULL)
521           // If there is no server, then there is no digest
522           return 0;
523
524       for(counter = 0, remaining = mSize; remaining > 0; counter++)
525       {
526           // Because the system may be either Endian...
527           UINT32_TO_BYTE_ARRAY(counter, swappedCounter);
528
529            // Start the hash and include the seed and counter
530            if(    (EVP_DigestInit_ex(&hashContext, hashServer, NULL) != 1)
531                || (EVP_DigestUpdate(&hashContext, seed, sSize) != 1)
532                || (EVP_DigestUpdate(&hashContext, swappedCounter, 4) != 1)
533              )
534                 FAIL(FATAL_ERROR_INTERNAL);
535
536            // Handling the completion depends on how much space remains in the mask
537            // buffer. If it can hold the entire digest, put it there. If not
538            // put the digest in a temp buffer and only copy the amount that
539            // will fit into the mask buffer.
540            if(remaining < (unsigned)dSize)
541            {
542                 if(EVP_DigestFinal_ex(&hashContext, b, &digestSize) != 1)
543                     FAIL(FATAL_ERROR_INTERNAL);
544                 memcpy(mask, b, remaining);
545                 break;
546            }
547            else
548            {
549                 if(EVP_DigestFinal_ex(&hashContext, mask, &digestSize) != 1)
550                     FAIL(FATAL_ERROR_INTERNAL);
551                 remaining -= dSize;
552                 mask = &mask[dSize];
553            }
554            retVal = (CRYPT_RESULT)mSize;
555       }
556
557       EVP_MD_CTX_cleanup(&hashContext);

      Family "2.0"                            TCG Published                                  Page 391
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

558        return retVal;
559   }


      B.8.6.2.    _cpri_KDFa()

      This function performs the key generation according to Part 1 of the TPM specification.
      This function returns the number of bytes generated which may be zero.
      The key and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL.
      The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes).
      The once parameter is set to allow incremental generation of a large value. If this flag is TRUE,
      sizeInBits will be used in the HMAC computation but only one iteration of the KDF is performed. This
      would be used for XOR obfuscation so that the mask value can be generated in digest-sized chunks
      rather than having to be generated all at once in an arbitrarily large buffer and then XORed() into the
      result. If once is TRUE, then sizeInBits must be a multiple of 8.
      Any error in the processing of this command is considered fatal.

      Return Value                      Meaning

      0                                 hash algorithm is not supported or is TPM_ALG_NULL
      >0                                the number of bytes in the keyStream buffer

560   LIB_EXPORT UINT16
561   _cpri__KDFa(
562        TPM_ALG_ID          hashAlg,             //   IN: hash algorithm used in HMAC
563        TPM2B              *key,                 //   IN: HMAC key
564        const char         *label,               //   IN: a 0-byte terminated label used in KDF
565        TPM2B              *contextU,            //   IN: context U
566        TPM2B              *contextV,            //   IN: context V
567        UINT32              sizeInBits,          //   IN: size of generated key in bit
568        BYTE               *keyStream,           //   OUT: key buffer
569        UINT32             *counterInOut,        //   IN/OUT: caller may provide the iteration
570                                                 //       counter for incremental operations to
571                                                 //       avoid large intermediate buffers.
572        BOOL                once                 //   IN: TRUE if only one iteration is performed
573                                                 //       FALSE if iteration count determined by
574                                                 //       "sizeInBits"
575        )
576   {
577        UINT32                         counter = 0;    // counter value
578        INT32                          lLen = 0;       // length of the label
579        INT16                          hLen;           // length of the hash
580        INT16                          bytes;          // number of bytes to produce
581        BYTE                          *stream = keyStream;
582        BYTE                           marshaledUint32[4];
583        CPRI_HASH_STATE                hashState;
584        TPM2B_MAX_HASH_BLOCK           hmacKey;
585
586        pAssert(key != NULL && keyStream != NULL);
587        pAssert(once == FALSE || (sizeInBits & 7) == 0);
588
589        if(counterInOut != NULL)
590            counter = *counterInOut;
591
592        // Prepare label buffer. Calculate its size and keep the last 0 byte
593        if(label != NULL)
594            for(lLen = 0; label[lLen++] != 0; );
595
596        // Get the hash size. If it is less than or 0, either the
597        // algorithm is not supported or the hash is TPM_ALG_NULL


      Page 392                                       TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                   Trusted Platform Module Library

598       // In either case the digest size is zero. This is the only return
599       // other than the one at the end. All other exits from this function
600       // are fatal errors. After we check that the algorithm is supported
601       // anything else that goes wrong is an implementation flaw.
602       if((hLen = (INT16) _cpri__GetDigestSize(hashAlg)) == 0)
603           return 0;
604
605       // If the size of the request is larger than the numbers will handle,
606       // it is a fatal error.
607       pAssert(((sizeInBits + 7)/ 8) <= INT16_MAX);
608
609       bytes = once ? hLen : (INT16)((sizeInBits + 7) / 8);
610
611       // Generate required bytes
612       for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
613       {
614           if(bytes < hLen)
615               hLen = bytes;
616
617            counter++;
618            // Start HMAC
619            if(_cpri__StartHMAC(hashAlg,
620                                FALSE,
621                                &hashState,
622                                key->size,
623                                &key->buffer[0],
624                                &hmacKey.b)          <= 0)
625                FAIL(FATAL_ERROR_INTERNAL);
626
627            // Adding counter
628            UINT32_TO_BYTE_ARRAY(counter, marshaledUint32);
629            _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
630
631            // Adding label
632            if(label != NULL)
633                _cpri__UpdateHash(&hashState,   lLen, (BYTE *)label);
634
635            // Adding contextU
636            if(contextU != NULL)
637                _cpri__UpdateHash(&hashState, contextU->size, contextU->buffer);
638
639            // Adding contextV
640            if(contextV != NULL)
641                _cpri__UpdateHash(&hashState, contextV->size, contextV->buffer);
642
643            // Adding size in bits
644            UINT32_TO_BYTE_ARRAY(sizeInBits, marshaledUint32);
645            _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
646
647            // Compute HMAC. At the start of each iteration, hLen is set
648            // to the smaller of hLen and bytes. This causes bytes to decrement
649            // exactly to zero to complete the loop
650            _cpri__CompleteHMAC(&hashState, &hmacKey.b, hLen, stream);
651       }
652
653       // Mask off bits if the required bits is not a multiple of byte size
654       if((sizeInBits % 8) != 0)
655           keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
656       if(counterInOut != NULL)
657           *counterInOut = counter;
658       return (CRYPT_RESULT)((sizeInBits + 7)/8);
659   }




      Family "2.0"                         TCG Published                                 Page 393
      Level 00 Revision 01.16        Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

      B.8.6.3.   _cpri__KDFe()

      KDFe() as defined in TPM specification part 1.
      This function returns the number of bytes generated which may be zero.
      The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. The
      value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any error in the processing
      of this command is considered fatal.

      Return Value                      Meaning

      0                                 hash algorithm is not supported or is TPM_ALG_NULL
      >0                                the number of bytes in the keyStream buffer

660   LIB_EXPORT UINT16
661   _cpri__KDFe(
662        TPM_ALG_ID          hashAlg,             //   IN: hash algorithm used in HMAC
663        TPM2B              *Z,                   //   IN: Z
664        const char         *label,               //   IN: a 0 terminated label using in KDF
665        TPM2B              *partyUInfo,          //   IN: PartyUInfo
666        TPM2B              *partyVInfo,          //   IN: PartyVInfo
667        UINT32              sizeInBits,          //   IN: size of generated key in bit
668        BYTE               *keyStream            //   OUT: key buffer
669        )
670   {
671        UINT32       counter = 0;        // counter value
672        UINT32       lSize = 0;
673        BYTE        *stream = keyStream;
674        CPRI_HASH_STATE         hashState;
675        INT16        hLen = (INT16) _cpri__GetDigestSize(hashAlg);
676        INT16        bytes;              // number of bytes to generate
677        BYTE         marshaledUint32[4];
678
679        pAssert(     keyStream != NULL
680                     && Z != NULL
681                     && ((sizeInBits + 7) / 8) < INT16_MAX);
682
683        if(hLen == 0)
684            return 0;
685
686        bytes = (INT16)((sizeInBits + 7) / 8);
687
688        // Prepare label buffer. Calculate its size and keep the last 0 byte
689        if(label != NULL)
690            for(lSize = 0; label[lSize++] != 0;);
691
692        // Generate required bytes
693        //The inner loop of that KDF uses:
694        // Hashi := H(counter | Z | OtherInfo) (5)
695        // Where:
696        // Hashi    the hash generated on the i-th iteration of the loop.
697        // H()      an approved hash function
698        // counter a 32-bit counter that is initialized to 1 and incremented
699        //          on each iteration
700        // Z        the X coordinate of the product of a public ECC key and a
701        //          different private ECC key.
702        // OtherInfo    a collection of qualifying data for the KDF defined below.
703        // In this specification, OtherInfo will be constructed by:
704        //      OtherInfo := Use | PartyUInfo | PartyVInfo
705        for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
706        {
707            if(bytes < hLen)
708                hLen = bytes;


      Page 394                                       TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

709
710            counter++;
711            // Start hash
712            if(_cpri__StartHash(hashAlg, FALSE,   &hashState) == 0)
713                return 0;
714
715            // Add counter
716            UINT32_TO_BYTE_ARRAY(counter, marshaledUint32);
717            _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
718
719            // Add Z
720            if(Z != NULL)
721                _cpri__UpdateHash(&hashState, Z->size, Z->buffer);
722
723            // Add label
724            if(label != NULL)
725                 _cpri__UpdateHash(&hashState, lSize, (BYTE *)label);
726            else
727
728                  // The SP800-108 specification requires a zero between the label
729                  // and the context.
730                  _cpri__UpdateHash(&hashState, 1, (BYTE *)"");
731
732            // Add PartyUInfo
733            if(partyUInfo != NULL)
734                _cpri__UpdateHash(&hashState, partyUInfo->size, partyUInfo->buffer);
735
736            // Add PartyVInfo
737            if(partyVInfo != NULL)
738                _cpri__UpdateHash(&hashState, partyVInfo->size, partyVInfo->buffer);
739
740            // Compute Hash. hLen was changed to be the smaller of bytes or hLen
741            // at the start of each iteration.
742            _cpri__CompleteHash(&hashState, hLen, stream);
743       }
744
745       // Mask off bits if the required bits is not a multiple of byte size
746       if((sizeInBits % 8) != 0)
747           keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
748
749       return (CRYPT_RESULT)((sizeInBits + 7) / 8);
750
751   }




      Family "2.0"                           TCG Published                                Page 395
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
     Trusted Platform Module Library                                   Part 4: Supporting Routines


     B.9   CpriHashData.c

     This file should be included by the library hash module.

 1      const HASH_INFO    g_hashData[HASH_COUNT + 1] = {
 2   #ifdef TPM_ALG_SHA1
 3       {TPM_ALG_SHA1,     SHA1_DIGEST_SIZE,   SHA1_BLOCK_SIZE,
 4       SHA1_DER_SIZE,    SHA1_DER},
 5   #endif
 6   #ifdef TPM_ALG_SHA256
 7       {TPM_ALG_SHA256,     SHA256_DIGEST_SIZE,   SHA256_BLOCK_SIZE,
 8       SHA256_DER_SIZE,    SHA256_DER},
 9   #endif
10   #ifdef TPM_ALG_SHA384
11       {TPM_ALG_SHA384,     SHA384_DIGEST_SIZE,   SHA384_BLOCK_SIZE,
12       SHA384_DER_SIZE,    SHA384_DER},
13   #endif
14   #ifdef TPM_ALG_SM3_256
15       {TPM_ALG_SM3_256,     SM3_256_DIGEST_SIZE,   SM3_256_BLOCK_SIZE,
16       SM3_256_DER_SIZE,    SM3_256_DER},
17   #endif
18   #ifdef TPM_ALG_SHA512
19       {TPM_ALG_SHA512,     SHA512_DIGEST_SIZE,   SHA512_BLOCK_SIZE,
20       SHA512_DER_SIZE,    SHA512_DER},
21   #endif
22          {TPM_ALG_NULL,0,0,0,{0}}
23      };




     Page 396                                     TCG Published                      Family "2.0"
     October 30, 2014                      Copyright © TCG 2006-2014    Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library


     B.10 CpriMisc.c

     B.10.1. Includes

 1   #include "OsslCryptoEngine.h"


     B.10.2. Functions

     B.10.2.1. BnTo2B()

     This function is used to convert a BigNum() to a byte array of the specified size. If the number is too large
     to fit, then 0 is returned. Otherwise, the number is converted into the low-order bytes of the provided array
     and the upper bytes are set to zero.

     Return Value                     Meaning

     0                                failure (probably fatal)
     1                                conversion successful

 2   BOOL
 3   BnTo2B(
 4        TPM2B               *outVal,             // OUT: place for the result
 5        BIGNUM              *inVal,              // IN: number to convert
 6        UINT16               size                // IN: size of the output.
 7        )
 8   {
 9        BYTE      *pb = outVal->buffer;
10
11        outVal->size = size;
12
13        size = size - (((UINT16) BN_num_bits(inVal) + 7) / 8);
14        if(size < 0)
15            return FALSE;
16        for(;size > 0; size--)
17            *pb++ = 0;
18        BN_bn2bin(inVal, pb);
19        return TRUE;
20   }


     B.10.2.2. Copy2B()

     This function copies a TPM2B structure. The compiler can't generate a copy of a TPM2B generic
     structure because the actual size is not known. This function performs the copy on any TPM2B pair. The
     size of the destination should have been checked before this call to make sure that it will hold the TPM2B
     being copied.
     This replicates the functionality in the MemoryLib.c.

21   void
22   Copy2B(
23        TPM2B               *out,                // OUT: The TPM2B to receive the copy
24        TPM2B               *in                  // IN: the TPM2B to copy
25        )
26   {
27        BYTE        *pIn = in->buffer;
28        BYTE        *pOut = out->buffer;
29        int          count;
30        out->size = in->size;
31        for(count = in->size; count > 0; count--)

     Family "2.0"                                   TCG Published                                      Page 397
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                              Part 4: Supporting Routines

32           *pOut++ = *pIn++;
33       return;
34   }


     B.10.2.3. BnFrom2B()

     This function creates a BIGNUM from a TPM2B and fails if the conversion fails.

35   BIGNUM *
36   BnFrom2B(
37       BIGNUM              *out,              // OUT: The BIGNUM
38       const TPM2B         *in                // IN: the TPM2B to copy
39       )
40   {
41       if(BN_bin2bn(in->buffer, in->size, out) == NULL)
42           FAIL(FATAL_ERROR_INTERNAL);
43       return out;
44   }




     Page 398                                    TCG Published                                   Family "2.0"
     October 30, 2014                    Copyright © TCG 2006-2014                    Level 00 Revision 01.16
     Part 4: Supporting Routines                                             Trusted Platform Module Library


     B.11 CpriSym.c

     B.11.1. Introduction

     This file contains the implementation of the symmetric block cipher modes allowed for a TPM. These
     function only use the single block encryption and decryption functions of OpesnSSL().
     Currently, this module only supports AES encryption. The SM4 code actually calls an AES routine

     B.11.2. Includes, Defines, and Typedefs

 1   #include       "OsslCryptoEngine.h"

     The following sets of defines are used to allow use of the SM4 algorithm identifier while waiting for the
     SM4 implementation code to appear.

 2   typedef   AES_KEY SM4_KEY;
 3   #define   SM4_set_encrypt_key            AES_set_encrypt_key
 4   #define   SM4_set_decrypt_key            AES_set_decrypt_key
 5   #define   SM4_decrypt                    AES_decrypt
 6   #define   SM4_encrypt                    AES_encrypt


     B.11.3. Utility Functions

     B.11.3.1. _cpri_SymStartup()

 7   LIB_EXPORT BOOL
 8   _cpri__SymStartup(
 9          void
10   )
11   {
12          return TRUE;
13   }


     B.11.3.2. _cpri__GetSymmetricBlockSize()

     This function returns the block size of the algorithm.

     Return Value                      Meaning

     <= 0                              cipher not supported
     >0                                the cipher block size in bytes

14   LIB_EXPORT INT16
15   _cpri__GetSymmetricBlockSize(
16          TPM_ALG_ID         symmetricAlg,        // IN: the symmetric algorithm
17          UINT16             keySizeInBits        // IN: the key size
18          )
19   {
20       switch (symmetricAlg)
21       {
22   #ifdef TPM_ALG_AES
23       case TPM_ALG_AES:
24   #endif
25   #ifdef TPM_ALG_SM4 // Both AES and SM4 use the same block size
26       case TPM_ALG_SM4:
27   #endif
28           if(keySizeInBits != 0) // This is mostly to have a reference to

     Family "2.0"                                   TCG Published                                  Page 399
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                       October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines

29                  // keySizeInBits for the compiler
30                  return 16;
31             else
32                 return 0;
33             break;
34
35        default:
36            return 0;
37        }
38   }


     B.11.4. AES Encryption

     B.11.4.1. _cpri__AESEncryptCBC()

     This function performs AES encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
     The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
     be a multiple of the block size.

     Return Value                      Meaning

     CRYPT_SUCCESS                     if success
     CRYPT_PARAMETER                   dInSize is not a multiple of the block size

39   LIB_EXPORT CRYPT_RESULT
40   _cpri__AESEncryptCBC(
41        BYTE                *dOut,          // OUT:
42        UINT32               keySizeInBits, // IN: key size in bit
43        BYTE                *key,           // IN: key buffer. The size of this buffer in
44                                            //      bytes is (keySizeInBits + 7) / 8
45        BYTE                *iv,            // IN/OUT: IV for decryption.
46        UINT32               dInSize,       // IN: data size (is required to be a multiple
47                                            //      of 16 bytes)
48        BYTE                *dIn            // IN: data buffer
49        )
50   {
51        AES_KEY         AesKey;
52        BYTE           *pIv;
53        INT32           dSize;              // Need a signed version
54        int             i;
55
56        pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
57
58        if(dInSize == 0)
59            return CRYPT_SUCCESS;
60
61        pAssert(dInSize <= INT32_MAX);
62        dSize = (INT32)dInSize;
63
64        // For CBC, the data size must be an even multiple of the
65        // cipher block size
66        if((dSize % 16) != 0)
67            return CRYPT_PARAMETER;
68
69        // Create AES encrypt key schedule
70        if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
71            FAIL(FATAL_ERROR_INTERNAL);
72
73        // XOR the data block into the IV, encrypt the IV into the IV
74        // and then copy the IV to the output
75        for(; dSize > 0; dSize -= 16)
76        {

     Page 400                                        TCG Published                                  Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library

 77             pIv = iv;
 78             for(i = 16; i > 0; i--)
 79                 *pIv++ ^= *dIn++;
 80             AES_encrypt(iv, iv, &AesKey);
 81             pIv = iv;
 82             for(i = 16; i > 0; i--)
 83                 *dOut++ = *pIv++;
 84        }
 85        return CRYPT_SUCCESS;
 86   }


      B.11.4.2. _cpri__AESDecryptCBC()

      This function performs AES decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
      The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
      be a multiple of the block size.

      Return Value                     Meaning

      CRYPT_SUCCESS                    if success
      CRYPT_PARAMETER                  dInSize is not a multiple of the block size

 87   LIB_EXPORT CRYPT_RESULT
 88   _cpri__AESDecryptCBC(
 89        BYTE                *dOut,          // OUT: the decrypted data
 90        UINT32               keySizeInBits, // IN: key size in bit
 91        BYTE                *key,           // IN: key buffer. The size of this buffer in
 92                                            //     bytes is (keySizeInBits + 7) / 8
 93        BYTE                *iv,            // IN/OUT: IV for decryption. The size of this
 94                                            //     buffer is 16 byte
 95        UINT32               dInSize,       // IN: data size
 96        BYTE                *dIn            // IN: data buffer
 97        )
 98   {
 99        AES_KEY         AesKey;
100        BYTE           *pIv;
101        int             i;
102        BYTE            tmp[16];
103        BYTE           *pT = NULL;
104        INT32           dSize;
105
106        pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
107
108        if(dInSize == 0)
109            return CRYPT_SUCCESS;
110
111        pAssert(dInSize <= INT32_MAX);
112        dSize = (INT32)dInSize;
113
114        // For CBC, the data size must be an even multiple of the
115        // cipher block size
116        if((dSize % 16) != 0)
117            return CRYPT_PARAMETER;
118
119        // Create AES key schedule
120        if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
121            FAIL(FATAL_ERROR_INTERNAL);
122
123        // Copy the input data to a temp buffer, decrypt the buffer into the output;
124        // XOR in the IV, and copy the temp buffer to the IV and repeat.
125        for(; dSize > 0; dSize -= 16)
126        {


      Family "2.0"                                  TCG Published                                        Page 401
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

127            pT = tmp;
128            for(i = 16; i> 0; i--)
129                *pT++ = *dIn++;
130            AES_decrypt(tmp, dOut, &AesKey);
131            pIv = iv;
132            pT = tmp;
133            for(i = 16; i> 0; i--)
134            {
135                *dOut++ ^= *pIv;
136                *pIv++ = *pT++;
137            }
138       }
139       return CRYPT_SUCCESS;
140   }


      B.11.4.3. _cpri__AESEncryptCFB()

      This function performs AES encryption in CFB chain mode. The dOut buffer receives the values
      encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
      be modified to contain the last encrypted block.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

141   LIB_EXPORT CRYPT_RESULT
142   _cpri__AESEncryptCFB(
143       BYTE                *dOut,          // OUT: the encrypted
144       UINT32               keySizeInBits, // IN: key size in bit
145       BYTE                *key,           // IN: key buffer. The size of this buffer in
146                                           //     bytes is (keySizeInBits + 7) / 8
147       BYTE                *iv,            // IN/OUT: IV for decryption.
148       UINT32               dInSize,       // IN: data size
149       BYTE                *dIn            // IN: data buffer
150       )
151   {
152       BYTE           *pIv = NULL;
153       AES_KEY         AesKey;
154       INT32           dSize;               // Need a signed version of dInSize
155       int             i;
156
157       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
158
159       if(dInSize == 0)
160           return CRYPT_SUCCESS;
161
162       pAssert(dInSize <= INT32_MAX);
163       dSize = (INT32)dInSize;
164
165       // Create AES encryption key schedule
166       if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
167           FAIL(FATAL_ERROR_INTERNAL);
168
169       // Encrypt the IV into the IV, XOR in the data, and copy to output
170       for(; dSize > 0; dSize -= 16)
171       {
172           // Encrypt the current value of the IV
173           AES_encrypt(iv, iv, &AesKey);
174           pIv = iv;
175           for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
176               // XOR the data into the IV to create the cipher text
177               // and put into the output
178               *dOut++ = *pIv++ ^= *dIn++;
179       }

      Page 402                                       TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library

180       // If the inner loop (i loop) was smaller than 16, then dSize would have been
181       // smaller than 16 and it is now negative. If it is negative, then it indicates
182       // how many bytes are needed to pad out the IV for the next round.
183       for(; dSize < 0; dSize++)
184           *pIv++ = 0;
185       return CRYPT_SUCCESS;
186   }


      B.11.4.4. _cpri__AESDecryptCFB()

      This function performs AES decrypt in CFB chain mode. The dOut buffer receives the values decrypted
      from dIn.
      The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
      contain the last decoded block, padded with zeros

      Return Value                    Meaning

      CRYPT_SUCCESS                   no non-fatal errors

187   LIB_EXPORT CRYPT_RESULT
188   _cpri__AESDecryptCFB(
189       BYTE                *dOut,          // OUT: the decrypted data
190       UINT32               keySizeInBits, // IN: key size in bit
191       BYTE                *key,           // IN: key buffer. The size of this buffer in
192                                           //     bytes is (keySizeInBits + 7) / 8
193       BYTE                *iv,            // IN/OUT: IV for decryption.
194       UINT32               dInSize,       // IN: data size
195       BYTE                *dIn            // IN: data buffer
196       )
197   {
198       BYTE           *pIv = NULL;
199       BYTE            tmp[16];
200       int             i;
201       BYTE           *pT;
202       AES_KEY         AesKey;
203       INT32           dSize;
204
205       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
206
207       if(dInSize == 0)
208           return CRYPT_SUCCESS;
209
210       pAssert(dInSize <= INT32_MAX);
211       dSize = (INT32)dInSize;
212
213       // Create AES encryption key schedule
214       if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
215           FAIL(FATAL_ERROR_INTERNAL);
216
217       for(; dSize > 0; dSize -= 16)
218       {
219           // Encrypt the IV into the temp buffer
220           AES_encrypt(iv, tmp, &AesKey);
221           pT = tmp;
222           pIv = iv;
223           for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
224               // Copy the current cipher text to IV, XOR
225               // with the temp buffer and put into the output
226               *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
227       }
228       // If the inner loop (i loop) was smaller than 16, then dSize
229       // would have been smaller than 16 and it is now negative
230       // If it is negative, then it indicates how may fill bytes

      Family "2.0"                                 TCG Published                                      Page 403
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

231       // are needed to pad out the IV for the next round.
232       for(; dSize < 0; dSize++)
233           *pIv++ = 0;
234
235       return CRYPT_SUCCESS;
236   }


      B.11.4.5. _cpri__AESEncryptCTR()

      This function performs AES encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
      dOut. The input iv buffer is assumed to have a size equal to the AES block size (16 bytes). The iv will be
      incremented by the number of blocks (full and partial) that were encrypted.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

237   LIB_EXPORT CRYPT_RESULT
238   _cpri__AESEncryptCTR(
239       BYTE                *dOut,          // OUT: the encrypted data
240       UINT32               keySizeInBits, // IN: key size in bit
241       BYTE                *key,           // IN: key buffer. The size of this buffer in
242                                           //     bytes is (keySizeInBits + 7) / 8
243       BYTE                *iv,            // IN/OUT: IV for decryption.
244       UINT32               dInSize,       // IN: data size
245       BYTE                *dIn            // IN: data buffer
246       )
247   {
248       BYTE            tmp[16];
249       BYTE           *pT;
250       AES_KEY         AesKey;
251       int             i;
252       INT32           dSize;
253
254       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
255
256       if(dInSize == 0)
257           return CRYPT_SUCCESS;
258
259       pAssert(dInSize <= INT32_MAX);
260       dSize = (INT32)dInSize;
261
262       // Create AES encryption schedule
263       if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
264           FAIL(FATAL_ERROR_INTERNAL);
265
266       for(; dSize > 0; dSize -= 16)
267       {
268           // Encrypt the current value of the IV(counter)
269           AES_encrypt(iv, (BYTE *)tmp, &AesKey);
270
271            //increment the counter (counter is big-endian so start at end)
272            for(i = 15; i >= 0; i--)
273                if((iv[i] += 1) != 0)
274                    break;
275
276            // XOR the encrypted counter value with input and put into output
277            pT = tmp;
278            for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
279                *dOut++ = *dIn++ ^ *pT++;
280       }
281       return CRYPT_SUCCESS;
282   }


      Page 404                                       TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

      B.11.4.6. _cpri__AESDecryptCTR()

      Counter mode decryption uses the same algorithm as encryption. The _cpri__AESDecryptCTR() function
      is implemented as a macro call to _cpri__AESEncryptCTR(). (skip)

283   //% #define _cpri__AESDecryptCTR(dOut, keySize, key, iv, dInSize, dIn) \
284   //%         _cpri__AESEncryptCTR(                           \
285   //%                               ((BYTE *)dOut),           \
286   //%                               ((UINT32)keySize),        \
287   //%                               ((BYTE *)key),            \
288   //%                               ((BYTE *)iv),             \
289   //%                               ((UINT32)dInSize),        \
290   //%                               ((BYTE *)dIn)             \
291   //%                             )
292   //%
293   // The //% is used by the prototype extraction program to cause it to include the
294   // line in the prototype file after removing the //%. Need an extra line with

      nothing on it so that a blank line will separate this macro from the next definition.

      B.11.4.7. _cpri__AESEncryptECB()

      AES encryption in ECB mode. The data buffer is modified to contain the cipher text.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

295   LIB_EXPORT CRYPT_RESULT
296   _cpri__AESEncryptECB(
297        BYTE                *dOut,          // OUT: encrypted data
298        UINT32               keySizeInBits, // IN: key size in bit
299        BYTE                *key,           // IN: key buffer. The size of this buffer in
300                                            //     bytes is (keySizeInBits + 7) / 8
301        UINT32               dInSize,       // IN: data size
302        BYTE                *dIn            // IN: clear text buffer
303        )
304   {
305        AES_KEY          AesKey;
306        INT32            dSize;
307
308        pAssert(dOut != NULL && key != NULL && dIn != NULL);
309
310        if(dInSize == 0)
311            return CRYPT_SUCCESS;
312
313        pAssert(dInSize <= INT32_MAX);
314        dSize = (INT32)dInSize;
315
316        // For ECB, the data size must be an even multiple of the
317        // cipher block size
318        if((dSize % 16) != 0)
319            return CRYPT_PARAMETER;
320        // Create AES encrypting key schedule
321        if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
322            FAIL(FATAL_ERROR_INTERNAL);
323
324        for(; dSize > 0; dSize -= 16)
325        {
326            AES_encrypt(dIn, dOut, &AesKey);
327            dIn = &dIn[16];
328            dOut = &dOut[16];
329        }

      Family "2.0"                                   TCG Published                                       Page 405
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

330       return CRYPT_SUCCESS;
331   }


      B.11.4.8. _cpri__AESDecryptECB()

      This function performs AES decryption using ECB (not recommended). The cipher text dIn is decrypted
      into dOut.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

332   LIB_EXPORT CRYPT_RESULT
333   _cpri__AESDecryptECB(
334       BYTE                *dOut,          // OUT: the clear text data
335       UINT32               keySizeInBits, // IN: key size in bit
336       BYTE                *key,           // IN: key buffer. The size of this buffer in
337                                           //     bytes is (keySizeInBits + 7) / 8
338       UINT32               dInSize,       // IN: data size
339       BYTE                *dIn            // IN: cipher text buffer
340       )
341   {
342       AES_KEY         AesKey;
343       INT32           dSize;
344
345       pAssert(dOut != NULL && key != NULL && dIn != NULL);
346
347       if(dInSize == 0)
348           return CRYPT_SUCCESS;
349
350       pAssert(dInSize <= INT32_MAX);
351       dSize = (INT32)dInSize;
352
353       // For ECB, the data size must be an even multiple of the
354       // cipher block size
355       if((dSize % 16) != 0)
356           return CRYPT_PARAMETER;
357
358       // Create AES decryption key schedule
359       if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
360           FAIL(FATAL_ERROR_INTERNAL);
361
362       for(; dSize > 0; dSize -= 16)
363       {
364           AES_decrypt(dIn, dOut, &AesKey);
365           dIn = &dIn[16];
366           dOut = &dOut[16];
367       }
368       return CRYPT_SUCCESS;
369   }


      B.11.4.9. _cpri__AESEncryptOFB()

      This function performs AES encryption/decryption in OFB chain mode. The dIn buffer is modified to
      contain the encrypted/decrypted text.
      The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
      will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.




      Page 406                                       TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                         Trusted Platform Module Library


      Return Value                  Meaning

      CRYPT_SUCCESS                 no non-fatal errors

370   LIB_EXPORT CRYPT_RESULT
371   _cpri__AESEncryptOFB(
372       BYTE               *dOut,          // OUT: the encrypted/decrypted data
373       UINT32              keySizeInBits, // IN: key size in bit
374       BYTE               *key,           // IN: key buffer. The size of this buffer in
375                                          //     bytes is (keySizeInBits + 7) / 8
376       BYTE               *iv,            // IN/OUT: IV for decryption. The size of this
377                                          //     buffer is 16 byte
378       UINT32              dInSize,       // IN: data size
379       BYTE               *dIn            // IN: data buffer
380       )
381   {
382       BYTE           *pIv;
383       AES_KEY         AesKey;
384       INT32           dSize;
385       int             i;
386
387       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
388
389       if(dInSize == 0)
390           return CRYPT_SUCCESS;
391
392       pAssert(dInSize <= INT32_MAX);
393       dSize = (INT32)dInSize;
394
395       // Create AES key schedule
396       if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
397           FAIL(FATAL_ERROR_INTERNAL);
398
399       // This is written so that dIn and dOut may be the same
400
401       for(; dSize > 0; dSize -= 16)
402       {
403           // Encrypt the current value of the "IV"
404           AES_encrypt(iv, iv, &AesKey);
405
406            // XOR the encrypted IV into dIn to create the cipher text (dOut)
407            pIv = iv;
408            for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
409                *dOut++ = (*pIv++ ^ *dIn++);
410       }
411       return CRYPT_SUCCESS;
412   }


      B.11.4.10. _cpri__AESDecryptOFB()

      OFB encryption and decryption use the same algorithms for both. The _cpri__AESDecryptOFB() function
      is implemented as a macro call to _cpri__AESEncrytOFB(). (skip)

413   //%#define _cpri__AESDecryptOFB(dOut,keySizeInBits, key, iv, dInSize, dIn) \
414   //%        _cpri__AESEncryptOFB (                               \
415   //%                               ((BYTE *)dOut),               \
416   //%                               ((UINT32)keySizeInBits),      \
417   //%                               ((BYTE *)key),                \
418   //%                               ((BYTE *)iv),                 \
419   //%                               ((UINT32)dInSize),            \
420   //%                               ((BYTE *)dIn)                 \
421   //%                             )
422   //%


      Family "2.0"                               TCG Published                                 Page 407
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                      October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

423   #ifdef    TPM_ALG_SM4          //%


      B.11.5. SM4 Encryption

      B.11.5.1. _cpri__SM4EncryptCBC()

      This function performs SM4 encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
      The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
      be a multiple of the block size.

      Return Value                      Meaning

      CRYPT_SUCCESS                     if success
      CRYPT_PARAMETER                   dInSize is not a multiple of the block size

424   LIB_EXPORT CRYPT_RESULT
425   _cpri__SM4EncryptCBC(
426        BYTE                *dOut,          // OUT:
427        UINT32               keySizeInBits, // IN: key size in bit
428        BYTE                *key,           // IN: key buffer. The size of this buffer in
429                                            //      bytes is (keySizeInBits + 7) / 8
430        BYTE                *iv,            // IN/OUT: IV for decryption.
431        UINT32               dInSize,       // IN: data size (is required to be a multiple
432                                            //      of 16 bytes)
433        BYTE                *dIn            // IN: data buffer
434        )
435   {
436        SM4_KEY         Sm4Key;
437        BYTE           *pIv;
438        INT32           dSize;              // Need a signed version
439        int             i;
440
441        pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
442
443        if(dInSize == 0)
444            return CRYPT_SUCCESS;
445
446        pAssert(dInSize <= INT32_MAX);
447        dSize = (INT32)dInSize;
448
449        // For CBC, the data size must be an even multiple of the
450        // cipher block size
451        if((dSize % 16) != 0)
452            return CRYPT_PARAMETER;
453
454        // Create SM4 encrypt key schedule
455        if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
456            FAIL(FATAL_ERROR_INTERNAL);
457
458        // XOR the data block into the IV, encrypt the IV into the IV
459        // and then copy the IV to the output
460        for(; dSize > 0; dSize -= 16)
461        {
462            pIv = iv;
463            for(i = 16; i > 0; i--)
464                *pIv++ ^= *dIn++;
465            SM4_encrypt(iv, iv, &Sm4Key);
466            pIv = iv;
467            for(i = 16; i > 0; i--)
468                *dOut++ = *pIv++;
469        }
470        return CRYPT_SUCCESS;

      Page 408                                        TCG Published                                  Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library

471   }


      B.11.5.2. _cpri__SM4DecryptCBC()

      This function performs SM4 decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
      The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
      be a multiple of the block size.

      Return Value                     Meaning

      CRYPT_SUCCESS                    if success
      CRYPT_PARAMETER                  dInSize is not a multiple of the block size

472   LIB_EXPORT CRYPT_RESULT
473   _cpri__SM4DecryptCBC(
474        BYTE                *dOut,          // OUT: the decrypted data
475        UINT32               keySizeInBits, // IN: key size in bit
476        BYTE                *key,           // IN: key buffer. The size of this buffer in
477                                            //     bytes is (keySizeInBits + 7) / 8
478        BYTE                *iv,            // IN/OUT: IV for decryption. The size of this
479                                            //     buffer is 16 byte
480        UINT32               dInSize,       // IN: data size
481        BYTE                *dIn            // IN: data buffer
482        )
483   {
484        SM4_KEY         Sm4Key;
485        BYTE           *pIv;
486        int             i;
487        BYTE            tmp[16];
488        BYTE           *pT = NULL;
489        INT32           dSize;
490
491        pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
492
493        if(dInSize == 0)
494            return CRYPT_SUCCESS;
495
496        pAssert(dInSize <= INT32_MAX);
497        dSize = (INT32)dInSize;
498
499        // For CBC, the data size must be an even multiple of the
500        // cipher block size
501        if((dSize % 16) != 0)
502            return CRYPT_PARAMETER;
503
504        // Create SM4 key schedule
505        if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
506            FAIL(FATAL_ERROR_INTERNAL);
507
508        // Copy the input data to a temp buffer, decrypt the buffer into the output;
509        // XOR in the IV, and copy the temp buffer to the IV and repeat.
510        for(; dSize > 0; dSize -= 16)
511        {
512            pT = tmp;
513            for(i = 16; i> 0; i--)
514                *pT++ = *dIn++;
515            SM4_decrypt(tmp, dOut, &Sm4Key);
516            pIv = iv;
517            pT = tmp;
518            for(i = 16; i> 0; i--)
519            {
520                *dOut++ ^= *pIv;


      Family "2.0"                                  TCG Published                                         Page 409
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

521                  *pIv++ = *pT++;
522            }
523       }
524       return CRYPT_SUCCESS;
525   }


      B.11.5.3. _cpri__SM4EncryptCFB()

      This function performs SM4 encryption in CFB chain mode. The dOut buffer receives the values
      encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
      be modified to contain the last encrypted block.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

526   LIB_EXPORT CRYPT_RESULT
527   _cpri__SM4EncryptCFB(
528       BYTE                *dOut,          // OUT: the encrypted
529       UINT32               keySizeInBits, // IN: key size in bit
530       BYTE                *key,           // IN: key buffer. The size of this buffer in
531                                           //     bytes is (keySizeInBits + 7) / 8
532       BYTE                *iv,            // IN/OUT: IV for decryption.
533       UINT32               dInSize,       // IN: data size
534       BYTE                *dIn            // IN: data buffer
535       )
536   {
537       BYTE           *pIv;
538       SM4_KEY         Sm4Key;
539       INT32           dSize;               // Need a signed version of dInSize
540       int             i;
541
542       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
543
544       if(dInSize == 0)
545           return CRYPT_SUCCESS;
546
547       pAssert(dInSize <= INT32_MAX);
548       dSize = (INT32)dInSize;
549
550       // Create SM4 encryption key schedule
551       if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
552           FAIL(FATAL_ERROR_INTERNAL);
553
554       // Encrypt the IV into the IV, XOR in the data, and copy to output
555       for(; dSize > 0; dSize -= 16)
556       {
557           // Encrypt the current value of the IV
558           SM4_encrypt(iv, iv, &Sm4Key);
559           pIv = iv;
560           for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
561               // XOR the data into the IV to create the cipher text
562               // and put into the output
563               *dOut++ = *pIv++ ^= *dIn++;
564       }
565       return CRYPT_SUCCESS;
566   }


      B.11.5.4. _cpri__SM4DecryptCFB()

      This function performs SM4 decrypt in CFB chain mode. The dOut buffer receives the values decrypted
      from dIn.

      Page 410                                       TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library


      The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
      contain the last decoded block, padded with zeros

      Return Value                    Meaning

      CRYPT_SUCCESS                   no non-fatal errors

567   LIB_EXPORT CRYPT_RESULT
568   _cpri__SM4DecryptCFB(
569       BYTE                *dOut,          // OUT: the decrypted data
570       UINT32               keySizeInBits, // IN: key size in bit
571       BYTE                *key,           // IN: key buffer. The size of this buffer in
572                                           //     bytes is (keySizeInBits + 7) / 8
573       BYTE                *iv,            // IN/OUT: IV for decryption.
574       UINT32               dInSize,       // IN: data size
575       BYTE                *dIn            // IN: data buffer
576       )
577   {
578       BYTE           *pIv;
579       BYTE            tmp[16];
580       int             i;
581       BYTE           *pT;
582       SM4_KEY         Sm4Key;
583       INT32           dSize;
584
585       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
586
587       if(dInSize == 0)
588           return CRYPT_SUCCESS;
589
590       pAssert(dInSize <= INT32_MAX);
591       dSize = (INT32)dInSize;
592
593       // Create SM4 encryption key schedule
594       if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
595           FAIL(FATAL_ERROR_INTERNAL);
596
597       for(; dSize > 0; dSize -= 16)
598       {
599           // Encrypt the IV into the temp buffer
600           SM4_encrypt(iv, tmp, &Sm4Key);
601           pT = tmp;
602           pIv = iv;
603           for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
604               // Copy the current cipher text to IV, XOR
605               // with the temp buffer and put into the output
606               *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
607       }
608       // If the inner loop (i loop) was smaller than 16, then dSize
609       // would have been smaller than 16 and it is now negative
610       // If it is negative, then it indicates how may fill bytes
611       // are needed to pad out the IV for the next round.
612       for(; dSize < 0; dSize++)
613           *iv++ = 0;
614
615       return CRYPT_SUCCESS;
616   }


      B.11.5.5. _cpri__SM4EncryptCTR()

      This function performs SM4 encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
      dOut. The input iv buffer is assumed to have a size equal to the SM4 block size (16 bytes). The iv will be
      incremented by the number of blocks (full and partial) that were encrypted.

      Family "2.0"                                 TCG Published                                      Page 411
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                         Part 4: Supporting Routines


      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

617   LIB_EXPORT CRYPT_RESULT
618   _cpri__SM4EncryptCTR(
619       BYTE               *dOut,          // OUT: the encrypted data
620       UINT32              keySizeInBits, // IN: key size in bit
621       BYTE               *key,           // IN: key buffer. The size of this buffer in
622                                          //     bytes is (keySizeInBits + 7) / 8
623       BYTE               *iv,            // IN/OUT: IV for decryption.
624       UINT32              dInSize,       // IN: data size
625       BYTE               *dIn            // IN: data buffer
626       )
627   {
628       BYTE            tmp[16];
629       BYTE           *pT;
630       SM4_KEY         Sm4Key;
631       int             i;
632       INT32           dSize;
633
634       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
635
636       if(dInSize == 0)
637           return CRYPT_SUCCESS;
638
639       pAssert(dInSize <= INT32_MAX);
640       dSize = (INT32)dInSize;
641
642       // Create SM4 encryption schedule
643       if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
644           FAIL(FATAL_ERROR_INTERNAL);
645
646       for(; dSize > 0; dSize--)
647       {
648           // Encrypt the current value of the IV(counter)
649           SM4_encrypt(iv, (BYTE *)tmp, &Sm4Key);
650
651            //increment the counter
652            for(i = 0; i < 16; i++)
653                if((iv[i] += 1) != 0)
654                    break;
655
656            // XOR the encrypted counter value with input and put into output
657            pT = tmp;
658            for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
659                *dOut++ = *dIn++ ^ *pT++;
660       }
661       return CRYPT_SUCCESS;
662   }


      B.11.5.6. _cpri__SM4DecryptCTR()

      Counter mode decryption uses the same algorithm as encryption. The _cpri__SM4DecryptCTR() function
      is implemented as a macro call to _cpri__SM4EncryptCTR(). (skip)

663   //% #define _cpri__SM4DecryptCTR(dOut, keySize, key, iv, dInSize, dIn) \
664   //%         _cpri__SM4EncryptCTR(                           \
665   //%                               ((BYTE *)dOut),           \
666   //%                               ((UINT32)keySize),        \
667   //%                               ((BYTE *)key),            \
668   //%                               ((BYTE *)iv),             \
669   //%                               ((UINT32)dInSize),        \


      Page 412                                       TCG Published                          Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

670   //%                               ((BYTE *)dIn)             \
671   //%                             )
672   //%
673   // The //% is used by the prototype extraction program to cause it to include the
674   // line in the prototype file after removing the //%. Need an extra line with

      nothing on it so that a blank line will separate this macro from the next definition.

      B.11.5.7. _cpri__SM4EncryptECB()

      SM4 encryption in ECB mode. The data buffer is modified to contain the cipher text.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

675   LIB_EXPORT CRYPT_RESULT
676   _cpri__SM4EncryptECB(
677        BYTE                *dOut,          // OUT: encrypted data
678        UINT32               keySizeInBits, // IN: key size in bit
679        BYTE                *key,           // IN: key buffer. The size of this buffer in
680                                            //     bytes is (keySizeInBits + 7) / 8
681        UINT32               dInSize,       // IN: data size
682        BYTE                *dIn            // IN: clear text buffer
683        )
684   {
685        SM4_KEY          Sm4Key;
686        INT32            dSize;
687
688        pAssert(dOut != NULL && key != NULL && dIn != NULL);
689
690        if(dInSize == 0)
691            return CRYPT_SUCCESS;
692
693        pAssert(dInSize <= INT32_MAX);
694        dSize = (INT32)dInSize;
695
696        // For ECB, the data size must be an even multiple of the
697        // cipher block size
698        if((dSize % 16) != 0)
699            return CRYPT_PARAMETER;
700        // Create SM4 encrypting key schedule
701        if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
702            FAIL(FATAL_ERROR_INTERNAL);
703
704        for(; dSize > 0; dSize -= 16)
705        {
706            SM4_encrypt(dIn, dOut, &Sm4Key);
707            dIn = &dIn[16];
708            dOut = &dOut[16];
709        }
710        return CRYPT_SUCCESS;
711   }


      B.11.5.8. _cpri__SM4DecryptECB()

      This function performs SM4 decryption using ECB (not recommended). The cipher text dIn is decrypted
      into dOut.




      Family "2.0"                                   TCG Published                                       Page 413
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines


      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

712   LIB_EXPORT CRYPT_RESULT
713   _cpri__SM4DecryptECB(
714       BYTE                *dOut,          // OUT: the clear text data
715       UINT32               keySizeInBits, // IN: key size in bit
716       BYTE                *key,           // IN: key buffer. The size of this buffer in
717                                           //     bytes is (keySizeInBits + 7) / 8
718       UINT32               dInSize,       // IN: data size
719       BYTE                *dIn            // IN: cipher text buffer
720       )
721   {
722       SM4_KEY         Sm4Key;
723       INT32           dSize;
724
725       pAssert(dOut != NULL && key != NULL && dIn != NULL);
726
727       if(dInSize == 0)
728           return CRYPT_SUCCESS;
729
730       pAssert(dInSize <= INT32_MAX);
731       dSize = (INT32)dInSize;
732
733       // For ECB, the data size must be an even multiple of the
734       // cipher block size
735       if((dSize % 16) != 0)
736           return CRYPT_PARAMETER;
737
738       // Create SM4 decryption key schedule
739       if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
740           FAIL(FATAL_ERROR_INTERNAL);
741
742       for(; dSize > 0; dSize -= 16)
743       {
744           SM4_decrypt(dIn, dOut, &Sm4Key);
745           dIn = &dIn[16];
746           dOut = &dOut[16];
747       }
748       return CRYPT_SUCCESS;
749   }


      B.11.5.9. _cpri__SM4EncryptOFB()

      This function performs SM4 encryption/decryption in OFB chain mode. The dIn buffer is modified to
      contain the encrypted/decrypted text.
      The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
      will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.

      Return Value                      Meaning

      CRYPT_SUCCESS                     no non-fatal errors

750   LIB_EXPORT CRYPT_RESULT
751   _cpri__SM4EncryptOFB(
752       BYTE                *dOut,          // OUT: the encrypted/decrypted data
753       UINT32               keySizeInBits, // IN: key size in bit
754       BYTE                *key,           // IN: key buffer. The size of this buffer in
755                                           //     bytes is (keySizeInBits + 7) / 8
756       BYTE                *iv,            // IN/OUT: IV for decryption. The size of this
757                                           //     buffer is 16 byte

      Page 414                                       TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                         Trusted Platform Module Library

758       UINT32              dInSize,         // IN: data size
759       BYTE               *dIn              // IN: data buffer
760       )
761   {
762       BYTE           *pIv;
763       SM4_KEY         Sm4Key;
764       INT32           dSize;
765       int             i;
766
767       pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
768
769       if(dInSize == 0)
770           return CRYPT_SUCCESS;
771
772       pAssert(dInSize <= INT32_MAX);
773       dSize = (INT32)dInSize;
774
775       // Create SM4 key schedule
776       if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
777           FAIL(FATAL_ERROR_INTERNAL);
778
779       // This is written so that dIn and dOut may be the same
780
781       for(; dSize > 0; dSize -= 16)
782       {
783           // Encrypt the current value of the "IV"
784           SM4_encrypt(iv, iv, &Sm4Key);
785
786            // XOR the encrypted IV into dIn to create the cipher text (dOut)
787            pIv = iv;
788            for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
789                *dOut++ = (*pIv++ ^ *dIn++);
790       }
791       return CRYPT_SUCCESS;
792   }


      B.11.5.10. _cpri__SM4DecryptOFB()

      OFB encryption and decryption use the same algorithms for both. The _cpri__SM4DecryptOFB() function
      is implemented as a macro call to _cpri__SM4EncrytOFB(). (skip)

793   //%#define _cpri__SM4DecryptOFB(dOut,keySizeInBits, key, iv, dInSize, dIn) \
794   //%        _cpri__SM4EncryptOFB (                               \
795   //%                               ((BYTE *)dOut),               \
796   //%                               ((UINT32)keySizeInBits),      \
797   //%                               ((BYTE *)key),                \
798   //%                               ((BYTE *)iv),                 \
799   //%                               ((UINT32)dInSize),            \
800   //%                               ((BYTE *)dIn)                 \
801   //%                             )
802   //%
803   #endif      //% TPM_ALG_SM4




      Family "2.0"                             TCG Published                                   Page 415
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                     October 30, 2014
     Trusted Platform Module Library                                                      Part 4: Supporting Routines


     B.12 RSA Files

     B.12.1. CpriRSA.c

     B.12.1.1. Introduction

     This file contains implementation of crypto primitives for RSA. This is a simulator of a crypto engine.
     Vendors may replace the implementation in this file with their own library functions.
     Integer format: the big integers passed in/out to the function interfaces in this library adopt the same
     format used in TPM 2.0 specification: Integer values are considered to be an array of one or more bytes.
     The byte at offset zero within the array is the most significant byte of the integer. The interface uses
     TPM2B as a big number format for numeric values passed to/from CryptUtil().

     B.12.1.2. Includes

 1   #include "OsslCryptoEngine.h"
 2   #ifdef TPM_ALG_RSA


     B.12.1.3. Local Functions

     B.12.1.3.1. RsaPrivateExponent()

     This function computes the private exponent de = 1 mod (p-1)*(q-1) The inputs are the public modulus
     and one of the primes.
     The results are returned in the key->private structure. The size of that structure is expanded to hold the
     private exponent. If the computed value is smaller than the public modulus, the private exponent is de-
     normalized.

     Return Value                      Meaning

     CRYPT_SUCCESS                     private exponent computed
     CRYPT_PARAMETER                   prime is not half the size of the modulus, or the modulus is not evenly
                                       divisible by the prime, or no private exponent could be computed
                                       from the input parameters

 3   static CRYPT_RESULT
 4   RsaPrivateExponent(
 5       RSA_KEY             *key                  // IN: the key to augment with the private
 6                                                 //     exponent
 7       )
 8   {
 9       BN_CTX              *context;
10       BIGNUM              *bnD;
11       BIGNUM              *bnN;
12       BIGNUM              *bnP;
13       BIGNUM              *bnE;
14       BIGNUM              *bnPhi;
15       BIGNUM              *bnQ;
16       BIGNUM              *bnQr;
17       UINT32               fill;
18
19       CRYPT_RESULT         retVal = CRYPT_SUCCESS;                // Assume success
20
21       pAssert(key != NULL && key->privateKey != NULL && key->publicKey != NULL);
22
23       context = BN_CTX_new();

     Page 416                                       TCG Published                                          Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
     Part 4: Supporting Routines                                 Trusted Platform Module Library

24       if(context == NULL)
25           FAIL(FATAL_ERROR_ALLOCATION);
26       BN_CTX_start(context);
27       bnE = BN_CTX_get(context);
28       bnD = BN_CTX_get(context);
29       bnN = BN_CTX_get(context);
30       bnP = BN_CTX_get(context);
31       bnPhi = BN_CTX_get(context);
32       bnQ = BN_CTX_get(context);
33       bnQr = BN_CTX_get(context);
34
35       if(bnQr == NULL)
36           FAIL(FATAL_ERROR_ALLOCATION);
37
38       // Assume the size of the public key value is within range
39       pAssert(key->publicKey->size <= MAX_RSA_KEY_BYTES);
40
41       if(   BN_bin2bn(key->publicKey->buffer, key->publicKey->size, bnN) == NULL
42          || BN_bin2bn(key->privateKey->buffer, key->privateKey->size, bnP) == NULL)
43
44            FAIL(FATAL_ERROR_INTERNAL);
45
46       // If P size is not 1/2 of n size, then this is not a valid value for this
47       // implementation. This will also catch the case were P is input as zero.
48       // This generates a return rather than an assert because the key being loaded
49       // might be SW generated and wrong.
50       if(BN_num_bits(bnP) < BN_num_bits(bnN)/2)
51       {
52           retVal = CRYPT_PARAMETER;
53           goto Cleanup;
54       }
55       // Get q = n/p;
56       if (BN_div(bnQ, bnQr, bnN, bnP, context) != 1)
57           FAIL(FATAL_ERROR_INTERNAL);
58
59       // If there is a remainder, then this is not a valid n
60       if(BN_num_bytes(bnQr) != 0 || BN_num_bits(bnQ) != BN_num_bits(bnP))
61       {
62           retVal = CRYPT_PARAMETER;      // problem may be recoverable
63           goto Cleanup;
64       }
65       // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1
66       if(   BN_copy(bnPhi, bnN) == NULL
67          || !BN_sub(bnPhi, bnPhi, bnP)
68          || !BN_sub(bnPhi, bnPhi, bnQ)
69          || !BN_add_word(bnPhi, 1))
70           FAIL(FATAL_ERROR_INTERNAL);
71
72       // Compute the multiplicative inverse
73       BN_set_word(bnE, key->exponent);
74       if(BN_mod_inverse(bnD, bnE, bnPhi, context) == NULL)
75       {
76           // Going to assume that the error is caused by a bad
77           // set of parameters. Specifically, an exponent that is
78           // not compatible with the primes. In an implementation that
79           // has better visibility to the error codes, this might be
80           // refined so that failures in the library would return
81           // a more informative value. Should not assume here that
82           // the error codes will remain unchanged.
83
84            retVal = CRYPT_PARAMETER;
85            goto Cleanup;
86       }
87
88       fill = key->publicKey->size - BN_num_bytes(bnD);
89       BN_bn2bin(bnD, &key->privateKey->buffer[fill]);

     Family "2.0"                           TCG Published                             Page 417
     Level 00 Revision 01.16        Copyright © TCG 2006-2014                October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines

 90       memset(key->privateKey->buffer, 0, fill);
 91
 92       // Change the size of the private key so that it is known to contain
 93       // a private exponent rather than a prime.
 94       key->privateKey->size = key->publicKey->size;
 95
 96   Cleanup:
 97       BN_CTX_end(context);
 98       BN_CTX_free(context);
 99       return retVal;
100   }


      B.12.1.3.2. _cpri__TestKeyRSA()

      This function computes the private exponent de = 1 mod (p-1)*(q-1) The inputs are the public modulus
      and one of the primes or two primes.
      If both primes are provided, the public modulus is computed. If only one prime is provided, the second
      prime is computed. In either case, a private exponent is produced and placed in d.
      If no modular inverse exists, then CRYPT_PARAMETER is returned.

      Return Value                      Meaning

      CRYPT_SUCCESS                     private exponent (d) was generated
      CRYPT_PARAMETER                   one or more parameters are invalid

101   LIB_EXPORT CRYPT_RESULT
102   _cpri__TestKeyRSA(
103       TPM2B              *d,                    //   OUT: the address to receive the private
104                                                 //       exponent
105       UINT32              exponent,             //   IN: the public modulu
106       TPM2B              *publicKey,            //   IN/OUT: an input if only one prime is
107                                                 //       provided. an output if both primes are
108                                                 //       provided
109       TPM2B              *prime1,               //   IN: a first prime
110       TPM2B              *prime2                //   IN: an optional second prime
111       )
112   {
113       BN_CTX             *context;
114       BIGNUM             *bnD;
115       BIGNUM             *bnN;
116       BIGNUM             *bnP;
117       BIGNUM             *bnE;
118       BIGNUM             *bnPhi;
119       BIGNUM             *bnQ;
120       BIGNUM             *bnQr;
121       UINT32             fill;
122
123       CRYPT_RESULT       retVal = CRYPT_SUCCESS;               // Assume success
124
125       pAssert(publicKey != NULL && prime1 != NULL);
126       // Make sure that the sizes are within range
127       pAssert(   prime1->size <= MAX_RSA_KEY_BYTES/2
128               && publicKey->size <= MAX_RSA_KEY_BYTES);
129       pAssert( prime2 == NULL || prime2->size < MAX_RSA_KEY_BYTES/2);
130
131       if(publicKey->size/2 != prime1->size)
132           return CRYPT_PARAMETER;
133
134       context = BN_CTX_new();
135       if(context == NULL)
136           FAIL(FATAL_ERROR_ALLOCATION);
137       BN_CTX_start(context);

      Page 418                                      TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                      Trusted Platform Module Library

138       bnE = BN_CTX_get(context);       //   public exponent (e)
139       bnD = BN_CTX_get(context);       //   private exponent (d)
140       bnN = BN_CTX_get(context);       //   public modulus (n)
141       bnP = BN_CTX_get(context);       //   prime1 (p)
142       bnPhi = BN_CTX_get(context);     //   (p-1)(q-1)
143       bnQ = BN_CTX_get(context);       //   prime2 (q)
144       bnQr = BN_CTX_get(context);      //   n mod p
145
146       if(bnQr == NULL)
147           FAIL(FATAL_ERROR_ALLOCATION);
148
149       if(BN_bin2bn(prime1->buffer, prime1->size, bnP) == NULL)
150           FAIL(FATAL_ERROR_INTERNAL);
151
152       // If prime2 is provided, then compute n
153       if(prime2 != NULL)
154       {
155           // Two primes provided so use them to compute n
156           if(BN_bin2bn(prime2->buffer, prime2->size, bnQ) == NULL)
157               FAIL(FATAL_ERROR_INTERNAL);
158
159            // Make sure that the sizes of the primes are compatible
160            if(BN_num_bits(bnQ) != BN_num_bits(bnP))
161            {
162                retVal = CRYPT_PARAMETER;
163                goto Cleanup;
164            }
165            // Multiply the primes to get the public modulus
166
167            if(BN_mul(bnN, bnP, bnQ, context) != 1)
168                FAIL(FATAL_ERROR_INTERNAL);
169
170            // if the space provided for the public modulus is large enough,
171            // save the created value
172            if(BN_num_bits(bnN) != (publicKey->size * 8))
173            {
174                retVal = CRYPT_PARAMETER;
175                goto Cleanup;
176            }
177            BN_bn2bin(bnN, publicKey->buffer);
178       }
179       else
180       {
181           // One prime provided so find the second prime by division
182           BN_bin2bn(publicKey->buffer, publicKey->size, bnN);
183
184            // Get q = n/p;
185            if(BN_div(bnQ, bnQr, bnN, bnP, context) != 1)
186                FAIL(FATAL_ERROR_INTERNAL);
187
188            // If there is a remainder, then this is not a valid n
189            if(BN_num_bytes(bnQr) != 0 || BN_num_bits(bnQ) != BN_num_bits(bnP))
190            {
191                retVal = CRYPT_PARAMETER;      // problem may be recoverable
192                goto Cleanup;
193            }
194       }
195       // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1
196       BN_copy(bnPhi, bnN);
197       BN_sub(bnPhi, bnPhi, bnP);
198       BN_sub(bnPhi, bnPhi, bnQ);
199       BN_add_word(bnPhi, 1);
200       // Compute the multiplicative inverse
201       BN_set_word(bnE, exponent);
202       if(BN_mod_inverse(bnD, bnE, bnPhi, context) == NULL)
203       {

      Family "2.0"                         TCG Published                                    Page 419
      Level 00 Revision 01.16        Copyright © TCG 2006-2014                     October 30, 2014
      Trusted Platform Module Library                                                       Part 4: Supporting Routines

204            // Going to assume that the error is caused by a bad set of parameters.
205            // Specifically, an exponent that is not compatible with the primes.
206            // In an implementation that has better visibility to the error codes,
207            // this might be refined so that failures in the library would return
208            // a more informative value.
209            // Do not assume that the error codes will remain unchanged.
210            retVal = CRYPT_PARAMETER;
211            goto Cleanup;
212       }
213       // Return the private exponent.
214       // Make sure it is normalized to have the correct size.
215       d->size = publicKey->size;
216       fill = d->size - BN_num_bytes(bnD);
217       BN_bn2bin(bnD, &d->buffer[fill]);
218       memset(d->buffer, 0, fill);
219   Cleanup:
220       BN_CTX_end(context);
221       BN_CTX_free(context);
222       return retVal;
223   }


      B.12.1.3.3. RSAEP()

      This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a value
      (m) with the public exponent (e), modulo the public (n).

      Return Value                      Meaning

      CRYPT_SUCCESS                     encryption complete
      CRYPT_PARAMETER                   number to exponentiate is larger than the modulus

224   static CRYPT_RESULT
225   RSAEP (
226       UINT32              dInOutSize,           // OUT size of the encrypted block
227       BYTE               *dInOut,               // OUT: the encrypted data
228       RSA_KEY            *key                   // IN: the key to use
229       )
230   {
231       UINT32       e;
232       BYTE         exponent[4];
233       CRYPT_RESULT retVal;
234
235       e = key->exponent;
236       if(e == 0)
237           e = RSA_DEFAULT_PUBLIC_EXPONENT;
238       UINT32_TO_BYTE_ARRAY(e, exponent);
239
240       //!!! Can put check for test of RSA here
241
242       retVal = _math__ModExp(dInOutSize, dInOut, dInOutSize, dInOut, 4, exponent,
243                              key->publicKey->size, key->publicKey->buffer);
244
245       // Exponentiation result is stored in-place, thus no space shortage is possible.
246       pAssert(retVal != CRYPT_UNDERFLOW);
247
248       return retVal;
249   }


      B.12.1.3.4. RSADP()

      This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a value (c)
      with the private exponent (d), modulo the public modulus (n). The decryption is in place.

      Page 420                                       TCG Published                                        Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                       Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library


      This function also checks the size of the private key. If the size indicates that only a prime value is
      present, the key is converted to being a private exponent.

      Return Value                   Meaning

      CRYPT_SUCCESS                  decryption succeeded
      CRYPT_PARAMETER                the value to decrypt is larger than the modulus

250   static CRYPT_RESULT
251   RSADP (
252       UINT32              dInOutSize,        // IN/OUT: size of decrypted data
253       BYTE               *dInOut,            // IN/OUT: the decrypted data
254       RSA_KEY            *key                // IN: the key
255       )
256   {
257       CRYPT_RESULT retVal;
258
259       //!!! Can put check for RSA tested here
260
261       // Make sure that the pointers are provided and that the private key is present
262       // If the private key is present it is assumed to have been created by
263       // so is presumed good _cpri__PrivateExponent
264       pAssert(key != NULL && dInOut != NULL &&
265               key->publicKey->size == key->publicKey->size);
266
267       // make sure that the value to be decrypted is smaller than the modulus
268       // note: this check is redundant as is also performed by _math__ModExp()
269       // which is optimized for use in RSA operations
270       if(_math__uComp(key->publicKey->size, key->publicKey->buffer,
271                       dInOutSize, dInOut) <= 0)
272           return CRYPT_PARAMETER;
273
274       // _math__ModExp can return CRYPT_PARAMTER or CRYPT_UNDERFLOW but actual
275       // underflow is not possible because everything is in the same buffer.
276       retVal = _math__ModExp(dInOutSize, dInOut, dInOutSize, dInOut,
277                              key->privateKey->size, key->privateKey->buffer,
278                              key->publicKey->size, key->publicKey->buffer);
279
280       // Exponentiation result is stored in-place, thus no space shortage is possible.
281       pAssert(retVal != CRYPT_UNDERFLOW);
282
283       return retVal;
284   }


      B.12.1.3.5. OaepEncode()

      This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must
      equal the size of the modulus

      Return Value                   Meaning

      CRYPT_SUCCESS                  encode successful
      CRYPT_PARAMETER                hashAlg is not valid
      CRYPT_FAIL                     message size is too large

285   static CRYPT_RESULT
286   OaepEncode(
287       UINT32          paddedSize,       //   IN: pad value size
288       BYTE           *padded,           //   OUT: the pad data
289       TPM_ALG_ID      hashAlg,          //   IN: algorithm to use for padding
290       const char     *label,            //   IN: null-terminated string (may be NULL)

      Family "2.0"                                TCG Published                                         Page 421
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

291       UINT32       messageSize,   // IN: the message size
292       BYTE        *message        // IN: the message being padded
293   #ifdef TEST_RSA                 //
294       , BYTE          *testSeed   // IN: optional seed used for testing.
295   #endif // TEST_RSA              //
296   )
297   {
298       UINT32       padLen;
299       UINT32       dbSize;
300       UINT32       i;
301       BYTE         mySeed[MAX_DIGEST_SIZE];
302       BYTE        *seed = mySeed;
303       INT32        hLen = _cpri__GetDigestSize(hashAlg);
304       BYTE         mask[MAX_RSA_KEY_BYTES];
305       BYTE        *pp;
306       BYTE        *pm;
307       UINT32       lSize = 0;
308       CRYPT_RESULT retVal = CRYPT_SUCCESS;
309
310       pAssert(padded != NULL && message != NULL);
311
312       // A value of zero is not allowed because the KDF can't produce a result
313       // if the digest size is zero.
314       if(hLen <= 0)
315           return CRYPT_PARAMETER;
316
317       // If a label is provided, get the length of the string, including the
318       // terminator
319       if(label != NULL)
320           lSize = (UINT32)strlen(label) + 1;
321
322       // Basic size check
323       // messageSize <= k 2hLen 2
324       if(messageSize > paddedSize - 2 * hLen - 2)
325           return CRYPT_FAIL;
326
327       // Hash L even if it is null
328       // Offset into padded leaving room for masked seed and byte of zero
329       pp = &padded[hLen + 1];
330       retVal = _cpri__HashBlock(hashAlg, lSize, (BYTE *)label, hLen, pp);
331
332       // concatenate PS of k mLen 2hLen 2
333       padLen = paddedSize - messageSize - (2 * hLen) - 2;
334       memset(&pp[hLen], 0, padLen);
335       pp[hLen+padLen] = 0x01;
336       padLen += 1;
337       memcpy(&pp[hLen+padLen], message, messageSize);
338
339       // The total size of db = hLen + pad + mSize;
340       dbSize = hLen+padLen+messageSize;
341
342       // If testing, then use the provided seed. Otherwise, use values
343       // from the RNG
344   #ifdef TEST_RSA
345       if(testSeed != NULL)
346           seed = testSeed;
347       else
348   #endif // TEST_RSA
349           _cpri__GenerateRandom(hLen, mySeed);
350
351       // mask = MGF1 (seed, nSize hLen 1)
352       if((retVal = _cpri__MGF1(dbSize, mask, hashAlg, hLen, seed)) < 0)
353           return retVal; // Don't expect an error because hash size is not zero
354                          // was detected in the call to _cpri__HashBlock() above.
355
356       // Create the masked db

      Page 422                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                                     Trusted Platform Module Library

357        pm = mask;
358        for(i = dbSize; i > 0; i--)
359            *pp++ ^= *pm++;
360        pp = &padded[hLen + 1];
361
362        // Run the masked data through MGF1
363        if((retVal = _cpri__MGF1(hLen, &padded[1], hashAlg, dbSize, pp)) < 0)
364            return retVal; // Don't expect zero here as the only case for zero
365                           // was detected in the call to _cpri__HashBlock() above.
366
367        // Now XOR the seed to create masked seed
368        pp = &padded[1];
369        pm = seed;
370        for(i = hLen; i > 0; i--)
371            *pp++ ^= *pm++;
372
373        // Set the first byte to zero
374        *padded = 0x00;
375        return CRYPT_SUCCESS;
376   }


      B.12.1.3.6. OaepDecode()

      This function performs OAEP padding checking. The size of the buffer to receive the recovered data. If
      the padding is not valid, the dSize size is set to zero and the function returns CRYPT_NO_RESULTS.
      The dSize parameter is used as an input to indicate the size available in the buffer. If insufficient space is
      available, the size is not changed and the return code is CRYPT_FAIL.

      Return Value                     Meaning

      CRYPT_SUCCESS                    decode complete
      CRYPT_PARAMETER                  the value to decode was larger than the modulus
      CRYPT_FAIL                       the padding is wrong or the buffer to receive the results is too small

377   static CRYPT_RESULT
378   OaepDecode(
379        UINT32              *dataOutSize,        //   IN/OUT: the recovered data size
380        BYTE                *dataOut,            //   OUT: the recovered data
381        TPM_ALG_ID           hashAlg,            //   IN: algorithm to use for padding
382        const char          *label,              //   IN: null-terminated string (may be NULL)
383        UINT32               paddedSize,         //   IN: the size of the padded data
384        BYTE                *padded              //   IN: the padded data
385        )
386   {
387        UINT32          dSizeSave;
388        UINT32          i;
389        BYTE            seedMask[MAX_DIGEST_SIZE];
390        INT32           hLen = _cpri__GetDigestSize(hashAlg);
391
392        BYTE         mask[MAX_RSA_KEY_BYTES];
393        BYTE        *pp;
394        BYTE        *pm;
395        UINT32       lSize = 0;
396        CRYPT_RESULT retVal = CRYPT_SUCCESS;
397
398        // Unknown hash
399        pAssert(hLen > 0 && dataOutSize != NULL && dataOut != NULL && padded != NULL);
400
401        // If there is a label, get its size including the terminating 0x00
402        if(label != NULL)
403            lSize = (UINT32)strlen(label) + 1;
404

      Family "2.0"                                  TCG Published                                               Page 423
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                                October 30, 2014
      Trusted Platform Module Library                                      Part 4: Supporting Routines

405       // Set the return size to zero so that it doesn't have to be done on each
406       // failure
407       dSizeSave = *dataOutSize;
408       *dataOutSize = 0;
409
410       // Strange size (anything smaller can't be an OAEP padded block)
411       // Also check for no leading 0
412       if(paddedSize < (unsigned)((2 * hLen) + 2) || *padded != 0)
413           return CRYPT_FAIL;
414
415       // Use the hash size to determine what to put through MGF1 in order
416       // to recover the seedMask
417       if((retVal = _cpri__MGF1(hLen, seedMask, hashAlg,
418                                paddedSize-hLen-1, &padded[hLen+1])) < 0)
419           return retVal;
420
421       // Recover the seed into seedMask
422       pp = &padded[1];
423       pm = seedMask;
424       for(i = hLen; i > 0; i--)
425           *pm++ ^= *pp++;
426
427       // Use the seed to generate the data mask
428       if((retVal = _cpri__MGF1(paddedSize-hLen-1, mask,     hashAlg,
429                                hLen, seedMask)) < 0)
430           return retVal;
431
432       // Use the mask generated from seed to recover the padded data
433       pp = &padded[hLen+1];
434       pm = mask;
435       for(i = paddedSize-hLen-1; i > 0; i--)
436           *pm++ ^= *pp++;
437
438       // Make sure that the recovered data has the hash of the label
439       // Put trial value in the seed mask
440       if((retVal=_cpri__HashBlock(hashAlg, lSize,(BYTE *)label, hLen, seedMask)) < 0)
441           return retVal;
442
443       if(memcmp(seedMask, mask, hLen) != 0)
444           return CRYPT_FAIL;
445
446       // find the start of the data
447       pm = &mask[hLen];
448       for(i = paddedSize-(2*hLen)-1; i > 0; i--)
449       {
450           if(*pm++ != 0)
451               break;
452       }
453       if(i == 0)
454           return CRYPT_PARAMETER;
455
456       // pm should be pointing at the first part of the data
457       // and i is one greater than the number of bytes to move
458       i--;
459       if(i > dSizeSave)
460       {
461            // Restore dSize
462            *dataOutSize = dSizeSave;
463            return CRYPT_FAIL;
464       }
465       memcpy(dataOut, pm, i);
466       *dataOutSize = i;
467       return CRYPT_SUCCESS;
468   }



      Page 424                               TCG Published                               Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014           Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

      B.12.1.3.7. PKSC1v1_5Encode()

      This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1

      Return Value                  Meaning

      CRYPT_SUCCESS                 data encoded
      CRYPT_PARAMETER               message size is too large

469   static CRYPT_RESULT
470   RSAES_PKSC1v1_5Encode(
471       UINT32              paddedSize,        //   IN: pad value size
472       BYTE               *padded,            //   OUT: the pad data
473       UINT32              messageSize,       //   IN: the message size
474       BYTE               *message            //   IN: the message being padded
475       )
476   {
477       UINT32      ps = paddedSize - messageSize - 3;
478       if(messageSize > paddedSize - 11)
479           return CRYPT_PARAMETER;
480
481       // move the message to the end of the buffer
482       memcpy(&padded[paddedSize - messageSize], message, messageSize);
483
484       // Set the first byte to 0x00 and the second to 0x02
485       *padded = 0;
486       padded[1] = 2;
487
488       // Fill with random bytes
489       _cpri__GenerateRandom(ps, &padded[2]);
490
491       // Set the delimiter for the random field to 0
492       padded[2+ps] = 0;
493
494       // Now, the only messy part. Make sure that all the ps bytes are non-zero
495       // In this implementation, use the value of the current index
496       for(ps++; ps > 1; ps--)
497       {
498           if(padded[ps] == 0)
499               padded[ps] = 0x55;    // In the < 0.5% of the cases that the random
500                                     // value is 0, just pick a value to put into
501                                     // the spot.
502       }
503       return CRYPT_SUCCESS;
504   }


      B.12.1.3.8. RSAES_Decode()

      This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1

      Return Value                  Meaning

      CRYPT_SUCCESS                 decode successful
      CRYPT_FAIL                    decoding error or results would no fit into provided buffer

505   static CRYPT_RESULT
506   RSAES_Decode(
507       UINT32             *messageSize,       //   IN/OUT: recovered message size
508       BYTE               *message,           //   OUT: the recovered message
509       UINT32              codedSize,         //   IN: the encoded message size
510       BYTE               *coded              //   IN: the encoded message
511       )

      Family "2.0"                               TCG Published                                           Page 425
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                                October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

512   {
513       BOOL           fail = FALSE;
514       UINT32         ps;
515
516       fail = (codedSize < 11);
517       fail |= (coded[0] != 0x00) || (coded[1] != 0x02);
518       for(ps = 2; ps < codedSize; ps++)
519       {
520           if(coded[ps] == 0)
521               break;
522       }
523       ps++;
524
525       // Make sure that ps has not gone over the end and that there are at least 8
526       // bytes of pad data.
527       fail |= ((ps >= codedSize) || ((ps-2) < 8));
528       if((*messageSize < codedSize - ps) || fail)
529           return CRYPT_FAIL;
530
531       *messageSize = codedSize - ps;
532       memcpy(message, &coded[ps], codedSize - ps);
533       return CRYPT_SUCCESS;
534   }


      B.12.1.3.9. PssEncode()

      This function creates an encoded block of data that is the size of modulus. The function uses the
      maximum salt size that will fit in the encoded block.

      Return Value                      Meaning

      CRYPT_SUCCESS                     encode successful
      CRYPT_PARAMETER                   hashAlg is not a supported hash algorithm

535   static CRYPT_RESULT
536   PssEncode   (
537       UINT32        eOutSize,        // IN: size of the encode data buffer
538       BYTE         *eOut,            // OUT: encoded data buffer
539       TPM_ALG_ID    hashAlg,         // IN: hash algorithm to use for the encoding
540       UINT32        hashInSize,      // IN: size of digest to encode
541       BYTE         *hashIn           // IN: the digest
542   #ifdef TEST_RSA                    //
543       , BYTE          *saltIn        // IN: optional parameter for testing
544   #endif // TEST_RSA                 //
545   )
546   {
547       INT32                  hLen = _cpri__GetDigestSize(hashAlg);
548       BYTE                   salt[MAX_RSA_KEY_BYTES - 1];
549       UINT16                 saltSize;
550       BYTE                 *ps = salt;
551       CRYPT_RESULT           retVal;
552       UINT16                 mLen;
553       CPRI_HASH_STATE        hashState;
554
555       // These are fatal errors indicating bad TPM firmware
556       pAssert(eOut != NULL && hLen > 0 && hashIn != NULL );
557
558       // Get the size of the mask
559       mLen = (UINT16)(eOutSize - hLen - 1);
560
561       // Maximum possible salt size is mask length - 1
562       saltSize = mLen - 1;
563

      Page 426                                       TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                           Trusted Platform Module Library

564       // Use the maximum salt size allowed by FIPS 186-4
565       if(saltSize > hLen)
566           saltSize = (UINT16)hLen;
567
568   //using eOut for scratch space
569       // Set the first 8 bytes to zero
570       memset(eOut, 0, 8);
571
572       // Get set the salt
573   #ifdef TEST_RSA
574       if(saltIn != NULL)
575       {
576           saltSize = hLen;
577           memcpy(salt, saltIn, hLen);
578       }
579       else
580   #endif // TEST_RSA
581           _cpri__GenerateRandom(saltSize, salt);
582
583       // Create the hash of the pad || input hash || salt
584       _cpri__StartHash(hashAlg, FALSE, &hashState);
585       _cpri__UpdateHash(&hashState, 8, eOut);
586       _cpri__UpdateHash(&hashState, hashInSize, hashIn);
587       _cpri__UpdateHash(&hashState, saltSize, salt);
588       _cpri__CompleteHash(&hashState, hLen, &eOut[eOutSize - hLen - 1]);
589
590       // Create a mask
591       if((retVal = _cpri__MGF1(mLen, eOut, hashAlg, hLen, &eOut[mLen])) < 0)
592       {
593           // Currently _cpri__MGF1 is not expected to return a CRYPT_RESULT error.
594           pAssert(0);
595       }
596       // Since this implementation uses key sizes that are all even multiples of
597       // 8, just need to make sure that the most significant bit is CLEAR
598       eOut[0] &= 0x7f;
599
600       // Before we mess up the eOut value, set the last byte to 0xbc
601       eOut[eOutSize - 1] = 0xbc;
602
603       // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed
604       eOut = &eOut[mLen - saltSize - 1];
605       *eOut++ ^= 0x01;
606
607       // XOR the salt data into the buffer
608       for(; saltSize > 0; saltSize--)
609           *eOut++ ^= *ps++;
610
611       // and we are done
612       return CRYPT_SUCCESS;
613   }


      B.12.1.3.10. PssDecode()

      This function checks that the PSS encoded block was built from the provided digest. If the check is
      successful, CRYPT_SUCCESS is returned. Any other value indicates an error.
      This implementation of PSS decoding is intended for the reference TPM implementation and is not at all
      generalized. It is used to check signatures over hashes and assumptions are made about the sizes of
      values. Those assumptions are enforce by this implementation. This implementation does allow for a
      variable size salt value to have been used by the creator of the signature.




      Family "2.0"                              TCG Published                                     Page 427
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines


      Return Value                      Meaning

      CRYPT_SUCCESS                     decode successful
      CRYPT_SCHEME                      hashAlg is not a supported hash algorithm
      CRYPT_FAIL                        decode operation failed

614   static CRYPT_RESULT
615   PssDecode(
616       TPM_ALG_ID          hashAlg,              //   IN:   hash algorithm to use for the encoding
617       UINT32              dInSize,              //   IN:   size of the digest to compare
618       BYTE               *dIn,                  //   In:   the digest to compare
619       UINT32              eInSize,              //   IN:   size of the encoded data
620       BYTE               *eIn,                  //   IN:   the encoded data
621       UINT32              saltSize              //   IN:   the expected size of the salt
622       )
623   {
624       INT32            hLen = _cpri__GetDigestSize(hashAlg);
625       BYTE             mask[MAX_RSA_KEY_BYTES];
626       BYTE            *pm = mask;
627       BYTE             pad[8] = {0};
628       UINT32           i;
629       UINT32           mLen;
630       BOOL             fail = FALSE;
631       CRYPT_RESULT     retVal;
632       CPRI_HASH_STATE hashState;
633
634       // These errors are indicative of failures due to programmer error
635       pAssert(dIn != NULL && eIn != NULL);
636
637       // check the hash scheme
638       if(hLen == 0)
639           return CRYPT_SCHEME;
640
641       // most significant bit must be zero
642       fail = ((eIn[0] & 0x80) != 0);
643
644       // last byte must be 0xbc
645       fail |= (eIn[eInSize - 1] != 0xbc);
646
647       // Use the hLen bytes at the end of the buffer to generate a mask
648       // Doesn't start at the end which is a flag byte
649       mLen = eInSize - hLen - 1;
650       if((retVal = _cpri__MGF1(mLen, mask, hashAlg, hLen, &eIn[mLen])) < 0)
651           return retVal;
652       if(retVal == 0)
653           return CRYPT_FAIL;
654
655       // Clear the MSO of the mask to make it consistent with the encoding.
656       mask[0] &= 0x7F;
657
658       // XOR the data into the mask to recover the salt. This sequence
659       // advances eIn so that it will end up pointing to the seed data
660       // which is the hash of the signature data
661       for(i = mLen; i > 0; i--)
662           *pm++ ^= *eIn++;
663
664       // Find the first byte of 0x01 after a string of all 0x00
665       for(pm = mask, i = mLen; i > 0; i--)
666       {
667           if(*pm == 0x01)
668                break;
669           else
670                fail |= (*pm++ != 0);
671       }

      Page 428                                       TCG Published                                Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                               Trusted Platform Module Library

672       fail |= (i == 0);
673
674       // if we have failed, will continue using the entire mask as the salt value so
675       // that the timing attacks will not disclose anything (I don't think that this
676       // is a problem for TPM applications but, usually, we don't fail so this
677       // doesn't cost anything).
678       if(fail)
679       {
680           i = mLen;
681           pm = mask;
682       }
683       else
684       {
685           pm++;
686           i--;
687       }
688       // If the salt size was provided, then the recovered size must match
689       fail |= (saltSize != 0 && i != saltSize);
690
691       // i contains the salt size and pm points to the salt. Going to use the input
692       // hash and the seed to recreate the hash in the lower portion of eIn.
693       _cpri__StartHash(hashAlg, FALSE, &hashState);
694
695       // add the pad of 8 zeros
696       _cpri__UpdateHash(&hashState, 8, pad);
697
698       // add the provided digest value
699       _cpri__UpdateHash(&hashState, dInSize, dIn);
700
701       // and the salt
702       _cpri__UpdateHash(&hashState, i, pm);
703
704       // get the result
705       retVal = _cpri__CompleteHash(&hashState, MAX_DIGEST_SIZE, mask);
706
707       // retVal will be the size of the digest or zero. If not equal to the indicated
708       // digest size, then the signature doesn't match
709       fail |= (retVal != hLen);
710       fail |= (memcmp(mask, eIn, hLen) != 0);
711       if(fail)
712           return CRYPT_FAIL;
713       else
714           return CRYPT_SUCCESS;
715   }


      B.12.1.3.11. PKSC1v1_5SignEncode()

      Encode a message using PKCS1v1().5 method.

      Return Value                  Meaning

      CRYPT_SUCCESS                 encode complete
      CRYPT_SCHEME                  hashAlg is not a supported hash algorithm
      CRYPT_PARAMETER               eOutSize is not large enough or hInSize does not match the digest
                                    size of hashAlg

716   static CRYPT_RESULT
717   RSASSA_Encode(
718       UINT32              eOutSize,         //   IN: the size of the resulting block
719       BYTE               *eOut,             //   OUT: the encoded block
720       TPM_ALG_ID          hashAlg,          //   IN: hash algorithm for PKSC1v1_5
721       UINT32              hInSize,          //   IN: size of hash to be signed
722       BYTE               *hIn               //   IN: hash buffer

      Family "2.0"                              TCG Published                                           Page 429
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines

723       )
724   {
725       BYTE               *der;
726       INT32               derSize = _cpri__GetHashDER(hashAlg, &der);
727       INT32               fillSize;
728
729       pAssert(eOut != NULL && hIn != NULL);
730
731       // Can't use this scheme if the algorithm doesn't have a DER string defined.
732       if(derSize == 0 )
733           return CRYPT_SCHEME;
734
735       // If the digest size of 'hashAl' doesn't match the input digest size, then
736       // the DER will misidentify the digest so return an error
737       if((unsigned)_cpri__GetDigestSize(hashAlg) != hInSize)
738           return CRYPT_PARAMETER;
739
740       fillSize = eOutSize - derSize - hInSize - 3;
741
742       // Make sure that this combination will fit in the provided space
743       if(fillSize < 8)
744           return CRYPT_PARAMETER;
745       // Start filling
746       *eOut++ = 0; // initial byte of zero
747       *eOut++ = 1; // byte of 0x01
748       for(; fillSize > 0; fillSize--)
749           *eOut++ = 0xff; // bunch of 0xff
750       *eOut++ = 0; // another 0
751       for(; derSize > 0; derSize--)
752           *eOut++ = *der++;   // copy the DER
753       for(; hInSize > 0; hInSize--)
754           *eOut++ = *hIn++;   // copy the hash
755       return CRYPT_SUCCESS;
756   }


      B.12.1.3.12. RSASSA_Decode()

      This function performs the RSASSA decoding of a signature.

      Return Value                      Meaning

      CRYPT_SUCCESS                     decode successful
      CRYPT_FAIL                        decode unsuccessful
      CRYPT_SCHEME                      haslAlg is not supported

757   static CRYPT_RESULT
758   RSASSA_Decode(
759       TPM_ALG_ID          hashAlg,              //   IN:   hash algorithm to use for the encoding
760       UINT32              hInSize,              //   IN:   size of the digest to compare
761       BYTE               *hIn,                  //   In:   the digest to compare
762       UINT32              eInSize,              //   IN:   size of the encoded data
763       BYTE               *eIn                   //   IN:   the encoded data
764       )
765   {
766       BOOL                fail = FALSE;
767       BYTE               *der;
768       INT32               derSize = _cpri__GetHashDER(hashAlg, &der);
769       INT32               hashSize = _cpri__GetDigestSize(hashAlg);
770       INT32               fillSize;
771
772       pAssert(hIn != NULL && eIn != NULL);
773
774       // Can't use this scheme if the algorithm doesn't have a DER string

      Page 430                                       TCG Published                               Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library

775        // defined or if the provided hash isn't the right size
776        if(derSize == 0 || (unsigned)hashSize != hInSize)
777            return CRYPT_SCHEME;
778
779        // Make sure that this combination will fit in the provided space
780        // Since no data movement takes place, can just walk though this
781        // and accept nearly random values. This can only be called from
782        // _cpri__ValidateSignature() so eInSize is known to be in range.
783        fillSize = eInSize - derSize - hashSize - 3;
784
785        // Start checking
786        fail |= (*eIn++ != 0); // initial byte of zero
787        fail |= (*eIn++ != 1); // byte of 0x01
788        for(; fillSize > 0; fillSize--)
789            fail |= (*eIn++ != 0xff); // bunch of 0xff
790        fail |= (*eIn++ != 0); // another 0
791        for(; derSize > 0; derSize--)
792            fail |= (*eIn++ != *der++); // match the DER
793        for(; hInSize > 0; hInSize--)
794            fail |= (*eIn++ != *hIn++); // match the hash
795        if(fail)
796            return CRYPT_FAIL;
797        return CRYPT_SUCCESS;
798   }


      B.12.1.4. Externally Accessible Functions

      B.12.1.4.1. _cpri__RsaStartup()

      Function that is called to initialize the hash service. In this implementation, this function does nothing but
      it is called by the CryptUtilStartup() function and must be present.

799   LIB_EXPORT BOOL
800   _cpri__RsaStartup(
801        void
802        )
803   {
804        return TRUE;
805   }


      B.12.1.4.2. _cpri__EncryptRSA()

      This is the entry point for encryption using RSA. Encryption is use of the public exponent. The padding
      parameter determines what padding will be used.
      The cOutSize parameter must be at least as large as the size of the key.
      If the padding is RSA_PAD_NONE, dIn is treaded as a number. It must be lower in value than the key
      modulus.




      Family "2.0"                                 TCG Published                                         Page 431
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                              Part 4: Supporting Routines

      NOTE:           If dIn has fewer bytes than cOut, then we don't add low-order zeros to dIn to make it the size of the RSA key for
                      the call to RSAEP. This is because the high order bytes of dIn might have a numeric value that is greater than
                      the value of the key modulus. If this had low-order zeros added, it would have a numeric value larger than the
                      modulus even though it started out with a lower numeric value.


      Return Value                        Meaning

      CRYPT_SUCCESS                       encryption complete
      CRYPT_PARAMETER                     cOutSize is too small (must be the size of the modulus)
      CRYPT_SCHEME                        padType is not a supported scheme

806   LIB_EXPORT CRYPT_RESULT
807   _cpri__EncryptRSA(
808       UINT32                *cOutSize,              //   OUT: the size of the encrypted data
809       BYTE                  *cOut,                  //   OUT: the encrypted data
810       RSA_KEY               *key,                   //   IN: the key to use for encryption
811       TPM_ALG_ID             padType,               //   IN: the type of padding
812       UINT32                 dInSize,               //   IN: the amount of data to encrypt
813       BYTE                  *dIn,                   //   IN: the data to encrypt
814       TPM_ALG_ID             hashAlg,               //   IN: in case this is needed
815       const char            *label                  //   IN: in case it is needed
816       )
817   {
818       CRYPT_RESULT          retVal = CRYPT_SUCCESS;
819
820       pAssert(cOutSize != NULL);
821
822       // All encryption schemes return the same size of data
823       if(*cOutSize < key->publicKey->size)
824           return CRYPT_PARAMETER;
825       *cOutSize = key->publicKey->size;
826
827       switch (padType)
828       {
829       case TPM_ALG_NULL: // 'raw' encryption
830           {
831               // dIn can have more bytes than cOut as long as the extra bytes
832               // are zero
833               for(; dInSize > *cOutSize; dInSize--)
834               {
835                   if(*dIn++ != 0)
836                       return CRYPT_PARAMETER;
837
838                  }
839                  // If dIn is smaller than cOut, fill cOut with zeros
840                  if(dInSize < *cOutSize)
841                      memset(cOut, 0, *cOutSize - dInSize);
842
843                  // Copy the rest of the value
844                  memcpy(&cOut[*cOutSize-dInSize], dIn, dInSize);
845                  // If the size of dIn is the same as cOut dIn could be larger than
846                  // the modulus. If it is, then RSAEP() will catch it.
847           }
848           break;
849       case TPM_ALG_RSAES:
850           retVal = RSAES_PKSC1v1_5Encode(*cOutSize, cOut, dInSize, dIn);
851           break;
852       case TPM_ALG_OAEP:
853           retVal = OaepEncode(*cOutSize, cOut, hashAlg, label, dInSize, dIn
854   #ifdef TEST_RSA
855                               ,NULL
856   #endif
857                              );
858           break;

      Page 432                                           TCG Published                                                Family "2.0"
      October 30, 2014                          Copyright © TCG 2006-2014                            Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

859       default:
860           return CRYPT_SCHEME;
861       }
862       // All the schemes that do padding will come here for the encryption step
863       // Check that the Encoding worked
864       if(retVal != CRYPT_SUCCESS)
865           return retVal;
866
867       // Padding OK so do the encryption
868       return RSAEP(*cOutSize, cOut, key);
869   }


      B.12.1.4.3. _cpri__DecryptRSA()

      This is the entry point for decryption using RSA. Decryption is use of the private exponent. The padType
      parameter determines what padding was used.

      Return Value                    Meaning

      CRYPT_SUCCESS                   successful completion
      CRYPT_PARAMETER                 cInSize is not the same as the size of the public modulus of key; or
                                      numeric value of the encrypted data is greater than the modulus
      CRYPT_FAIL                      dOutSize is not large enough for the result
      CRYPT_SCHEME                    padType is not supported

870   LIB_EXPORT CRYPT_RESULT
871   _cpri__DecryptRSA(
872       UINT32              *dOutSize,          //   OUT: the size of the decrypted data
873       BYTE                *dOut,              //   OUT: the decrypted data
874       RSA_KEY             *key,               //   IN: the key to use for decryption
875       TPM_ALG_ID           padType,           //   IN: the type of padding
876       UINT32               cInSize,           //   IN: the amount of data to decrypt
877       BYTE                *cIn,               //   IN: the data to decrypt
878       TPM_ALG_ID           hashAlg,           //   IN: in case this is needed for the scheme
879       const char          *label              //   IN: in case it is needed for the scheme
880       )
881   {
882       CRYPT_RESULT        retVal;
883
884       // Make sure that the necessary parameters are provided
885       pAssert(cIn != NULL && dOut != NULL && dOutSize != NULL && key != NULL);
886
887       // Size is checked to make sure that the decryption works properly
888       if(cInSize != key->publicKey->size)
889           return CRYPT_PARAMETER;
890
891       // For others that do padding, do the decryption in place and then
892       // go handle the decoding.
893       if((retVal = RSADP(cInSize, cIn, key)) != CRYPT_SUCCESS)
894           return retVal;      // Decryption failed
895
896       // Remove padding
897       switch (padType)
898       {
899       case TPM_ALG_NULL:
900           if(*dOutSize < key->publicKey->size)
901               return CRYPT_FAIL;
902           *dOutSize = key->publicKey->size;
903           memcpy(dOut, cIn, *dOutSize);
904           return CRYPT_SUCCESS;
905       case TPM_ALG_RSAES:
906           return RSAES_Decode(dOutSize, dOut, cInSize, cIn);

      Family "2.0"                                 TCG Published                                             Page 433
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                 Part 4: Supporting Routines

907           break;
908       case TPM_ALG_OAEP:
909           return OaepDecode(dOutSize, dOut, hashAlg, label, cInSize, cIn);
910           break;
911       default:
912           return CRYPT_SCHEME;
913           break;
914       }
915   }


      B.12.1.4.4. _cpri__SignRSA()

      This function is used to generate an RSA signature of the type indicated in scheme.

      Return Value                      Meaning

      CRYPT_SUCCESS                     sign operation completed normally
      CRYPT_SCHEME                      scheme or hashAlg are not supported
      CRYPT_PARAMETER                   hInSize does not match hashAlg (for RSASSA)

916   LIB_EXPORT CRYPT_RESULT
917   _cpri__SignRSA(
918       UINT32              *sigOutSize,          //   OUT: size of signature
919       BYTE                *sigOut,              //   OUT: signature
920       RSA_KEY             *key,                 //   IN: key to use
921       TPM_ALG_ID           scheme,              //   IN: the scheme to use
922       TPM_ALG_ID           hashAlg,             //   IN: hash algorithm for PKSC1v1_5
923       UINT32               hInSize,             //   IN: size of digest to be signed
924       BYTE                *hIn                  //   IN: digest buffer
925       )
926   {
927       CRYPT_RESULT        retVal;
928
929       // Parameter checks
930       pAssert(sigOutSize != NULL && sigOut != NULL && key != NULL && hIn != NULL);
931
932       // For all signatures the size is the size of the key modulus
933       *sigOutSize = key->publicKey->size;
934       switch (scheme)
935       {
936       case TPM_ALG_NULL:
937           *sigOutSize = 0;
938           return CRYPT_SUCCESS;
939       case TPM_ALG_RSAPSS:
940           // PssEncode can return CRYPT_PARAMETER
941           retVal = PssEncode(*sigOutSize, sigOut, hashAlg, hInSize, hIn
942   #ifdef TEST_RSA
943                              , NULL
944   #endif
945                             );
946           break;
947       case TPM_ALG_RSASSA:
948           // RSASSA_Encode can return CRYPT_PARAMETER or CRYPT_SCHEME
949           retVal = RSASSA_Encode(*sigOutSize, sigOut, hashAlg, hInSize, hIn);
950           break;
951       default:
952           return CRYPT_SCHEME;
953       }
954       if(retVal != CRYPT_SUCCESS)
955           return retVal;
956       // Do the encryption using the private key
957       // RSADP can return CRYPT_PARAMETR
958       return RSADP(*sigOutSize,sigOut, key);

      Page 434                                      TCG Published                                   Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                            Trusted Platform Module Library

959   }


      B.12.1.4.5. _cpri__ValidateSignatureRSA()

      This function is used to validate an RSA signature. If the signature is valid CRYPT_SUCCESS is
      returned. If the signature is not valid, CRYPT_FAIL is returned. Other return codes indicate either
      parameter problems or fatal errors.

      Return Value                  Meaning

      CRYPT_SUCCESS                 the signature checks
      CRYPT_FAIL                    the signature does not check
      CRYPT_SCHEME                  unsupported scheme or hash algorithm

960   LIB_EXPORT CRYPT_RESULT
961   _cpri__ValidateSignatureRSA(
962       RSA_KEY            *key,               //   IN:   key to use
963       TPM_ALG_ID          scheme,            //   IN:   the scheme to use
964       TPM_ALG_ID          hashAlg,           //   IN:   hash algorithm
965       UINT32              hInSize,           //   IN:   size of digest to be checked
966       BYTE               *hIn,               //   IN:   digest buffer
967       UINT32              sigInSize,         //   IN:   size of signature
968       BYTE               *sigIn,             //   IN:   signature
969       UINT16              saltSize           //   IN:   salt size for PSS
970       )
971   {
972       CRYPT_RESULT        retVal;
973
974       // Fatal programming errors
975       pAssert(key != NULL && sigIn != NULL && hIn != NULL);
976
977       // Errors that might be caused by calling parameters
978       if(sigInSize != key->publicKey->size)
979           return CRYPT_FAIL;
980       // Decrypt the block
981       if((retVal = RSAEP(sigInSize, sigIn, key)) != CRYPT_SUCCESS)
982           return CRYPT_FAIL;
983       switch (scheme)
984       {
985       case TPM_ALG_NULL:
986           return CRYPT_SCHEME;
987           break;
988       case TPM_ALG_RSAPSS:
989           return PssDecode(hashAlg, hInSize, hIn, sigInSize, sigIn, saltSize);
990           break;
991       case TPM_ALG_RSASSA:
992           return RSASSA_Decode(hashAlg, hInSize, hIn, sigInSize, sigIn);
993           break;
994       default:
995           break;
996       }
997       return CRYPT_SCHEME;
998   }
999   #ifndef RSA_KEY_SIEVE


      B.12.1.4.6. _cpri__GenerateKeyRSA()

      Generate an RSA key from a provided seed




      Family "2.0"                               TCG Published                                    Page 435
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                          October 30, 2014
       Trusted Platform Module Library                                                       Part 4: Supporting Routines


       Return Value                      Meaning

       CRYPT_FAIL                        exponent is not prime or is less than 3; or could not find a prime using
                                         the provided parameters
       CRYPT_CANCEL                      operation was canceled

1000   LIB_EXPORT CRYPT_RESULT
1001   _cpri__GenerateKeyRSA(
1002       TPM2B              *n,                     //   OUT: The public modulu
1003       TPM2B              *p,                     //   OUT: One of the prime factors of n
1004       UINT16              keySizeInBits,         //   IN: Size of the public modulus in bit
1005       UINT32              e,                     //   IN: The public exponent
1006       TPM_ALG_ID          hashAlg,               //   IN: hash algorithm to use in the key
1007                                                  //       generation proce
1008       TPM2B              *seed,                  //   IN: the seed to use
1009       const char         *label,                 //   IN: A label for the generation process.
1010       TPM2B              *extra,                 //   IN: Party 1 data for the KDF
1011       UINT32             *counter                //   IN/OUT: Counter value to allow KFD iteration
1012                                                  //       to be propagated across multiple routine
1013       )
1014   {
1015       UINT32              lLen;          // length of the label
1016                                          // (counting the terminating 0);
1017       UINT16              digestSize = _cpri__GetDigestSize(hashAlg);
1018
1019       TPM2B_HASH_BLOCK         oPadKey;
1020
1021       UINT32             outer;
1022       UINT32             inner;
1023       BYTE               swapped[4];
1024
1025       CRYPT_RESULT    retVal;
1026       int             i, fill;
1027       const static char     defaultLabel[] = "RSA key";
1028       BYTE            *pb;
1029
1030       CPRI_HASH_STATE     h1;                    // contains the hash of the
1031                                                  //   HMAC key w/ iPad
1032       CPRI_HASH_STATE     h2;                    // contains the hash of the
1033                                                  //   HMAC key w/ oPad
1034       CPRI_HASH_STATE     h;                     // the working hash context
1035
1036       BIGNUM             *bnP;
1037       BIGNUM             *bnQ;
1038       BIGNUM             *bnT;
1039       BIGNUM             *bnE;
1040       BIGNUM             *bnN;
1041       BN_CTX             *context;
1042       UINT32              rem;
1043
1044       // Make sure that hashAlg is valid hash
1045       pAssert(digestSize != 0);
1046
1047       // if present, use externally provided counter
1048       if(counter != NULL)
1049           outer = *counter;
1050       else
1051           outer = 1;
1052
1053       // Validate exponent
1054       UINT32_TO_BYTE_ARRAY(e, swapped);
1055
1056       // Need to check that the exponent is prime and not less than 3
1057       if( e != 0 && (e < 3 || !_math__IsPrime(e)))

       Page 436                                       TCG Published                                           Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                        Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

1058            return CRYPT_FAIL;
1059
1060       // Get structures for the big number representations
1061       context = BN_CTX_new();
1062       if(context == NULL)
1063           FAIL(FATAL_ERROR_ALLOCATION);
1064       BN_CTX_start(context);
1065       bnP = BN_CTX_get(context);
1066       bnQ = BN_CTX_get(context);
1067       bnT = BN_CTX_get(context);
1068       bnE = BN_CTX_get(context);
1069       bnN = BN_CTX_get(context);
1070       if(bnN == NULL)
1071           FAIL(FATAL_ERROR_INTERNAL);
1072
1073       // Set Q to zero. This is used as a flag. The prime is computed in P. When a
1074       // new prime is found, Q is checked to see if it is zero. If so, P is copied
1075       // to Q and a new P is found. When both P and Q are non-zero, the modulus and
1076       // private exponent are computed and a trial encryption/decryption is
1077       // performed. If the encrypt/decrypt fails, assume that at least one of the
1078       // primes is composite. Since we don't know which one, set Q to zero and start
1079       // over and find a new pair of primes.
1080       BN_zero(bnQ);
1081
1082       // Need to have some label
1083       if(label == NULL)
1084           label = (const char *)&defaultLabel;
1085       // Get the label size
1086       for(lLen = 0; label[lLen++] != 0;);
1087
1088       // Start the hash using the seed and get the intermediate hash value
1089       _cpri__StartHMAC(hashAlg, FALSE, &h1, seed->size, seed->buffer, &oPadKey.b);
1090       _cpri__StartHash(hashAlg, FALSE, &h2);
1091       _cpri__UpdateHash(&h2, oPadKey.b.size, oPadKey.b.buffer);
1092
1093       n->size = (keySizeInBits +7)/8;
1094       pAssert(n->size <= MAX_RSA_KEY_BYTES);
1095       p->size = n->size / 2;
1096       if(e == 0)
1097           e = RSA_DEFAULT_PUBLIC_EXPONENT;
1098
1099       BN_set_word(bnE, e);
1100
1101       // The first test will increment the counter from zero.
1102       for(outer += 1; outer != 0; outer++)
1103       {
1104           if(_plat__IsCanceled())
1105           {
1106               retVal = CRYPT_CANCEL;
1107               goto Cleanup;
1108           }
1109
1110            // Need to fill in the candidate with the hash
1111            fill = digestSize;
1112            pb = p->buffer;
1113
1114            // Reset the inner counter
1115            inner = 0;
1116            for(i = p->size; i > 0; i -= digestSize)
1117            {
1118                inner++;
1119                // Initialize the HMAC with saved state
1120                _cpri__CopyHashState(&h, &h1);
1121
1122                  // Hash the inner counter (the one that changes on each HMAC iteration)
1123                  UINT32_TO_BYTE_ARRAY(inner, swapped);

       Family "2.0"                           TCG Published                                Page 437
       Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
       Trusted Platform Module Library                                  Part 4: Supporting Routines

1124                 _cpri__UpdateHash(&h, 4, swapped);
1125                 _cpri__UpdateHash(&h, lLen, (BYTE *)label);
1126
1127                 // Is there any party 1 data
1128                 if(extra != NULL)
1129                     _cpri__UpdateHash(&h, extra->size, extra->buffer);
1130
1131                 // Include the outer counter (the one that changes on each prime
1132                 // prime candidate generation
1133                 UINT32_TO_BYTE_ARRAY(outer, swapped);
1134                 _cpri__UpdateHash(&h, 4, swapped);
1135                 _cpri__UpdateHash(&h, 2, (BYTE *)&keySizeInBits);
1136                 if(i < fill)
1137                     fill = i;
1138                 _cpri__CompleteHash(&h, fill, pb);
1139
1140                 // Restart the oPad hash
1141                 _cpri__CopyHashState(&h, &h2);
1142
1143                 // Add the last hashed data
1144                 _cpri__UpdateHash(&h, fill, pb);
1145
1146                 // gives a completed HMAC
1147                 _cpri__CompleteHash(&h, fill, pb);
1148                 pb += fill;
1149            }
1150            // Set the Most significant 2 bits and the low bit of the candidate
1151            p->buffer[0] |= 0xC0;
1152            p->buffer[p->size - 1] |= 1;
1153
1154            // Convert the candidate to a BN
1155            BN_bin2bn(p->buffer, p->size, bnP);
1156
1157            // If this is the second prime, make sure that it differs from the
1158            // first prime by at least 2^100
1159            if(!BN_is_zero(bnQ))
1160            {
1161                // bnQ is non-zero if we already found it
1162                if(BN_ucmp(bnP, bnQ) < 0)
1163                    BN_sub(bnT, bnQ, bnP);
1164                else
1165                    BN_sub(bnT, bnP, bnQ);
1166                if(BN_num_bits(bnT) < 100) // Difference has to be at least 100 bits
1167                    continue;
1168            }
1169            // Make sure that the prime candidate (p) is not divisible by the exponent
1170            // and that (p-1) is not divisible by the exponent
1171            // Get the remainder after dividing by the modulus
1172            rem = BN_mod_word(bnP, e);
1173            if(rem == 0) // evenly divisible so add two keeping the number odd and
1174                // making sure that 1 != p mod e
1175                BN_add_word(bnP, 2);
1176            else if(rem == 1) // leaves a remainder of 1 so subtract two keeping the
1177                // number odd and making (e-1) = p mod e
1178                BN_sub_word(bnP, 2);
1179
1180            // Have a candidate, check for primality
1181            if((retVal = (CRYPT_RESULT)BN_is_prime_ex(bnP,
1182                         BN_prime_checks, NULL, NULL)) < 0)
1183                FAIL(FATAL_ERROR_INTERNAL);
1184
1185            if(retVal != 1)
1186                continue;
1187
1188            // Found a prime, is this the first or second.
1189            if(BN_is_zero(bnQ))

       Page 438                               TCG Published                           Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014        Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

1190            {
1191                  // copy p to q and compute another prime in p
1192                  BN_copy(bnQ, bnP);
1193                  continue;
1194            }
1195            //Form the public modulus
1196            BN_mul(bnN, bnP, bnQ, context);
1197            if(BN_num_bits(bnN) != keySizeInBits)
1198                FAIL(FATAL_ERROR_INTERNAL);
1199
1200            // Save the public modulus
1201            BnTo2B(n, bnN, n->size); // Will pad the buffer to the correct size
1202            pAssert((n->buffer[0] & 0x80) != 0);
1203
1204            // And one prime
1205            BnTo2B(p, bnP, p->size);
1206            pAssert((p->buffer[0] & 0x80) != 0);
1207
1208            // Finish by making sure that we can form the modular inverse of PHI
1209            // with respect to the public exponent
1210            // Compute PHI = (p - 1)(q - 1) = n - p - q + 1
1211            // Make sure that we can form the modular inverse
1212            BN_sub(bnT, bnN, bnP);
1213            BN_sub(bnT, bnT, bnQ);
1214            BN_add_word(bnT, 1);
1215
1216            // find d such that (Phi * d) mod e ==1
1217            // If there isn't then we are broken because we took the step
1218            // of making sure that the prime != 1 mod e so the modular inverse
1219            // must exist
1220            if(BN_mod_inverse(bnT, bnE, bnT, context) == NULL || BN_is_zero(bnT))
1221                FAIL(FATAL_ERROR_INTERNAL);
1222
1223            // And, finally, do a trial encryption decryption
1224            {
1225                TPM2B_TYPE(RSA_KEY, MAX_RSA_KEY_BYTES);
1226                TPM2B_RSA_KEY        r;
1227                r.t.size = sizeof(n->size);
1228
1229                  // If we are using a seed, then results must be reproducible on each
1230                  // call. Otherwise, just get a random number
1231                  if(seed == NULL)
1232                      _cpri__GenerateRandom(n->size, r.t.buffer);
1233                  else
1234                  {
1235                      // this this version does not have a deterministic RNG, XOR the
1236                      // public key and private exponent to get a deterministic value
1237                      // for testing.
1238                      int          i;
1239
1240                      // Generate a random-ish number starting with the public modulus
1241                      // XORed with the MSO of the seed
1242                      for(i = 0; i < n->size; i++)
1243                          r.t.buffer[i] = n->buffer[i] ^ seed->buffer[0];
1244                  }
1245                  // Make sure that the number is smaller than the public modulus
1246                  r.t.buffer[0] &= 0x7F;
1247                         // Convert
1248                  if(    BN_bin2bn(r.t.buffer, r.t.size, bnP) == NULL
1249                         // Encrypt with the public exponent
1250                      || BN_mod_exp(bnQ, bnP, bnE, bnN, context) != 1
1251                         // Decrypt with the private exponent
1252                      || BN_mod_exp(bnQ, bnQ, bnT, bnN, context) != 1)
1253                       FAIL(FATAL_ERROR_INTERNAL);
1254                  // If the starting and ending values are not the same, start over )-;
1255                  if(BN_ucmp(bnP, bnQ) != 0)

       Family "2.0"                           TCG Published                                Page 439
       Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
       Trusted Platform Module Library                                                  Part 4: Supporting Routines

1256                  {
1257                       BN_zero(bnQ);
1258                       continue;
1259                 }
1260             }
1261             retVal = CRYPT_SUCCESS;
1262             goto Cleanup;
1263        }
1264        retVal = CRYPT_FAIL;
1265
1266   Cleanup:
1267       // Close out the hash sessions
1268       _cpri__CompleteHash(&h2, 0, NULL);
1269       _cpri__CompleteHash(&h1, 0, NULL);
1270
1271        // Free up allocated BN values
1272        BN_CTX_end(context);
1273        BN_CTX_free(context);
1274        if(counter != NULL)
1275            *counter = outer;
1276        return retVal;
1277   }
1278   #endif      // RSA_KEY_SIEVE
1279   #endif // TPM_ALG_RSA


       B.12.2. Alternative RSA Key Generation

       B.12.2.1. Introduction

       The files in this clause implement an alternative RSA key generation method that is about an order of
       magnitude faster than the regular method in B.14.1 and is provided simply to speed testing of the test
       functions. The method implemented in this clause uses a sieve rather than choosing prime candidates at
       random and testing for primeness. In this alternative, the sieve filed starting address is chosen at random
       and a sieve operation is performed on the field using small prime values. After sieving, the bits
       representing values that are not divisible by the small primes tested, will be checked in a pseudo-random
       order until a prime is found.
       The size of the sieve field is tunable as is the value indicating the number of primes that should be
       checked. As the size of the prime increases, the density of primes is reduced so the size of the sieve field
       should be increased to improve the probability that the field will contain at least one prime. In addition, as
       the sieve field increases the number of small primes that should be checked increases. Eliminating a
       number from consideration by using division is considerably faster than eliminating the number with a
       Miller-Rabin test.

       B.12.2.2. RSAKeySieve.h

       This header file is used to for parameterization of the Sieve and RNG used by the RSA module

   1   #ifndef        RSA_H
   2   #define        RSA_H

       This value is used to set the size of the table that is searched by the prime iterator. This is used during
       the generation of different primes. The smaller tables are used when generating smaller primes.

   3   extern const UINT16        primeTableBytes;

       The following define determines how large the prime number difference table will be defined. The value of
       13 will allocate the maximum size table which allows generation of the first 6542 primes which is all the
       primes less than 2^16.

       Page 440                                      TCG Published                                     Family "2.0"
       October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
     Part 4: Supporting Routines                                                   Trusted Platform Module Library

 4   #define PRIME_DIFF_TABLE_512_BYTE_PAGES                  13

     This set of macros used the value above to set the table size.

 5   #ifndef PRIME_DIFF_TABLE_512_BYTE_PAGES
 6   #   define PRIME_DIFF_TABLE_512_BYTE_PAGES      4
 7   #endif
 8   #ifdef PRIME_DIFF_TABLE_512_BYTE_PAGES
 9   #   if PRIME_DIFF_TABLE_512_BYTE_PAGES > 12
10   #        define PRIME_DIFF_TABLE_BYTES 6542
11   #   else
12   #        if PRIME_DIFF_TABLE_512_BYTE_PAGES <= 0
13   #             define PRIME_DIFF_TABLE_BYTES 512
14   #        else
15   #             define PRIME_DIFF_TABLE_BYTES (PRIME_DIFF_TABLE_512_BYTE_PAGES * 512)
16   #        endif
17   #   endif
18   #endif
19   extern const BYTE primeDiffTable [PRIME_DIFF_TABLE_BYTES];

     This determines the number of bits in the sieve field This must be a power of two.

20   #define FIELD_POWER            14  // This is the only value in this group that should be
21                                      // changed
22   #define FIELD_BITS             (1 << FIELD_POWER)
23   #define MAX_FIELD_SIZE             ((FIELD_BITS / 8) + 1)

     This is the pre-sieved table. It already has the bits for multiples of 3, 5, and 7 cleared.

24   #define SEED_VALUES_SIZE                    105
25   const extern BYTE                           seedValues[SEED_VALUES_SIZE];

     This allows determination of the number of bits that are set in a byte without having to count them
     individually.

26   const extern BYTE                           bitsInByte[256];

     This is the iterator structure for accessing the compressed prime number table. The expectation is that
     values will need to be accesses sequentially. This tries to save some data access.

27   typedef struct {
28       UINT32       lastPrime;
29       UINT32       index;
30       UINT32       final;
31   } PRIME_ITERATOR;
32   #ifdef RSA_INSTRUMENT
33   #   define INSTRUMENT_SET(a, b) ((a) = (b))
34   #   define INSTRUMENT_ADD(a, b) (a) = (a) + (b)
35   #   define INSTRUMENT_INC(a)     (a) = (a) + 1
36   extern UINT32 failedAtIteration[10];
37   extern UINT32 MillerRabinTrials;
38   extern UINT32 totalFieldsSieved;
39   extern UINT32 emptyFieldsSieved;
40   extern UINT32 noPrimeFields;
41   extern UINT32 primesChecked;
42   extern UINT16    lastSievePrime;
43   #else
44   #   define INSTRUMENT_SET(a, b)
45   #   define INSTRUMENT_ADD(a, b)
46   #   define INSTRUMENT_INC(a)
47   #endif
48   #ifdef RSA_DEBUG
49   extern UINT16    defaultFieldSize;

     Family "2.0"                                   TCG Published                                         Page 441
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                              October 30, 2014
     Trusted Platform Module Library                                 Part 4: Supporting Routines

50   #define NUM_PRIMES                2047
51   extern const __int16              primes[NUM_PRIMES];
52   #else
53   #define defaultFieldSize          MAX_FIELD_SIZE
54   #endif
55   #endif




     Page 442                                  TCG Published                       Family "2.0"
     October 30, 2014                    Copyright © TCG 2006-2014    Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library


     B.12.2.3. RSAKeySieve.c

     B.12.2.3.1. Includes and defines

 1   #include       "OsslCryptoEngine.h"
 2   #ifdef       TPM_ALG_RSA

     This file produces no code unless the compile switch is set to cause it to generate code.

 3   #ifdef          RSA_KEY_SIEVE                          //%
 4   #include        "RsaKeySieve.h"

     This next line will show up in the header file for this code. It will make the local functions public when
     debugging.

 5   //%#ifdef       RSA_DEBUG


     B.12.2.3.2. Bit Manipulation Functions

     B.12.2.3.2.1.     Introduction

     These functions operate on a bit array. A bit array is an array of bytes with the 0th byte being the byte
     with the lowest memory address. Within the byte, bit 0 is the least significant bit.

     B.12.2.3.2.2.     ClearBit()

     This function will CLEAR a bit in a bit array.

 6   void
 7   ClearBit(
 8        unsigned char         *a,                     // IN: A pointer to an array of byte
 9        int                    i                      // IN: the number of the bit to CLEAR
10        )
11   {
12        a[i >> 3] &= 0xff ^ (1 << (i & 7));
13   }


     B.12.2.3.2.3.     SetBit()

     Function to SET a bit in a bit array.

14   void
15   SetBit(
16        unsigned char         *a,                     // IN: A pointer to an array of byte
17        int                    i                      // IN: the number of the bit to SET
18        )
19   {
20        a[i >> 3] |= (1 << (i & 7));
21   }


     B.12.2.3.2.4.     IsBitSet()

     Function to test if a bit in a bit array is SET.




     Family "2.0"                                       TCG Published                                Page 443
     Level 00 Revision 01.16                  Copyright © TCG 2006-2014                      October 30, 2014
     Trusted Platform Module Library                                               Part 4: Supporting Routines


     Return Value                      Meaning

     0                                 bit is CLEAR
     1                                 bit is SET

22   UINT32
23   IsBitSet(
24        unsigned char       *a,                   // IN: A pointer to an array of byte
25        int                  i                    // IN: the number of the bit to test
26        )
27   {
28        return ((a[i >> 3] & (1 << (i & 7))) != 0);
29   }


     B.12.2.3.2.5.   BitsInArry()

     This function counts the number of bits set in an array of bytes.

30   int
31   BitsInArray(
32        unsigned char       *a,                   // IN: A pointer to an array of byte
33        int                  i                    // IN: the number of bytes to sum
34        )
35   {
36        int     j = 0;
37        for(; i ; i--)
38            j += bitsInByte[*a++];
39        return j;
40   }


     B.12.2.3.2.6.   FindNthSetBit()

     This function finds the nth SET bit in a bit array. The caller should check that the offset of the returned
     value is not out of range. If called when the array does not have n bits set, it will return a fatal error

41   UINT32
42   FindNthSetBit(
43        const UINT16         aSize,               // IN: the size of the array to check
44        const BYTE          *a,                   // IN: the array to check
45        const UINT32         n                    // IN, the number of the SET bit
46        )
47   {
48        UINT32          i;
49        const BYTE     *pA = a;
50        UINT32          retValue;
51        BYTE            sel;
52
53        (aSize);
54
55        //find the bit
56        for(i = 0; i < n; i += bitsInByte[*pA++]);
57
58        // The chosen bit is in the byte that was just accessed
59        // Compute the offset to the start of that byte
60        pA--;
61        retValue = (UINT32)(pA - a) * 8;
62
63        // Subtract the bits in the last byte added.
64        i -= bitsInByte[*pA];
65
66        // Now process the byte, one bit at a time.

     Page 444                                         TCG Published                               Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

 67        for(sel = *pA; sel != 0 ; sel = sel >> 1)
 68        {
 69            if(sel & 1)
 70            {
 71                i += 1;
 72                if(i == n)
 73                    return retValue;
 74            }
 75            retValue += 1;
 76        }
 77        FAIL(FATAL_ERROR_INTERNAL);
 78   }


      B.12.2.3.3. Miscellaneous Functions

      B.12.2.3.3.1.    RandomForRsa()

      This function uses a special form of KDFa() to produces a pseudo random sequence. It's input is a
      structure that contains pointers to a pre-computed set of hash contexts that are set up for the HMAC
      computations using the seed.
      This function will test that ktx.outer will not wrap to zero if incremented. If so, the function returns FALSE.
      Otherwise, the ktx.outer is incremented before each number is generated.

 79   void
 80   RandomForRsa(
 81        KDFa_CONTEXT        *ktx,                // IN: a context for the KDF
 82        const char          *label,              // IN: a use qualifying label
 83        TPM2B               *p                   // OUT: the pseudo random result
 84        )
 85   {
 86        INT16                           i;
 87        UINT32                          inner;
 88        BYTE                            swapped[4];
 89        UINT16                          fill;
 90        BYTE                            *pb;
 91        UINT16                          lLen = 0;
 92        UINT16                          digestSize = _cpri__GetDigestSize(ktx->hashAlg);
 93        CPRI_HASH_STATE                 h;      // the working hash context
 94
 95        if(label != NULL)
 96            for(lLen = 0; label[lLen++];);
 97        fill = digestSize;
 98        pb = p->buffer;
 99        inner = 0;
100        *(ktx->outer) += 1;
101        for(i = p->size; i > 0; i -= digestSize)
102        {
103            inner++;
104
105             // Initialize the HMAC with saved state
106             _cpri__CopyHashState(&h, &(ktx->iPadCtx));
107
108             // Hash the inner counter (the one that changes on each HMAC iteration)
109             UINT32_TO_BYTE_ARRAY(inner, swapped);
110             _cpri__UpdateHash(&h, 4, swapped);
111             if(lLen != 0)
112                 _cpri__UpdateHash(&h, lLen, (BYTE *)label);
113
114             // Is there any party 1 data
115             if(ktx->extra != NULL)
116                 _cpri__UpdateHash(&h, ktx->extra->size, ktx->extra->buffer);
117

      Family "2.0"                                  TCG Published                                         Page 445
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

118            // Include the outer counter (the one that changes on each prime
119            // prime candidate generation
120            UINT32_TO_BYTE_ARRAY(*(ktx->outer), swapped);
121            _cpri__UpdateHash(&h, 4, swapped);
122            _cpri__UpdateHash(&h, 2, (BYTE *)&ktx->keySizeInBits);
123            if(i < fill)
124                fill = i;
125            _cpri__CompleteHash(&h, fill, pb);
126
127            // Restart the oPad hash
128            _cpri__CopyHashState(&h, &(ktx->oPadCtx));
129
130            // Add the last hashed data
131            _cpri__UpdateHash(&h, fill, pb);
132
133            // gives a completed HMAC
134            _cpri__CompleteHash(&h, fill, pb);
135            pb += fill;
136       }
137       return;
138   }


      B.12.2.3.3.2.   MillerRabinRounds()

      Function returns the number of Miller-Rabin rounds necessary to give an error probability equal to the
      security strength of the prime. These values are from FIPS 186-3.

139   UINT32
140   MillerRabinRounds(
141       UINT32               bits                 // IN: Number of bits in the RSA prime
142       )
143   {
144       if(bits < 511) return 8;            // don't really expect this
145       if(bits < 1536) return 5;           // for 512 and 1K primes
146       return 4;                           // for 3K public modulus and greater
147   }


      B.12.2.3.3.3.   MillerRabin()

      This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the number. I all
      likelihood, if the number is not prime, the first test fails.
      If a KDFa(), PRNG context is provide (ktx), then it is used to provide the random values. Otherwise, the
      random numbers are retrieved from the random number generator.

      Return Value                      Meaning

      TRUE                              probably prime
      FALSE                             composite

148   BOOL
149   MillerRabin(
150       BIGNUM              *bnW,
151       int                  iterations,
152       KDFa_CONTEXT        *ktx,
153       BN_CTX              *context
154       )
155   {
156       BIGNUM         *bnWm1;
157       BIGNUM         *bnM;
158       BIGNUM         *bnB;
159       BIGNUM         *bnZ;

      Page 446                                      TCG Published                                 Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

160       BOOL         ret = FALSE;   // Assumed composite for easy exit
161       TPM2B_TYPE(MAX_PRIME, MAX_RSA_KEY_BYTES/2);
162       TPM2B_MAX_PRIME    b;
163       int          a;
164       int          j;
165       int          wLen;
166       int          i;
167
168       pAssert(BN_is_bit_set(bnW, 0));
169       INSTRUMENT_INC(MillerRabinTrials);    // Instrumentation
170
171       BN_CTX_start(context);
172       bnWm1 = BN_CTX_get(context);
173       bnB = BN_CTX_get(context);
174       bnZ = BN_CTX_get(context);
175       bnM = BN_CTX_get(context);
176       if(bnM == NULL)
177           FAIL(FATAL_ERROR_ALLOCATION);
178
179   // Let a be the largest integer such that 2^a divides w1.
180       BN_copy(bnWm1, bnW);
181       BN_sub_word(bnWm1, 1);
182       // Since w is odd (w-1) is even so start at bit number 1 rather than 0
183       for(a = 1; !BN_is_bit_set(bnWm1, a); a++);
184
185   // 2. m = (w1) / 2^a
186       BN_rshift(bnM, bnWm1, a);
187
188   // 3. wlen = len (w).
189       wLen = BN_num_bits(bnW);
190       pAssert((wLen & 7) == 0);
191
192       // Set the size for the random number
193       b.b.size = (UINT16)(wLen + 7)/8;
194
195   // 4. For i = 1 to iterations do
196       for(i = 0; i < iterations ; i++)
197       {
198
199   // 4.1 Obtain a string b of wlen bits from an RBG.
200   step4point1:
201           // In the reference implementation, wLen is always a multiple of 8
202           if(ktx != NULL)
203                RandomForRsa(ktx, "Miller-Rabin witness", &b.b);
204           else
205                _cpri__GenerateRandom(b.t.size, b.t.buffer);
206
207            if(BN_bin2bn(b.t.buffer, b.t.size, bnB) == NULL)
208                FAIL(FATAL_ERROR_ALLOCATION);
209
210   // 4.2 If ((b 1) or (b w1)), then go to step 4.1.
211           if(BN_is_zero(bnB))
212               goto step4point1;
213           if(BN_is_one(bnB))
214               goto step4point1;
215           if(BN_ucmp(bnB, bnWm1) >= 0)
216               goto step4point1;
217
218   // 4.3 z = b^m mod w.
219           if(BN_mod_exp(bnZ, bnB, bnM, bnW, context) != 1)
220               FAIL(FATAL_ERROR_ALLOCATION);
221
222   // 4.4 If ((z = 1) or (z = w 1)), then go to step 4.7.
223           if(BN_is_one(bnZ) || BN_ucmp(bnZ, bnWm1) == 0)
224               goto step4point7;
225

      Family "2.0"                           TCG Published                                Page 447
      Level 00 Revision 01.16         Copyright © TCG 2006-2014                  October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

226   // 4.5 For j = 1 to a 1 do.
227           for(j = 1; j < a; j++)
228           {
229   // 4.5.1 z = z^2 mod w.
230               if(BN_mod_mul(bnZ, bnZ, bnZ, bnW, context) != 1)
231                   FAIL(FATAL_ERROR_ALLOCATION);
232
233   // 4.5.2 If (z = w1), then go to step 4.7.
234               if(BN_ucmp(bnZ, bnWm1) == 0)
235                   goto step4point7;
236
237   // 4.5.3 If (z = 1), then go to step 4.6.
238                if(BN_is_one(bnZ))
239                    goto step4point6;
240           }
241   // 4.6 Return COMPOSITE.
242   step4point6:
243           if(i > 9)
244                INSTRUMENT_INC(failedAtIteration[9]);
245           else
246                INSTRUMENT_INC(failedAtIteration[i]);
247           goto end;
248
249   // 4.7 Continue. Comment: Increment i for the do-loop in step 4.
250   step4point7:
251           continue;
252       }
253   // 5. Return PROBABLY PRIME
254       ret = TRUE;
255
256   end:
257       BN_CTX_end(context);
258       return ret;
259   }


      B.12.2.3.3.4.   NextPrime()

      This function is used to access the next prime number in the sequence of primes. It requires a pre-
      initialized iterator.

260   UINT32
261   NextPrime(
262       PRIME_ITERATOR      *iter
263       )
264   {
265       if(iter->index >= iter->final)
266           return (iter->lastPrime = 0);
267       return (iter->lastPrime += primeDiffTable[iter->index++]);
268   }


      B.12.2.3.3.5.   AdjustNumberOfPrimes()

      Modifies the input parameter to be a valid value for the number of primes. The adjusted value is either the
      input value rounded up to the next 512 bytes boundary or the maximum value of the implementation. If
      the input is 0, the return is set to the maximum.

269   UINT32
270   AdjustNumberOfPrimes(
271       UINT32               p
272       )
273   {
274       p = ((p + 511) / 512) * 512;


      Page 448                                     TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                  Trusted Platform Module Library

275          if(p == 0 || p > PRIME_DIFF_TABLE_BYTES)
276              p = PRIME_DIFF_TABLE_BYTES;
277          return p;
278   }


      B.12.2.3.3.6.    PrimeInit()

      This function is used to initialize the prime sequence generator iterator. The iterator is initialized and
      returns the first prime that is equal to the requested starting value. If the starting value is no a prime, then
      the iterator is initialized to the next higher prime number.

279   UINT32
280   PrimeInit(
281          UINT32             first,              // IN: the initial prime
282          PRIME_ITERATOR    *iter,               // IN/OUT: the iterator structure
283          UINT32             primes              // IN: the table length
284          )
285   {
286
287          iter->lastPrime = 1;
288          iter->index = 0;
289          iter->final = AdjustNumberOfPrimes(primes);
290          while(iter->lastPrime < first)
291              NextPrime(iter);
292          return iter->lastPrime;
293   }


      B.12.2.3.3.7.    SetDefaultNumberOfPrimes()

      This macro sets the default number of primes to the indicated value.

294   //%#define SetDefaultNumberOfPrimes(p) (primeTableBytes = AdjustNumberOfPrimes(p))


      B.12.2.3.3.8.    IsPrimeWord()

      Checks to see if a UINT32 is prime

      Return Value                      Meaning

      TRUE                              number is prime
      FAIL                              number is not prime

295   BOOL
296   IsPrimeWord(
297          UINT32              p                  // IN: number to test
298          )
299   {
300   #if defined RSA_KEY_SIEVE && (PRIME_DIFF_TABLE_BYTES >= 6542)
301
302          UINT32       test;
303          UINT32       index;
304          UINT32       stop;
305
306          if((p & 1) == 0)
307              return FALSE;
308          if(p == 1 || p == 3)
309              return TRUE;
310
311          // Get a high value for the stopping point
312          for(index = p, stop = 0; index; index >>= 2)

      Family "2.0"                                  TCG Published                                          Page 449
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

313            stop = (stop << 1) + 1;
314        stop++;
315
316        // If the full prime difference value table is present, can check here
317
318        test = 3;
319        for(index = 1; index < PRIME_DIFF_TABLE_BYTES; index += 1)
320        {
321            if((p % test) == 0)
322                return (p == test);
323            if(test > stop)
324                return TRUE;
325            test += primeDiffTable[index];
326        }
327        return TRUE;
328
329   #else
330
331       BYTE        b[4];
332       if(p == RSA_DEFAULT_PUBLIC_EXPONENT || p == 1 || p == 3 )
333           return TRUE;
334       if((p & 1) == 0)
335           return FALSE;
336       UINT32_TO_BYTE_ARRAY(p,b);
337       return _math__IsPrime(p);
338   #endif
339   }
340   typedef struct {
341       UINT16      prime;
342       UINT16      count;
343   } SIEVE_MARKS;
344   const SIEVE_MARKS sieveMarks[5] = {
345       {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}};


      B.12.2.3.3.9.    PrimeSieve()

      This function does a prime sieve over the input field which has as its starting address the value in bnN.
      Since this initializes the Sieve using a pre-computed field with the bits associated with 3, 5 and 7 already
      turned off, the value of pnN may need to be adjusted by a few counts to allow the pre-computed field to
      be used without modification. The fieldSize parameter must be 2^N + 1 and is probably not useful if it is
      less than 129 bytes (1024 bits).

346   UINT32
347   PrimeSieve(
348        BIGNUM        *bnN,            //   IN/OUT: number to sieve
349        UINT32         fieldSize,      //   IN: size of the field area in bytes
350        BYTE          *field,          //   IN: field
351        UINT32         primes          //   IN: the number of primes to use
352        )
353   {
354        UINT32              i;
355        UINT32              j;
356        UINT32              fieldBits = fieldSize * 8;
357        UINT32              r;
358        const BYTE         *p1;
359        BYTE               *p2;
360        PRIME_ITERATOR      iter;
361        UINT32              adjust;
362        UINT32              mark = 0;
363        UINT32              count = sieveMarks[0].count;
364        UINT32              stop = sieveMarks[0].prime;
365        UINT32              composite;
366
367   //      UINT64              test;           //DEBUG

      Page 450                                      TCG Published                                   Family "2.0"
      October 30, 2014                         Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

368
369       pAssert(field != NULL && bnN != NULL);
370       // Need to have a field that has a size of 2^n + 1 bytes
371       pAssert(BitsInArray((BYTE *)&fieldSize, 2) == 2);
372
373       primes = AdjustNumberOfPrimes(primes);
374
375       // If the remainder is odd, then subtracting the value
376       // will give an even number, but we want an odd number,
377       // so subtract the 105+rem. Otherwise, just subtract
378       // the even remainder.
379       adjust = BN_mod_word(bnN,105);
380       if(adjust & 1)
381           adjust += 105;
382
383       // seed the field
384       // This starts the pointer at the nearest byte to the input value
385       p1 = &seedValues[adjust/16];
386
387       // Reduce the number of bytes to transfer by the amount skipped
388       j = sizeof(seedValues) - adjust/16;
389       adjust = adjust % 16;
390       BN_sub_word(bnN, adjust);
391       adjust >>= 1;
392
393       // This offsets the field
394       p2 = field;
395       for(i = fieldSize; i > 0; i--)
396       {
397           *p2++ = *p1++;
398           if(--j == 0)
399           {
400               j = sizeof(seedValues);
401               p1 = seedValues;
402           }
403       }
404       // Mask the first bits in the field and the last byte in order to eliminate
405       // bytes not in the field from consideration.
406       field[0] &= 0xff << adjust;
407       field[fieldSize-1] &= 0xff >> (8 - adjust);
408
409       // Cycle through the primes, clearing bits
410       // Have already done 3, 5, and 7
411       PrimeInit(7, &iter, primes);
412
413       // Get the next N primes where N is determined by the mark in the sieveMarks
414       while((composite = NextPrime(&iter)) != 0)
415       {
416           UINT32 pList[8];
417           UINT32   next = 0;
418           i = count;
419           pList[i--] = composite;
420           for(; i > 0; i--)
421           {
422               next = NextPrime(&iter);
423               pList[i] = next;
424               if(next != 0)
425                   composite *= next;
426           }
427           composite = BN_mod_word(bnN, composite);
428           for(i = count; i > 0; i--)
429           {
430               next = pList[i];
431               if(next == 0)
432                   goto done;
433               r = composite % next;

      Family "2.0"                        TCG Published                                   Page 451
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                    October 30, 2014
      Trusted Platform Module Library                                                  Part 4: Supporting Routines

434                  if(r & 1)           j = (next - r)/2;
435                  else if(r == 0)     j = 0;
436                  else                j = next - r/2;
437                  for(; j < fieldBits; j += next)
438                      ClearBit(field, j);
439             }
440             if(next >= stop)
441             {
442                 mark++;
443                 count = sieveMarks[mark].count;
444                 stop = sieveMarks[mark].prime;
445             }
446       }
447   done:
448       INSTRUMENT_INC(totalFieldsSieved);
449       i = BitsInArray(field, fieldSize);
450       if(i == 0) INSTRUMENT_INC(emptyFieldsSieved);
451       return i;
452   }


      B.12.2.3.3.10. PrimeSelectWithSieve()

      This function will sieve the field around the input prime candidate. If the sieve field is not empty, one of
      the one bits in the field is chosen for testing with Miller-Rabin. If the value is prime, pnP is updated with
      this value and the function returns success. If this value is not prime, another pseudo-random candidate
      is chosen and tested. This process repeats until all values in the field have been checked. If all bits in the
      field have been checked and none is prime, the function returns FALSE and a new random value needs
      to be chosen.

453   BOOL
454   PrimeSelectWithSieve(
455       BIGNUM               *bnP,                    // IN/OUT: The candidate to filter
456       KDFa_CONTEXT         *ktx,                    // IN: KDFa iterator structure
457       UINT32                e,                      // IN: the exponent
458       BN_CTX               *context                 // IN: the big number context to play in
459   #ifdef RSA_DEBUG                                  //%
460      ,UINT16                fieldSize,              // IN: number of bytes in the field, as
461                                                     //     determined by the caller
462       UINT16            primes                      // IN: number of primes to use.
463   #endif                                            //%
464   )
465   {
466       BYTE              field[MAX_FIELD_SIZE];
467       UINT32            first;
468       UINT32            ones;
469       INT32             chosen;
470       UINT32            rounds = MillerRabinRounds(BN_num_bits(bnP));
471   #ifndef RSA_DEBUG
472       UINT32            primes;
473       UINT32            fieldSize;
474       // Adjust the field size and prime table list to fit the size of the prime
475       // being tested.
476       primes = BN_num_bits(bnP);
477       if(primes <= 512)
478       {
479           primes = AdjustNumberOfPrimes(2048);
480           fieldSize = 65;
481       }
482       else if(primes <= 1024)
483       {
484           primes = AdjustNumberOfPrimes(4096);
485           fieldSize = 129;
486       }


      Page 452                                      TCG Published                                     Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

487       else
488       {
489           primes = AdjustNumberOfPrimes(0);             // Set to the maximum
490           fieldSize = MAX_FIELD_SIZE;
491       }
492       if(fieldSize > MAX_FIELD_SIZE)
493           fieldSize = MAX_FIELD_SIZE;
494   #endif
495
496        // Save the low-order word to use as a search generator and make sure that
497        // it has some interesting range to it
498        first = bnP->d[0] | 0x80000000;
499
500       // Align to field boundary
501       bnP->d[0] &= ~((UINT32)(fieldSize-3));
502       pAssert(BN_is_bit_set(bnP, 0));
503       bnP->d[0] &= (UINT32_MAX << (FIELD_POWER + 1)) + 1;
504       ones = PrimeSieve(bnP, fieldSize, field, primes);
505   #ifdef RSA_FILTER_DEBUG
506       pAssert(ones == BitsInArray(field, defaultFieldSize));
507   #endif
508       for(; ones > 0; ones--)
509       {
510   #ifdef RSA_FILTER_DEBUG
511           if(ones != BitsInArray(field, defaultFieldSize))
512               FAIL(FATAL_ERROR_INTERNAL);
513   #endif
514           // Decide which bit to look at and find its offset
515           if(ones == 1)
516               ones = ones;
517           chosen = FindNthSetBit(defaultFieldSize, field,((first % ones) + 1));
518           if(chosen >= ((defaultFieldSize) * 8))
519               FAIL(FATAL_ERROR_INTERNAL);
520
521             // Set this as the trial prime
522             BN_add_word(bnP, chosen * 2);
523
524             // Use MR to see if this is prime
525             if(MillerRabin(bnP, rounds, ktx, context))
526             {
527                 // Final check is to make sure that 0 != (p-1) mod e
528                 // This is the same as -1 != p mod e ; or
529                 // (e - 1) != p mod e
530                 if((e <= 3) || (BN_mod_word(bnP, e) != (e-1)))
531                     return TRUE;
532             }
533             // Back out the bit number
534             BN_sub_word(bnP, chosen * 2);
535
536             // Clear the bit just tested
537             ClearBit(field, chosen);
538   }
539        // Ran out of bits and couldn't find a prime in this field
540        INSTRUMENT_INC(noPrimeFields);
541        return FALSE;
542   }


      B.12.2.3.3.11. AdjustPrimeCandiate()

      This function adjusts the candidate prime so that it is odd and > root(2)/2. This allows the product of these
      two numbers to be .5, which, in fixed point notation means that the most significant bit is 1. For this
      routine, the root(2)/2 is approximated with 0xB505 which is, in fixed point is 0.7071075439453125 or an
      error of 0.0001%. Just setting the upper two bits would give a value > 0.75 which is an error of > 6%.


      Family "2.0"                                 TCG Published                                        Page 453
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines


      Given the amount of time all the other computations take, reducing the error is not much of a cost, but it
      isn't totally required either.
      The function also puts the number on a field boundary.

543   void
544   AdjustPrimeCandidate(
545       BYTE                *a,
546       UINT16               len
547       )
548   {
549       UINT16    highBytes;
550
551       highBytes = BYTE_ARRAY_TO_UINT16(a);
552       // This is fixed point arithmetic on 16-bit values
553       highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16;
554       highBytes += 0xB505;
555       UINT16_TO_BYTE_ARRAY(highBytes, a);
556       a[len-1] |= 1;
557   }


      B.12.2.3.3.12. GeneratateRamdomPrime()

558   void
559   GenerateRandomPrime(
560       TPM2B  *p,
561       BN_CTX *ctx
562   #ifdef RSA_DEBUG               //%
563      ,UINT16  field,
564       UINT16  primes
565   #endif                         //%
566       )
567   {
568       BIGNUM *bnP;
569       BN_CTX *context;
570
571       if(ctx == NULL) context = BN_CTX_new();
572       else context = ctx;
573       if(context == NULL)
574           FAIL(FATAL_ERROR_ALLOCATION);
575       BN_CTX_start(context);
576       bnP = BN_CTX_get(context);
577
578       while(TRUE)
579       {
580           _cpri__GenerateRandom(p->size, p->buffer);
581           p->buffer[p->size-1] |= 1;
582           p->buffer[0] |= 0x80;
583           BN_bin2bn(p->buffer, p->size, bnP);
584   #ifdef RSA_DEBUG
585           if(PrimeSelectWithSieve(bnP, NULL, 0, context, field, primes))
586   #else
587           if(PrimeSelectWithSieve(bnP, NULL, 0, context))
588   #endif
589               break;
590       }
591       BnTo2B(p, bnP, (UINT16)BN_num_bytes(bnP));
592       BN_CTX_end(context);
593       if(ctx == NULL)
594           BN_CTX_free(context);
595       return;
596   }
597   KDFa_CONTEXT *
598   KDFaContextStart(

      Page 454                                    TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                                     Trusted Platform Module Library

599        KDFa_CONTEXT        *ktx,                //   IN/OUT:   the context structure to initialize
600        TPM2B               *seed,               //   IN: the   seed for the digest proce
601        TPM_ALG_ID           hashAlg,            //   IN: the   hash algorithm
602        TPM2B               *extra,              //   IN: the   extra data
603        UINT32              *outer,              //   IN: the   outer iteration counter
604        UINT16               keySizeInBit
605        )
606   {
607        UINT16                     digestSize = _cpri__GetDigestSize(hashAlg);
608        TPM2B_HASH_BLOCK           oPadKey;
609
610        if(seed == NULL)
611            return NULL;
612
613        pAssert(ktx != NULL && outer != NULL && digestSize != 0);
614
615       // Start the hash using the seed and get the intermediate hash value
616       _cpri__StartHMAC(hashAlg, FALSE, &(ktx->iPadCtx), seed->size, seed->buffer,
617                        &oPadKey.b);
618       _cpri__StartHash(hashAlg, FALSE, &(ktx->oPadCtx));
619       _cpri__UpdateHash(&(ktx->oPadCtx), oPadKey.b.size, oPadKey.b.buffer);
620       ktx->extra = extra;
621       ktx->hashAlg = hashAlg;
622       ktx->outer = outer;
623       ktx->keySizeInBits = keySizeInBits;
624       return ktx;
625   }
626   void
627   KDFaContextEnd(
628        KDFa_CONTEXT        *ktx                 // IN/OUT: the context structure to close
629        )
630   {
631        if(ktx != NULL)
632        {
633            // Close out the hash sessions
634            _cpri__CompleteHash(&(ktx->iPadCtx), 0, NULL);
635            _cpri__CompleteHash(&(ktx->oPadCtx), 0, NULL);
636        }
637   }
638   //%#endif


      B.12.2.3.4. Public Function

      B.12.2.3.4.1.   Introduction

      This is the external entry for this replacement function. All this file provides is the substitute function to
      generate an RSA key. If the compiler settings are set appropriately, this this function will be used instead
      of the similarly named function in CpriRSA.c.

      B.12.2.3.4.2.   _cpri__GenerateKeyRSA()

      Generate an RSA key from a provided seed

      Return Value                     Meaning

      CRYPT_FAIL                       exponent is not prime or is less than 3; or could not find a prime using
                                       the provided parameters
      CRYPT_CANCEL                     operation was canceled

639   LIB_EXPORT CRYPT_RESULT
640   _cpri__GenerateKeyRSA(

      Family "2.0"                                  TCG Published                                                 Page 455
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                                October 30, 2014
      Trusted Platform Module Library                                     Part 4: Supporting Routines

641       TPM2B              *n,               // OUT: The public modulus
642       TPM2B              *p,               // OUT: One of the prime factors of n
643       UINT16              keySizeInBits,   // IN: Size of the public modulus in bits
644       UINT32              e,               // IN: The public exponent
645       TPM_ALG_ID          hashAlg,         // IN: hash algorithm to use in the key
646                                            //     generation process
647       TPM2B              *seed,            // IN: the seed to use
648       const char         *label,           // IN: A label for the generation process.
649       TPM2B              *extra,           // IN: Party 1 data for the KDF
650       UINT32             *counter          // IN/OUT: Counter value to allow KDF
651                                            //         iteration to be propagated across
652                                            //         multiple routines
653   #ifdef RSA_DEBUG                         //%
654      ,UINT16              primes,          // IN: number of primes to test
655       UINT16              fieldSize        // IN: the field size to use
656   #endif                                   //%
657       )
658   {
659       CRYPT_RESULT             retVal;
660       UINT32                   myCounter = 0;
661       UINT32                  *pCtr = (counter == NULL) ? &myCounter : counter;
662
663       KDFa_CONTEXT             ktx;
664       KDFa_CONTEXT            *ktxPtr;
665       UINT32                   i;
666       BIGNUM                  *bnP;
667       BIGNUM                  *bnQ;
668       BIGNUM                  *bnT;
669       BIGNUM                  *bnE;
670       BIGNUM                  *bnN;
671       BN_CTX                  *context;
672
673       // Make sure that the required pointers are provided
674       pAssert(n != NULL && p != NULL);
675
676       // If the seed is provided, then use KDFa for generation of the 'random'
677       // values
678       ktxPtr = KDFaContextStart(&ktx, seed, hashAlg, extra, pCtr, keySizeInBits);
679
680       n->size = keySizeInBits/8;
681       p->size = n->size / 2;
682
683       // Validate exponent
684       if(e == 0 || e == RSA_DEFAULT_PUBLIC_EXPONENT)
685           e = RSA_DEFAULT_PUBLIC_EXPONENT;
686       else
687           if(!IsPrimeWord(e))
688               return CRYPT_FAIL;
689
690       // Get structures for the big number representations
691       context = BN_CTX_new();
692       BN_CTX_start(context);
693       bnP = BN_CTX_get(context);
694       bnQ = BN_CTX_get(context);
695       bnT = BN_CTX_get(context);
696       bnE = BN_CTX_get(context);
697       bnN = BN_CTX_get(context);
698       if(bnN == NULL)
699           FAIL(FATAL_ERROR_INTERNAL);
700
701       //   Set Q to zero. This is used as a flag. The prime is computed in P. When a
702       //   new prime is found, Q is checked to see if it is zero. If so, P is copied
703       //   to Q and a new P is found. When both P and Q are non-zero, the modulus and
704       //   private exponent are computed and a trial encryption/decryption is
705       //   performed. If the encrypt/decrypt fails, assume that at least one of the
706       //   primes is composite. Since we don't know which one, set Q to zero and start

      Page 456                                 TCG Published                            Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014         Level 00 Revision 01.16
      Part 4: Supporting Routines                                     Trusted Platform Module Library

707       // over and find a new pair of primes.
708       BN_zero(bnQ);
709       BN_set_word(bnE, e);
710
711       // Each call to generate a random value will increment ktx.outer
712       // it doesn't matter if ktx.outer wraps. This lets the caller
713       // use the initial value of the counter for additional entropy.
714       for(i = 0; i < UINT32_MAX; i++)
715       {
716           if(_plat__IsCanceled())
717           {
718                retVal = CRYPT_CANCEL;
719                goto end;
720           }
721           // Get a random prime candidate.
722           if(seed == NULL)
723                _cpri__GenerateRandom(p->size, p->buffer);
724           else
725                RandomForRsa(&ktx, label, p);
726           AdjustPrimeCandidate(p->buffer, p->size);
727
728             // Convert the candidate to a BN
729             if(BN_bin2bn(p->buffer, p->size, bnP) == NULL)
730                 FAIL(FATAL_ERROR_INTERNAL);
731             // If this is the second prime, make sure that it differs from the
732             // first prime by at least 2^100. Since BIGNUMS use words, the check
733             // below will make sure they are different by at least 128 bits
734             if(!BN_is_zero(bnQ))
735             { // bnQ is non-zero, we have a first value
736                 UINT32       *pP = (UINT32 *)(&bnP->d[4]);
737                 UINT32       *pQ = (UINT32 *)(&bnQ->d[4]);
738                 INT32        k = ((INT32)bnP->top) - 4;
739                 for(;k > 0; k--)
740                     if(*pP++ != *pQ++)
741                         break;
742                 // Didn't find any difference so go get a new value
743                 if(k == 0)
744                     continue;
745             }
746             // If PrimeSelectWithSieve   returns success, bnP is a prime,
747   #ifdef    RSA_DEBUG
748             if(!PrimeSelectWithSieve(bnP, ktxPtr, e, context, fieldSize, primes))
749   #else
750             if(!PrimeSelectWithSieve(bnP, ktxPtr, e, context))
751   #endif
752                  continue;      // If not, get another
753
754             // Found a prime, is this the first or second.
755             if(BN_is_zero(bnQ))
756             {    // copy p to q and compute another prime in p
757                  BN_copy(bnQ, bnP);
758                  continue;
759             }
760             //Form the public modulus
761            if(    BN_mul(bnN, bnP, bnQ, context) != 1
762                || BN_num_bits(bnN) != keySizeInBits)
763                  FAIL(FATAL_ERROR_INTERNAL);
764            // Save the public modulus
765            BnTo2B(n, bnN, n->size);
766            // And one prime
767            BnTo2B(p, bnP, p->size);
768
769   #ifdef EXTENDED_CHECKS
770           // Finish by making sure that we can form the modular inverse of PHI
771           // with respect to the public exponent
772           // Compute PHI = (p - 1)(q - 1) = n - p - q + 1

      Family "2.0"                              TCG Published                              Page 457
      Level 00 Revision 01.16             Copyright © TCG 2006-2014               October 30, 2014
      Trusted Platform Module Library                                  Part 4: Supporting Routines

773            // Make sure that we can form the modular inverse
774            if(    BN_sub(bnT, bnN, bnP) != 1
775                || BN_sub(bnT, bnT, bnQ) != 1
776                || BN_add_word(bnT, 1) != 1)
777                 FAIL(FATAL_ERROR_INTERNAL);
778
779            // find d such that (Phi * d) mod e ==1
780            // If there isn't then we are broken because we took the step
781            // of making sure that the prime != 1 mod e so the modular inverse
782            // must exist
783            if(    BN_mod_inverse(bnT, bnE, bnT, context) == NULL
784                || BN_is_zero(bnT))
785                 FAIL(FATAL_ERROR_INTERNAL);
786
787            // And, finally, do a trial encryption decryption
788            {
789                TPM2B_TYPE(RSA_KEY, MAX_RSA_KEY_BYTES);
790                TPM2B_RSA_KEY        r;
791                r.t.size = sizeof(r.t.buffer);
792                // If we are using a seed, then results must be reproducible on each
793                // call. Otherwise, just get a random number
794                if(seed == NULL)
795                    _cpri__GenerateRandom(keySizeInBits/8, r.t.buffer);
796                else
797                    RandomForRsa(&ktx, label, &r.b);
798
799                 // Make sure that the number is smaller than the public modulus
800                 r.t.buffer[0] &= 0x7F;
801                        // Convert
802                 if(    BN_bin2bn(r.t.buffer, r.t.size, bnP) == NULL
803                        // Encrypt with the public exponent
804                     || BN_mod_exp(bnQ, bnP, bnE, bnN, context) != 1
805                        // Decrypt with the private exponent
806                     || BN_mod_exp(bnQ, bnQ, bnT, bnN, context) != 1)
807                      FAIL(FATAL_ERROR_INTERNAL);
808                 // If the starting and ending values are not the same, start over )-;
809                 if(BN_ucmp(bnP, bnQ) != 0)
810                 {
811                      BN_zero(bnQ);
812                      continue;
813                 }
814           }
815   #endif // EXTENDED_CHECKS
816           retVal = CRYPT_SUCCESS;
817           goto end;
818       }
819       retVal = CRYPT_FAIL;
820
821   end:
822       KDFaContextEnd(&ktx);
823
824       // Free up allocated BN values
825       BN_CTX_end(context);
826       BN_CTX_free(context);
827       return retVal;
828   }
829   #else
830   static void noFuntion(
831       void
832       )
833   {
834       pAssert(1);
835   }
836   #endif              //%
837   #endif // TPM_ALG_RSA


      Page 458                               TCG Published                           Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014        Level 00 Revision 01.16
     Part 4: Supporting Routines                                               Trusted Platform Module Library


     B.12.2.4. RSAData.c

 1   #include "OsslCryptoEngine.h"
 2   #ifdef RSA_KEY_SIEVE
 3   #include "RsaKeySieve.h"
 4   #ifdef RSA_DEBUG
 5   UINT16 defaultFieldSize = MAX_FIELD_SIZE;
 6   #endif

     This table contains a pre-sieved table. It has the bits for 3, 5, and 7 removed. Because of the factors, it
     needs to be aligned to 105 and has a repeat of 105.

 7   const BYTE   seedValues[SEED_VALUES_SIZE] = {
 8       0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30,           0x6c,
 9       0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52,           0x96,
10       0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d,           0x99,
11       0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96,           0x69,
12       0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89,           0xb6,
13       0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61,           0xcb,
14       0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2,           0x4c,
15       0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9,           0x34,
16       0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c,           0x1b,
17       0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4,           0x45,
18       0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b,           0xa6,
19       0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65,           0xd2,
20       0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6,           0x29,
21       0xd1};
22   const BYTE bitsInByte[256] = {
23       0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,           0x03,
24       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03,           0x04,
25       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03,           0x04,
26       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
27       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03,           0x04,
28       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
29       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
30       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
31       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03,           0x04,
32       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
33       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
34       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
35       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
36       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
37       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
38       0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06,           0x07,
39       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03,           0x04,
40       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
41       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
42       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
43       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
44       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
45       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
46       0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06,           0x07,
47       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04,           0x05,
48       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
49       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
50       0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06,           0x07,
51       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05,           0x06,
52       0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06,           0x07,
53       0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06,           0x07,
54       0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07,           0x08
55   };




     Family "2.0"                                TCG Published                                       Page 459
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines


      Following table contains a byte that is the difference between two successive primes. This reduces the
      table size by a factor of two. It is optimized for sequential access to the prime table which is the most
      common case.
      When the table size is at its max, the table will have all primes less than 2^16. This is 6542 primes in
      6542 bytes.

 56   const UINT16      primeTableBytes = PRIME_DIFF_TABLE_BYTES;
 57   #if PRIME_DIFF_TABLE_BYTES > 0
 58   const BYTE primeDiffTable [PRIME_DIFF_TABLE_BYTES] = {
 59      0x02,0x02,0x02,0x04,0x02,0x04,0x02,0x04,0x06,0x02,0x06,0x04,0x02,0x04,0x06,0x06,
 60      0x02,0x06,0x04,0x02,0x06,0x04,0x06,0x08,0x04,0x02,0x04,0x02,0x04,0x0E,0x04,0x06,
 61      0x02,0x0A,0x02,0x06,0x06,0x04,0x06,0x06,0x02,0x0A,0x02,0x04,0x02,0x0C,0x0C,0x04,
 62      0x02,0x04,0x06,0x02,0x0A,0x06,0x06,0x06,0x02,0x06,0x04,0x02,0x0A,0x0E,0x04,0x02,
 63      0x04,0x0E,0x06,0x0A,0x02,0x04,0x06,0x08,0x06,0x06,0x04,0x06,0x08,0x04,0x08,0x0A,
 64      0x02,0x0A,0x02,0x06,0x04,0x06,0x08,0x04,0x02,0x04,0x0C,0x08,0x04,0x08,0x04,0x06,
 65      0x0C,0x02,0x12,0x06,0x0A,0x06,0x06,0x02,0x06,0x0A,0x06,0x06,0x02,0x06,0x06,0x04,
 66      0x02,0x0C,0x0A,0x02,0x04,0x06,0x06,0x02,0x0C,0x04,0x06,0x08,0x0A,0x08,0x0A,0x08,
 67      0x06,0x06,0x04,0x08,0x06,0x04,0x08,0x04,0x0E,0x0A,0x0C,0x02,0x0A,0x02,0x04,0x02,
 68      0x0A,0x0E,0x04,0x02,0x04,0x0E,0x04,0x02,0x04,0x14,0x04,0x08,0x0A,0x08,0x04,0x06,
 69      0x06,0x0E,0x04,0x06,0x06,0x08,0x06,0x0C,0x04,0x06,0x02,0x0A,0x02,0x06,0x0A,0x02,
 70      0x0A,0x02,0x06,0x12,0x04,0x02,0x04,0x06,0x06,0x08,0x06,0x06,0x16,0x02,0x0A,0x08,
 71      0x0A,0x06,0x06,0x08,0x0C,0x04,0x06,0x06,0x02,0x06,0x0C,0x0A,0x12,0x02,0x04,0x06,
 72      0x02,0x06,0x04,0x02,0x04,0x0C,0x02,0x06,0x22,0x06,0x06,0x08,0x12,0x0A,0x0E,0x04,
 73      0x02,0x04,0x06,0x08,0x04,0x02,0x06,0x0C,0x0A,0x02,0x04,0x02,0x04,0x06,0x0C,0x0C,
 74      0x08,0x0C,0x06,0x04,0x06,0x08,0x04,0x08,0x04,0x0E,0x04,0x06,0x02,0x04,0x06,0x02
 75   #endif
 76   // 256
 77   #if PRIME_DIFF_TABLE_BYTES > 256
 78     ,0x06,0x0A,0x14,0x06,0x04,0x02,0x18,0x04,0x02,0x0A,0x0C,0x02,0x0A,0x08,0x06,0x06,
 79      0x06,0x12,0x06,0x04,0x02,0x0C,0x0A,0x0C,0x08,0x10,0x0E,0x06,0x04,0x02,0x04,0x02,
 80      0x0A,0x0C,0x06,0x06,0x12,0x02,0x10,0x02,0x16,0x06,0x08,0x06,0x04,0x02,0x04,0x08,
 81      0x06,0x0A,0x02,0x0A,0x0E,0x0A,0x06,0x0C,0x02,0x04,0x02,0x0A,0x0C,0x02,0x10,0x02,
 82      0x06,0x04,0x02,0x0A,0x08,0x12,0x18,0x04,0x06,0x08,0x10,0x02,0x04,0x08,0x10,0x02,
 83      0x04,0x08,0x06,0x06,0x04,0x0C,0x02,0x16,0x06,0x02,0x06,0x04,0x06,0x0E,0x06,0x04,
 84      0x02,0x06,0x04,0x06,0x0C,0x06,0x06,0x0E,0x04,0x06,0x0C,0x08,0x06,0x04,0x1A,0x12,
 85      0x0A,0x08,0x04,0x06,0x02,0x06,0x16,0x0C,0x02,0x10,0x08,0x04,0x0C,0x0E,0x0A,0x02,
 86      0x04,0x08,0x06,0x06,0x04,0x02,0x04,0x06,0x08,0x04,0x02,0x06,0x0A,0x02,0x0A,0x08,
 87      0x04,0x0E,0x0A,0x0C,0x02,0x06,0x04,0x02,0x10,0x0E,0x04,0x06,0x08,0x06,0x04,0x12,
 88      0x08,0x0A,0x06,0x06,0x08,0x0A,0x0C,0x0E,0x04,0x06,0x06,0x02,0x1C,0x02,0x0A,0x08,
 89      0x04,0x0E,0x04,0x08,0x0C,0x06,0x0C,0x04,0x06,0x14,0x0A,0x02,0x10,0x1A,0x04,0x02,
 90      0x0C,0x06,0x04,0x0C,0x06,0x08,0x04,0x08,0x16,0x02,0x04,0x02,0x0C,0x1C,0x02,0x06,
 91      0x06,0x06,0x04,0x06,0x02,0x0C,0x04,0x0C,0x02,0x0A,0x02,0x10,0x02,0x10,0x06,0x14,
 92      0x10,0x08,0x04,0x02,0x04,0x02,0x16,0x08,0x0C,0x06,0x0A,0x02,0x04,0x06,0x02,0x06,
 93      0x0A,0x02,0x0C,0x0A,0x02,0x0A,0x0E,0x06,0x04,0x06,0x08,0x06,0x06,0x10,0x0C,0x02
 94   #endif
 95   // 512
 96   #if PRIME_DIFF_TABLE_BYTES > 512
 97     ,0x04,0x0E,0x06,0x04,0x08,0x0A,0x08,0x06,0x06,0x16,0x06,0x02,0x0A,0x0E,0x04,0x06,
 98      0x12,0x02,0x0A,0x0E,0x04,0x02,0x0A,0x0E,0x04,0x08,0x12,0x04,0x06,0x02,0x04,0x06,
 99      0x02,0x0C,0x04,0x14,0x16,0x0C,0x02,0x04,0x06,0x06,0x02,0x06,0x16,0x02,0x06,0x10,
100      0x06,0x0C,0x02,0x06,0x0C,0x10,0x02,0x04,0x06,0x0E,0x04,0x02,0x12,0x18,0x0A,0x06,
101      0x02,0x0A,0x02,0x0A,0x02,0x0A,0x06,0x02,0x0A,0x02,0x0A,0x06,0x08,0x1E,0x0A,0x02,
102      0x0A,0x08,0x06,0x0A,0x12,0x06,0x0C,0x0C,0x02,0x12,0x06,0x04,0x06,0x06,0x12,0x02,
103      0x0A,0x0E,0x06,0x04,0x02,0x04,0x18,0x02,0x0C,0x06,0x10,0x08,0x06,0x06,0x12,0x10,
104      0x02,0x04,0x06,0x02,0x06,0x06,0x0A,0x06,0x0C,0x0C,0x12,0x02,0x06,0x04,0x12,0x08,
105      0x18,0x04,0x02,0x04,0x06,0x02,0x0C,0x04,0x0E,0x1E,0x0A,0x06,0x0C,0x0E,0x06,0x0A,
106      0x0C,0x02,0x04,0x06,0x08,0x06,0x0A,0x02,0x04,0x0E,0x06,0x06,0x04,0x06,0x02,0x0A,
107      0x02,0x10,0x0C,0x08,0x12,0x04,0x06,0x0C,0x02,0x06,0x06,0x06,0x1C,0x06,0x0E,0x04,
108      0x08,0x0A,0x08,0x0C,0x12,0x04,0x02,0x04,0x18,0x0C,0x06,0x02,0x10,0x06,0x06,0x0E,
109      0x0A,0x0E,0x04,0x1E,0x06,0x06,0x06,0x08,0x06,0x04,0x02,0x0C,0x06,0x04,0x02,0x06,
110      0x16,0x06,0x02,0x04,0x12,0x02,0x04,0x0C,0x02,0x06,0x04,0x1A,0x06,0x06,0x04,0x08,
111      0x0A,0x20,0x10,0x02,0x06,0x04,0x02,0x04,0x02,0x0A,0x0E,0x06,0x04,0x08,0x0A,0x06,
112      0x14,0x04,0x02,0x06,0x1E,0x04,0x08,0x0A,0x06,0x06,0x08,0x06,0x0C,0x04,0x06,0x02
113   #endif

      Page 460                                    TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

114   // 768
115   #if PRIME_DIFF_TABLE_BYTES > 768
116     ,0x06,0x04,0x06,0x02,0x0A,0x02,0x10,0x06,0x14,0x04,0x0C,0x0E,0x1C,0x06,0x14,0x04,
117      0x12,0x08,0x06,0x04,0x06,0x0E,0x06,0x06,0x0A,0x02,0x0A,0x0C,0x08,0x0A,0x02,0x0A,
118      0x08,0x0C,0x0A,0x18,0x02,0x04,0x08,0x06,0x04,0x08,0x12,0x0A,0x06,0x06,0x02,0x06,
119      0x0A,0x0C,0x02,0x0A,0x06,0x06,0x06,0x08,0x06,0x0A,0x06,0x02,0x06,0x06,0x06,0x0A,
120      0x08,0x18,0x06,0x16,0x02,0x12,0x04,0x08,0x0A,0x1E,0x08,0x12,0x04,0x02,0x0A,0x06,
121      0x02,0x06,0x04,0x12,0x08,0x0C,0x12,0x10,0x06,0x02,0x0C,0x06,0x0A,0x02,0x0A,0x02,
122      0x06,0x0A,0x0E,0x04,0x18,0x02,0x10,0x02,0x0A,0x02,0x0A,0x14,0x04,0x02,0x04,0x08,
123      0x10,0x06,0x06,0x02,0x0C,0x10,0x08,0x04,0x06,0x1E,0x02,0x0A,0x02,0x06,0x04,0x06,
124      0x06,0x08,0x06,0x04,0x0C,0x06,0x08,0x0C,0x04,0x0E,0x0C,0x0A,0x18,0x06,0x0C,0x06,
125      0x02,0x16,0x08,0x12,0x0A,0x06,0x0E,0x04,0x02,0x06,0x0A,0x08,0x06,0x04,0x06,0x1E,
126      0x0E,0x0A,0x02,0x0C,0x0A,0x02,0x10,0x02,0x12,0x18,0x12,0x06,0x10,0x12,0x06,0x02,
127      0x12,0x04,0x06,0x02,0x0A,0x08,0x0A,0x06,0x06,0x08,0x04,0x06,0x02,0x0A,0x02,0x0C,
128      0x04,0x06,0x06,0x02,0x0C,0x04,0x0E,0x12,0x04,0x06,0x14,0x04,0x08,0x06,0x04,0x08,
129      0x04,0x0E,0x06,0x04,0x0E,0x0C,0x04,0x02,0x1E,0x04,0x18,0x06,0x06,0x0C,0x0C,0x0E,
130      0x06,0x04,0x02,0x04,0x12,0x06,0x0C,0x08,0x06,0x04,0x0C,0x02,0x0C,0x1E,0x10,0x02,
131      0x06,0x16,0x0E,0x06,0x0A,0x0C,0x06,0x02,0x04,0x08,0x0A,0x06,0x06,0x18,0x0E,0x06
132   #endif
133   // 1024
134   #if PRIME_DIFF_TABLE_BYTES > 1024
135     ,0x04,0x08,0x0C,0x12,0x0A,0x02,0x0A,0x02,0x04,0x06,0x14,0x06,0x04,0x0E,0x04,0x02,
136      0x04,0x0E,0x06,0x0C,0x18,0x0A,0x06,0x08,0x0A,0x02,0x1E,0x04,0x06,0x02,0x0C,0x04,
137      0x0E,0x06,0x22,0x0C,0x08,0x06,0x0A,0x02,0x04,0x14,0x0A,0x08,0x10,0x02,0x0A,0x0E,
138      0x04,0x02,0x0C,0x06,0x10,0x06,0x08,0x04,0x08,0x04,0x06,0x08,0x06,0x06,0x0C,0x06,
139      0x04,0x06,0x06,0x08,0x12,0x04,0x14,0x04,0x0C,0x02,0x0A,0x06,0x02,0x0A,0x0C,0x02,
140      0x04,0x14,0x06,0x1E,0x06,0x04,0x08,0x0A,0x0C,0x06,0x02,0x1C,0x02,0x06,0x04,0x02,
141      0x10,0x0C,0x02,0x06,0x0A,0x08,0x18,0x0C,0x06,0x12,0x06,0x04,0x0E,0x06,0x04,0x0C,
142      0x08,0x06,0x0C,0x04,0x06,0x0C,0x06,0x0C,0x02,0x10,0x14,0x04,0x02,0x0A,0x12,0x08,
143      0x04,0x0E,0x04,0x02,0x06,0x16,0x06,0x0E,0x06,0x06,0x0A,0x06,0x02,0x0A,0x02,0x04,
144      0x02,0x16,0x02,0x04,0x06,0x06,0x0C,0x06,0x0E,0x0A,0x0C,0x06,0x08,0x04,0x24,0x0E,
145      0x0C,0x06,0x04,0x06,0x02,0x0C,0x06,0x0C,0x10,0x02,0x0A,0x08,0x16,0x02,0x0C,0x06,
146      0x04,0x06,0x12,0x02,0x0C,0x06,0x04,0x0C,0x08,0x06,0x0C,0x04,0x06,0x0C,0x06,0x02,
147      0x0C,0x0C,0x04,0x0E,0x06,0x10,0x06,0x02,0x0A,0x08,0x12,0x06,0x22,0x02,0x1C,0x02,
148      0x16,0x06,0x02,0x0A,0x0C,0x02,0x06,0x04,0x08,0x16,0x06,0x02,0x0A,0x08,0x04,0x06,
149      0x08,0x04,0x0C,0x12,0x0C,0x14,0x04,0x06,0x06,0x08,0x04,0x02,0x10,0x0C,0x02,0x0A,
150      0x08,0x0A,0x02,0x04,0x06,0x0E,0x0C,0x16,0x08,0x1C,0x02,0x04,0x14,0x04,0x02,0x04
151   #endif
152   // 1280
153   #if PRIME_DIFF_TABLE_BYTES > 1280
154     ,0x0E,0x0A,0x0C,0x02,0x0C,0x10,0x02,0x1C,0x08,0x16,0x08,0x04,0x06,0x06,0x0E,0x04,
155      0x08,0x0C,0x06,0x06,0x04,0x14,0x04,0x12,0x02,0x0C,0x06,0x04,0x06,0x0E,0x12,0x0A,
156      0x08,0x0A,0x20,0x06,0x0A,0x06,0x06,0x02,0x06,0x10,0x06,0x02,0x0C,0x06,0x1C,0x02,
157      0x0A,0x08,0x10,0x06,0x08,0x06,0x0A,0x18,0x14,0x0A,0x02,0x0A,0x02,0x0C,0x04,0x06,
158      0x14,0x04,0x02,0x0C,0x12,0x0A,0x02,0x0A,0x02,0x04,0x14,0x10,0x1A,0x04,0x08,0x06,
159      0x04,0x0C,0x06,0x08,0x0C,0x0C,0x06,0x04,0x08,0x16,0x02,0x10,0x0E,0x0A,0x06,0x0C,
160      0x0C,0x0E,0x06,0x04,0x14,0x04,0x0C,0x06,0x02,0x06,0x06,0x10,0x08,0x16,0x02,0x1C,
161      0x08,0x06,0x04,0x14,0x04,0x0C,0x18,0x14,0x04,0x08,0x0A,0x02,0x10,0x02,0x0C,0x0C,
162      0x22,0x02,0x04,0x06,0x0C,0x06,0x06,0x08,0x06,0x04,0x02,0x06,0x18,0x04,0x14,0x0A,
163      0x06,0x06,0x0E,0x04,0x06,0x06,0x02,0x0C,0x06,0x0A,0x02,0x0A,0x06,0x14,0x04,0x1A,
164      0x04,0x02,0x06,0x16,0x02,0x18,0x04,0x06,0x02,0x04,0x06,0x18,0x06,0x08,0x04,0x02,
165      0x22,0x06,0x08,0x10,0x0C,0x02,0x0A,0x02,0x0A,0x06,0x08,0x04,0x08,0x0C,0x16,0x06,
166      0x0E,0x04,0x1A,0x04,0x02,0x0C,0x0A,0x08,0x04,0x08,0x0C,0x04,0x0E,0x06,0x10,0x06,
167      0x08,0x04,0x06,0x06,0x08,0x06,0x0A,0x0C,0x02,0x06,0x06,0x10,0x08,0x06,0x06,0x0C,
168      0x0A,0x02,0x06,0x12,0x04,0x06,0x06,0x06,0x0C,0x12,0x08,0x06,0x0A,0x08,0x12,0x04,
169      0x0E,0x06,0x12,0x0A,0x08,0x0A,0x0C,0x02,0x06,0x0C,0x0C,0x24,0x04,0x06,0x08,0x04
170   #endif
171   // 1536
172   #if PRIME_DIFF_TABLE_BYTES > 1536
173     ,0x06,0x02,0x04,0x12,0x0C,0x06,0x08,0x06,0x06,0x04,0x12,0x02,0x04,0x02,0x18,0x04,
174      0x06,0x06,0x0E,0x1E,0x06,0x04,0x06,0x0C,0x06,0x14,0x04,0x08,0x04,0x08,0x06,0x06,
175      0x04,0x1E,0x02,0x0A,0x0C,0x08,0x0A,0x08,0x18,0x06,0x0C,0x04,0x0E,0x04,0x06,0x02,
176      0x1C,0x0E,0x10,0x02,0x0C,0x06,0x04,0x14,0x0A,0x06,0x06,0x06,0x08,0x0A,0x0C,0x0E,
177      0x0A,0x0E,0x10,0x0E,0x0A,0x0E,0x06,0x10,0x06,0x08,0x06,0x10,0x14,0x0A,0x02,0x06,
178      0x04,0x02,0x04,0x0C,0x02,0x0A,0x02,0x06,0x16,0x06,0x02,0x04,0x12,0x08,0x0A,0x08,
179      0x16,0x02,0x0A,0x12,0x0E,0x04,0x02,0x04,0x12,0x02,0x04,0x06,0x08,0x0A,0x02,0x1E,

      Family "2.0"                        TCG Published                                Page 461
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

180      0x04,0x1E,0x02,0x0A,0x02,0x12,0x04,0x12,0x06,0x0E,0x0A,0x02,0x04,0x14,0x24,0x06,
181      0x04,0x06,0x0E,0x04,0x14,0x0A,0x0E,0x16,0x06,0x02,0x1E,0x0C,0x0A,0x12,0x02,0x04,
182      0x0E,0x06,0x16,0x12,0x02,0x0C,0x06,0x04,0x08,0x04,0x08,0x06,0x0A,0x02,0x0C,0x12,
183      0x0A,0x0E,0x10,0x0E,0x04,0x06,0x06,0x02,0x06,0x04,0x02,0x1C,0x02,0x1C,0x06,0x02,
184      0x04,0x06,0x0E,0x04,0x0C,0x0E,0x10,0x0E,0x04,0x06,0x08,0x06,0x04,0x06,0x06,0x06,
185      0x08,0x04,0x08,0x04,0x0E,0x10,0x08,0x06,0x04,0x0C,0x08,0x10,0x02,0x0A,0x08,0x04,
186      0x06,0x1A,0x06,0x0A,0x08,0x04,0x06,0x0C,0x0E,0x1E,0x04,0x0E,0x16,0x08,0x0C,0x04,
187      0x06,0x08,0x0A,0x06,0x0E,0x0A,0x06,0x02,0x0A,0x0C,0x0C,0x0E,0x06,0x06,0x12,0x0A,
188      0x06,0x08,0x12,0x04,0x06,0x02,0x06,0x0A,0x02,0x0A,0x08,0x06,0x06,0x0A,0x02,0x12
189   #endif
190   // 1792
191   #if PRIME_DIFF_TABLE_BYTES > 1792
192     ,0x0A,0x02,0x0C,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x0C,0x04,0x08,0x0A,0x06,0x06,0x14,
193      0x04,0x0E,0x10,0x0E,0x0A,0x08,0x0A,0x0C,0x02,0x12,0x06,0x0C,0x0A,0x0C,0x02,0x04,
194      0x02,0x0C,0x06,0x04,0x08,0x04,0x2C,0x04,0x02,0x04,0x02,0x0A,0x0C,0x06,0x06,0x0E,
195      0x04,0x06,0x06,0x06,0x08,0x06,0x24,0x12,0x04,0x06,0x02,0x0C,0x06,0x06,0x06,0x04,
196      0x0E,0x16,0x0C,0x02,0x12,0x0A,0x06,0x1A,0x18,0x04,0x02,0x04,0x02,0x04,0x0E,0x04,
197      0x06,0x06,0x08,0x10,0x0C,0x02,0x2A,0x04,0x02,0x04,0x18,0x06,0x06,0x02,0x12,0x04,
198      0x0E,0x06,0x1C,0x12,0x0E,0x06,0x0A,0x0C,0x02,0x06,0x0C,0x1E,0x06,0x04,0x06,0x06,
199      0x0E,0x04,0x02,0x18,0x04,0x06,0x06,0x1A,0x0A,0x12,0x06,0x08,0x06,0x06,0x1E,0x04,
200      0x0C,0x0C,0x02,0x10,0x02,0x06,0x04,0x0C,0x12,0x02,0x06,0x04,0x1A,0x0C,0x06,0x0C,
201      0x04,0x18,0x18,0x0C,0x06,0x02,0x0C,0x1C,0x08,0x04,0x06,0x0C,0x02,0x12,0x06,0x04,
202      0x06,0x06,0x14,0x10,0x02,0x06,0x06,0x12,0x0A,0x06,0x02,0x04,0x08,0x06,0x06,0x18,
203      0x10,0x06,0x08,0x0A,0x06,0x0E,0x16,0x08,0x10,0x06,0x02,0x0C,0x04,0x02,0x16,0x08,
204      0x12,0x22,0x02,0x06,0x12,0x04,0x06,0x06,0x08,0x0A,0x08,0x12,0x06,0x04,0x02,0x04,
205      0x08,0x10,0x02,0x0C,0x0C,0x06,0x12,0x04,0x06,0x06,0x06,0x02,0x06,0x0C,0x0A,0x14,
206      0x0C,0x12,0x04,0x06,0x02,0x10,0x02,0x0A,0x0E,0x04,0x1E,0x02,0x0A,0x0C,0x02,0x18,
207      0x06,0x10,0x08,0x0A,0x02,0x0C,0x16,0x06,0x02,0x10,0x14,0x0A,0x02,0x0C,0x0C,0x00
208   #endif
209   // 2048
210   #if PRIME_DIFF_TABLE_BYTES > 2048
211     ,0x12,0x0A,0x0C,0x06,0x02,0x0A,0x02,0x06,0x0A,0x12,0x02,0x0C,0x06,0x04,0x06,0x02,
212      0x18,0x1C,0x02,0x04,0x02,0x0A,0x02,0x10,0x0C,0x08,0x16,0x02,0x06,0x04,0x02,0x0A,
213      0x06,0x14,0x0C,0x0A,0x08,0x0C,0x06,0x06,0x06,0x04,0x12,0x02,0x04,0x0C,0x12,0x02,
214      0x0C,0x06,0x04,0x02,0x10,0x0C,0x0C,0x0E,0x04,0x08,0x12,0x04,0x0C,0x0E,0x06,0x06,
215      0x04,0x08,0x06,0x04,0x14,0x0C,0x0A,0x0E,0x04,0x02,0x10,0x02,0x0C,0x1E,0x04,0x06,
216      0x18,0x14,0x18,0x0A,0x08,0x0C,0x0A,0x0C,0x06,0x0C,0x0C,0x06,0x08,0x10,0x0E,0x06,
217      0x04,0x06,0x24,0x14,0x0A,0x1E,0x0C,0x02,0x04,0x02,0x1C,0x0C,0x0E,0x06,0x16,0x08,
218      0x04,0x12,0x06,0x0E,0x12,0x04,0x06,0x02,0x06,0x22,0x12,0x02,0x10,0x06,0x12,0x02,
219      0x18,0x04,0x02,0x06,0x0C,0x06,0x0C,0x0A,0x08,0x06,0x10,0x0C,0x08,0x0A,0x0E,0x28,
220      0x06,0x02,0x06,0x04,0x0C,0x0E,0x04,0x02,0x04,0x02,0x04,0x08,0x06,0x0A,0x06,0x06,
221      0x02,0x06,0x06,0x06,0x0C,0x06,0x18,0x0A,0x02,0x0A,0x06,0x0C,0x06,0x06,0x0E,0x06,
222      0x06,0x34,0x14,0x06,0x0A,0x02,0x0A,0x08,0x0A,0x0C,0x0C,0x02,0x06,0x04,0x0E,0x10,
223      0x08,0x0C,0x06,0x16,0x02,0x0A,0x08,0x06,0x16,0x02,0x16,0x06,0x08,0x0A,0x0C,0x0C,
224      0x02,0x0A,0x06,0x0C,0x02,0x04,0x0E,0x0A,0x02,0x06,0x12,0x04,0x0C,0x08,0x12,0x0C,
225      0x06,0x06,0x04,0x06,0x06,0x0E,0x04,0x02,0x0C,0x0C,0x04,0x06,0x12,0x12,0x0C,0x02,
226      0x10,0x0C,0x08,0x12,0x0A,0x1A,0x04,0x06,0x08,0x06,0x06,0x04,0x02,0x0A,0x14,0x04
227   #endif
228   // 2304
229   #if PRIME_DIFF_TABLE_BYTES > 2304
230     ,0x06,0x08,0x04,0x14,0x0A,0x02,0x22,0x02,0x04,0x18,0x02,0x0C,0x0C,0x0A,0x06,0x02,
231      0x0C,0x1E,0x06,0x0C,0x10,0x0C,0x02,0x16,0x12,0x0C,0x0E,0x0A,0x02,0x0C,0x0C,0x04,
232      0x02,0x04,0x06,0x0C,0x02,0x10,0x12,0x02,0x28,0x08,0x10,0x06,0x08,0x0A,0x02,0x04,
233      0x12,0x08,0x0A,0x08,0x0C,0x04,0x12,0x02,0x12,0x0A,0x02,0x04,0x02,0x04,0x08,0x1C,
234      0x02,0x06,0x16,0x0C,0x06,0x0E,0x12,0x04,0x06,0x08,0x06,0x06,0x0A,0x08,0x04,0x02,
235      0x12,0x0A,0x06,0x14,0x16,0x08,0x06,0x1E,0x04,0x02,0x04,0x12,0x06,0x1E,0x02,0x04,
236      0x08,0x06,0x04,0x06,0x0C,0x0E,0x22,0x0E,0x06,0x04,0x02,0x06,0x04,0x0E,0x04,0x02,
237      0x06,0x1C,0x02,0x04,0x06,0x08,0x0A,0x02,0x0A,0x02,0x0A,0x02,0x04,0x1E,0x02,0x0C,
238      0x0C,0x0A,0x12,0x0C,0x0E,0x0A,0x02,0x0C,0x06,0x0A,0x06,0x0E,0x0C,0x04,0x0E,0x04,
239      0x12,0x02,0x0A,0x08,0x04,0x08,0x0A,0x0C,0x12,0x12,0x08,0x06,0x12,0x10,0x0E,0x06,
240      0x06,0x0A,0x0E,0x04,0x06,0x02,0x0C,0x0C,0x04,0x06,0x06,0x0C,0x02,0x10,0x02,0x0C,
241      0x06,0x04,0x0E,0x06,0x04,0x02,0x0C,0x12,0x04,0x24,0x12,0x0C,0x0C,0x02,0x04,0x02,
242      0x04,0x08,0x0C,0x04,0x24,0x06,0x12,0x02,0x0C,0x0A,0x06,0x0C,0x18,0x08,0x06,0x06,
243      0x10,0x0C,0x02,0x12,0x0A,0x14,0x0A,0x02,0x06,0x12,0x04,0x02,0x28,0x06,0x02,0x10,
244      0x02,0x04,0x08,0x12,0x0A,0x0C,0x06,0x02,0x0A,0x08,0x04,0x06,0x0C,0x02,0x0A,0x12,
245      0x08,0x06,0x04,0x14,0x04,0x06,0x24,0x06,0x02,0x0A,0x06,0x18,0x06,0x0E,0x10,0x06

      Page 462                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

246   #endif
247   // 2560
248   #if PRIME_DIFF_TABLE_BYTES > 2560
249     ,0x12,0x02,0x0A,0x14,0x0A,0x08,0x06,0x04,0x06,0x02,0x0A,0x02,0x0C,0x04,0x02,0x04,
250      0x08,0x0A,0x06,0x0C,0x12,0x0E,0x0C,0x10,0x08,0x06,0x10,0x08,0x04,0x02,0x06,0x12,
251      0x18,0x12,0x0A,0x0C,0x02,0x04,0x0E,0x0A,0x06,0x06,0x06,0x12,0x0C,0x02,0x1C,0x12,
252      0x0E,0x10,0x0C,0x0E,0x18,0x0C,0x16,0x06,0x02,0x0A,0x08,0x04,0x02,0x04,0x0E,0x0C,
253      0x06,0x04,0x06,0x0E,0x04,0x02,0x04,0x1E,0x06,0x02,0x06,0x0A,0x02,0x1E,0x16,0x02,
254      0x04,0x06,0x08,0x06,0x06,0x10,0x0C,0x0C,0x06,0x08,0x04,0x02,0x18,0x0C,0x04,0x06,
255      0x08,0x06,0x06,0x0A,0x02,0x06,0x0C,0x1C,0x0E,0x06,0x04,0x0C,0x08,0x06,0x0C,0x04,
256      0x06,0x0E,0x06,0x0C,0x0A,0x06,0x06,0x08,0x06,0x06,0x04,0x02,0x04,0x08,0x0C,0x04,
257      0x0E,0x12,0x0A,0x02,0x10,0x06,0x14,0x06,0x0A,0x08,0x04,0x1E,0x24,0x0C,0x08,0x16,
258      0x0C,0x02,0x06,0x0C,0x10,0x06,0x06,0x02,0x12,0x04,0x1A,0x04,0x08,0x12,0x0A,0x08,
259      0x0A,0x06,0x0E,0x04,0x14,0x16,0x12,0x0C,0x08,0x1C,0x0C,0x06,0x06,0x08,0x06,0x0C,
260      0x18,0x10,0x0E,0x04,0x0E,0x0C,0x06,0x0A,0x0C,0x14,0x06,0x04,0x08,0x12,0x0C,0x12,
261      0x0A,0x02,0x04,0x14,0x0A,0x0E,0x04,0x06,0x02,0x0A,0x18,0x12,0x02,0x04,0x14,0x10,
262      0x0E,0x0A,0x0E,0x06,0x04,0x06,0x14,0x06,0x0A,0x06,0x02,0x0C,0x06,0x1E,0x0A,0x08,
263      0x06,0x04,0x06,0x08,0x28,0x02,0x04,0x02,0x0C,0x12,0x04,0x06,0x08,0x0A,0x06,0x12,
264      0x12,0x02,0x0C,0x10,0x08,0x06,0x04,0x06,0x06,0x02,0x34,0x0E,0x04,0x14,0x10,0x02
265   #endif
266   // 2816
267   #if PRIME_DIFF_TABLE_BYTES > 2816
268     ,0x04,0x06,0x0C,0x02,0x06,0x0C,0x0C,0x06,0x04,0x0E,0x0A,0x06,0x06,0x0E,0x0A,0x0E,
269      0x10,0x08,0x06,0x0C,0x04,0x08,0x16,0x06,0x02,0x12,0x16,0x06,0x02,0x12,0x06,0x10,
270      0x0E,0x0A,0x06,0x0C,0x02,0x06,0x04,0x08,0x12,0x0C,0x10,0x02,0x04,0x0E,0x04,0x08,
271      0x0C,0x0C,0x1E,0x10,0x08,0x04,0x02,0x06,0x16,0x0C,0x08,0x0A,0x06,0x06,0x06,0x0E,
272      0x06,0x12,0x0A,0x0C,0x02,0x0A,0x02,0x04,0x1A,0x04,0x0C,0x08,0x04,0x12,0x08,0x0A,
273      0x0E,0x10,0x06,0x06,0x08,0x0A,0x06,0x08,0x06,0x0C,0x0A,0x14,0x0A,0x08,0x04,0x0C,
274      0x1A,0x12,0x04,0x0C,0x12,0x06,0x1E,0x06,0x08,0x06,0x16,0x0C,0x02,0x04,0x06,0x06,
275      0x02,0x0A,0x02,0x04,0x06,0x06,0x02,0x06,0x16,0x12,0x06,0x12,0x0C,0x08,0x0C,0x06,
276      0x0A,0x0C,0x02,0x10,0x02,0x0A,0x02,0x0A,0x12,0x06,0x14,0x04,0x02,0x06,0x16,0x06,
277      0x06,0x12,0x06,0x0E,0x0C,0x10,0x02,0x06,0x06,0x04,0x0E,0x0C,0x04,0x02,0x12,0x10,
278      0x24,0x0C,0x06,0x0E,0x1C,0x02,0x0C,0x06,0x0C,0x06,0x04,0x02,0x10,0x1E,0x08,0x18,
279      0x06,0x1E,0x0A,0x02,0x12,0x04,0x06,0x0C,0x08,0x16,0x02,0x06,0x16,0x12,0x02,0x0A,
280      0x02,0x0A,0x1E,0x02,0x1C,0x06,0x0E,0x10,0x06,0x14,0x10,0x02,0x06,0x04,0x20,0x04,
281      0x02,0x04,0x06,0x02,0x0C,0x04,0x06,0x06,0x0C,0x02,0x06,0x04,0x06,0x08,0x06,0x04,
282      0x14,0x04,0x20,0x0A,0x08,0x10,0x02,0x16,0x02,0x04,0x06,0x08,0x06,0x10,0x0E,0x04,
283      0x12,0x08,0x04,0x14,0x06,0x0C,0x0C,0x06,0x0A,0x02,0x0A,0x02,0x0C,0x1C,0x0C,0x12
284   #endif
285   // 3072
286   #if PRIME_DIFF_TABLE_BYTES > 3072
287     ,0x02,0x12,0x0A,0x08,0x0A,0x30,0x02,0x04,0x06,0x08,0x0A,0x02,0x0A,0x1E,0x02,0x24,
288      0x06,0x0A,0x06,0x02,0x12,0x04,0x06,0x08,0x10,0x0E,0x10,0x06,0x0E,0x04,0x14,0x04,
289      0x06,0x02,0x0A,0x0C,0x02,0x06,0x0C,0x06,0x06,0x04,0x0C,0x02,0x06,0x04,0x0C,0x06,
290      0x08,0x04,0x02,0x06,0x12,0x0A,0x06,0x08,0x0C,0x06,0x16,0x02,0x06,0x0C,0x12,0x04,
291      0x0E,0x06,0x04,0x14,0x06,0x10,0x08,0x04,0x08,0x16,0x08,0x0C,0x06,0x06,0x10,0x0C,
292      0x12,0x1E,0x08,0x04,0x02,0x04,0x06,0x1A,0x04,0x0E,0x18,0x16,0x06,0x02,0x06,0x0A,
293      0x06,0x0E,0x06,0x06,0x0C,0x0A,0x06,0x02,0x0C,0x0A,0x0C,0x08,0x12,0x12,0x0A,0x06,
294      0x08,0x10,0x06,0x06,0x08,0x10,0x14,0x04,0x02,0x0A,0x02,0x0A,0x0C,0x06,0x08,0x06,
295      0x0A,0x14,0x0A,0x12,0x1A,0x04,0x06,0x1E,0x02,0x04,0x08,0x06,0x0C,0x0C,0x12,0x04,
296      0x08,0x16,0x06,0x02,0x0C,0x22,0x06,0x12,0x0C,0x06,0x02,0x1C,0x0E,0x10,0x0E,0x04,
297      0x0E,0x0C,0x04,0x06,0x06,0x02,0x24,0x04,0x06,0x14,0x0C,0x18,0x06,0x16,0x02,0x10,
298      0x12,0x0C,0x0C,0x12,0x02,0x06,0x06,0x06,0x04,0x06,0x0E,0x04,0x02,0x16,0x08,0x0C,
299      0x06,0x0A,0x06,0x08,0x0C,0x12,0x0C,0x06,0x0A,0x02,0x16,0x0E,0x06,0x06,0x04,0x12,
300      0x06,0x14,0x16,0x02,0x0C,0x18,0x04,0x12,0x12,0x02,0x16,0x02,0x04,0x0C,0x08,0x0C,
301      0x0A,0x0E,0x04,0x02,0x12,0x10,0x26,0x06,0x06,0x06,0x0C,0x0A,0x06,0x0C,0x08,0x06,
302      0x04,0x06,0x0E,0x1E,0x06,0x0A,0x08,0x16,0x06,0x08,0x0C,0x0A,0x02,0x0A,0x02,0x06
303   #endif
304   // 3328
305   #if PRIME_DIFF_TABLE_BYTES > 3328
306     ,0x0A,0x02,0x0A,0x0C,0x12,0x14,0x06,0x04,0x08,0x16,0x06,0x06,0x1E,0x06,0x0E,0x06,
307      0x0C,0x0C,0x06,0x0A,0x02,0x0A,0x1E,0x02,0x10,0x08,0x04,0x02,0x06,0x12,0x04,0x02,
308      0x06,0x04,0x1A,0x04,0x08,0x06,0x0A,0x02,0x04,0x06,0x08,0x04,0x06,0x1E,0x0C,0x02,
309      0x06,0x06,0x04,0x14,0x16,0x08,0x04,0x02,0x04,0x48,0x08,0x04,0x08,0x16,0x02,0x04,
310      0x0E,0x0A,0x02,0x04,0x14,0x06,0x0A,0x12,0x06,0x14,0x10,0x06,0x08,0x06,0x04,0x14,
311      0x0C,0x16,0x02,0x04,0x02,0x0C,0x0A,0x12,0x02,0x16,0x06,0x12,0x1E,0x02,0x0A,0x0E,

      Family "2.0"                        TCG Published                                Page 463
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

312      0x0A,0x08,0x10,0x32,0x06,0x0A,0x08,0x0A,0x0C,0x06,0x12,0x02,0x16,0x06,0x02,0x04,
313      0x06,0x08,0x06,0x06,0x0A,0x12,0x02,0x16,0x02,0x10,0x0E,0x0A,0x06,0x02,0x0C,0x0A,
314      0x14,0x04,0x0E,0x06,0x04,0x24,0x02,0x04,0x06,0x0C,0x02,0x04,0x0E,0x0C,0x06,0x04,
315      0x06,0x02,0x06,0x04,0x14,0x0A,0x02,0x0A,0x06,0x0C,0x02,0x18,0x0C,0x0C,0x06,0x06,
316      0x04,0x18,0x02,0x04,0x18,0x02,0x06,0x04,0x06,0x08,0x10,0x06,0x02,0x0A,0x0C,0x0E,
317      0x06,0x22,0x06,0x0E,0x06,0x04,0x02,0x1E,0x16,0x08,0x04,0x06,0x08,0x04,0x02,0x1C,
318      0x02,0x06,0x04,0x1A,0x12,0x16,0x02,0x06,0x10,0x06,0x02,0x10,0x0C,0x02,0x0C,0x04,
319      0x06,0x06,0x0E,0x0A,0x06,0x08,0x0C,0x04,0x12,0x02,0x0A,0x08,0x10,0x06,0x06,0x1E,
320      0x02,0x0A,0x12,0x02,0x0A,0x08,0x04,0x08,0x0C,0x18,0x28,0x02,0x0C,0x0A,0x06,0x0C,
321      0x02,0x0C,0x04,0x02,0x04,0x06,0x12,0x0E,0x0C,0x06,0x04,0x0E,0x1E,0x04,0x08,0x0A
322   #endif
323   // 3584
324   #if PRIME_DIFF_TABLE_BYTES > 3584
325     ,0x08,0x06,0x0A,0x12,0x08,0x04,0x0E,0x10,0x06,0x08,0x04,0x06,0x02,0x0A,0x02,0x0C,
326      0x04,0x02,0x04,0x06,0x08,0x04,0x06,0x20,0x18,0x0A,0x08,0x12,0x0A,0x02,0x06,0x0A,
327      0x02,0x04,0x12,0x06,0x0C,0x02,0x10,0x02,0x16,0x06,0x06,0x08,0x12,0x04,0x12,0x0C,
328      0x08,0x06,0x04,0x14,0x06,0x1E,0x16,0x0C,0x02,0x06,0x12,0x04,0x3E,0x04,0x02,0x0C,
329      0x06,0x0A,0x02,0x0C,0x0C,0x1C,0x02,0x04,0x0E,0x16,0x06,0x02,0x06,0x06,0x0A,0x0E,
330      0x04,0x02,0x0A,0x06,0x08,0x0A,0x0E,0x0A,0x06,0x02,0x0C,0x16,0x12,0x08,0x0A,0x12,
331      0x0C,0x02,0x0C,0x04,0x0C,0x02,0x0A,0x02,0x06,0x12,0x06,0x06,0x22,0x06,0x02,0x0C,
332      0x04,0x06,0x12,0x12,0x02,0x10,0x06,0x06,0x08,0x06,0x0A,0x12,0x08,0x0A,0x08,0x0A,
333      0x02,0x04,0x12,0x1A,0x0C,0x16,0x02,0x04,0x02,0x16,0x06,0x06,0x0E,0x10,0x06,0x14,
334      0x0A,0x0C,0x02,0x12,0x2A,0x04,0x18,0x02,0x06,0x0A,0x0C,0x02,0x06,0x0A,0x08,0x04,
335      0x06,0x0C,0x0C,0x08,0x04,0x06,0x0C,0x1E,0x14,0x06,0x18,0x06,0x0A,0x0C,0x02,0x0A,
336      0x14,0x06,0x06,0x04,0x0C,0x0E,0x0A,0x12,0x0C,0x08,0x06,0x0C,0x04,0x0E,0x0A,0x02,
337      0x0C,0x1E,0x10,0x02,0x0C,0x06,0x04,0x02,0x04,0x06,0x1A,0x04,0x12,0x02,0x04,0x06,
338      0x0E,0x36,0x06,0x34,0x02,0x10,0x06,0x06,0x0C,0x1A,0x04,0x02,0x06,0x16,0x06,0x02,
339      0x0C,0x0C,0x06,0x0A,0x12,0x02,0x0C,0x0C,0x0A,0x12,0x0C,0x06,0x08,0x06,0x0A,0x06,
340      0x08,0x04,0x02,0x04,0x14,0x18,0x06,0x06,0x0A,0x0E,0x0A,0x02,0x16,0x06,0x0E,0x0A
341   #endif
342   // 3840
343   #if PRIME_DIFF_TABLE_BYTES > 3840
344     ,0x1A,0x04,0x12,0x08,0x0C,0x0C,0x0A,0x0C,0x06,0x08,0x10,0x06,0x08,0x06,0x06,0x16,
345      0x02,0x0A,0x14,0x0A,0x06,0x2C,0x12,0x06,0x0A,0x02,0x04,0x06,0x0E,0x04,0x1A,0x04,
346      0x02,0x0C,0x0A,0x08,0x04,0x08,0x0C,0x04,0x0C,0x08,0x16,0x08,0x06,0x0A,0x12,0x06,
347      0x06,0x08,0x06,0x0C,0x04,0x08,0x12,0x0A,0x0C,0x06,0x0C,0x02,0x06,0x04,0x02,0x10,
348      0x0C,0x0C,0x0E,0x0A,0x0E,0x06,0x0A,0x0C,0x02,0x0C,0x06,0x04,0x06,0x02,0x0C,0x04,
349      0x1A,0x06,0x12,0x06,0x0A,0x06,0x02,0x12,0x0A,0x08,0x04,0x1A,0x0A,0x14,0x06,0x10,
350      0x14,0x0C,0x0A,0x08,0x0A,0x02,0x10,0x06,0x14,0x0A,0x14,0x04,0x1E,0x02,0x04,0x08,
351      0x10,0x02,0x12,0x04,0x02,0x06,0x0A,0x12,0x0C,0x0E,0x12,0x06,0x10,0x14,0x06,0x04,
352      0x08,0x06,0x04,0x06,0x0C,0x08,0x0A,0x02,0x0C,0x06,0x04,0x02,0x06,0x0A,0x02,0x10,
353      0x0C,0x0E,0x0A,0x06,0x08,0x06,0x1C,0x02,0x06,0x12,0x1E,0x22,0x02,0x10,0x0C,0x02,
354      0x12,0x10,0x06,0x08,0x0A,0x08,0x0A,0x08,0x0A,0x2C,0x06,0x06,0x04,0x14,0x04,0x02,
355      0x04,0x0E,0x1C,0x08,0x06,0x10,0x0E,0x1E,0x06,0x1E,0x04,0x0E,0x0A,0x06,0x06,0x08,
356      0x04,0x12,0x0C,0x06,0x02,0x16,0x0C,0x08,0x06,0x0C,0x04,0x0E,0x04,0x06,0x02,0x04,
357      0x12,0x14,0x06,0x10,0x26,0x10,0x02,0x04,0x06,0x02,0x28,0x2A,0x0E,0x04,0x06,0x02,
358      0x18,0x0A,0x06,0x02,0x12,0x0A,0x0C,0x02,0x10,0x02,0x06,0x10,0x06,0x08,0x04,0x02,
359      0x0A,0x06,0x08,0x0A,0x02,0x12,0x10,0x08,0x0C,0x12,0x0C,0x06,0x0C,0x0A,0x06,0x06
360   #endif
361   // 4096
362   #if PRIME_DIFF_TABLE_BYTES > 4096
363     ,0x12,0x0C,0x0E,0x04,0x02,0x0A,0x14,0x06,0x0C,0x06,0x10,0x1A,0x04,0x12,0x02,0x04,
364      0x20,0x0A,0x08,0x06,0x04,0x06,0x06,0x0E,0x06,0x12,0x04,0x02,0x12,0x0A,0x08,0x0A,
365      0x08,0x0A,0x02,0x04,0x06,0x02,0x0A,0x2A,0x08,0x0C,0x04,0x06,0x12,0x02,0x10,0x08,
366      0x04,0x02,0x0A,0x0E,0x0C,0x0A,0x14,0x04,0x08,0x0A,0x26,0x04,0x06,0x02,0x0A,0x14,
367      0x0A,0x0C,0x06,0x0C,0x1A,0x0C,0x04,0x08,0x1C,0x08,0x04,0x08,0x18,0x06,0x0A,0x08,
368      0x06,0x10,0x0C,0x08,0x0A,0x0C,0x08,0x16,0x06,0x02,0x0A,0x02,0x06,0x0A,0x06,0x06,
369      0x08,0x06,0x04,0x0E,0x1C,0x08,0x10,0x12,0x08,0x04,0x06,0x14,0x04,0x12,0x06,0x02,
370      0x18,0x18,0x06,0x06,0x0C,0x0C,0x04,0x02,0x16,0x02,0x0A,0x06,0x08,0x0C,0x04,0x14,
371      0x12,0x06,0x04,0x0C,0x18,0x06,0x06,0x36,0x08,0x06,0x04,0x1A,0x24,0x04,0x02,0x04,
372      0x1A,0x0C,0x0C,0x04,0x06,0x06,0x08,0x0C,0x0A,0x02,0x0C,0x10,0x12,0x06,0x08,0x06,
373      0x0C,0x12,0x0A,0x02,0x36,0x04,0x02,0x0A,0x1E,0x0C,0x08,0x04,0x08,0x10,0x0E,0x0C,
374      0x06,0x04,0x06,0x0C,0x06,0x02,0x04,0x0E,0x0C,0x04,0x0E,0x06,0x18,0x06,0x06,0x0A,
375      0x0C,0x0C,0x14,0x12,0x06,0x06,0x10,0x08,0x04,0x06,0x14,0x04,0x20,0x04,0x0E,0x0A,
376      0x02,0x06,0x0C,0x10,0x02,0x04,0x06,0x0C,0x02,0x0A,0x08,0x06,0x04,0x02,0x0A,0x0E,
377      0x06,0x06,0x0C,0x12,0x22,0x08,0x0A,0x06,0x18,0x06,0x02,0x0A,0x0C,0x02,0x1E,0x0A,

      Page 464                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

378      0x0E,0x0C,0x0C,0x10,0x06,0x06,0x02,0x12,0x04,0x06,0x1E,0x0E,0x04,0x06,0x06,0x02
379   #endif
380   // 4352
381   #if PRIME_DIFF_TABLE_BYTES > 4352
382     ,0x06,0x04,0x06,0x0E,0x06,0x04,0x08,0x0A,0x0C,0x06,0x20,0x0A,0x08,0x16,0x02,0x0A,
383      0x06,0x18,0x08,0x04,0x1E,0x06,0x02,0x0C,0x10,0x08,0x06,0x04,0x06,0x08,0x10,0x0E,
384      0x06,0x06,0x04,0x02,0x0A,0x0C,0x02,0x10,0x0E,0x04,0x02,0x04,0x14,0x12,0x0A,0x02,
385      0x0A,0x06,0x0C,0x1E,0x08,0x12,0x0C,0x0A,0x02,0x06,0x06,0x04,0x0C,0x0C,0x02,0x04,
386      0x0C,0x12,0x18,0x02,0x0A,0x06,0x08,0x10,0x08,0x06,0x0C,0x0A,0x0E,0x06,0x0C,0x06,
387      0x06,0x04,0x02,0x18,0x04,0x06,0x08,0x06,0x04,0x02,0x04,0x06,0x0E,0x04,0x08,0x0A,
388      0x18,0x18,0x0C,0x02,0x06,0x0C,0x16,0x1E,0x02,0x06,0x12,0x0A,0x06,0x06,0x08,0x04,
389      0x02,0x06,0x0A,0x08,0x0A,0x06,0x08,0x10,0x06,0x0E,0x06,0x04,0x18,0x08,0x0A,0x02,
390      0x0C,0x06,0x04,0x24,0x02,0x16,0x06,0x08,0x06,0x0A,0x08,0x06,0x0C,0x0A,0x0E,0x0A,
391      0x06,0x12,0x0C,0x02,0x0C,0x04,0x1A,0x0A,0x0E,0x10,0x12,0x08,0x12,0x0C,0x0C,0x06,
392      0x10,0x0E,0x18,0x0A,0x0C,0x08,0x16,0x06,0x02,0x0A,0x3C,0x06,0x02,0x04,0x08,0x10,
393      0x0E,0x0A,0x06,0x18,0x06,0x0C,0x12,0x18,0x02,0x1E,0x04,0x02,0x0C,0x06,0x0A,0x02,
394      0x04,0x0E,0x06,0x10,0x02,0x0A,0x08,0x16,0x14,0x06,0x04,0x20,0x06,0x12,0x04,0x02,
395      0x04,0x02,0x04,0x08,0x34,0x0E,0x16,0x02,0x16,0x14,0x0A,0x08,0x0A,0x02,0x06,0x04,
396      0x0E,0x04,0x06,0x14,0x04,0x06,0x02,0x0C,0x0C,0x06,0x0C,0x10,0x02,0x0C,0x0A,0x08,
397      0x04,0x06,0x02,0x1C,0x0C,0x08,0x0A,0x0C,0x02,0x04,0x0E,0x1C,0x08,0x06,0x04,0x02
398   #endif
399   // 4608
400   #if PRIME_DIFF_TABLE_BYTES > 4608
401     ,0x04,0x06,0x02,0x0C,0x3A,0x06,0x0E,0x0A,0x02,0x06,0x1C,0x20,0x04,0x1E,0x08,0x06,
402      0x04,0x06,0x0C,0x0C,0x02,0x04,0x06,0x06,0x0E,0x10,0x08,0x1E,0x04,0x02,0x0A,0x08,
403      0x06,0x04,0x06,0x1A,0x04,0x0C,0x02,0x0A,0x12,0x0C,0x0C,0x12,0x02,0x04,0x0C,0x08,
404      0x0C,0x0A,0x14,0x04,0x08,0x10,0x0C,0x08,0x06,0x10,0x08,0x0A,0x0C,0x0E,0x06,0x04,
405      0x08,0x0C,0x04,0x14,0x06,0x28,0x08,0x10,0x06,0x24,0x02,0x06,0x04,0x06,0x02,0x16,
406      0x12,0x02,0x0A,0x06,0x24,0x0E,0x0C,0x04,0x12,0x08,0x04,0x0E,0x0A,0x02,0x0A,0x08,
407      0x04,0x02,0x12,0x10,0x0C,0x0E,0x0A,0x0E,0x06,0x06,0x2A,0x0A,0x06,0x06,0x14,0x0A,
408      0x08,0x0C,0x04,0x0C,0x12,0x02,0x0A,0x0E,0x12,0x0A,0x12,0x08,0x06,0x04,0x0E,0x06,
409      0x0A,0x1E,0x0E,0x06,0x06,0x04,0x0C,0x26,0x04,0x02,0x04,0x06,0x08,0x0C,0x0A,0x06,
410      0x12,0x06,0x32,0x06,0x04,0x06,0x0C,0x08,0x0A,0x20,0x06,0x16,0x02,0x0A,0x0C,0x12,
411      0x02,0x06,0x04,0x1E,0x08,0x06,0x06,0x12,0x0A,0x02,0x04,0x0C,0x14,0x0A,0x08,0x18,
412      0x0A,0x02,0x06,0x16,0x06,0x02,0x12,0x0A,0x0C,0x02,0x1E,0x12,0x0C,0x1C,0x02,0x06,
413      0x04,0x06,0x0E,0x06,0x0C,0x0A,0x08,0x04,0x0C,0x1A,0x0A,0x08,0x06,0x10,0x02,0x0A,
414      0x12,0x0E,0x06,0x04,0x06,0x0E,0x10,0x02,0x06,0x04,0x0C,0x14,0x04,0x14,0x04,0x06,
415      0x0C,0x02,0x24,0x04,0x06,0x02,0x0A,0x02,0x16,0x08,0x06,0x0A,0x0C,0x0C,0x12,0x0E,
416      0x18,0x24,0x04,0x14,0x18,0x0A,0x06,0x02,0x1C,0x06,0x12,0x08,0x04,0x06,0x08,0x06
417   #endif
418   // 4864
419   #if PRIME_DIFF_TABLE_BYTES > 4864
420     ,0x04,0x02,0x0C,0x1C,0x12,0x0E,0x10,0x0E,0x12,0x0A,0x08,0x06,0x04,0x06,0x06,0x08,
421      0x16,0x0C,0x02,0x0A,0x12,0x06,0x02,0x12,0x0A,0x02,0x0C,0x0A,0x12,0x20,0x06,0x04,
422      0x06,0x06,0x08,0x06,0x06,0x0A,0x14,0x06,0x0C,0x0A,0x08,0x0A,0x0E,0x06,0x0A,0x0E,
423      0x04,0x02,0x16,0x12,0x02,0x0A,0x02,0x04,0x14,0x04,0x02,0x22,0x02,0x0C,0x06,0x0A,
424      0x02,0x0A,0x12,0x06,0x0E,0x0C,0x0C,0x16,0x08,0x06,0x10,0x06,0x08,0x04,0x0C,0x06,
425      0x08,0x04,0x24,0x06,0x06,0x14,0x18,0x06,0x0C,0x12,0x0A,0x02,0x0A,0x1A,0x06,0x10,
426      0x08,0x06,0x04,0x18,0x12,0x08,0x0C,0x0C,0x0A,0x12,0x0C,0x02,0x18,0x04,0x0C,0x12,
427      0x0C,0x0E,0x0A,0x02,0x04,0x18,0x0C,0x0E,0x0A,0x06,0x02,0x06,0x04,0x06,0x1A,0x04,
428      0x06,0x06,0x02,0x16,0x08,0x12,0x04,0x12,0x08,0x04,0x18,0x02,0x0C,0x0C,0x04,0x02,
429      0x34,0x02,0x12,0x06,0x04,0x06,0x0C,0x02,0x06,0x0C,0x0A,0x08,0x04,0x02,0x18,0x0A,
430      0x02,0x0A,0x02,0x0C,0x06,0x12,0x28,0x06,0x14,0x10,0x02,0x0C,0x06,0x0A,0x0C,0x02,
431      0x04,0x06,0x0E,0x0C,0x0C,0x16,0x06,0x08,0x04,0x02,0x10,0x12,0x0C,0x02,0x06,0x10,
432      0x06,0x02,0x06,0x04,0x0C,0x1E,0x08,0x10,0x02,0x12,0x0A,0x18,0x02,0x06,0x18,0x04,
433      0x02,0x16,0x02,0x10,0x02,0x06,0x0C,0x04,0x12,0x08,0x04,0x0E,0x04,0x12,0x18,0x06,
434      0x02,0x06,0x0A,0x02,0x0A,0x26,0x06,0x0A,0x0E,0x06,0x06,0x18,0x04,0x02,0x0C,0x10,
435      0x0E,0x10,0x0C,0x02,0x06,0x0A,0x1A,0x04,0x02,0x0C,0x06,0x04,0x0C,0x08,0x0C,0x0A
436   #endif
437   // 5120
438   #if PRIME_DIFF_TABLE_BYTES > 5120
439     ,0x12,0x06,0x0E,0x1C,0x02,0x06,0x0A,0x02,0x04,0x0E,0x22,0x02,0x06,0x16,0x02,0x0A,
440      0x0E,0x04,0x02,0x10,0x08,0x0A,0x06,0x08,0x0A,0x08,0x04,0x06,0x02,0x10,0x06,0x06,
441      0x12,0x1E,0x0E,0x06,0x04,0x1E,0x02,0x0A,0x0E,0x04,0x14,0x0A,0x08,0x04,0x08,0x12,
442      0x04,0x0E,0x06,0x04,0x18,0x06,0x06,0x12,0x12,0x02,0x24,0x06,0x0A,0x0E,0x0C,0x04,
443      0x06,0x02,0x1E,0x06,0x04,0x02,0x06,0x1C,0x14,0x04,0x14,0x0C,0x18,0x10,0x12,0x0C,

      Family "2.0"                        TCG Published                                Page 465
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

444      0x0E,0x06,0x04,0x0C,0x20,0x0C,0x06,0x0A,0x08,0x0A,0x06,0x12,0x02,0x10,0x0E,0x06,
445      0x16,0x06,0x0C,0x02,0x12,0x04,0x08,0x1E,0x0C,0x04,0x0C,0x02,0x0A,0x26,0x16,0x02,
446      0x04,0x0E,0x06,0x0C,0x18,0x04,0x02,0x04,0x0E,0x0C,0x0A,0x02,0x10,0x06,0x14,0x04,
447      0x14,0x16,0x0C,0x02,0x04,0x02,0x0C,0x16,0x18,0x06,0x06,0x02,0x06,0x04,0x06,0x02,
448      0x0A,0x0C,0x0C,0x06,0x02,0x06,0x10,0x08,0x06,0x04,0x12,0x0C,0x0C,0x0E,0x04,0x0C,
449      0x06,0x08,0x06,0x12,0x06,0x0A,0x0C,0x0E,0x06,0x04,0x08,0x16,0x06,0x02,0x1C,0x12,
450      0x02,0x12,0x0A,0x06,0x0E,0x0A,0x02,0x0A,0x0E,0x06,0x0A,0x02,0x16,0x06,0x08,0x06,
451      0x10,0x0C,0x08,0x16,0x02,0x04,0x0E,0x12,0x0C,0x06,0x18,0x06,0x0A,0x02,0x0C,0x16,
452      0x12,0x06,0x14,0x06,0x0A,0x0E,0x04,0x02,0x06,0x0C,0x16,0x0E,0x0C,0x04,0x06,0x08,
453      0x16,0x02,0x0A,0x0C,0x08,0x28,0x02,0x06,0x0A,0x08,0x04,0x2A,0x14,0x04,0x20,0x0C,
454      0x0A,0x06,0x0C,0x0C,0x02,0x0A,0x08,0x06,0x04,0x08,0x04,0x1A,0x12,0x04,0x08,0x1C
455   #endif
456   // 5376
457   #if PRIME_DIFF_TABLE_BYTES > 5376
458     ,0x06,0x12,0x06,0x0C,0x02,0x0A,0x06,0x06,0x0E,0x0A,0x0C,0x0E,0x18,0x06,0x04,0x14,
459      0x16,0x02,0x12,0x04,0x06,0x0C,0x02,0x10,0x12,0x0E,0x06,0x06,0x04,0x06,0x08,0x12,
460      0x04,0x0E,0x1E,0x04,0x12,0x08,0x0A,0x02,0x04,0x08,0x0C,0x04,0x0C,0x12,0x02,0x0C,
461      0x0A,0x02,0x10,0x08,0x04,0x1E,0x02,0x06,0x1C,0x02,0x0A,0x02,0x12,0x0A,0x0E,0x04,
462      0x1A,0x06,0x12,0x04,0x14,0x06,0x04,0x08,0x12,0x04,0x0C,0x1A,0x18,0x04,0x14,0x16,
463      0x02,0x12,0x16,0x02,0x04,0x0C,0x02,0x06,0x06,0x06,0x04,0x06,0x0E,0x04,0x18,0x0C,
464      0x06,0x12,0x02,0x0C,0x1C,0x0E,0x04,0x06,0x08,0x16,0x06,0x0C,0x12,0x08,0x04,0x14,
465      0x06,0x04,0x06,0x02,0x12,0x06,0x04,0x0C,0x0C,0x08,0x1C,0x06,0x08,0x0A,0x02,0x18,
466      0x0C,0x0A,0x18,0x08,0x0A,0x14,0x0C,0x06,0x0C,0x0C,0x04,0x0E,0x0C,0x18,0x22,0x12,
467      0x08,0x0A,0x06,0x12,0x08,0x04,0x08,0x10,0x0E,0x06,0x04,0x06,0x18,0x02,0x06,0x04,
468      0x06,0x02,0x10,0x06,0x06,0x14,0x18,0x04,0x02,0x04,0x0E,0x04,0x12,0x02,0x06,0x0C,
469      0x04,0x0E,0x04,0x02,0x12,0x10,0x06,0x06,0x02,0x10,0x14,0x06,0x06,0x1E,0x04,0x08,
470      0x06,0x18,0x10,0x06,0x06,0x08,0x0C,0x1E,0x04,0x12,0x12,0x08,0x04,0x1A,0x0A,0x02,
471      0x16,0x08,0x0A,0x0E,0x06,0x04,0x12,0x08,0x0C,0x1C,0x02,0x06,0x04,0x0C,0x06,0x18,
472      0x06,0x08,0x0A,0x14,0x10,0x08,0x1E,0x06,0x06,0x04,0x02,0x0A,0x0E,0x06,0x0A,0x20,
473      0x16,0x12,0x02,0x04,0x02,0x04,0x08,0x16,0x08,0x12,0x0C,0x1C,0x02,0x10,0x0C,0x12
474   #endif
475   // 5632
476   #if PRIME_DIFF_TABLE_BYTES > 5632
477     ,0x0E,0x0A,0x12,0x0C,0x06,0x20,0x0A,0x0E,0x06,0x0A,0x02,0x0A,0x02,0x06,0x16,0x02,
478      0x04,0x06,0x08,0x0A,0x06,0x0E,0x06,0x04,0x0C,0x1E,0x18,0x06,0x06,0x08,0x06,0x04,
479      0x02,0x04,0x06,0x08,0x06,0x06,0x16,0x12,0x08,0x04,0x02,0x12,0x06,0x04,0x02,0x10,
480      0x12,0x14,0x0A,0x06,0x06,0x1E,0x02,0x0C,0x1C,0x06,0x06,0x06,0x02,0x0C,0x0A,0x08,
481      0x12,0x12,0x04,0x08,0x12,0x0A,0x02,0x1C,0x02,0x0A,0x0E,0x04,0x02,0x1E,0x0C,0x16,
482      0x1A,0x0A,0x08,0x06,0x0A,0x08,0x10,0x0E,0x06,0x06,0x0A,0x0E,0x06,0x04,0x02,0x0A,
483      0x0C,0x02,0x06,0x0A,0x08,0x04,0x02,0x0A,0x1A,0x16,0x06,0x02,0x0C,0x12,0x04,0x1A,
484      0x04,0x08,0x0A,0x06,0x0E,0x0A,0x02,0x12,0x06,0x0A,0x14,0x06,0x06,0x04,0x18,0x02,
485      0x04,0x08,0x06,0x10,0x0E,0x10,0x12,0x02,0x04,0x0C,0x02,0x0A,0x02,0x06,0x0C,0x0A,
486      0x06,0x06,0x14,0x06,0x04,0x06,0x26,0x04,0x06,0x0C,0x0E,0x04,0x0C,0x08,0x0A,0x0C,
487      0x0C,0x08,0x04,0x06,0x0E,0x0A,0x06,0x0C,0x02,0x0A,0x12,0x02,0x12,0x0A,0x08,0x0A,
488      0x02,0x0C,0x04,0x0E,0x1C,0x02,0x10,0x02,0x12,0x06,0x0A,0x06,0x08,0x10,0x0E,0x1E,
489      0x0A,0x14,0x06,0x0A,0x18,0x02,0x1C,0x02,0x0C,0x10,0x06,0x08,0x24,0x04,0x08,0x04,
490      0x0E,0x0C,0x0A,0x08,0x0C,0x04,0x06,0x08,0x04,0x06,0x0E,0x16,0x08,0x06,0x04,0x02,
491      0x0A,0x06,0x14,0x0A,0x08,0x06,0x06,0x16,0x12,0x02,0x10,0x06,0x14,0x04,0x1A,0x04,
492      0x0E,0x16,0x0E,0x04,0x0C,0x06,0x08,0x04,0x06,0x06,0x1A,0x0A,0x02,0x12,0x12,0x04
493   #endif
494   // 5888
495   #if PRIME_DIFF_TABLE_BYTES > 5888
496     ,0x02,0x10,0x02,0x12,0x04,0x06,0x08,0x04,0x06,0x0C,0x02,0x06,0x06,0x1C,0x26,0x04,
497      0x08,0x10,0x1A,0x04,0x02,0x0A,0x0C,0x02,0x0A,0x08,0x06,0x0A,0x0C,0x02,0x0A,0x02,
498      0x18,0x04,0x1E,0x1A,0x06,0x06,0x12,0x06,0x06,0x16,0x02,0x0A,0x12,0x1A,0x04,0x12,
499      0x08,0x06,0x06,0x0C,0x10,0x06,0x08,0x10,0x06,0x08,0x10,0x02,0x2A,0x3A,0x08,0x04,
500      0x06,0x02,0x04,0x08,0x10,0x06,0x14,0x04,0x0C,0x0C,0x06,0x0C,0x02,0x0A,0x02,0x06,
501      0x16,0x02,0x0A,0x06,0x08,0x06,0x0A,0x0E,0x06,0x06,0x04,0x12,0x08,0x0A,0x08,0x10,
502      0x0E,0x0A,0x02,0x0A,0x02,0x0C,0x06,0x04,0x14,0x0A,0x08,0x34,0x08,0x0A,0x06,0x02,
503      0x0A,0x08,0x0A,0x06,0x06,0x08,0x0A,0x02,0x16,0x02,0x04,0x06,0x0E,0x04,0x02,0x18,
504      0x0C,0x04,0x1A,0x12,0x04,0x06,0x0E,0x1E,0x06,0x04,0x06,0x02,0x16,0x08,0x04,0x06,
505      0x02,0x16,0x06,0x08,0x10,0x06,0x0E,0x04,0x06,0x12,0x08,0x0C,0x06,0x0C,0x18,0x1E,
506      0x10,0x08,0x22,0x08,0x16,0x06,0x0E,0x0A,0x12,0x0E,0x04,0x0C,0x08,0x04,0x24,0x06,
507      0x06,0x02,0x0A,0x02,0x04,0x14,0x06,0x06,0x0A,0x0C,0x06,0x02,0x28,0x08,0x06,0x1C,
508      0x06,0x02,0x0C,0x12,0x04,0x18,0x0E,0x06,0x06,0x0A,0x14,0x0A,0x0E,0x10,0x0E,0x10,
509      0x06,0x08,0x24,0x04,0x0C,0x0C,0x06,0x0C,0x32,0x0C,0x06,0x04,0x06,0x06,0x08,0x06,

      Page 466                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                             Trusted Platform Module Library

510      0x0A,0x02,0x0A,0x02,0x12,0x0A,0x0E,0x10,0x08,0x06,0x04,0x14,0x04,0x02,0x0A,0x06,
511      0x0E,0x12,0x0A,0x26,0x0A,0x12,0x02,0x0A,0x02,0x0C,0x04,0x02,0x04,0x0E,0x06,0x0A
512   #endif
513   // 6144
514   #if PRIME_DIFF_TABLE_BYTES > 6144
515     ,0x08,0x28,0x06,0x14,0x04,0x0C,0x08,0x06,0x22,0x08,0x16,0x08,0x0C,0x0A,0x02,0x10,
516      0x2A,0x0C,0x08,0x16,0x08,0x16,0x08,0x06,0x22,0x02,0x06,0x04,0x0E,0x06,0x10,0x02,
517      0x16,0x06,0x08,0x18,0x16,0x06,0x02,0x0C,0x04,0x06,0x0E,0x04,0x08,0x18,0x04,0x06,
518      0x06,0x02,0x16,0x14,0x06,0x04,0x0E,0x04,0x06,0x06,0x08,0x06,0x0A,0x06,0x08,0x06,
519      0x10,0x0E,0x06,0x06,0x16,0x06,0x18,0x20,0x06,0x12,0x06,0x12,0x0A,0x08,0x1E,0x12,
520      0x06,0x10,0x0C,0x06,0x0C,0x02,0x06,0x04,0x0C,0x08,0x06,0x16,0x08,0x06,0x04,0x0E,
521      0x0A,0x12,0x14,0x0A,0x02,0x06,0x04,0x02,0x1C,0x12,0x02,0x0A,0x06,0x06,0x06,0x0E,
522      0x28,0x18,0x02,0x04,0x08,0x0C,0x04,0x14,0x04,0x20,0x12,0x10,0x06,0x24,0x08,0x06,
523      0x04,0x06,0x0E,0x04,0x06,0x1A,0x06,0x0A,0x0E,0x12,0x0A,0x06,0x06,0x0E,0x0A,0x06,
524      0x06,0x0E,0x06,0x18,0x04,0x0E,0x16,0x08,0x0C,0x0A,0x08,0x0C,0x12,0x0A,0x12,0x08,
525      0x18,0x0A,0x08,0x04,0x18,0x06,0x12,0x06,0x02,0x0A,0x1E,0x02,0x0A,0x02,0x04,0x02,
526      0x28,0x02,0x1C,0x08,0x06,0x06,0x12,0x06,0x0A,0x0E,0x04,0x12,0x1E,0x12,0x02,0x0C,
527      0x1E,0x06,0x1E,0x04,0x12,0x0C,0x02,0x04,0x0E,0x06,0x0A,0x06,0x08,0x06,0x0A,0x0C,
528      0x02,0x06,0x0C,0x0A,0x02,0x12,0x04,0x14,0x04,0x06,0x0E,0x06,0x06,0x16,0x06,0x06,
529      0x08,0x12,0x12,0x0A,0x02,0x0A,0x02,0x06,0x04,0x06,0x0C,0x12,0x02,0x0A,0x08,0x04,
530      0x12,0x02,0x06,0x06,0x06,0x0A,0x08,0x0A,0x06,0x12,0x0C,0x08,0x0C,0x06,0x04,0x06
531   #endif
532   // 6400
533   #if PRIME_DIFF_TABLE_BYTES > 6400
534     ,0x0E,0x10,0x02,0x0C,0x04,0x06,0x26,0x06,0x06,0x10,0x14,0x1C,0x14,0x0A,0x06,0x06,
535      0x0E,0x04,0x1A,0x04,0x0E,0x0A,0x12,0x0E,0x1C,0x02,0x04,0x0E,0x10,0x02,0x1C,0x06,
536      0x08,0x06,0x22,0x08,0x04,0x12,0x02,0x10,0x08,0x06,0x28,0x08,0x12,0x04,0x1E,0x06,
537      0x0C,0x02,0x1E,0x06,0x0A,0x0E,0x28,0x0E,0x0A,0x02,0x0C,0x0A,0x08,0x04,0x08,0x06,
538      0x06,0x1C,0x02,0x04,0x0C,0x0E,0x10,0x08,0x1E,0x10,0x12,0x02,0x0A,0x12,0x06,0x20,
539      0x04,0x12,0x06,0x02,0x0C,0x0A,0x12,0x02,0x06,0x0A,0x0E,0x12,0x1C,0x06,0x08,0x10,
540      0x02,0x04,0x14,0x0A,0x08,0x12,0x0A,0x02,0x0A,0x08,0x04,0x06,0x0C,0x06,0x14,0x04,
541      0x02,0x06,0x04,0x14,0x0A,0x1A,0x12,0x0A,0x02,0x12,0x06,0x10,0x0E,0x04,0x1A,0x04,
542      0x0E,0x0A,0x0C,0x0E,0x06,0x06,0x04,0x0E,0x0A,0x02,0x1E,0x12,0x16,0x02
543   #endif
544   // 6542
545   #if PRIME_DIFF_TABLE_BYTES > 0
546      };
547   #endif
548   #if defined RSA_INSTRUMENT || defined RSA_DEBUG
549   UINT32 failedAtIteration[10];
550   UINT32 MillerRabinTrials;
551   UINT32 totalFields;
552   UINT32 emptyFields;
553   UINT32 noPrimeFields;
554   UINT16 lastSievePrime;
555   UINT32 primesChecked;
556   #endif

      Only want this table when doing debug of the prime number stuff This is a table of the first 2048 primes
      and takes 4096 bytes

557   #ifdef RSA_DEBUG
558   const __int16 primes[NUM_PRIMES]=
559       {
560              3,   5,   7, 11, 13,          17,    19, 23, 29, 31, 37, 41, 43, 47, 53,
561         59, 61, 67, 71, 73, 79,            83,    89, 97, 101, 103, 107, 109, 113, 127, 131,
562       137, 139, 149, 151, 157, 163,       167,   173, 179, 181, 191, 193, 197, 199, 211, 223,
563       227, 229, 233, 239, 241, 251,       257,   263, 269, 271, 277, 281, 283, 293, 307, 311,
564       313, 317, 331, 337, 347, 349,       353,   359, 367, 373, 379, 383, 389, 397, 401, 409,
565       419, 421, 431, 433, 439, 443,       449,   457, 461, 463, 467, 479, 487, 491, 499, 503,
566       509, 521, 523, 541, 547, 557,       563,   569, 571, 577, 587, 593, 599, 601, 607, 613,
567       617, 619, 631, 641, 643, 647,       653,   659, 661, 673, 677, 683, 691, 701, 709, 719,
568       727, 733, 739, 743, 751, 757,       761,   769, 773, 787, 797, 809, 811, 821, 823, 827,
569       829, 839, 853, 857, 859, 863,       877,   881, 883, 887, 907, 911, 919, 929, 937, 941,
570       947, 953, 967, 971, 977, 983,       991,   997,1009,1013,1019,1021,1031,1033,1039,1049,

      Family "2.0"                               TCG Published                                     Page 467
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                        October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

571      1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,
572      1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,
573      1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,
574      1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,
575      1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,
576      1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,
577      1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,
578      1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,
579      2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,
580      2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,
581      2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,
582      2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,
583      2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,
584      2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,
585      2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,
586      2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,
587      3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,
588      3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,
589      3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,
590      3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,
591      3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,
592      3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,
593      3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,
594      3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,
595      4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,
596      4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,
597      4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,
598      4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,
599      4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,
600      4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,
601      4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,
602      5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,
603      5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,
604      5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,
605      5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,
606      5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,
607      5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,
608      5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,
609      6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,
610      6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,
611      6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,
612      6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,
613      6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,
614      6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,
615      6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,
616      6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,
617      7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,
618      7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,
619      7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,
620      7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,
621      7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,
622      7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,
623      8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,
624      8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,
625      8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,
626      8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,
627      8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,
628      8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,
629      8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,
630      9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,
631      9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,
632      9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,
633      9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,
634      9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,
635      9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,
636      9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929,

      Page 468                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                               Trusted Platform Module Library

637      9931, 9941, 9949, 9967, 9973,10007,10009,10037,
638      10039,10061,10067,10069,10079,10091,10093,10099,
639      10103,10111,10133,10139,10141,10151,10159,10163,
640      10169,10177,10181,10193,10211,10223,10243,10247,
641      10253,10259,10267,10271,10273,10289,10301,10303,
642      10313,10321,10331,10333,10337,10343,10357,10369,
643      10391,10399,10427,10429,10433,10453,10457,10459,
644      10463,10477,10487,10499,10501,10513,10529,10531,
645      10559,10567,10589,10597,10601,10607,10613,10627,
646      10631,10639,10651,10657,10663,10667,10687,10691,
647      10709,10711,10723,10729,10733,10739,10753,10771,
648      10781,10789,10799,10831,10837,10847,10853,10859,
649      10861,10867,10883,10889,10891,10903,10909,10937,
650      10939,10949,10957,10973,10979,10987,10993,11003,
651      11027,11047,11057,11059,11069,11071,11083,11087,
652      11093,11113,11117,11119,11131,11149,11159,11161,
653      11171,11173,11177,11197,11213,11239,11243,11251,
654      11257,11261,11273,11279,11287,11299,11311,11317,
655      11321,11329,11351,11353,11369,11383,11393,11399,
656      11411,11423,11437,11443,11447,11467,11471,11483,
657      11489,11491,11497,11503,11519,11527,11549,11551,
658      11579,11587,11593,11597,11617,11621,11633,11657,
659      11677,11681,11689,11699,11701,11717,11719,11731,
660      11743,11777,11779,11783,11789,11801,11807,11813,
661      11821,11827,11831,11833,11839,11863,11867,11887,
662      11897,11903,11909,11923,11927,11933,11939,11941,
663      11953,11959,11969,11971,11981,11987,12007,12011,
664      12037,12041,12043,12049,12071,12073,12097,12101,
665      12107,12109,12113,12119,12143,12149,12157,12161,
666      12163,12197,12203,12211,12227,12239,12241,12251,
667      12253,12263,12269,12277,12281,12289,12301,12323,
668      12329,12343,12347,12373,12377,12379,12391,12401,
669      12409,12413,12421,12433,12437,12451,12457,12473,
670      12479,12487,12491,12497,12503,12511,12517,12527,
671      12539,12541,12547,12553,12569,12577,12583,12589,
672      12601,12611,12613,12619,12637,12641,12647,12653,
673      12659,12671,12689,12697,12703,12713,12721,12739,
674      12743,12757,12763,12781,12791,12799,12809,12821,
675      12823,12829,12841,12853,12889,12893,12899,12907,
676      12911,12917,12919,12923,12941,12953,12959,12967,
677      12973,12979,12983,13001,13003,13007,13009,13033,
678      13037,13043,13049,13063,13093,13099,13103,13109,
679      13121,13127,13147,13151,13159,13163,13171,13177,
680      13183,13187,13217,13219,13229,13241,13249,13259,
681      13267,13291,13297,13309,13313,13327,13331,13337,
682      13339,13367,13381,13397,13399,13411,13417,13421,
683      13441,13451,13457,13463,13469,13477,13487,13499,
684      13513,13523,13537,13553,13567,13577,13591,13597,
685      13613,13619,13627,13633,13649,13669,13679,13681,
686      13687,13691,13693,13697,13709,13711,13721,13723,
687      13729,13751,13757,13759,13763,13781,13789,13799,
688      13807,13829,13831,13841,13859,13873,13877,13879,
689      13883,13901,13903,13907,13913,13921,13931,13933,
690      13963,13967,13997,13999,14009,14011,14029,14033,
691      14051,14057,14071,14081,14083,14087,14107,14143,
692      14149,14153,14159,14173,14177,14197,14207,14221,
693      14243,14249,14251,14281,14293,14303,14321,14323,
694      14327,14341,14347,14369,14387,14389,14401,14407,
695      14411,14419,14423,14431,14437,14447,14449,14461,
696      14479,14489,14503,14519,14533,14537,14543,14549,
697      14551,14557,14561,14563,14591,14593,14621,14627,
698      14629,14633,14639,14653,14657,14669,14683,14699,
699      14713,14717,14723,14731,14737,14741,14747,14753,
700      14759,14767,14771,14779,14783,14797,14813,14821,
701      14827,14831,14843,14851,14867,14869,14879,14887,
702      14891,14897,14923,14929,14939,14947,14951,14957,

      Family "2.0"                        TCG Published                              Page 469
      Level 00 Revision 01.16       Copyright © TCG 2006-2014               October 30, 2014
      Trusted Platform Module Library                               Part 4: Supporting Routines

703      14969,14983,15013,15017,15031,15053,15061,15073,
704      15077,15083,15091,15101,15107,15121,15131,15137,
705      15139,15149,15161,15173,15187,15193,15199,15217,
706      15227,15233,15241,15259,15263,15269,15271,15277,
707      15287,15289,15299,15307,15313,15319,15329,15331,
708      15349,15359,15361,15373,15377,15383,15391,15401,
709      15413,15427,15439,15443,15451,15461,15467,15473,
710      15493,15497,15511,15527,15541,15551,15559,15569,
711      15581,15583,15601,15607,15619,15629,15641,15643,
712      15647,15649,15661,15667,15671,15679,15683,15727,
713      15731,15733,15737,15739,15749,15761,15767,15773,
714      15787,15791,15797,15803,15809,15817,15823,15859,
715      15877,15881,15887,15889,15901,15907,15913,15919,
716      15923,15937,15959,15971,15973,15991,16001,16007,
717      16033,16057,16061,16063,16067,16069,16073,16087,
718      16091,16097,16103,16111,16127,16139,16141,16183,
719      16187,16189,16193,16217,16223,16229,16231,16249,
720      16253,16267,16273,16301,16319,16333,16339,16349,
721      16361,16363,16369,16381,16411,16417,16421,16427,
722      16433,16447,16451,16453,16477,16481,16487,16493,
723      16519,16529,16547,16553,16561,16567,16573,16603,
724      16607,16619,16631,16633,16649,16651,16657,16661,
725      16673,16691,16693,16699,16703,16729,16741,16747,
726      16759,16763,16787,16811,16823,16829,16831,16843,
727      16871,16879,16883,16889,16901,16903,16921,16927,
728      16931,16937,16943,16963,16979,16981,16987,16993,
729      17011,17021,17027,17029,17033,17041,17047,17053,
730      17077,17093,17099,17107,17117,17123,17137,17159,
731      17167,17183,17189,17191,17203,17207,17209,17231,
732      17239,17257,17291,17293,17299,17317,17321,17327,
733      17333,17341,17351,17359,17377,17383,17387,17389,
734      17393,17401,17417,17419,17431,17443,17449,17467,
735      17471,17477,17483,17489,17491,17497,17509,17519,
736      17539,17551,17569,17573,17579,17581,17597,17599,
737      17609,17623,17627,17657,17659,17669,17681,17683,
738      17707,17713,17729,17737,17747,17749,17761,17783,
739      17789,17791,17807,17827,17837,17839,17851,17863
740   };
741   #endif
742   #endif




      Page 470                               TCG Published                        Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014    Level 00 Revision 01.16
     Part 4: Supporting Routines                                       Trusted Platform Module Library


     B.13 Elliptic Curve Files

     B.13.1. CpriDataEcc.h

 1   #ifndef        _CRYPTDATAECC_H_
 2   #define        _CRYPTDATAECC_H_

     Structure for the curve parameters. This is an analog to the TPMS_ALGORITHM_DETAIL_ECC

 3   typedef struct {
 4       const TPM2B     *p;         // a prime number
 5       const TPM2B     *a;         // linear coefficient
 6       const TPM2B     *b;         // constant term
 7       const TPM2B     *x;         // generator x coordinate
 8       const TPM2B     *y;         // generator y coordinate
 9       const TPM2B     *n;         // the order of the curve
10       const TPM2B     *h;         // cofactor
11   } ECC_CURVE_DATA;
12   typedef struct
13   {
14       TPM_ECC_CURVE            curveId;
15       UINT16                   keySizeBits;
16       TPMT_KDF_SCHEME          kdf;
17       TPMT_ECC_SCHEME          sign;
18       const ECC_CURVE_DATA    *curveData; // the address of the curve data
19   } ECC_CURVE;
20   extern const ECC_CURVE_DATA SM2_P256;
21   extern const ECC_CURVE_DATA NIST_P256;
22   extern const ECC_CURVE_DATA BN_P256;
23   extern const ECC_CURVE eccCurves[];
24   extern const UINT16 ECC_CURVE_COUNT;
25   #endif




     Family "2.0"                           TCG Published                                   Page 471
     Level 00 Revision 01.16           Copyright © TCG 2006-2014                   October 30, 2014
     Trusted Platform Module Library                                 Part 4: Supporting Routines


     B.13.2. CpriDataEcc.c

     Defines for the sizes of ECC parameters

 1   #include    "TPMB.h"
 2   TPM2B_BYTE_VALUE(1);
 3   TPM2B_BYTE_VALUE(16);
 4   TPM2B_BYTE_VALUE(2);
 5   TPM2B_BYTE_VALUE(24);
 6   TPM2B_BYTE_VALUE(28);
 7   TPM2B_BYTE_VALUE(32);
 8   TPM2B_BYTE_VALUE(4);
 9   TPM2B_BYTE_VALUE(48);
10   TPM2B_BYTE_VALUE(64);
11   TPM2B_BYTE_VALUE(66);
12   TPM2B_BYTE_VALUE(8);
13   TPM2B_BYTE_VALUE(80);
14   #if defined ECC_NIST_P192 && ECC_NIST_P192 == YES
15   const TPM2B_24_BYTE_VALUE NIST_P192_p = {24,
16           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
17            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
18            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
19   const TPM2B_24_BYTE_VALUE NIST_P192_a = {24,
20           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
21            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
22            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}};
23   const TPM2B_24_BYTE_VALUE NIST_P192_b = {24,
24           {0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7,
25            0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49,
26            0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1}};
27   const TPM2B_24_BYTE_VALUE NIST_P192_gX = {24,
28           {0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6,
29            0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00,
30            0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12}};
31   const TPM2B_24_BYTE_VALUE NIST_P192_gY = {24,
32           {0x07, 0x19, 0x2B, 0x95, 0xFFC, 0x8D, 0xA7, 0x86,
33            0x31, 0x01, 0x1ED, 0x6B, 0x24, 0xCD, 0xD5, 0x73,
34            0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11}};
35   const TPM2B_24_BYTE_VALUE NIST_P192_n = {24,
36           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37            0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36,
38            0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31}};
39   const TPM2B_1_BYTE_VALUE NIST_P192_h = {1,{1}};
40   const ECC_CURVE_DATA NIST_P192 = {&NIST_P192_p.b, &NIST_P192_a.b, &NIST_P192_b.b,
41                                      &NIST_P192_gX.b, &NIST_P192_gY.b, &NIST_P192_n.b,
42                                      &NIST_P192_h.b};
43   #endif // ECC_NIST_P192
44   #if defined ECC_NIST_P224 && ECC_NIST_P224 == YES
45   const TPM2B_28_BYTE_VALUE NIST_P224_p = {28,
46           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
47            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
48            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49            0x00, 0x00, 0x00, 0x01}};
50   const TPM2B_28_BYTE_VALUE NIST_P224_a = {28,
51           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
52            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
53            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
54            0xFF, 0xFF, 0xFF, 0xFE}};
55   const TPM2B_28_BYTE_VALUE NIST_P224_b = {28,
56           {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB,
57            0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7,
58            0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
59            0x23, 0x55, 0xFF, 0xB4}};
60   const TPM2B_28_BYTE_VALUE NIST_P224_gX = {28,
61           {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F,

     Page 472                                  TCG Published                       Family "2.0"
     October 30, 2014                    Copyright © TCG 2006-2014    Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

 62            0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3,
 63            0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
 64            0x11, 0x5C, 0x1D, 0x21}};
 65   const TPM2B_28_BYTE_VALUE NIST_P224_gY = {28,
 66           {0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB,
 67            0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, 0x75, 0xA0,
 68            0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99,
 69            0x85, 0x00, 0x7E, 0x34}};
 70   const TPM2B_28_BYTE_VALUE NIST_P224_n = {28,
 71           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 72            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0xA2,
 73            0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
 74            0x5C, 0x5C, 0x2A, 0x3D}};
 75   const TPM2B_1_BYTE_VALUE NIST_P224_h = {1,{1}};
 76   const ECC_CURVE_DATA NIST_P224 = {&NIST_P224_p.b, &NIST_P224_a.b, &NIST_P224_b.b,
 77                                      &NIST_P224_gX.b, &NIST_P224_gY.b, &NIST_P224_n.b,
 78                                      &NIST_P224_h.b};
 79   #endif // ECC_NIST_P224
 80   #if defined ECC_NIST_P256 && ECC_NIST_P256 == YES
 81   const TPM2B_32_BYTE_VALUE NIST_P256_p = {32,
 82           {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
 83            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 84            0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 85            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
 86   const TPM2B_32_BYTE_VALUE NIST_P256_a = {32,
 87           {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
 88            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 89            0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 90            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}};
 91   const TPM2B_32_BYTE_VALUE NIST_P256_b = {32,
 92           {0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7,
 93            0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC,
 94            0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
 95            0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B}};
 96   const TPM2B_32_BYTE_VALUE NIST_P256_gX = {32,
 97           {0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47,
 98            0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2,
 99            0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
100            0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96}};
101   const TPM2B_32_BYTE_VALUE NIST_P256_gY = {32,
102           {0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B,
103            0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16,
104            0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
105            0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5}};
106   const TPM2B_32_BYTE_VALUE NIST_P256_n = {32,
107           {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
108            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109            0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
110            0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}};
111   const TPM2B_1_BYTE_VALUE NIST_P256_h = {1,{1}};
112   const ECC_CURVE_DATA NIST_P256 = {&NIST_P256_p.b, &NIST_P256_a.b, &NIST_P256_b.b,
113                                      &NIST_P256_gX.b, &NIST_P256_gY.b, &NIST_P256_n.b,
114                                      &NIST_P256_h.b};
115   #endif // ECC_NIST_P256
116   #if defined ECC_NIST_P384 && ECC_NIST_P384 == YES
117   const TPM2B_48_BYTE_VALUE NIST_P384_p = {48,
118           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
119            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
120            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
122            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
123            0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}};
124   const TPM2B_48_BYTE_VALUE NIST_P384_a = {48,
125           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
126            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
127            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,

      Family "2.0"                        TCG Published                                Page 473
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

128            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
129            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
130            0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC}};
131   const TPM2B_48_BYTE_VALUE NIST_P384_b = {48,
132           {0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4,
133            0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19,
134            0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
135            0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A,
136            0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D,
137            0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF}};
138   const TPM2B_48_BYTE_VALUE NIST_P384_gX = {48,
139           {0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37,
140            0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74,
141            0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
142            0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38,
143            0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C,
144            0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7}};
145   const TPM2B_48_BYTE_VALUE NIST_P384_gY = {48,
146           {0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F,
147            0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29,
148            0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
149            0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0,
150            0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D,
151            0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F}};
152   const TPM2B_48_BYTE_VALUE NIST_P384_n = {48,
153           {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
154            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
155            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
156            0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF,
157            0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A,
158            0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73}};
159   const TPM2B_1_BYTE_VALUE NIST_P384_h = {1,{1}};
160   const ECC_CURVE_DATA NIST_P384 = {&NIST_P384_p.b, &NIST_P384_a.b, &NIST_P384_b.b,
161                                     &NIST_P384_gX.b, &NIST_P384_gY.b, &NIST_P384_n.b,
162                                     &NIST_P384_h.b};
163   #endif // ECC_NIST_P384
164   #if defined ECC_NIST_P521 && ECC_NIST_P521 == YES
165   const TPM2B_66_BYTE_VALUE NIST_P521_p = {66,
166           {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
167            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
168            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
169            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
170            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
171            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
172            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
173            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
174            0xFF, 0xFF}};
175   const TPM2B_66_BYTE_VALUE NIST_P521_a = {66,
176           {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
177            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
178            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
179            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
180            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
181            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
182            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
183            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
184            0xFF, 0xFC}};
185   const TPM2B_66_BYTE_VALUE NIST_P521_b = {66,
186           {0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C,
187            0x9A, 0x1F, 0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85,
188            0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
189            0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1,
190            0x09, 0xE1, 0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E,
191            0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
192            0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C,
193            0x34, 0xF1, 0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50,

      Page 474                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                                 Trusted Platform Module Library

194            0x3F, 0x00}};
195   const TPM2B_66_BYTE_VALUE NIST_P521_gX = {66,
196           {0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04,
197            0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95,
198            0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
199            0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D,
200            0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7,
201            0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
202            0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A,
203            0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5,
204            0xBD, 0x66}};
205   const TPM2B_66_BYTE_VALUE NIST_P521_gY = {66,
206           {0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B,
207            0xC0, 0x04, 0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D,
208            0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
209            0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E,
210            0x66, 0x2C, 0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4,
211            0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
212            0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72,
213            0xC2, 0x40, 0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1,
214            0x66, 0x50}};
215   const TPM2B_66_BYTE_VALUE NIST_P521_n = {66,
216           {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
217            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
218            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
219            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
220            0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
221            0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
222            0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
223            0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
224            0x64, 0x09}};
225   const TPM2B_1_BYTE_VALUE NIST_P521_h = {1,{1}};
226   const ECC_CURVE_DATA NIST_P521 = {&NIST_P521_p.b, &NIST_P521_a.b, &NIST_P521_b.b,
227                                     &NIST_P521_gX.b, &NIST_P521_gY.b, &NIST_P521_n.b,
228                                     &NIST_P521_h.b};
229   #endif // ECC_NIST_P521
230   #if defined ECC_BN_P256 && ECC_BN_P256 == YES
231   const TPM2B_32_BYTE_VALUE BN_P256_p = {32,
232           {0xFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFC, 0XF0, 0XCD,
233            0X46, 0XE5, 0XF2, 0X5E, 0XEE, 0X71, 0XA4, 0X9F,
234            0X0C, 0XDC, 0X65, 0XFB, 0X12, 0X98, 0X0A, 0X82,
235            0XD3, 0X29, 0X2D, 0XDB, 0XAE, 0XD3, 0X30, 0X13}};
236   const TPM2B_1_BYTE_VALUE BN_P256_a = {1,{0}};
237   const TPM2B_1_BYTE_VALUE BN_P256_b = {1,{3}};
238   const TPM2B_1_BYTE_VALUE BN_P256_gX = {1,{1}};
239   const TPM2B_1_BYTE_VALUE BN_P256_gY = {1,{2}};;
240   const TPM2B_32_BYTE_VALUE BN_P256_n = {32,
241           {0xFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFC, 0XF0, 0XCD,
242            0X46, 0XE5, 0XF2, 0X5E, 0XEE, 0X71, 0XA4, 0X9E,
243            0X0C, 0XDC, 0X65, 0XFB, 0X12, 0X99, 0X92, 0X1A,
244            0XF6, 0X2D, 0X53, 0X6C, 0XD1, 0X0B, 0X50, 0X0D}};
245   const TPM2B_1_BYTE_VALUE BN_P256_h = {1,{1}};
246   const ECC_CURVE_DATA BN_P256 = {&BN_P256_p.b, &BN_P256_a.b, &BN_P256_b.b,
247                                     &BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_n.b,
248                                     &BN_P256_h.b};
249   #endif // ECC_BN_P256
250   #if defined ECC_BN_P638 && ECC_BN_P638 == YES
251   const TPM2B_80_BYTE_VALUE BN_P638_p = {80,
252           {0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D,
253            0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3,
254            0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E,
255            0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F,
256            0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55,
257            0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B,
258            0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80,
259            0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD,

      Family "2.0"                        TCG Published                                Page 475
      Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

260            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0,
261            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67}};
262   const TPM2B_1_BYTE_VALUE BN_P638_a = {1,{0}};
263   const TPM2B_2_BYTE_VALUE BN_P638_b = {2,{0x01,0x01}};
264   const TPM2B_80_BYTE_VALUE BN_P638_gX = {80,
265           {0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D,
266            0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3,
267            0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E,
268            0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F,
269            0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55,
270            0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B,
271            0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80,
272            0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD,
273            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0,
274            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66}};
275   const TPM2B_1_BYTE_VALUE BN_P638_gY = {1,{0x10}};
276   const TPM2B_80_BYTE_VALUE BN_P638_n = {80,
277           {0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D,
278            0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3,
279            0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E,
280            0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F,
281            0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55,
282            0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55,
283            0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0,
284            0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9,
285            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0,
286            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61}};
287   const TPM2B_1_BYTE_VALUE BN_P638_h = {1,{1}};
288   const ECC_CURVE_DATA BN_P638 = {&BN_P638_p.b, &BN_P638_a.b, &BN_P638_b.b,
289                                     &BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_n.b,
290                                     &BN_P638_h.b};
291   #endif // ECC_BN_P638
292   #if defined ECC_SM2_P256 && ECC_SM2_P256 == YES
293   const TPM2B_32_BYTE_VALUE SM2_P256_p = {32,
294           {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
295            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
296            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
297            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
298   const TPM2B_32_BYTE_VALUE SM2_P256_a = {32,
299           {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
300            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
301            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
302            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}};
303   const TPM2B_32_BYTE_VALUE SM2_P256_b = {32,
304           {0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34,
305            0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7,
306            0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92,
307            0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93}};
308   const TPM2B_32_BYTE_VALUE SM2_P256_gX = {32,
309           {0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19,
310            0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94,
311            0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1,
312            0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7}};
313   const TPM2B_32_BYTE_VALUE SM2_P256_gY = {32,
314           {0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C,
315            0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53,
316            0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40,
317            0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0}};
318   const TPM2B_32_BYTE_VALUE SM2_P256_n = {32,
319           {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
320            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
321            0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B,
322            0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23}};
323   const TPM2B_1_BYTE_VALUE SM2_P256_h = {1,{1}};
324   const ECC_CURVE_DATA SM2_P256 = {&SM2_P256_p.b, &SM2_P256_a.b, &SM2_P256_b.b,
325                                     &SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_n.b,

      Page 476                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
      Part 4: Supporting Routines                               Trusted Platform Module Library

326                                      &SM2_P256_h.b};
327   #endif // ECC_SM2_P256
328   #define comma
329   const ECC_CURVE    eccCurves[] = {
330   #if defined ECC_NIST_P192 && ECC_NIST_P192 == YES
331       comma
332       {TPM_ECC_NIST_P192,
333       192,
334       {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA256},
335       {TPM_ALG_NULL,TPM_ALG_NULL},
336       &NIST_P192}
337   #   undef comma
338   #   define comma ,
339   #endif // ECC_NIST_P192
340   #if defined ECC_NIST_P224 && ECC_NIST_P224 == YES
341       comma
342       {TPM_ECC_NIST_P224,
343       224,
344       {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA256},
345       {TPM_ALG_NULL,TPM_ALG_NULL},
346       &NIST_P224}
347   #   undef comma
348   #   define comma ,
349   #endif // ECC_NIST_P224
350   #if defined ECC_NIST_P256 && ECC_NIST_P256 == YES
351       comma
352       {TPM_ECC_NIST_P256,
353       256,
354       {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA256},
355       {TPM_ALG_NULL,TPM_ALG_NULL},
356       &NIST_P256}
357   #   undef comma
358   #   define comma ,
359   #endif // ECC_NIST_P256
360   #if defined ECC_NIST_P384 && ECC_NIST_P384 == YES
361       comma
362       {TPM_ECC_NIST_P384,
363       384,
364       {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA384},
365       {TPM_ALG_NULL,TPM_ALG_NULL},
366       &NIST_P384}
367   #   undef comma
368   #   define comma ,
369   #endif // ECC_NIST_P384
370   #if defined ECC_NIST_P521 && ECC_NIST_P521 == YES
371       comma
372       {TPM_ECC_NIST_P521,
373       521,
374       {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA512},
375       {TPM_ALG_NULL,TPM_ALG_NULL},
376       &NIST_P521}
377   #   undef comma
378   #   define comma ,
379   #endif // ECC_NIST_P521
380   #if defined ECC_BN_P256 && ECC_BN_P256 == YES
381       comma
382       {TPM_ECC_BN_P256,
383       256,
384       {TPM_ALG_NULL,TPM_ALG_NULL},
385       {TPM_ALG_NULL,TPM_ALG_NULL},
386       &BN_P256}
387   #   undef comma
388   #   define comma ,
389   #endif // ECC_BN_P256
390   #if defined ECC_BN_P638 && ECC_BN_P638 == YES
391       comma

      Family "2.0"                        TCG Published                              Page 477
      Level 00 Revision 01.16       Copyright © TCG 2006-2014               October 30, 2014
      Trusted Platform Module Library                                Part 4: Supporting Routines

392       {TPM_ECC_BN_P638,
393       638,
394       {TPM_ALG_NULL,TPM_ALG_NULL},
395       {TPM_ALG_NULL,TPM_ALG_NULL},
396       &BN_P638}
397   #   undef comma
398   #   define comma ,
399   #endif // ECC_BN_P638
400   #if defined ECC_SM2_P256 && ECC_SM2_P256 == YES
401       comma
402       {TPM_ECC_SM2_P256,
403       256,
404       {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SM3_256},
405       {TPM_ALG_NULL,TPM_ALG_NULL},
406       &SM2_P256}
407   #   undef comma
408   #   define comma ,
409   #endif // ECC_SM2_P256
410   };
411   const UINT16    ECC_CURVE_COUNT = sizeof(eccCurves) / sizeof(ECC_CURVE);




      Page 478                               TCG Published                         Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
     Part 4: Supporting Routines                                                  Trusted Platform Module Library


     B.13.3. CpriECC.c

     B.13.3.1. Includes and Defines

     Need to include OsslCryptEngine.h to determine if ECC is defined for this Implementation

 1   #include   "OsslCryptoEngine.h"
 2   #ifdef TPM_ALG_ECC
 3   #include   "CpriDataEcc.h"
 4   #include   "CpriDataEcc.c"


     B.13.3.2. Functions

     B.13.3.2.1. _cpri__EccStartup()

     This function is called at TPM Startup to initialize the crypto units.
     In this implementation, no initialization is performed at startup but a future version may initialize the self-
     test functions here.

 5   LIB_EXPORT BOOL
 6   _cpri__EccStartup(
 7        void
 8        )
 9   {
10        return TRUE;
11   }


     B.13.3.2.2. _cpri__GetCurveIdByIndex()

     This function returns the number of the i-th implemented curve. The normal use would be to call this
     function with i starting at 0. When the i is greater than or equal to the number of implemented curves,
     TPM_ECC_NONE is returned.

12   LIB_EXPORT TPM_ECC_CURVE
13   _cpri__GetCurveIdByIndex(
14        UINT16                i
15        )
16   {
17        if(i >= ECC_CURVE_COUNT)
18            return TPM_ECC_NONE;
19        return eccCurves[i].curveId;
20   }
21   LIB_EXPORT UINT32
22   _cpri__EccGetCurveCount(
23        void
24        )
25   {
26        return ECC_CURVE_COUNT;
27   }


     B.13.3.2.3. _cpri__EccGetParametersByCurveId()

     This function returns a pointer to the curve data that is associated with the indicated curveId. If there is no
     curve with the indicated ID, the function returns NULL.




     Family "2.0"                                   TCG Published                                        Page 479
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                           October 30, 2014
     Trusted Platform Module Library                                               Part 4: Supporting Routines


     Return Value                      Meaning

     NULL                              curve with the      indicated   TPM_ECC_CURVE    value   is   not
                                       implemented
     non-NULL                          pointer to the curve data

28   LIB_EXPORT const ECC_CURVE *
29   _cpri__EccGetParametersByCurveId(
30       TPM_ECC_CURVE       curveId               // IN: the curveID
31       )
32   {
33       int          i;
34       for(i = 0; i < ECC_CURVE_COUNT; i++)
35       {
36           if(eccCurves[i].curveId == curveId)
37               return &eccCurves[i];
38       }
39       FAIL(FATAL_ERROR_INTERNAL);
40   }
41   static const ECC_CURVE_DATA *
42   GetCurveData(
43       TPM_ECC_CURVE       curveId               // IN: the curveID
44       )
45   {
46       const ECC_CURVE     *curve = _cpri__EccGetParametersByCurveId(curveId);
47       return curve->curveData;
48   }


     B.13.3.2.4. Point2B()

     This function makes a TPMS_ECC_POINT from a BIGNUM EC_POINT.

49   static BOOL
50   Point2B(
51       EC_GROUP           *group,                //   IN: group for the point
52       TPMS_ECC_POINT     *p,                    //   OUT: receives the converted point
53       EC_POINT           *ecP,                  //   IN: the point to convert
54       INT16               size,                 //   IN: size of the coordinates
55       BN_CTX             *context               //   IN: working context
56       )
57   {
58       BIGNUM             *bnX;
59       BIGNUM             *bnY;
60
61       BN_CTX_start(context);
62       bnX = BN_CTX_get(context);
63       bnY = BN_CTX_get(context);
64
65       if(        bnY == NULL
66
67            // Get the coordinate values
68           || EC_POINT_get_affine_coordinates_GFp(group, ecP, bnX, bnY, context) != 1
69
70           // Convert x
71           || (!BnTo2B(&p->x.b, bnX, size))
72
73           // Convert y
74           || (!BnTo2B(&p->y.b, bnY, size))
75          )
76                FAIL(FATAL_ERROR_INTERNAL);
77
78       BN_CTX_end(context);
79       return TRUE;

     Page 480                                       TCG Published                                    Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

 80   }


      B.13.3.2.5. EccCurveInit()

      This function initializes the OpenSSL() group definition structure
      This function is only used within this file.
      It is a fatal error if groupContext is not provided.

      Return Value                       Meaning

      NULL                               the TPM_ECC_CURVE is not valid
      non-NULL                           points to a structure in groupContext static EC_GROUP *

 81   static EC_GROUP *
 82   EccCurveInit(
 83        TPM_ECC_CURVE         curveId,             // IN: the ID of the curve
 84        BN_CTX               *groupContext         // IN: the context in which the group is to be
 85                                                   //     created
 86        )
 87   {
 88        const ECC_CURVE_DATA            *curveData = GetCurveData(curveId);
 89        EC_GROUP                        *group = NULL;
 90        EC_POINT                        *P = NULL;
 91        BN_CTX                          *context;
 92        BIGNUM                          *bnP;
 93        BIGNUM                          *bnA;
 94        BIGNUM                          *bnB;
 95        BIGNUM                          *bnX;
 96        BIGNUM                          *bnY;
 97        BIGNUM                          *bnN;
 98        BIGNUM                          *bnH;
 99        int                              ok = FALSE;
100
101        // Context must be provided and curve selector must be valid
102        pAssert(groupContext != NULL && curveData != NULL);
103
104        context = BN_CTX_new();
105        if(context == NULL)
106            FAIL(FATAL_ERROR_ALLOCATION);
107
108        BN_CTX_start(context);
109        bnP = BN_CTX_get(context);
110        bnA = BN_CTX_get(context);
111        bnB = BN_CTX_get(context);
112        bnX = BN_CTX_get(context);
113        bnY = BN_CTX_get(context);
114        bnN = BN_CTX_get(context);
115        bnH = BN_CTX_get(context);
116
117        if (bnH == NULL)
118            goto Cleanup;
119
120        // Convert the number formats
121
122        BnFrom2B(bnP,      curveData->p);
123        BnFrom2B(bnA,      curveData->a);
124        BnFrom2B(bnB,      curveData->b);
125        BnFrom2B(bnX,      curveData->x);
126        BnFrom2B(bnY,      curveData->y);
127        BnFrom2B(bnN,      curveData->n);
128        BnFrom2B(bnH,      curveData->h);
129

      Family "2.0"                                    TCG Published                                       Page 481
      Level 00 Revision 01.16                 Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                          Part 4: Supporting Routines

130       // initialize EC group, associate a generator point and initialize the point
131       // from the parameter data
132       ok = (   (group = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, groupContext)) != NULL
133             && (P = EC_POINT_new(group)) != NULL
134             && EC_POINT_set_affine_coordinates_GFp(group, P, bnX, bnY, groupContext)
135             && EC_GROUP_set_generator(group, P, bnN, bnH)
136            );
137   Cleanup:
138       if (!ok && group != NULL)
139       {
140           EC_GROUP_free(group);
141           group = NULL;
142       }
143       if(P != NULL)
144           EC_POINT_free(P);
145       BN_CTX_end(context);
146       BN_CTX_free(context);
147       return group;
148   }


      B.13.3.2.6. PointFrom2B()

      This function sets the coordinates of an existing BN Point from a TPMS_ECC_POINT.

149   static EC_POINT *
150   PointFrom2B(
151       EC_GROUP           *group,           //   IN:   the group for the point
152       EC_POINT           *ecP,             //   IN:   an existing BN point in the group
153       TPMS_ECC_POINT     *p,               //   IN:   the 2B coordinates of the point
154       BN_CTX             *context          //   IN:   the BIGNUM context
155       )
156   {
157       BIGNUM             *bnX;
158       BIGNUM             *bnY;
159
160       // If the point is not allocated then just return a NULL
161       if(ecP == NULL)
162           return NULL;
163
164       BN_CTX_start(context);
165       bnX = BN_CTX_get(context);
166       bnY = BN_CTX_get(context);
167       if( // Set the coordinates of the point
168             bnY == NULL
169          || BN_bin2bn(p->x.t.buffer, p->x.t.size, bnX) == NULL
170          || BN_bin2bn(p->y.t.buffer, p->y.t.size, bnY) == NULL
171          || !EC_POINT_set_affine_coordinates_GFp(group, ecP, bnX, bnY, context)
172          )
173          FAIL(FATAL_ERROR_INTERNAL);
174
175       BN_CTX_end(context);
176       return ecP;
177   }


      B.13.3.2.7. EccInitPoint2B()

      This function allocates a point in the provided group and initializes it with the values in a
      TPMS_ECC_POINT.

178   static EC_POINT *
179   EccInitPoint2B(
180       EC_GROUP           *group,           // IN: group for the point
181       TPMS_ECC_POINT     *p,               // IN: the coordinates for the point

      Page 482                                  TCG Published                                Family "2.0"
      October 30, 2014                   Copyright © TCG 2006-2014               Level 00 Revision 01.16
      Part 4: Supporting Routines                                                    Trusted Platform Module Library

182        BN_CTX              *context                // IN: the BIGNUM context
183        )
184   {
185        EC_POINT            *ecP;
186
187        BN_CTX_start(context);
188        ecP = EC_POINT_new(group);
189
190        if(PointFrom2B(group, ecP, p, context) == NULL)
191            FAIL(FATAL_ERROR_INTERNAL);
192
193        BN_CTX_end(context);
194        return ecP;
195   }


      B.13.3.2.8. PointMul()

      This function does a point multiply and checks for the result being the point at infinity. Q = ([A]G + [B]P)

      Return Value                      Meaning

      CRYPT_NO_RESULT                   point is at infinity
      CRYPT_SUCCESS                     point not at infinity

196   static CRYPT_RESULT
197   PointMul(
198        EC_GROUP            *group,                 //      IN: group curve
199        EC_POINT            *ecpQ,                  //      OUT: result
200        BIGNUM              *bnA,                   //      IN: scalar for [A]G
201        EC_POINT            *ecpP,                  //      IN: point for [B]P
202        BIGNUM              *bnB,                   //      IN: scalar for [B]P
203        BN_CTX              *context                //      IN: working context
204        )
205   {
206           if(EC_POINT_mul(group, ecpQ, bnA, ecpP, bnB, context) != 1)
207                FAIL(FATAL_ERROR_INTERNAL);
208            if(EC_POINT_is_at_infinity(group, ecpQ))
209                return CRYPT_NO_RESULT;
210            return CRYPT_SUCCESS;
211   }


      B.13.3.2.9. GetRandomPrivate()

      This function gets a random value (d) to use as a private ECC key and then qualifies the key so that it is
      between 0 < d < n.
      It is a fatal error if dOut or pIn is not provided or if the size of pIn is larger than MAX_ECC_KEY_BYTES
      (the largest buffer size of a TPM2B_ECC_PARAMETER)

212   static void
213   GetRandomPrivate(
214        TPM2B_ECC_PARAMETER            *dOut,                    // OUT: the qualified random value
215        const TPM2B                    *pIn                      // IN: the maximum value for the key
216        )
217   {
218        int             i;
219        BYTE           *pb;
220
221        pAssert(pIn != NULL && dOut != NULL && pIn->size <= MAX_ECC_KEY_BYTES);
222
223        // Set the size of the output
224        dOut->t.size = pIn->size;

      Family "2.0"                                     TCG Published                                      Page 483
      Level 00 Revision 01.16                Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                    Part 4: Supporting Routines

225        // Get some random bits
226        while(TRUE)
227        {
228            _cpri__GenerateRandom(dOut->t.size, dOut->t.buffer);
229            // See if the d < n
230            if(memcmp(dOut->t.buffer, pIn->buffer, pIn->size) < 0)
231            {
232                // dOut < n so make sure that 0 < dOut
233                for(pb = dOut->t.buffer, i = dOut->t.size; i > 0; i--)
234                {
235                    if(*pb++ != 0)
236                        return;
237                }
238            }
239        }
240   }


      B.13.3.2.10. Mod2B()

      Function does modular reduction of TPM2B values.

241   static CRYPT_RESULT
242   Mod2B(
243        TPM2B                *x,                 // IN/OUT: value to reduce
244        const TPM2B          *n                  // IN: mod
245        )
246   {
247        int         compare;
248        compare = _math__uComp(x->size, x->buffer, n->size, n->buffer);
249        if(compare < 0)
250            // if x < n, then mod is x
251            return CRYPT_SUCCESS;
252        if(compare == 0)
253        {
254            // if x == n then mod is 0
255            x->size = 0;
256            x->buffer[0] = 0;
257            return CRYPT_SUCCESS;
258        }
259       return _math__Div(x, n, NULL, x);
260   }


      B.13.3.2.11. _cpri__EccPointMultiply

      This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are points on
      the specified curve and G is the default generator of the curve.
      The xOut and yOut parameters are optional and may be set to NULL if not used.
      It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be provided. If dIn and
      QIn are specified but uIn is not provided, then R = [dIn]QIn.
      If the multiply produces the point at infinity, the CRYPT_NO_RESULT is returned.
      The sizes of xOut and yOut' will be set to be the size of the degree of the curve
      It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is unspecified.




      Page 484                                       TCG Published                                       Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library


      Return Value                    Meaning

      CRYPT_SUCCESS                   point multiplication succeeded
      CRYPT_POINT                     the point Qin is not on the curve
      CRYPT_NO_RESULT                 the product point is at infinity

261   LIB_EXPORT CRYPT_RESULT
262   _cpri__EccPointMultiply(
263       TPMS_ECC_POINT                *Rout,                  //   OUT: the product point R
264       TPM_ECC_CURVE                  curveId,               //   IN: the curve to use
265       TPM2B_ECC_PARAMETER           *dIn,                   //   IN: value to multiply against the
266                                                             //       curve generator
267       TPMS_ECC_POINT                *Qin,                   //   IN: point Q
268       TPM2B_ECC_PARAMETER           *uIn                    //   IN: scalar value for the multiplier
269                                                             //       of Q
270       )
271   {
272       BN_CTX                    *context;
273       BIGNUM                    *bnD;
274       BIGNUM                    *bnU;
275       EC_GROUP                  *group;
276       EC_POINT                  *R = NULL;
277       EC_POINT                  *Q = NULL;
278       CRYPT_RESULT               retVal = CRYPT_SUCCESS;
279
280       // Validate that the required parameters are provided.
281       pAssert((dIn != NULL || uIn != NULL) && (Qin != NULL || dIn != NULL));
282
283       // If a point is provided for the multiply, make sure that it is on the curve
284       if(Qin != NULL && !_cpri__EccIsPointOnCurve(curveId, Qin))
285           return CRYPT_POINT;
286
287       context = BN_CTX_new();
288       if(context == NULL)
289           FAIL(FATAL_ERROR_ALLOCATION);
290
291       BN_CTX_start(context);
292       bnU = BN_CTX_get(context);
293       bnD = BN_CTX_get(context);
294       group = EccCurveInit(curveId, context);
295
296       // There should be no path for getting a bad curve ID into this function.
297       pAssert(group != NULL);
298
299       // check allocations should have worked and allocate R
300       if(   bnD == NULL
301          || (R = EC_POINT_new(group)) == NULL)
302           FAIL(FATAL_ERROR_ALLOCATION);
303
304       // If Qin is present, create the point
305       if(Qin != NULL)
306       {
307           // Assume the size variables do not overflow. This should not happen in
308           // the contexts in which this function will be called.
309           assert2Bsize(Qin->x.t);
310           assert2Bsize(Qin->x.t);
311           Q = EccInitPoint2B(group, Qin, context);
312
313       }
314       if(dIn != NULL)
315       {
316           // Assume the size variables do not overflow, which should not happen in
317           // the contexts that this function will be called.
318           assert2Bsize(dIn->t);

      Family "2.0"                                  TCG Published                                      Page 485
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

319            BnFrom2B(bnD, &dIn->b);
320        }
321        else
322            bnD = NULL;
323
324        // If uIn is specified, initialize its BIGNUM
325        if(uIn != NULL)
326        {
327            // Assume the size variables do not overflow, which should not happen in
328            // the contexts that this function will be called.
329            assert2Bsize(uIn->t);
330            BnFrom2B(bnU, &uIn->b);
331        }
332        // If uIn is not specified but Q is, then we are going to
333        // do R = [d]Q
334        else if(Qin != NULL)
335        {
336            bnU = bnD;
337            bnD = NULL;
338        }
339        // If neither Q nor u is specified, then null this pointer
340        else
341            bnU = NULL;
342
343        // Use the generator of the curve
344        if((retVal = PointMul(group, R, bnD, Q, bnU, context)) == CRYPT_SUCCESS)
345            Point2B(group, Rout, R, (INT16) BN_num_bytes(&group->field), context);
346
347        if (Q)
348            EC_POINT_free(Q);
349        if(R)
350            EC_POINT_free(R);
351        if(group)
352            EC_GROUP_free(group);
353        BN_CTX_end(context);
354        BN_CTX_free(context);
355        return retVal;
356   }


      B.13.3.2.12. ClearPoint2B()

      Initialize the size values of a point

357   static void
358   ClearPoint2B(
359        TPMS_ECC_POINT       *p                 // IN: the point
360        )
361   {
362        if(p != NULL) {
363            p->x.t.size = 0;
364            p->y.t.size = 0;
365        }
366   }
367   #if defined TPM_ALG_ECDAA || defined TPM_ALG_SM2 //%


      B.13.3.2.13. _cpri__EccCommitCompute()

      This function performs the point multiply operations required by TPM2_Commit().
      If B or M is provided, they must be on the curve defined by curveId. This routine does not check that they
      are on the curve and results are unpredictable if they are not.



      Page 486                                     TCG Published                                  Family "2.0"
      October 30, 2014                        Copyright © TCG 2006-2014              Level 00 Revision 01.16
      Part 4: Supporting Routines                                                       Trusted Platform Module Library


      It is a fatal error if r or d is NULL. If B is not NULL, then it is a fatal error if K and L are both NULL. If M is
      not NULL, then it is a fatal error if E is NULL.

      Return Value                       Meaning

      CRYPT_SUCCESS                      computations completed normally
      CRYPT_NO_RESULT                    if K, L or E was computed to be the point at infinity
      CRYPT_CANCEL                       a cancel indication was asserted during this function

368   LIB_EXPORT CRYPT_RESULT
369   _cpri__EccCommitCompute(
370        TPMS_ECC_POINT                  *K,                   //   OUT: [d]B or [r]Q
371        TPMS_ECC_POINT                  *L,                   //   OUT: [r]B
372        TPMS_ECC_POINT                  *E,                   //   OUT: [r]M
373        TPM_ECC_CURVE                    curveId,             //   IN: the curve for the computations
374        TPMS_ECC_POINT                  *M,                   //   IN: M (optional)
375        TPMS_ECC_POINT                  *B,                   //   IN: B (optional)
376        TPM2B_ECC_PARAMETER             *d,                   //   IN: d (required)
377        TPM2B_ECC_PARAMETER             *r                    //   IN: the computed r value (required)
378        )
379   {
380        BN_CTX                    *context;
381        BIGNUM                    *bnX, *bnY, *bnR, *bnD;
382        EC_GROUP                  *group;
383        EC_POINT                  *pK = NULL, *pL = NULL, *pE = NULL, *pM = NULL, *pB = NULL;
384        UINT16                     keySizeInBytes;
385        CRYPT_RESULT               retVal = CRYPT_SUCCESS;
386
387        // Validate that the required parameters are provided.
388        // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do
389        // E := [r]Q if both M and B are NULL.
390        pAssert(   r != NULL && (K != NULL || B == NULL) && (L != NULL || B == NULL)
391                || (E != NULL || (M == NULL && B != NULL)));
392
393        context = BN_CTX_new();
394        if(context == NULL)
395            FAIL(FATAL_ERROR_ALLOCATION);
396        BN_CTX_start(context);
397        bnR = BN_CTX_get(context);
398        bnD = BN_CTX_get(context);
399        bnX = BN_CTX_get(context);
400        bnY = BN_CTX_get(context);
401        if(bnY == NULL)
402            FAIL(FATAL_ERROR_ALLOCATION);
403
404        // Initialize the output points in case they are not computed
405        ClearPoint2B(K);
406        ClearPoint2B(L);
407        ClearPoint2B(E);
408
409        if((group = EccCurveInit(curveId, context)) == NULL)
410        {
411            retVal = CRYPT_PARAMETER;
412            goto Cleanup2;
413        }
414        keySizeInBytes = (UINT16) BN_num_bytes(&group->field);
415
416        // Sizes of the r and d parameters may not be zero
417        pAssert(((int) r->t.size > 0) && ((int) d->t.size > 0));
418
419        // Convert scalars to BIGNUM
420        BnFrom2B(bnR, &r->b);
421        BnFrom2B(bnD, &d->b);
422

      Family "2.0"                                    TCG Published                                          Page 487
      Level 00 Revision 01.16                 Copyright © TCG 2006-2014                             October 30, 2014
      Trusted Platform Module Library                                   Part 4: Supporting Routines

423       // If B is provided, compute K=[d]B and L=[r]B
424       if(B != NULL)
425       {
426           // Allocate the points to receive the value
427           if(    (pK = EC_POINT_new(group)) == NULL
428               || (pL = EC_POINT_new(group)) == NULL)
429           FAIL(FATAL_ERROR_ALLOCATION);
430           // need to compute K = [d]B
431           // Allocate and initialize BIGNUM version of B
432           pB = EccInitPoint2B(group, B, context);
433
434            // do the math for K = [d]B
435            if((retVal = PointMul(group, pK, NULL, pB, bnD, context)) != CRYPT_SUCCESS)
436                goto Cleanup;
437
438            // Convert BN K to TPM2B K
439            Point2B(group, K, pK, (INT16)keySizeInBytes, context);
440
441            // compute L= [r]B after checking for cancel
442            if(_plat__IsCanceled())
443            {
444                retVal = CRYPT_CANCEL;
445                goto Cleanup;
446            }
447            // compute L = [r]B
448            if((retVal = PointMul(group, pL, NULL, pB, bnR, context)) != CRYPT_SUCCESS)
449                goto Cleanup;
450
451            // Convert BN L to TPM2B L
452            Point2B(group, L, pL, (INT16)keySizeInBytes, context);
453       }
454       if(M != NULL || B == NULL)
455       {
456           // if this is the third point multiply, check for cancel first
457           if(B != NULL && _plat__IsCanceled())
458           {
459               retVal = CRYPT_CANCEL;
460               goto Cleanup;
461           }
462
463            // Allocate E
464            if((pE = EC_POINT_new(group)) == NULL)
465                FAIL(FATAL_ERROR_ALLOCATION);
466
467            // Create BIGNUM version of M unless M is NULL
468            if(M != NULL)
469            {
470                 // M provided so initialize a BIGNUM M and compute E = [r]M
471                 pM = EccInitPoint2B(group, M, context);
472                 retVal = PointMul(group, pE, NULL, pM, bnR, context);
473            }
474            else
475                 // compute E = [r]G (this is only done if M and B are both NULL
476                 retVal = PointMul(group, pE, bnR, NULL, NULL, context);
477
478            if(retVal == CRYPT_SUCCESS)
479                // Convert E to 2B format
480                Point2B(group, E, pE, (INT16)keySizeInBytes, context);
481       }
482   Cleanup:
483       EC_GROUP_free(group);
484       if(pK != NULL) EC_POINT_free(pK);
485       if(pL != NULL) EC_POINT_free(pL);
486       if(pE != NULL) EC_POINT_free(pE);
487       if(pM != NULL) EC_POINT_free(pM);
488       if(pB != NULL) EC_POINT_free(pB);

      Page 488                               TCG Published                            Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014        Level 00 Revision 01.16
      Part 4: Supporting Routines                                                       Trusted Platform Module Library

489   Cleanup2:
490       BN_CTX_end(context);
491       BN_CTX_free(context);
492       return retVal;
493   }
494   #endif //%


      B.13.3.2.14. _cpri__EccIsPointOnCurve()

      This function is used to test if a point is on a defined curve. It does this by checking that y^2 mod p = x^3
      + a*x + b mod p
      It is a fatal error if Q is not specified (is NULL).

      Return Value                        Meaning

      TRUE                                point is on curve
      FALSE                               point is not on curve or curve is not supported

495   LIB_EXPORT BOOL
496   _cpri__EccIsPointOnCurve(
497        TPM_ECC_CURVE          curveId,             // IN: the curve selector
498        TPMS_ECC_POINT        *Q                    // IN: the point.
499        )
500   {
501        BN_CTX                           *context;
502        BIGNUM                           *bnX;
503        BIGNUM                           *bnY;
504        BIGNUM                           *bnA;
505        BIGNUM                           *bnB;
506        BIGNUM                           *bnP;
507        BIGNUM                           *bn3;
508        const ECC_CURVE_DATA             *curveData = GetCurveData(curveId);
509        BOOL                              retVal;
510
511        pAssert(Q != NULL && curveData != NULL);
512
513        if((context = BN_CTX_new()) == NULL)
514            FAIL(FATAL_ERROR_ALLOCATION);
515        BN_CTX_start(context);
516        bnX = BN_CTX_get(context);
517        bnY = BN_CTX_get(context);
518        bnA = BN_CTX_get(context);
519        bnB = BN_CTX_get(context);
520        bn3 = BN_CTX_get(context);
521        bnP = BN_CTX_get(context);
522        if(bnP == NULL)
523            FAIL(FATAL_ERROR_ALLOCATION);
524
525        // Convert values
526        if (    !BN_bin2bn(Q->x.t.buffer, Q->x.t.size, bnX)
527             || !BN_bin2bn(Q->y.t.buffer, Q->y.t.size, bnY)
528             || !BN_bin2bn(curveData->p->buffer, curveData->p->size, bnP)
529             || !BN_bin2bn(curveData->a->buffer, curveData->a->size, bnA)
530             || !BN_set_word(bn3, 3)
531             || !BN_bin2bn(curveData->b->buffer, curveData->b->size, bnB)
532           )
533             FAIL(FATAL_ERROR_INTERNAL);
534
535        // The following sequence is probably not optimal but it seems to be correct.
536        // compute x^3 + a*x + b mod p
537                // first, compute a*x mod p
538        if(   !BN_mod_mul(bnA, bnA, bnX, bnP, context)


      Family "2.0"                                     TCG Published                                         Page 489
      Level 00 Revision 01.16                  Copyright © TCG 2006-2014                            October 30, 2014
      Trusted Platform Module Library                                                              Part 4: Supporting Routines

539                  // next, compute a*x + b mod p
540             || !BN_mod_add(bnA, bnA, bnB, bnP, context)
541                  // next, compute X^3 mod p
542             || !BN_mod_exp(bnX, bnX, bn3, bnP, context)
543                  // finally, compute x^3 + a*x + b mod p
544             || !BN_mod_add(bnX, bnX, bnA, bnP, context)
545                  // then compute y^2
546             || !BN_mod_mul(bnY, bnY, bnY, bnP, context)
547            )
548              FAIL(FATAL_ERROR_INTERNAL);
549
550        retVal = BN_cmp(bnX, bnY) == 0;
551        BN_CTX_end(context);
552        BN_CTX_free(context);
553        return retVal;
554   }


      B.13.3.2.15. _cpri__GenerateKeyEcc()

      This function generates an ECC key pair based on the input parameters. This routine uses KDFa() to
      produce candidate numbers. The method is according to FIPS 186-3, section B.4.1 "GKey() Pair
      Generation Using Extra Random Bits." According to the method in FIPS 186-3, the resulting private value
      d should be 1 <= d < n where n is the order of the base point. In this implementation, the range of the
      private value is further restricted to be 2^(nLen/2) <= d < n where nLen is the order of n.

      EXAMPLE:         If the curve is NIST-P256, then nLen is 256 bits and d will need to be between 2^128 <= d < n

      It is a fatal error if Qout, dOut, or seed is not provided (is NULL).

      Return Value                         Meaning

      CRYPT_PARAMETER                      the hash algorithm is not supported

555   LIB_EXPORT CRYPT_RESULT
556   _cpri__GenerateKeyEcc(
557        TPMS_ECC_POINT                    *Qout,                  //   OUT: the public point
558        TPM2B_ECC_PARAMETER               *dOut,                  //   OUT: the private scalar
559        TPM_ECC_CURVE                      curveId,               //   IN: the curve identifier
560        TPM_ALG_ID                         hashAlg,               //   IN: hash algorithm to use in the key
561                                                                  //       generation process
562        TPM2B                             *seed,                  //   IN: the seed to use
563        const char                        *label,                 //   IN: A label for the generation
564                                                                  //       process.
565        TPM2B                             *extra,                 //   IN: Party 1 data for the KDF
566        UINT32                            *counter                //   IN/OUT: Counter value to allow KDF
567                                                                  //       iteration to be propagated across
568                                                                  //       multiple functions
569        )
570   {
571        const ECC_CURVE_DATA              *curveData = GetCurveData(curveId);
572        INT16                              keySizeInBytes;
573        UINT32                             count = 0;
574        CRYPT_RESULT                       retVal;
575        UINT16                             hLen = _cpri__GetDigestSize(hashAlg);
576        BIGNUM                            *bnNm1;          // Order of the curve minus one
577        BIGNUM                            *bnD;            // the private scalar
578        BN_CTX                            *context;        // the context for the BIGNUM values
579        BYTE                               withExtra[MAX_ECC_KEY_BYTES + 8]; // trial key with
580                                                                               //extra bits
581        TPM2B_4_BYTE_VALUE                 marshaledCounter = {4, {0}};
582        UINT32                             totalBits;
583
584        // Validate parameters (these are fatal)

      Page 490                                            TCG Published                                                Family "2.0"
      October 30, 2014                           Copyright © TCG 2006-2014                           Level 00 Revision 01.16
      Part 4: Supporting Routines                                   Trusted Platform Module Library

585       pAssert(     seed != NULL && dOut != NULL && Qout != NULL && curveData != NULL);
586
587       // Non-fatal parameter checks.
588       if(hLen <= 0)
589           return CRYPT_PARAMETER;
590
591       // allocate the local BN values
592       context = BN_CTX_new();
593       if(context == NULL)
594           FAIL(FATAL_ERROR_ALLOCATION);
595       BN_CTX_start(context);
596       bnNm1 = BN_CTX_get(context);
597       bnD = BN_CTX_get(context);
598
599       // The size of the input scalars is limited by the size of the size of a
600       // TPM2B_ECC_PARAMETER. Make sure that it is not irrational.
601       pAssert((int) curveData->n->size <= MAX_ECC_KEY_BYTES);
602
603       if(   bnD == NULL
604          || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnNm1) == NULL
605          || (keySizeInBytes = (INT16) BN_num_bytes(bnNm1)) > MAX_ECC_KEY_BYTES)
606           FAIL(FATAL_ERROR_INTERNAL);
607
608       // get the total number of bits
609       totalBits = BN_num_bits(bnNm1) + 64;
610
611       // Reduce bnNm1 from 'n' to 'n' - 1
612       BN_sub_word(bnNm1, 1);
613
614       // Initialize the count value
615       if(counter != NULL)
616           count = *counter;
617       if(count == 0)
618           count = 1;
619
620       // Start search for key (should be quick)
621       for(; count != 0; count++)
622       {
623
624            UINT32_TO_BYTE_ARRAY(count, marshaledCounter.t.buffer);
625            _cpri__KDFa(hashAlg, seed, label, extra, &marshaledCounter.b,
626                        totalBits, withExtra, NULL, FALSE);
627
628            // Convert the result and modular reduce
629            // Assume the size variables do not overflow, which should not happen in
630            // the contexts that this function will be called.
631            pAssert(keySizeInBytes <= MAX_ECC_KEY_BYTES);
632            if (    BN_bin2bn(withExtra, keySizeInBytes+8, bnD) == NULL
633                 || BN_mod(bnD, bnD, bnNm1, context) != 1)
634                 FAIL(FATAL_ERROR_INTERNAL);
635
636            // Add one to get 0 < d < n
637            BN_add_word(bnD, 1);
638            if(BnTo2B(&dOut->b, bnD, keySizeInBytes) != 1)
639                    FAIL(FATAL_ERROR_INTERNAL);
640
641            // Do the point multiply to create the public portion of the key. If
642            // the multiply generates the point at infinity (unlikely), do another
643            // iteration.
644            if(    (retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL))
645                != CRYPT_NO_RESULT)
646                break;
647       }
648
649       if(count == 0) // if counter wrapped, then the TPM should go into failure mode
650           FAIL(FATAL_ERROR_INTERNAL);

      Family "2.0"                          TCG Published                                Page 491
      Level 00 Revision 01.16         Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                             Part 4: Supporting Routines

651
652       // Free up allocated BN values
653       BN_CTX_end(context);
654       BN_CTX_free(context);
655       if(counter != NULL)
656           *counter = count;
657       return retVal;
658   }


      B.13.3.2.16. _cpri__GetEphemeralEcc()

      This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the
      key will be discarded

659   LIB_EXPORT CRYPT_RESULT
660   _cpri__GetEphemeralEcc(
661       TPMS_ECC_POINT                *Qout,            // OUT: the public point
662       TPM2B_ECC_PARAMETER           *dOut,            // OUT: the private scalar
663       TPM_ECC_CURVE                  curveId          // IN: the curve for the key
664       )
665   {
666       CRYPT_RESULT                   retVal;
667       const ECC_CURVE_DATA          *curveData = GetCurveData(curveId);
668
669       pAssert(curveData != NULL);
670
671       // Keep getting random values until one is found that doesn't create a point
672       // at infinity. This will never, ever, ever, ever, ever, happen but if it does
673       // we have to get a next random value.
674       while(TRUE)
675       {
676           GetRandomPrivate(dOut, curveData->p);
677
678            // _cpri__EccPointMultiply does not return CRYPT_ECC_POINT if no point is
679            // provided. CRYPT_PARAMTER should not be returned because the curve ID
680            // has to be supported. Thus the only possible error is CRYPT_NO_RESULT.
681            retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL);
682            if(retVal != CRYPT_NO_RESULT)
683                return retVal; // Will return CRYPT_SUCCESS
684       }
685   }
686   #ifdef TPM_ALG_ECDSA      //%


      B.13.3.2.17. SignEcdsa()

      This function implements the ECDSA signing algorithm. The method is described in the comments below.
      It is a fatal error if rOut, sOut, dIn, or digest are not provided.

687   LIB_EXPORT CRYPT_RESULT
688   SignEcdsa(
689       TPM2B_ECC_PARAMETER           *rOut,            //   OUT: r component of the signature
690       TPM2B_ECC_PARAMETER           *sOut,            //   OUT: s component of the signature
691       TPM_ECC_CURVE                  curveId,         //   IN: the curve used in the signature
692                                                       //       process
693       TPM2B_ECC_PARAMETER           *dIn,             //   IN: the private key
694       TPM2B                         *digest           //   IN: the value to sign
695       )
696   {
697       BIGNUM                        *bnK;
698       BIGNUM                        *bnIk;
699       BIGNUM                        *bnN;
700       BIGNUM                        *bnR;


      Page 492                                     TCG Published                                 Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

701        BIGNUM                    *bnD;
702        BIGNUM                    *bnZ;
703        TPM2B_ECC_PARAMETER        k;
704        TPMS_ECC_POINT             R;
705        BN_CTX                    *context;
706        CRYPT_RESULT               retVal = CRYPT_SUCCESS;
707        const ECC_CURVE_DATA      *curveData = GetCurveData(curveId);
708
709        pAssert(rOut != NULL && sOut != NULL && dIn != NULL && digest != NULL);
710
711        context = BN_CTX_new();
712        if(context == NULL)
713            FAIL(FATAL_ERROR_ALLOCATION);
714        BN_CTX_start(context);
715        bnN = BN_CTX_get(context);
716        bnZ = BN_CTX_get(context);
717        bnR = BN_CTX_get(context);
718        bnD = BN_CTX_get(context);
719        bnIk = BN_CTX_get(context);
720        bnK = BN_CTX_get(context);
721        // Assume the size variables do not overflow, which should not happen in
722        // the contexts that this function will be called.
723        pAssert(curveData->n->size <= MAX_ECC_PARAMETER_BYTES);
724        if(   bnK == NULL
725           || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL)
726            FAIL(FATAL_ERROR_INTERNAL);
727
728   //   The algorithm as described in "Suite B Implementer's Guide to FIPS 186-3(ECDSA)"
729   //   1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a per-message
730   //      secret number and its inverse modulo n. Since n is prime, the
731   //      output will be invalid only if there is a failure in the RBG.
732   //   2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar
733   //      multiplication (see [Routines]), where G is the base point included in
734   //      the set of domain parameters.
735   //   3. Compute r = xR mod n. If r = 0, then return to Step 1. 1.
736   //   4. Use the selected hash function to compute H = Hash(M).
737   //   5. Convert the bit string H to an integer e as described in Appendix B.2.
738   //   6. Compute s = (k^-1 * (e + d * r)) mod n. If s = 0, return to Step 1.2.
739   //   7. Return (r, s).
740
741        // Generate a random value k in the range 1 <= k < n
742        // Want a K value that is the same size as the curve order
743        k.t.size = curveData->n->size;
744
745        while(TRUE) // This implements the loop at step 6. If s is zero, start over.
746        {
747            while(TRUE)
748            {
749                // Step 1 and 2 -- generate an ephemeral key and the modular inverse
750                // of the private key.
751                while(TRUE)
752                {
753                    GetRandomPrivate(&k, curveData->n);
754
755                      // Do the point multiply to generate a point and check to see if
756                      // the point it at infinity
757                      if(    _cpri__EccPointMultiply(&R, curveId, &k, NULL, NULL)
758                          != CRYPT_NO_RESULT)
759                          break; // can only be CRYPT_SUCCESS
760                  }
761
762                  // x coordinate is mod p. Make it mod n
763                  // Assume the size variables do not overflow, which should not happen
764                  // in the contexts that this function will be called.
765                  assert2Bsize(R.x.t);
766                  BN_bin2bn(R.x.t.buffer, R.x.t.size, bnR);

      Family "2.0"                           TCG Published                                Page 493
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                      Part 4: Supporting Routines

767                  BN_mod(bnR, bnR, bnN, context);
768
769                  // Make sure that it is not zero;
770                  if(BN_is_zero(bnR))
771                      continue;
772
773                  // Make sure that a modular inverse exists
774                  // Assume the size variables do not overflow, which should not happen
775                  // in the contexts that this function will be called.
776                  assert2Bsize(k.t);
777                  BN_bin2bn(k.t.buffer, k.t.size, bnK);
778                  if( BN_mod_inverse(bnIk, bnK, bnN, context) != NULL)
779                      break;
780            }
781
782            // Set z = leftmost bits of the digest
783            // NOTE: This is implemented such that the key size needs to be
784            //        an even number of bytes in length.
785            if(digest->size > curveData->n->size)
786            {
787                 // Assume the size variables do not overflow, which should not happen
788                 // in the contexts that this function will be called.
789                 pAssert(curveData->n->size <= MAX_ECC_KEY_BYTES);
790                 // digest is larger than n so truncate
791                 BN_bin2bn(digest->buffer, curveData->n->size, bnZ);
792            }
793            else
794            {
795                 // Assume the size variables do not overflow, which should not happen
796                 // in the contexts that this function will be called.
797                 pAssert(digest->size <= MAX_DIGEST_SIZE);
798                 // digest is same or smaller than n so use it all
799                 BN_bin2bn(digest->buffer, digest->size, bnZ);
800            }
801
802            // Assume the size variables do not overflow, which should not happen in
803            // the contexts that this function will be called.
804            assert2Bsize(dIn->t);
805            if(   bnZ == NULL
806
807                 // need the private scalar of the signing key
808                 || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL)
809                  FAIL(FATAL_ERROR_INTERNAL);
810
811            //   NOTE: When the result of an operation is going to be reduced mod x
812            //   any modular multiplication is done so that the intermediate values
813            //   don't get too large.
814            //
815            // now have inverse of K (bnIk), z (bnZ), r (bnR),      d (bnD) and n (bnN)
816            // Compute s = k^-1 (z + r*d)(mod n)
817                // first do d = r*d mod n
818            if( !BN_mod_mul(bnD, bnR, bnD, bnN, context)
819
820                 // d = z + r * d
821                 || !BN_add(bnD, bnZ, bnD)
822
823                 // d = k^(-1)(z + r * d)(mod n)
824                 || !BN_mod_mul(bnD, bnIk, bnD, bnN, context)
825
826                 // convert to TPM2B format
827                 || !BnTo2B(&sOut->b, bnD, curveData->n->size)
828
829                 //   and write the modular reduced version of r
830                 //   NOTE: this was deferred to reduce the number of
831                 //   error checks.
832                 ||   !BnTo2B(&rOut->b, bnR, curveData->n->size))

      Page 494                                  TCG Published                            Family "2.0"
      October 30, 2014                   Copyright © TCG 2006-2014           Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library

833                  FAIL(FATAL_ERROR_INTERNAL);
834
835            if(!BN_is_zero(bnD))
836                break; // signature not zero so done
837
838            // if the signature value was zero, start over
839       }
840
841       // Free up allocated BN values
842       BN_CTX_end(context);
843       BN_CTX_free(context);
844       return retVal;
845   }
846   #endif //%
847   #if defined TPM_ALG_ECDAA || defined TPM_ALG_ECSCHNORR                //%


      B.13.3.2.18. EcDaa()

      This function is used to perform a modified Schnorr signature for ECDAA.
      This function performs s = k + T * d mod n where
      a) 'k is a random, or pseudo-random value used in the commit phase
      b) T is the digest to be signed, and
      c) d is a private key.
      If tIn is NULL then use tOut as T

      Return Value                        Meaning

      CRYPT_SUCCESS                       signature created

848   static CRYPT_RESULT
849   EcDaa(
850       TPM2B_ECC_PARAMETER              *tOut,             //   OUT: T component of the signature
851       TPM2B_ECC_PARAMETER              *sOut,             //   OUT: s component of the signature
852       TPM_ECC_CURVE                     curveId,          //   IN: the curve used in signing
853       TPM2B_ECC_PARAMETER              *dIn,              //   IN: the private key
854       TPM2B                            *tIn,              //   IN: the value to sign
855       TPM2B_ECC_PARAMETER              *kIn               //   IN: a random value from commit
856       )
857   {
858       BIGNUM                           *bnN, *bnK, *bnT, *bnD;
859       BN_CTX                           *context;
860       const TPM2B                      *n;
861       const ECC_CURVE_DATA             *curveData = GetCurveData(curveId);
862       BOOL                              OK = TRUE;
863
864       // Parameter checks
865        pAssert(   sOut != NULL && dIn != NULL && tOut != NULL
866                && kIn != NULL && curveData != NULL);
867
868       // this just saves key strokes
869       n = curveData->n;
870
871       if(tIn != NULL)
872           Copy2B(&tOut->b, tIn);
873
874       // The size of dIn and kIn input scalars is limited by the size of the size
875       // of a TPM2B_ECC_PARAMETER and tIn can be no larger than a digest.
876       // Make sure they are within range.
877       pAssert(   (int) dIn->t.size <= MAX_ECC_KEY_BYTES
878               && (int) kIn->t.size <= MAX_ECC_KEY_BYTES


      Family "2.0"                                    TCG Published                                    Page 495
      Level 00 Revision 01.16                 Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                   Part 4: Supporting Routines

879                 && (int) tOut->t.size <= MAX_DIGEST_SIZE
880                );
881
882       context = BN_CTX_new();
883       if(context == NULL)
884           FAIL(FATAL_ERROR_ALLOCATION);
885       BN_CTX_start(context);
886       bnN = BN_CTX_get(context);
887       bnK = BN_CTX_get(context);
888       bnT = BN_CTX_get(context);
889       bnD = BN_CTX_get(context);
890
891       // Check for allocation problems
892       if(bnD == NULL)
893           FAIL(FATAL_ERROR_ALLOCATION);
894
895       // Convert values
896       if(   BN_bin2bn(n->buffer, n->size, bnN) == NULL
897          || BN_bin2bn(kIn->t.buffer, kIn->t.size, bnK) == NULL
898          || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL
899          || BN_bin2bn(tOut->t.buffer, tOut->t.size, bnT) == NULL)
900
901           FAIL(FATAL_ERROR_INTERNAL);
902       // Compute T = T mod n
903       OK = OK && BN_mod(bnT, bnT, bnN, context);
904
905       // compute (s = k + T * d mod n)
906               //   d = T * d mod n
907       OK = OK && BN_mod_mul(bnD, bnT, bnD, bnN, context) == 1;
908               //   d = k + T * d mod n
909       OK = OK && BN_mod_add(bnD, bnK, bnD, bnN, context) == 1;
910               //   s = d
911       OK = OK && BnTo2B(&sOut->b, bnD, n->size);
912               //   r = T
913       OK = OK && BnTo2B(&tOut->b, bnT, n->size);
914       if(!OK)
915           FAIL(FATAL_ERROR_INTERNAL);
916
917       // Cleanup
918       BN_CTX_end(context);
919       BN_CTX_free(context);
920
921       return CRYPT_SUCCESS;
922   }
923   #endif //%
924   #ifdef TPM_ALG_ECSCHNORR //%


      B.13.3.2.19. SchnorrEcc()

      This function is used to perform a modified Schnorr signature.
      This function will generate a random value k and compute
      a) (xR, yR) = [k]G
      b) r = hash(P || xR)(mod n)
      c) s= k + r * ds
      d) return the tuple T, s




      Page 496                                    TCG Published                       Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014     Level 00 Revision 01.16
      Part 4: Supporting Routines                                              Trusted Platform Module Library


      Return Value                  Meaning

      CRYPT_SUCCESS                 signature created
      CRYPT_SCHEME                  hashAlg can't produce zero-length digest

925   static CRYPT_RESULT
926   SchnorrEcc(
927       TPM2B_ECC_PARAMETER        *rOut,               //   OUT: r component of the signature
928       TPM2B_ECC_PARAMETER        *sOut,               //   OUT: s component of the signature
929       TPM_ALG_ID                  hashAlg,            //   IN: hash algorithm used
930       TPM_ECC_CURVE               curveId,            //   IN: the curve used in signing
931       TPM2B_ECC_PARAMETER        *dIn,                //   IN: the private key
932       TPM2B                      *digest,             //   IN: the digest to sign
933       TPM2B_ECC_PARAMETER        *kIn                 //   IN: for testing
934       )
935   {
936       TPM2B_ECC_PARAMETER      k;
937       BIGNUM                  *bnR, *bnN, *bnK, *bnT, *bnD;
938       BN_CTX                  *context;
939       const TPM2B             *n;
940       EC_POINT                *pR = NULL;
941       EC_GROUP                *group = NULL;
942       CPRI_HASH_STATE          hashState;
943       UINT16                   digestSize = _cpri__GetDigestSize(hashAlg);
944       const ECC_CURVE_DATA    *curveData = GetCurveData(curveId);
945       TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_PARAMETER_BYTES));
946       TPM2B_T                  T2b;
947       BOOL                     OK = TRUE;
948
949       // Parameter checks
950
951       // Must have a place for the 'r' and 's' parts of the signature, a private
952       // key ('d')
953       pAssert(   rOut != NULL && sOut != NULL && dIn != NULL
954               && digest != NULL && curveData != NULL);
955
956       // to save key strokes
957       n = curveData->n;
958
959       // If the digest does not produce a hash, then null the signature and return
960       // a failure.
961       if(digestSize == 0)
962       {
963           rOut->t.size = 0;
964           sOut->t.size = 0;
965           return CRYPT_SCHEME;
966       }
967
968       // Allocate big number values
969       context = BN_CTX_new();
970       if(context == NULL)
971           FAIL(FATAL_ERROR_ALLOCATION);
972       BN_CTX_start(context);
973       bnR = BN_CTX_get(context);
974       bnN = BN_CTX_get(context);
975       bnK = BN_CTX_get(context);
976       bnT = BN_CTX_get(context);
977       bnD = BN_CTX_get(context);
978       if(   bnD == NULL
979               // initialize the group parameters
980          || (group = EccCurveInit(curveId, context)) == NULL
981              // allocate a local point
982          || (pR = EC_POINT_new(group)) == NULL
983         )

      Family "2.0"                              TCG Published                                       Page 497
      Level 00 Revision 01.16           Copyright © TCG 2006-2014                          October 30, 2014
       Trusted Platform Module Library                                  Part 4: Supporting Routines

 984            FAIL(FATAL_ERROR_ALLOCATION);
 985
 986       if(BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL)
 987           FAIL(FATAL_ERROR_INTERNAL);
 988
 989       while(OK)
 990       {
 991   // a) set k to a random value such that 1 k n-1
 992           if(kIn != NULL)
 993           {
 994                Copy2B(&k.b, &kIn->b); // copy input k if testing
 995                OK = FALSE;              // not OK to loop
 996           }
 997           else
 998           // If get a random value in the correct range
 999                GetRandomPrivate(&k, n);
1000
1001            // Convert 'k' and generate pR = ['k']G
1002            BnFrom2B(bnK, &k.b);
1003
1004   // b) compute E (xE, yE) [k]G
1005           if(PointMul(group, pR, bnK, NULL, NULL, context) == CRYPT_NO_RESULT)
1006   // c) if E is the point at infinity, go to a)
1007               continue;
1008
1009   // d) compute e xE (mod n)
1010           // Get the x coordinate of the point
1011           EC_POINT_get_affine_coordinates_GFp(group, pR, bnR, NULL, context);
1012
1013            // make (mod n)
1014            BN_mod(bnR, bnR, bnN, context);
1015
1016   // e) if e is zero, go to a)
1017           if(BN_is_zero(bnR))
1018               continue;
1019
1020            // Convert xR to a string (use T as a temp)
1021            BnTo2B(&T2b.b, bnR, (UINT16)(BN_num_bits(bnR)+7)/8);
1022
1023   // f) compute r HschemeHash(P || e) (mod n)
1024           _cpri__StartHash(hashAlg, FALSE, &hashState);
1025           _cpri__UpdateHash(&hashState, digest->size, digest->buffer);
1026           _cpri__UpdateHash(&hashState, T2b.t.size, T2b.t.buffer);
1027           if(_cpri__CompleteHash(&hashState, digestSize, T2b.b.buffer) != digestSize)
1028               FAIL(FATAL_ERROR_INTERNAL);
1029           T2b.t.size = digestSize;
1030           BnFrom2B(bnT, &T2b.b);
1031           BN_div(NULL, bnT, bnT, bnN, context);
1032           BnTo2B(&rOut->b, bnT, (UINT16)BN_num_bytes(bnT));
1033
1034            // We have a value and we are going to exit the loop successfully
1035            OK = TRUE;
1036            break;
1037       }
1038       // Cleanup
1039       EC_POINT_free(pR);
1040       EC_GROUP_free(group);
1041       BN_CTX_end(context);
1042       BN_CTX_free(context);
1043
1044       // If we have a value, finish the signature
1045       if(OK)
1046           return EcDaa(rOut, sOut, curveId, dIn, NULL, &k);
1047       else
1048           return CRYPT_NO_RESULT;
1049   }

       Page 498                               TCG Published                           Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014       Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

1050   #endif //%
1051   #ifdef TPM_ALG_SM2 //%
1052   #ifdef _SM2_SIGN_DEBUG //%
1053   static int
1054   cmp_bn2hex(
1055       BIGNUM              *bn,               // IN: big number value
1056       const char          *c                 // IN: character string number
1057       )
1058   {
1059       int         result;
1060       BIGNUM      *bnC = BN_new();
1061       pAssert(bnC != NULL);
1062
1063       BN_hex2bn(&bnC, c);
1064       result = BN_ucmp(bn, bnC);
1065       BN_free(bnC);
1066       return result;
1067   }
1068   static int
1069   cmp_2B2hex(
1070       TPM2B               *a,                // IN: TPM2B number to compare
1071       const char          *c                 // IN: character string
1072       )
1073   {
1074       int            result;
1075       int            sl = strlen(c);
1076       BIGNUM         *bnA;
1077
1078       result = (a->size * 2) - sl;
1079       if(result != 0)
1080           return result;
1081       pAssert((bnA = BN_bin2bn(a->buffer, a->size, NULL)) != NULL);
1082       result = cmp_bn2hex(bnA, c);
1083       BN_free(bnA);
1084       return result;
1085   }
1086   static void
1087   cpy_hexTo2B(
1088       TPM2B               *b,                // OUT: receives value
1089       const char          *c                 // IN: source string
1090       )
1091   {
1092       BIGNUM      *bnB = BN_new();
1093       pAssert((strlen(c) & 1) == 0);         // must have an even number of digits
1094       b->size = strlen(c) / 2;
1095       BN_hex2bn(&bnB, c);
1096       pAssert(bnB != NULL);
1097       BnTo2B(b, bnB, b->size);
1098       BN_free(bnB);
1099
1100   }
1101   #endif //% _SM2_SIGN_DEBUG


       B.13.3.2.20. SignSM2()

       This function signs a digest using the method defined in SM2 Part 2. The method in the standard will add
       a header to the message to be signed that is a hash of the values that define the key. This then hashed
       with the message to produce a digest (e) that is signed. This function signs e.




       Family "2.0"                               TCG Published                                     Page 499
       Level 00 Revision 01.16             Copyright © TCG 2006-2014                        October 30, 2014
       Trusted Platform Module Library                                                Part 4: Supporting Routines


       Return Value                      Meaning

       CRYPT_SUCCESS                     sign worked

1102   static CRYPT_RESULT
1103   SignSM2(
1104       TPM2B_ECC_PARAMETER            *rOut,                 //   OUT: r component of the signature
1105       TPM2B_ECC_PARAMETER            *sOut,                 //   OUT: s component of the signature
1106       TPM_ECC_CURVE                   curveId,              //   IN: the curve used in signing
1107       TPM2B_ECC_PARAMETER            *dIn,                  //   IN: the private key
1108       TPM2B                          *digest                //   IN: the digest to sign
1109       )
1110   {
1111       BIGNUM                         *bnR;
1112       BIGNUM                         *bnS;
1113       BIGNUM                         *bnN;
1114       BIGNUM                         *bnK;
1115       BIGNUM                         *bnX1;
1116       BIGNUM                         *bnD;
1117       BIGNUM                         *bnT;        // temp
1118       BIGNUM                         *bnE;
1119
1120       BN_CTX                  *context;
1121       TPM2B_TYPE(DIGEST, MAX_DIGEST_SIZE);
1122       TPM2B_ECC_PARAMETER      k;
1123       TPMS_ECC_POINT           p2Br;
1124       const ECC_CURVE_DATA    *curveData = GetCurveData(curveId);
1125
1126       pAssert(curveData != NULL);
1127       context = BN_CTX_new();
1128       BN_CTX_start(context);
1129       bnK = BN_CTX_get(context);
1130       bnR = BN_CTX_get(context);
1131       bnS = BN_CTX_get(context);
1132       bnX1 = BN_CTX_get(context);
1133       bnN = BN_CTX_get(context);
1134       bnD = BN_CTX_get(context);
1135       bnT = BN_CTX_get(context);
1136       bnE = BN_CTX_get(context);
1137       if(bnE == NULL)
1138           FAIL(FATAL_ERROR_ALLOCATION);
1139
1140       BnFrom2B(bnE, digest);
1141       BnFrom2B(bnN, curveData->n);
1142       BnFrom2B(bnD, &dIn->b);
1143
1144   #ifdef _SM2_SIGN_DEBUG
1145   BN_hex2bn(&bnE, "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76");
1146   BN_hex2bn(&bnD, "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263");
1147   #endif
1148   // A3: Use random number generator to generate random number 1 <= k <= n-1;
1149   // NOTE: Ax: numbers are from the SM2 standard
1150       k.t.size = curveData->n->size;
1151   loop:
1152       {
1153           // Get a random number
1154           _cpri__GenerateRandom(k.t.size, k.t.buffer);
1155
1156   #ifdef _SM2_SIGN_DEBUG
1157   BN_hex2bn(&bnK, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F");
1158   BnTo2B(&k.b,bnK, 32);
1159   k.t.size = 32;
1160   #endif
1161           //make sure that the number is 0 < k < n
1162           BnFrom2B(bnK, &k.b);

       Page 500                                        TCG Published                                Family "2.0"
       October 30, 2014                      Copyright © TCG 2006-2014                  Level 00 Revision 01.16
       Part 4: Supporting Routines                                  Trusted Platform Module Library

1163            if(      BN_ucmp(bnK, bnN) >= 0
1164                  || BN_is_zero(bnK))
1165                  goto loop;
1166
1167   // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according
1168   // to details specified in 4.2.7 in Part 1 of this document, transform the
1169   // data type of x1 into an integer;
1170           if(    _cpri__EccPointMultiply(&p2Br, curveId, &k, NULL, NULL)
1171               == CRYPT_NO_RESULT)
1172                goto loop;
1173
1174            BnFrom2B(bnX1, &p2Br.x.b);
1175
1176    // A5: Figure out r = (e + x1) mod n,
1177           if(!BN_mod_add(bnR, bnE, bnX1, bnN, context))
1178               FAIL(FATAL_ERROR_INTERNAL);
1179   #ifdef _SM2_SIGN_DEBUG
1180   pAssert(cmp_bn2hex(bnR,
1181                   "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1")
1182           == 0);
1183   #endif
1184
1185               // if r=0 or r+k=n, return to A3;
1186             if(!BN_add(bnT, bnK, bnR))
1187                FAIL(FATAL_ERROR_INTERNAL);
1188
1189            if(BN_is_zero(bnR) || BN_ucmp(bnT, bnN) == 0)
1190                goto loop;
1191
1192   // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, if s=0, return to A3;
1193           // compute t = (1+d)-1
1194           BN_copy(bnT, bnD);
1195           if(     !BN_add_word(bnT, 1)
1196               || !BN_mod_inverse(bnT, bnT, bnN, context) // (1 + dA)^-1 mod n
1197               )
1198                 FAIL(FATAL_ERROR_INTERNAL);
1199   #ifdef _SM2_SIGN_DEBUG
1200   pAssert(cmp_bn2hex(bnT,
1201                     "79BFCF3052C80DA7B939E0C6914A18CBB2D96D8555256E83122743A7D4F5F956")
1202           == 0);
1203   #endif
1204           // compute s = t * (k - r * dA) mod n
1205           if(     !BN_mod_mul(bnS, bnD, bnR, bnN, context) // (r * dA) mod n
1206               || !BN_mod_sub(bnS, bnK, bnS, bnN, context) // (k - (r * dA) mod n
1207               || !BN_mod_mul(bnS, bnT, bnS, bnN, context))// t * (k - (r * dA) mod n
1208               FAIL(FATAL_ERROR_INTERNAL);
1209   #ifdef _SM2_SIGN_DEBUG
1210   pAssert(cmp_bn2hex(bnS,
1211                     "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7")
1212           == 0);
1213   #endif
1214
1215            if(BN_is_zero(bnS))
1216                goto loop;
1217       }
1218
1219   // A7: According to details specified in 4.2.1 in Part 1 of this document, transform
1220   // the data type of r, s into bit strings, signature of message M is (r, s).
1221
1222       BnTo2B(&rOut->b, bnR, curveData->n->size);
1223       BnTo2B(&sOut->b, bnS, curveData->n->size);
1224   #ifdef _SM2_SIGN_DEBUG
1225   pAssert(cmp_2B2hex(&rOut->b,
1226                   "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1")
1227           == 0);
1228   pAssert(cmp_2B2hex(&sOut->b,

       Family "2.0"                           TCG Published                              Page 501
       Level 00 Revision 01.16          Copyright © TCG 2006-2014               October 30, 2014
       Trusted Platform Module Library                                              Part 4: Supporting Routines

1229                      "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7")
1230            == 0);
1231   #endif
1232       BN_CTX_end(context);
1233       BN_CTX_free(context);
1234       return CRYPT_SUCCESS;
1235   }
1236   #endif //% TPM_ALG_SM2


       B.13.3.2.21. _cpri__SignEcc()

       This function is the dispatch function for the various ECC-based signing schemes.

       Return Value                      Meaning

       CRYPT_SCHEME                      scheme is not supported

1237   LIB_EXPORT CRYPT_RESULT
1238   _cpri__SignEcc(
1239       TPM2B_ECC_PARAMETER            *rOut,              //   OUT: r component of the signature
1240       TPM2B_ECC_PARAMETER            *sOut,              //   OUT: s component of the signature
1241       TPM_ALG_ID                      scheme,            //   IN: the scheme selector
1242       TPM_ALG_ID                      hashAlg,           //   IN: the hash algorithm if need
1243       TPM_ECC_CURVE                   curveId,           //   IN: the curve used in the signature
1244                                                          //       process
1245       TPM2B_ECC_PARAMETER            *dIn,               //   IN: the private key
1246       TPM2B                          *digest,            //   IN: the digest to sign
1247       TPM2B_ECC_PARAMETER            *kIn                //   IN: k for input
1248       )
1249   {
1250       switch (scheme)
1251       {
1252           case TPM_ALG_ECDSA:
1253               // SignEcdsa always works
1254               return SignEcdsa(rOut, sOut, curveId, dIn, digest);
1255               break;
1256   #ifdef TPM_ALG_ECDAA
1257           case TPM_ALG_ECDAA:
1258               if(rOut != NULL)
1259                    rOut->b.size = 0;
1260               return EcDaa(rOut, sOut, curveId, dIn, digest, kIn);
1261               break;
1262   #endif
1263   #ifdef TPM_ALG_ECSCHNORR
1264           case TPM_ALG_ECSCHNORR:
1265               return SchnorrEcc(rOut, sOut, hashAlg, curveId, dIn, digest, kIn);
1266               break;
1267   #endif
1268   #ifdef TPM_ALG_SM2
1269           case TPM_ALG_SM2:
1270               return SignSM2(rOut, sOut, curveId, dIn, digest);
1271               break;
1272   #endif
1273           default:
1274               return CRYPT_SCHEME;
1275       }
1276   }
1277   #ifdef TPM_ALG_ECDSA //%


       B.13.3.2.22. ValidateSignatureEcdsa()

       This function validates an ECDSA signature. rIn and sIn shoudl have been checked to make sure that
       they are not zero.

       Page 502                                      TCG Published                                Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014              Level 00 Revision 01.16
       Part 4: Supporting Routines                                           Trusted Platform Module Library


       Return Value                  Meaning

       CRYPT_SUCCESS                 signature valid
       CRYPT_FAIL                    signature not valid

1278   static CRYPT_RESULT
1279   ValidateSignatureEcdsa(
1280       TPM2B_ECC_PARAMETER        *rIn,                //   IN: r component of the signature
1281       TPM2B_ECC_PARAMETER        *sIn,                //   IN: s component of the signature
1282       TPM_ECC_CURVE               curveId,            //   IN: the curve used in the signature
1283                                                       //       process
1284       TPMS_ECC_POINT             *Qin,                //   IN: the public point of the key
1285       TPM2B                      *digest              //   IN: the digest that was signed
1286       )
1287   {
1288       TPM2B_ECC_PARAMETER         U1;
1289       TPM2B_ECC_PARAMETER         U2;
1290       TPMS_ECC_POINT              R;
1291       const TPM2B                *n;
1292       BN_CTX                     *context;
1293       EC_POINT                   *pQ = NULL;
1294       EC_GROUP                   *group = NULL;
1295       BIGNUM                     *bnU1;
1296       BIGNUM                     *bnU2;
1297       BIGNUM                     *bnR;
1298       BIGNUM                     *bnS;
1299       BIGNUM                     *bnW;
1300       BIGNUM                     *bnV;
1301       BIGNUM                     *bnN;
1302       BIGNUM                     *bnE;
1303       BIGNUM                     *bnGx;
1304       BIGNUM                     *bnGy;
1305       BIGNUM                     *bnQx;
1306       BIGNUM                     *bnQy;
1307       CRYPT_RESULT                retVal = CRYPT_FAIL;
1308       int                         t;
1309
1310       const ECC_CURVE_DATA       *curveData = GetCurveData(curveId);
1311
1312       // The curve selector should have been filtered by the unmarshaling process
1313       pAssert (curveData != NULL);
1314       n = curveData->n;
1315
1316   // 1. If r and s are not both integers in the interval [1, n - 1], output
1317   //    INVALID.
1318   // rIn and sIn are known to be greater than zero (was checked by the caller).
1319       if(     _math__uComp(rIn->t.size, rIn->t.buffer, n->size, n->buffer) >= 0
1320           || _math__uComp(sIn->t.size, sIn->t.buffer, n->size, n->buffer) >= 0
1321         )
1322          return CRYPT_FAIL;
1323
1324       context = BN_CTX_new();
1325       if(context == NULL)
1326           FAIL(FATAL_ERROR_ALLOCATION);
1327       BN_CTX_start(context);
1328       bnR = BN_CTX_get(context);
1329       bnS = BN_CTX_get(context);
1330       bnN = BN_CTX_get(context);
1331       bnE = BN_CTX_get(context);
1332       bnV = BN_CTX_get(context);
1333       bnW = BN_CTX_get(context);
1334       bnGx = BN_CTX_get(context);
1335       bnGy = BN_CTX_get(context);
1336       bnQx = BN_CTX_get(context);

       Family "2.0"                               TCG Published                                   Page 503
       Level 00 Revision 01.16           Copyright © TCG 2006-2014                       October 30, 2014
       Trusted Platform Module Library                                   Part 4: Supporting Routines

1337       bnQy = BN_CTX_get(context);
1338       bnU1 = BN_CTX_get(context);
1339       bnU2 = BN_CTX_get(context);
1340
1341       // Assume the size variables do not overflow, which should not happen in
1342       // the contexts that this function will be called.
1343       assert2Bsize(Qin->x.t);
1344       assert2Bsize(rIn->t);
1345       assert2Bsize(sIn->t);
1346
1347       // BN_CTX_get() is sticky so only need to check the last value to know that
1348       // all worked.
1349       if(   bnU2 == NULL
1350
1351            // initialize the group parameters
1352           || (group = EccCurveInit(curveId, context)) == NULL
1353
1354           // allocate a local point
1355           || (pQ = EC_POINT_new(group)) == NULL
1356
1357           //   use the public key values (QxIn and QyIn) to initialize Q
1358           ||   BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQx) == NULL
1359           ||   BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQy) == NULL
1360           ||   !EC_POINT_set_affine_coordinates_GFp(group, pQ, bnQx, bnQy, context)
1361
1362           // convert the signature values
1363           || BN_bin2bn(rIn->t.buffer, rIn->t.size, bnR) == NULL
1364           || BN_bin2bn(sIn->t.buffer, sIn->t.size, bnS) == NULL
1365
1366           // convert the curve order
1367           || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL)
1368            FAIL(FATAL_ERROR_INTERNAL);
1369
1370   // 2. Use the selected hash function to compute H0 = Hash(M0).
1371       // This is an input parameter
1372
1373   // 3. Convert the bit string H0 to an integer e as described in Appendix B.2.
1374       t = (digest->size > rIn->t.size) ? rIn->t.size : digest->size;
1375       if(BN_bin2bn(digest->buffer, t, bnE) == NULL)
1376           FAIL(FATAL_ERROR_INTERNAL);
1377
1378   // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1.
1379       if (BN_mod_inverse(bnW, bnS, bnN, context) == NULL)
1380           FAIL(FATAL_ERROR_INTERNAL);
1381
1382   // 5. Compute u1 = (e' *   w) mod n, and compute u2 = (r' *     w) mod n.
1383       if(   !BN_mod_mul(bnU1, bnE, bnW, bnN, context)
1384          || !BN_mod_mul(bnU2, bnR, bnW, bnN, context))
1385           FAIL(FATAL_ERROR_INTERNAL);
1386
1387       BnTo2B(&U1.b, bnU1, (INT16) BN_num_bytes(bnU1));
1388       BnTo2B(&U2.b, bnU2, (INT16) BN_num_bytes(bnU2));
1389
1390   // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC
1391   //    scalar multiplication and EC addition (see [Routines]). If R is equal to
1392   //    the point at infinity O, output INVALID.
1393       if(_cpri__EccPointMultiply(&R, curveId, &U1, Qin, &U2) == CRYPT_SUCCESS)
1394       {
1395           // 7. Compute v = Rx mod n.
1396           if(    BN_bin2bn(R.x.t.buffer, R.x.t.size, bnV) == NULL
1397               || !BN_mod(bnV, bnV, bnN, context))
1398                FAIL(FATAL_ERROR_INTERNAL);
1399
1400       // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID
1401           if(BN_cmp(bnV, bnR) == 0)
1402               retVal = CRYPT_SUCCESS;

       Page 504                               TCG Published                            Family "2.0"
       October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
       Part 4: Supporting Routines                                            Trusted Platform Module Library

1403       }
1404
1405       if(pQ != NULL) EC_POINT_free(pQ);
1406       if(group != NULL) EC_GROUP_free(group);
1407       BN_CTX_end(context);
1408       BN_CTX_free(context);
1409
1410       return retVal;
1411   }
1412   #endif      //% TPM_ALG_ECDSA
1413   #ifdef TPM_ALG_ECSCHNORR //%


       B.13.3.2.23. ValidateSignatureEcSchnorr()

       This function is used to validate an EC Schnorr signature. rIn and sIn are required to be greater than
       zero. This is checked in _cpri__ValidateSignatureEcc().

       Return Value                   Meaning

       CRYPT_SUCCESS                  signature valid
       CRYPT_FAIL                     signature not valid
       CRYPT_SCHEME                   hashAlg is not supported

1414   static CRYPT_RESULT
1415   ValidateSignatureEcSchnorr(
1416       TPM2B_ECC_PARAMETER         *rIn,                //   IN: r component of the signature
1417       TPM2B_ECC_PARAMETER         *sIn,                //   IN: s component of the signature
1418       TPM_ALG_ID                   hashAlg,            //   IN: hash algorithm of the signature
1419       TPM_ECC_CURVE                curveId,            //   IN: the curve used in the signature
1420                                                        //       process
1421       TPMS_ECC_POINT              *Qin,                //   IN: the public point of the key
1422       TPM2B                       *digest              //   IN: the digest that was signed
1423       )
1424   {
1425       TPMS_ECC_POINT               pE;
1426       const TPM2B                 *n;
1427       CPRI_HASH_STATE              hashState;
1428       TPM2B_DIGEST                 rPrime;
1429       TPM2B_ECC_PARAMETER          minusR;
1430       UINT16                       digestSize = _cpri__GetDigestSize(hashAlg);
1431       const ECC_CURVE_DATA        *curveData = GetCurveData(curveId);
1432
1433       // The curve parameter should have been filtered by unmarshaling code
1434       pAssert(curveData != NULL);
1435
1436       if(digestSize == 0)
1437           return CRYPT_SCHEME;
1438
1439       // Input parameter validation
1440       pAssert(rIn != NULL && sIn != NULL && Qin != NULL && digest != NULL);
1441
1442       n = curveData->n;
1443
1444       // if sIn or rIn are not between 1 and N-1, signature check fails
1445       // sIn and rIn were verified to be non-zero by the caller
1446       if(   _math__uComp(sIn->b.size, sIn->b.buffer, n->size, n->buffer) >= 0
1447          || _math__uComp(rIn->b.size, rIn->b.buffer, n->size, n->buffer) >= 0
1448         )
1449           return CRYPT_FAIL;
1450
1451       //E = [s]InG - [r]InQ
1452       _math__sub(n->size, n->buffer,
1453                  rIn->t.size, rIn->t.buffer,

       Family "2.0"                                TCG Published                                   Page 505
       Level 00 Revision 01.16            Copyright © TCG 2006-2014                       October 30, 2014
       Trusted Platform Module Library                                              Part 4: Supporting Routines

1454                  &minusR.t.size, minusR.t.buffer);
1455       if(_cpri__EccPointMultiply(&pE, curveId, sIn, Qin, &minusR) != CRYPT_SUCCESS)
1456           return CRYPT_FAIL;
1457
1458       // Ex = Ex mod N
1459       if(Mod2B(&pE.x.b, n) != CRYPT_SUCCESS)
1460           FAIL(FATAL_ERROR_INTERNAL);
1461
1462       _math__Normalize2B(&pE.x.b);
1463
1464       // rPrime = h(digest || pE.x) mod n;
1465       _cpri__StartHash(hashAlg, FALSE, &hashState);
1466       _cpri__UpdateHash(&hashState, digest->size, digest->buffer);
1467       _cpri__UpdateHash(&hashState, pE.x.t.size, pE.x.t.buffer);
1468       if(_cpri__CompleteHash(&hashState, digestSize, rPrime.t.buffer) != digestSize)
1469           FAIL(FATAL_ERROR_INTERNAL);
1470
1471       rPrime.t.size = digestSize;
1472
1473       // rPrime = rPrime (mod n)
1474       if(Mod2B(&rPrime.b, n) != CRYPT_SUCCESS)
1475           FAIL(FATAL_ERROR_INTERNAL);
1476
1477       // if the values don't match, then the signature is bad
1478       if(_math__uComp(rIn->t.size, rIn->t.buffer,
1479                       rPrime.t.size, rPrime.t.buffer) != 0)
1480           return CRYPT_FAIL;
1481       else
1482           return CRYPT_SUCCESS;
1483   }
1484   #endif //% TPM_ALG_ECSCHNORR
1485   #ifdef TPM_ALG_SM2 //%


       B.13.3.2.24. ValidateSignatueSM2Dsa()

       This function is used to validate an SM2 signature.

       Return Value                      Meaning

       CRYPT_SUCCESS                     signature valid
       CRYPT_FAIL                        signature not valid

1486   static CRYPT_RESULT
1487   ValidateSignatureSM2Dsa(
1488       TPM2B_ECC_PARAMETER            *rIn,                //   IN: r component of the signature
1489       TPM2B_ECC_PARAMETER            *sIn,                //   IN: s component of the signature
1490       TPM_ECC_CURVE                   curveId,            //   IN: the curve used in the signature
1491                                                           //       process
1492       TPMS_ECC_POINT                 *Qin,                //   IN: the public point of the key
1493       TPM2B                          *digest              //   IN: the digest that was signed
1494       )
1495   {
1496       BIGNUM                         *bnR;
1497       BIGNUM                         *bnRp;
1498       BIGNUM                         *bnT;
1499       BIGNUM                         *bnS;
1500       BIGNUM                         *bnE;
1501       EC_POINT                       *pQ;
1502       BN_CTX                         *context;
1503       EC_GROUP                       *group = NULL;
1504       const ECC_CURVE_DATA           *curveData = GetCurveData(curveId);
1505       BOOL                            fail = FALSE;
1506


       Page 506                                       TCG Published                               Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
       Part 4: Supporting Routines                                 Trusted Platform Module Library

1507       if((context = BN_CTX_new()) == NULL || curveData == NULL)
1508           FAIL(FATAL_ERROR_INTERNAL);
1509       bnR = BN_CTX_get(context);
1510       bnRp= BN_CTX_get(context);
1511       bnE = BN_CTX_get(context);
1512       bnT = BN_CTX_get(context);
1513       bnS = BN_CTX_get(context);
1514       if(   bnS == NULL
1515          || (group = EccCurveInit(curveId, context)) == NULL)
1516           FAIL(FATAL_ERROR_INTERNAL);
1517
1518   #ifdef _SM2_SIGN_DEBUG
1519       cpy_hexTo2B(&Qin->x.b,
1520              "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A");
1521       cpy_hexTo2B(&Qin->y.b,
1522              "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857");
1523       cpy_hexTo2B(digest,
1524              "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76");
1525   #endif
1526       pQ = EccInitPoint2B(group, Qin, context);
1527
1528   #ifdef _SM2_SIGN_DEBUG
1529       pAssert(EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, bnS, context));
1530       pAssert(cmp_bn2hex(bnT,
1531                   "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A")
1532               == 0);
1533       pAssert(cmp_bn2hex(bnS,
1534                   "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857")
1535               == 0);
1536   #endif
1537
1538       BnFrom2B(bnR, &rIn->b);
1539       BnFrom2B(bnS, &sIn->b);
1540       BnFrom2B(bnE, digest);
1541
1542   #ifdef _SM2_SIGN_DEBUG
1543   // Make sure that the input signature is the test signature
1544   pAssert(cmp_2B2hex(&rIn->b,
1545           "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") == 0);
1546   pAssert(cmp_2B2hex(&sIn->b,
1547           "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") == 0);
1548   #endif
1549
1550   // a) verify that r and s are in the inclusive interval 1 to (n   1)
1551       fail = (BN_ucmp(bnR, &group->order) >= 0);
1552
1553       fail = (BN_ucmp(bnS, &group->order) >= 0) || fail;
1554       if(fail)
1555       // There is no reason to continue. Since r and s are inputs from the caller,
1556       // they can know that the values are not in the proper range. So, exiting here
1557       // does not disclose any information.
1558           goto Cleanup;
1559
1560   // b) compute t := (r + s) mod n
1561       if(!BN_mod_add(bnT, bnR, bnS, &group->order, context))
1562           FAIL(FATAL_ERROR_INTERNAL);
1563   #ifdef _SM2_SIGN_DEBUG
1564       pAssert(cmp_bn2hex(bnT,
1565                   "2B75F07ED7ECE7CCC1C8986B991F441AD324D6D619FE06DD63ED32E0C997C801")
1566               == 0);
1567   #endif
1568
1569   // c) verify that t > 0
1570       if(BN_is_zero(bnT)) {
1571           fail = TRUE;
1572           // set to a value that should allow rest of the computations to run without

       Family "2.0"                        TCG Published                                Page 507
       Level 00 Revision 01.16       Copyright © TCG 2006-2014                 October 30, 2014
       Trusted Platform Module Library                                                Part 4: Supporting Routines

1573             // trouble
1574             BN_copy(bnT, bnS);
1575       }
1576   // d) compute (x, y) := [s]G + [t]Q
1577       if(!EC_POINT_mul(group, pQ, bnS, pQ, bnT, context))
1578           FAIL(FATAL_ERROR_INTERNAL);
1579       // Get the x coordinate of the point
1580       if(!EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, NULL, context))
1581           FAIL(FATAL_ERROR_INTERNAL);
1582
1583   #ifdef _SM2_SIGN_DEBUG
1584       pAssert(cmp_bn2hex(bnT,
1585                   "110FCDA57615705D5E7B9324AC4B856D23E6D9188B2AE47759514657CE25D112")
1586                   == 0);
1587   #endif
1588
1589   // e) compute r' := (e + x) mod n (the x coordinate is in bnT)
1590       if(!BN_mod_add(bnRp, bnE, bnT, &group->order, context))
1591           FAIL(FATAL_ERROR_INTERNAL);
1592
1593   // f) verify that r' = r
1594       fail = BN_ucmp(bnR, bnRp) != 0 || fail;
1595
1596   Cleanup:
1597       if(pQ) EC_POINT_free(pQ);
1598       if(group) EC_GROUP_free(group);
1599       BN_CTX_end(context);
1600       BN_CTX_free(context);
1601
1602        if(fail)
1603            return CRYPT_FAIL;
1604        else
1605            return CRYPT_SUCCESS;
1606   }
1607   #endif //% TPM_ALG_SM2


       B.13.3.2.25. _cpri__ValidateSignatureEcc()

       This function validates

       Return Value                      Meaning

       CRYPT_SUCCESS                     signature is valid
       CRYPT_FAIL                        not a valid signature
       CRYPT_SCHEME                      unsupported scheme

1608   LIB_EXPORT CRYPT_RESULT
1609   _cpri__ValidateSignatureEcc(
1610        TPM2B_ECC_PARAMETER           *rIn,                  //   IN: r component of the signature
1611        TPM2B_ECC_PARAMETER           *sIn,                  //   IN: s component of the signature
1612        TPM_ALG_ID                     scheme,               //   IN: the scheme selector
1613        TPM_ALG_ID                     hashAlg,              //   IN: the hash algorithm used (not used
1614                                                             //       in all schemes)
1615        TPM_ECC_CURVE                   curveId,             //   IN: the curve used in the signature
1616                                                             //       process
1617        TPMS_ECC_POINT                *Qin,                  //   IN: the public point of the key
1618        TPM2B                         *digest                //   IN: the digest that was signed
1619        )
1620   {
1621        CRYPT_RESULT                  retVal;
1622
1623        // return failure if either part of the signature is zero
1624        if(_math__Normalize2B(&rIn->b) == 0 || _math__Normalize2B(&sIn->b) == 0)

       Page 508                                        TCG Published                                Family "2.0"
       October 30, 2014                       Copyright © TCG 2006-2014                 Level 00 Revision 01.16
       Part 4: Supporting Routines                                             Trusted Platform Module Library

1625            return CRYPT_FAIL;
1626
1627       switch (scheme)
1628       {
1629           case TPM_ALG_ECDSA:
1630               retVal = ValidateSignatureEcdsa(rIn, sIn, curveId, Qin, digest);
1631               break;
1632
1633   #ifdef   TPM_ALG_ECSCHNORR
1634            case TPM_ALG_ECSCHNORR:
1635                retVal = ValidateSignatureEcSchnorr(rIn, sIn, hashAlg, curveId, Qin,
1636                                                  digest);
1637                break;
1638   #endif
1639
1640   #ifdef TPM_ALG_SM2
1641           case TPM_ALG_SM2:
1642               retVal = ValidateSignatureSM2Dsa(rIn, sIn, curveId, Qin, digest);
1643   #endif
1644           default:
1645               retVal = CRYPT_SCHEME;
1646               break;
1647       }
1648       return retVal;
1649   }
1650   #if CC_ZGen_2Phase == YES //%
1651   #ifdef TPM_ALG_ECMQV


       B.13.3.2.26. avf1()

       This function does the associated value computation required by MQV key exchange. Process:
       a) Convert xQ to an integer xqi using the convention specified in Appendix C.3.
       b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)).
       c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2)

1652   static BOOL
1653   avf1(
1654       BIGNUM              *bnX,               // IN/OUT: the reduced value
1655       BIGNUM              *bnN                // IN: the order of the curve
1656       )
1657   {
1658   // compute f = 2^(ceil(ceil(log2(n)) / 2))
1659       int                      f = (BN_num_bits(bnN) + 1) / 2;
1660   // x' = 2^f + (x mod 2^f)
1661       BN_mask_bits(bnX, f);   // This is mod 2*2^f but it doesn't matter because
1662                               // the next operation will SET the extra bit anyway
1663       BN_set_bit(bnX, f);
1664       return TRUE;
1665   }


       B.13.3.2.27. C_2_2_MQV()

       This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC MQV).
       CAUTION: Implementation of this function may require use of essential claims in patents not owned by
       TCG members.
       Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly
       catastrophically, if this is not the case.



       Family "2.0"                                TCG Published                                    Page 509
       Level 00 Revision 01.16              Copyright © TCG 2006-2014                      October 30, 2014
       Trusted Platform Module Library                                                      Part 4: Supporting Routines


       Return Value                      Meaning

       CRYPT_SUCCESS                     results is valid
       CRYPT_NO_RESULT                   the value for dsA does not give a valid point on the curve

1666   static CRYPT_RESULT
1667   C_2_2_MQV(
1668       TPMS_ECC_POINT                  *outZ,                //   OUT: the computed point
1669       TPM_ECC_CURVE                    curveId,             //   IN: the curve for the computations
1670       TPM2B_ECC_PARAMETER             *dsA,                 //   IN: static private TPM key
1671       TPM2B_ECC_PARAMETER             *deA,                 //   IN: ephemeral private TPM key
1672       TPMS_ECC_POINT                  *QsB,                 //   IN: static public party B key
1673       TPMS_ECC_POINT                  *QeB                  //   IN: ephemeral public party B key
1674       )
1675   {
1676       BN_CTX                          *context;
1677       EC_POINT                        *pQeA = NULL;
1678       EC_POINT                        *pQeB = NULL;
1679       EC_POINT                        *pQsB = NULL;
1680       EC_GROUP                        *group = NULL;
1681       BIGNUM                          *bnTa;
1682       BIGNUM                          *bnDeA;
1683       BIGNUM                          *bnDsA;
1684       BIGNUM                          *bnXeA;         // x coordinate of ephemeral party A key
1685       BIGNUM                          *bnH;
1686       BIGNUM                          *bnN;
1687       BIGNUM                          *bnXeB;
1688       const ECC_CURVE_DATA            *curveData = GetCurveData(curveId);
1689       CRYPT_RESULT                    retVal;
1690
1691       pAssert(       curveData != NULL && outZ != NULL && dsA != NULL
1692               &&           deA != NULL && QsB != NULL && QeB != NULL);
1693
1694       context = BN_CTX_new();
1695       if(context == NULL || curveData == NULL)
1696           FAIL(FATAL_ERROR_ALLOCATION);
1697       BN_CTX_start(context);
1698       bnTa = BN_CTX_get(context);
1699       bnDeA = BN_CTX_get(context);
1700       bnDsA = BN_CTX_get(context);
1701       bnXeA = BN_CTX_get(context);
1702       bnH = BN_CTX_get(context);
1703       bnN = BN_CTX_get(context);
1704       bnXeB = BN_CTX_get(context);
1705       if(bnXeB == NULL)
1706           FAIL(FATAL_ERROR_ALLOCATION);
1707
1708   // Process:
1709   // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
1710   // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
1711   // 3. If P = O, output an error indicator.
1712   // 4. Z=xP, where xP is the x-coordinate of P.
1713
1714       // Initialize group parameters and local values of input
1715       if((group = EccCurveInit(curveId, context)) == NULL)
1716           FAIL(FATAL_ERROR_INTERNAL);
1717
1718       if((pQeA = EC_POINT_new(group)) == NULL)
1719           FAIL(FATAL_ERROR_ALLOCATION);
1720
1721       BnFrom2B(bnDeA, &deA->b);
1722       BnFrom2B(bnDsA, &dsA->b);
1723       BnFrom2B(bnH, curveData->h);
1724       BnFrom2B(bnN, curveData->n);

       Page 510                                         TCG Published                                     Family "2.0"
       October 30, 2014                        Copyright © TCG 2006-2014                      Level 00 Revision 01.16
       Part 4: Supporting Routines                                   Trusted Platform Module Library

1725       BnFrom2B(bnXeB, &QeB->x.b);
1726       pQeB = EccInitPoint2B(group, QeB, context);
1727       pQsB = EccInitPoint2B(group, QsB, context);
1728
1729       // Compute the public ephemeral key pQeA = [de,A]G
1730       if(    (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context))
1731          != CRYPT_SUCCESS)
1732           goto Cleanup;
1733
1734       if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1)
1735               FAIL(FATAL_ERROR_INTERNAL);
1736
1737   // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
1738   // tA := (ds,A + de,A avf(Xe,A)) mod n (3)
1739   // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n
1740       // Ta = avf(XeA);
1741       BN_copy(bnTa, bnXeA);
1742       avf1(bnTa, bnN);
1743       if(// do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n
1744             !BN_mod_mul(bnTa, bnDsA, bnTa, bnN, context)
1745
1746           // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n
1747           || !BN_mod_add(bnTa, bnDeA, bnTa, bnN, context)
1748          )
1749                FAIL(FATAL_ERROR_INTERNAL);
1750
1751   // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
1752   // Put this in because almost every case of h is == 1 so skip the call when
1753       // not necessary.
1754       if(!BN_is_one(bnH))
1755       {
1756           // Cofactor is not 1 so compute Ta := Ta * h mod n
1757           if(!BN_mul(bnTa, bnTa, bnH, context))
1758               FAIL(FATAL_ERROR_INTERNAL);
1759       }
1760
1761       // Now that 'tA' is (h * 'tA' mod n)
1762       // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B).
1763
1764       // first, compute XeB = avf(XeB)
1765       avf1(bnXeB, bnN);
1766
1767       // QsB := [XeB]QsB
1768       if(     !EC_POINT_mul(group, pQsB, NULL, pQsB, bnXeB, context)
1769
1770            // QeB := QsB + QeB
1771            || !EC_POINT_add(group, pQeB, pQeB, pQsB, context)
1772           )
1773            FAIL(FATAL_ERROR_INTERNAL);
1774
1775       // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
1776       if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS)
1777           // Convert BIGNUM E to TPM2B E
1778           Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context);
1779
1780   Cleanup:
1781       if(pQeA != NULL) EC_POINT_free(pQeA);
1782       if(pQeB != NULL) EC_POINT_free(pQeB);
1783       if(pQsB != NULL) EC_POINT_free(pQsB);
1784       if(group != NULL) EC_GROUP_free(group);
1785       BN_CTX_end(context);
1786       BN_CTX_free(context);
1787
1788       return retVal;
1789
1790   }

       Family "2.0"                           TCG Published                              Page 511
       Level 00 Revision 01.16        Copyright © TCG 2006-2014                  October 30, 2014
       Trusted Platform Module Library                                                      Part 4: Supporting Routines

1791   #endif // TPM_ALG_ECMQV
1792   #ifdef TPM_ALG_SM2 //%


       B.13.3.2.28. avfSm2()

       This function does the associated value computation required by SM2 key exchange. This is different
       form the avf() in the international standards because it returns a value that is half the size of the value
       returned by the standard avf. For example, if n is 15, Ws (w in the standard) is 2 but the W here is 1. This
       means that an input value of 14 (1110b) would return a value of 110b with the standard but 10b with the
       scheme in SM2.

1793   static BOOL
1794   avfSm2(
1795        BIGNUM              *bnX,                  // IN/OUT: the reduced value
1796        BIGNUM              *bnN                   // IN: the order of the curve
1797        )
1798   {
1799   // a) set w := ceil(ceil(log2(n)) / 2) - 1
1800       int                      w = ((BN_num_bits(bnN) + 1) / 2) - 1;
1801
1802   // b) set x' := 2^w + ( x & (2^w - 1))
1803   // This is just like the avf for MQV where x' = 2^w + (x mod 2^w)
1804       BN_mask_bits(bnX, w);   // as wiht avf1, this is too big by a factor of 2 but
1805                               // it doesn't matter becasue we SET the extra bit anyway
1806       BN_set_bit(bnX, w);
1807       return TRUE;
1808   }

       SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to compute
       tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA +
       [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral private
       key. All points are required to be on the curve of inQsA. The function will fail catastrophically if this is not
       the case

       Return Value                      Meaning

       CRYPT_SUCCESS                     results is valid
       CRYPT_NO_RESULT                   the value for dsA does not give a valid point on the curve

1809   static CRYPT_RESULT
1810   SM2KeyExchange(
1811        TPMS_ECC_POINT                 *outZ,                //   OUT: the computed point
1812        TPM_ECC_CURVE                   curveId,             //   IN: the curve for the computations
1813        TPM2B_ECC_PARAMETER            *dsA,                 //   IN: static private TPM key
1814        TPM2B_ECC_PARAMETER            *deA,                 //   IN: ephemeral private TPM key
1815        TPMS_ECC_POINT                 *QsB,                 //   IN: static public party B key
1816        TPMS_ECC_POINT                 *QeB                  //   IN: ephemeral public party B key
1817        )
1818   {
1819        BN_CTX                         *context;
1820        EC_POINT                       *pQeA = NULL;
1821        EC_POINT                       *pQeB = NULL;
1822        EC_POINT                       *pQsB = NULL;
1823        EC_GROUP                       *group = NULL;
1824        BIGNUM                         *bnTa;
1825        BIGNUM                         *bnDeA;
1826        BIGNUM                         *bnDsA;
1827        BIGNUM                         *bnXeA;               // x coordinate of ephemeral party A key
1828        BIGNUM                         *bnH;
1829        BIGNUM                         *bnN;
1830        BIGNUM                         *bnXeB;


       Page 512                                         TCG Published                                     Family "2.0"
       October 30, 2014                        Copyright © TCG 2006-2014                      Level 00 Revision 01.16
       Part 4: Supporting Routines                                    Trusted Platform Module Library

1831       const ECC_CURVE_DATA      *curveData = GetCurveData(curveId);
1832       CRYPT_RESULT              retVal;
1833
1834       pAssert(       curveData != NULL && outZ != NULL && dsA != NULL
1835               &&           deA != NULL && QsB != NULL && QeB != NULL);
1836
1837       context = BN_CTX_new();
1838       if(context == NULL || curveData == NULL)
1839           FAIL(FATAL_ERROR_ALLOCATION);
1840       BN_CTX_start(context);
1841       bnTa = BN_CTX_get(context);
1842       bnDeA = BN_CTX_get(context);
1843       bnDsA = BN_CTX_get(context);
1844       bnXeA = BN_CTX_get(context);
1845       bnH = BN_CTX_get(context);
1846       bnN = BN_CTX_get(context);
1847       bnXeB = BN_CTX_get(context);
1848       if(bnXeB == NULL)
1849           FAIL(FATAL_ERROR_ALLOCATION);
1850
1851       // Initialize group parameters and local values of input
1852       if((group = EccCurveInit(curveId, context)) == NULL)
1853           FAIL(FATAL_ERROR_INTERNAL);
1854
1855       if((pQeA = EC_POINT_new(group)) == NULL)
1856           FAIL(FATAL_ERROR_ALLOCATION);
1857
1858       BnFrom2B(bnDeA, &deA->b);
1859       BnFrom2B(bnDsA, &dsA->b);
1860       BnFrom2B(bnH, curveData->h);
1861       BnFrom2B(bnN, curveData->n);
1862       BnFrom2B(bnXeB, &QeB->x.b);
1863       pQeB = EccInitPoint2B(group, QeB, context);
1864       pQsB = EccInitPoint2B(group, QsB, context);
1865
1866       // Compute the public ephemeral key pQeA = [de,A]G
1867       if(    (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context))
1868          != CRYPT_SUCCESS)
1869           goto Cleanup;
1870
1871       if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1)
1872               FAIL(FATAL_ERROR_INTERNAL);
1873
1874   // tA := (ds,A + de,A avf(Xe,A)) mod n (3)
1875   // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n
1876       // Ta = avf(XeA);
1877       BN_copy(bnTa, bnXeA);
1878       avfSm2(bnTa, bnN);
1879       if(// do Ta = de,A * Ta mod n = deA * avf(XeA) mod n
1880             !BN_mod_mul(bnTa, bnDeA, bnTa, bnN, context)
1881
1882           // now Ta = dsA + Ta mod n = dsA + deA * avf(XeA) mod n
1883           || !BN_mod_add(bnTa, bnDsA, bnTa, bnN, context)
1884          )
1885                FAIL(FATAL_ERROR_INTERNAL);
1886
1887   // outZ ? [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4)
1888       // Put this in because almost every case of h is == 1 so skip the call when
1889       // not necessary.
1890       if(!BN_is_one(bnH))
1891       {
1892           // Cofactor is not 1 so compute Ta := Ta * h mod n
1893           if(!BN_mul(bnTa, bnTa, bnH, context))
1894               FAIL(FATAL_ERROR_INTERNAL);
1895       }
1896

       Family "2.0"                          TCG Published                                 Page 513
       Level 00 Revision 01.16         Copyright © TCG 2006-2014                  October 30, 2014
       Trusted Platform Module Library                                          Part 4: Supporting Routines

1897       // Now that 'tA' is (h * 'tA' mod n)
1898       // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)).
1899
1900       // first, compute XeB = avf(XeB)
1901       avfSm2(bnXeB, bnN);
1902
1903       // QeB := [XeB]QeB
1904       if(     !EC_POINT_mul(group, pQeB, NULL, pQeB, bnXeB, context)
1905
1906             // QeB := QsB + QeB
1907             || !EC_POINT_add(group, pQeB, pQeB, pQsB, context)
1908            )
1909             FAIL(FATAL_ERROR_INTERNAL);
1910
1911       // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
1912       if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS)
1913           // Convert BIGNUM E to TPM2B E
1914           Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context);
1915
1916   Cleanup:
1917       if(pQeA != NULL) EC_POINT_free(pQeA);
1918       if(pQeB != NULL) EC_POINT_free(pQeB);
1919       if(pQsB != NULL) EC_POINT_free(pQsB);
1920       if(group != NULL) EC_GROUP_free(group);
1921       BN_CTX_end(context);
1922       BN_CTX_free(context);
1923
1924       return retVal;
1925
1926   }
1927   #endif       //% TPM_ALG_SM2


       B.13.3.2.29. C_2_2_ECDH()

       This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified Model,
       C(2, 2, ECC CDH).

1928   static CRYPT_RESULT
1929   C_2_2_ECDH(
1930       TPMS_ECC_POINT                *outZ1,         //   OUT: Zs
1931       TPMS_ECC_POINT                *outZ2,         //   OUT: Ze
1932       TPM_ECC_CURVE                  curveId,       //   IN: the curve for the computations
1933       TPM2B_ECC_PARAMETER           *dsA,           //   IN: static private TPM key
1934       TPM2B_ECC_PARAMETER           *deA,           //   IN: ephemeral private TPM key
1935       TPMS_ECC_POINT                *QsB,           //   IN: static public party B key
1936       TPMS_ECC_POINT                *QeB            //   IN: ephemeral public party B key
1937       )
1938   {
1939       BN_CTX                        *context;
1940       EC_POINT                      *pQ = NULL;
1941       EC_GROUP                      *group = NULL;
1942       BIGNUM                        *bnD;
1943       INT16                          size;
1944       const ECC_CURVE_DATA          *curveData = GetCurveData(curveId);
1945
1946       context = BN_CTX_new();
1947       if(context == NULL || curveData == NULL)
1948           FAIL(FATAL_ERROR_ALLOCATION);
1949       BN_CTX_start(context);
1950       if((bnD = BN_CTX_get(context)) == NULL)
1951           FAIL(FATAL_ERROR_INTERNAL);
1952
1953       // Initialize group parameters and local values of input
1954       if((group = EccCurveInit(curveId, context)) == NULL)

       Page 514                                  TCG Published                                Family "2.0"
       October 30, 2014                    Copyright © TCG 2006-2014             Level 00 Revision 01.16
       Part 4: Supporting Routines                                              Trusted Platform Module Library

1955           FAIL(FATAL_ERROR_INTERNAL);
1956       size = (INT16)BN_num_bytes(&group->order);
1957
1958       // Get the static private key of A
1959       BnFrom2B(bnD, &dsA->b);
1960
1961       // Initialize the static public point from B
1962       pQ = EccInitPoint2B(group, QsB, context);
1963
1964       // Do the point multiply for the Zs value
1965       if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT)
1966           // Convert the Zs value
1967           Point2B(group, outZ1, pQ, size, context);
1968
1969       // Get the ephemeral private key of A
1970       BnFrom2B(bnD, &deA->b);
1971
1972       // Initalize the ephemeral public point from B
1973       PointFrom2B(group, pQ, QeB, context);
1974
1975       // Do the point multiply for the Ze value
1976       if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT)
1977           // Convert the Ze value.
1978           Point2B(group, outZ2, pQ, size, context);
1979
1980       if(pQ != NULL) EC_POINT_free(pQ);
1981       if(group != NULL) EC_GROUP_free(group);
1982       BN_CTX_end(context);
1983       BN_CTX_free(context);
1984       return CRYPT_SUCCESS;
1985   }


       B.13.3.2.30. _cpri__C_2_2_KeyExchange()

       This function is the dispatch routine for the EC key exchange function that use two ephemeral and two
       static keys.

       Return Value                   Meaning

       CRYPT_SCHEME                   scheme is not defined

1986   LIB_EXPORT CRYPT_RESULT
1987   _cpri__C_2_2_KeyExchange(
1988       TPMS_ECC_POINT              *outZ1,                //   OUT: a computed point
1989       TPMS_ECC_POINT              *outZ2,                //   OUT: and optional second point
1990       TPM_ECC_CURVE                curveId,              //   IN: the curve for the computations
1991       TPM_ALG_ID                   scheme,               //   IN: the key exchange scheme
1992       TPM2B_ECC_PARAMETER         *dsA,                  //   IN: static private TPM key
1993       TPM2B_ECC_PARAMETER         *deA,                  //   IN: ephemeral private TPM key
1994       TPMS_ECC_POINT              *QsB,                  //   IN: static public party B key
1995       TPMS_ECC_POINT              *QeB                   //   IN: ephemeral public party B key
1996       )
1997   {
1998       pAssert(   outZ1 != NULL
1999               && dsA != NULL && deA != NULL
2000               && QsB != NULL && QeB != NULL);
2001
2002       // Initalize the output points so that they are empty until one of the
2003       // functions decides otherwise
2004       outZ1->x.b.size = 0;
2005       outZ1->y.b.size = 0;
2006       if(outZ2 != NULL)
2007       {
2008           outZ2->x.b.size = 0;

       Family "2.0"                               TCG Published                                      Page 515
       Level 00 Revision 01.16            Copyright © TCG 2006-2014                         October 30, 2014
       Trusted Platform Module Library                                          Part 4: Supporting Routines

2009            outZ2->y.b.size = 0;
2010       }
2011
2012       switch (scheme)
2013       {
2014           case TPM_ALG_ECDH:
2015               return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB);
2016               break;
2017   #ifdef TPM_ALG_ECMQV
2018           case TPM_ALG_ECMQV:
2019               return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB);
2020               break;
2021   #endif
2022   #ifdef TPM_ALG_SM2
2023           case TPM_ALG_SM2:
2024               return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB);
2025               break;
2026   #endif
2027           default:
2028               return CRYPT_SCHEME;
2029       }
2030   }
2031   #else       //%

       Stub used when the 2-phase key exchange is not defined so that the linker has something to associate
       with the value in the .def file.

2032   LIB_EXPORT CRYPT_RESULT
2033   _cpri__C_2_2_KeyExchange(
2034       void
2035       )
2036   {
2037       return CRYPT_FAIL;
2038   }
2039   #endif //% CC_ZGen_2Phase
2040   #endif // TPM_ALG_ECC




       Page 516                                  TCG Published                                Family "2.0"
       October 30, 2014                   Copyright © TCG 2006-2014               Level 00 Revision 01.16
     Part 4: Supporting Routines                                              Trusted Platform Module Library


                                                    Annex C
                                                  (informative)
                                             Simulation Environment

     C.1      Introduction

     These files are used to simulate some of the implementation-dependent hardware of a TPM. These files
     are provided to allow creation of a simulation environment for the TPM. These files are not expected to be
     part of a hardware TPM implementation.

     C.2      Cancel.c

     C.2.1.     Introduction

     This module simulates the cancel pins on the TPM.

     C.2.2.     Includes, Typedefs, Structures, and Defines

 1   #include "PlatformData.h"


     C.2.3.     Functions

     C.2.3.1.     _plat__IsCanceled()

     Check if the cancel flag is set

     Return Value                      Meaning

     TRUE                              if cancel flag is set
     FALSE                             if cancel flag is not set

 2   LIB_EXPORT BOOL
 3   _plat__IsCanceled(
 4         void
 5         )
 6   {
 7         // return cancel flag
 8         return s_isCanceled;
 9   }


     C.2.3.2.     _plat__SetCancel()

     Set cancel flag.

10   LIB_EXPORT void
11   _plat__SetCancel(
12         void
13         )
14   {
15         s_isCanceled = TRUE;
16         return;
17   }




     Family "2.0"                                    TCG Published                                  Page 517
     Level 00 Revision 01.16                Copyright © TCG 2006-2014                       October 30, 2014
     Trusted Platform Module Library                               Part 4: Supporting Routines

     C.2.3.3.   _plat__ClearCancel()

     Clear cancel flag

18   LIB_EXPORT void
19   _plat__ClearCancel(
20       void
21       )
22   {
23       s_isCanceled = FALSE;
24       return;
25   }




     Page 518                               TCG Published                        Family "2.0"
     October 30, 2014                  Copyright © TCG 2006-2014    Level 00 Revision 01.16
     Part 4: Supporting Routines                                                    Trusted Platform Module Library


     C.3      Clock.c

     C.3.1.     Introduction

     This file contains the routines that are used by the simulator to mimic a hardware clock on a TPM. In this
     implementation, all the time values are measured in millisecond. However, the precision of the clock
     functions may be implementation dependent.

     C.3.2.     Includes and Data Definitions

 1   #include <time.h>
 2   #include "PlatformData.h"
 3   #include "Platform.h"


     C.3.3.     Functions

     C.3.3.1.     _plat__ClockReset()

     Set the current clock time as initial time. This function is called at a power on event to reset the clock

 4   LIB_EXPORT void
 5   _plat__ClockReset(
 6         void
 7         )
 8   {
 9         // Implementation specific: Microsoft C set CLOCKS_PER_SEC to be 1/1000,
10         // so here the measurement of clock() is in millisecond.
11         s_initClock = clock();
12         s_adjustRate = CLOCK_NOMINAL;
13
14         return;
15   }


     C.3.3.2.     _plat__ClockTimeFromStart()

     Function returns the compensated                time    from    the    start    of   the    command      when
     _plat__ClockTimeFromStart() was called.

16   unsigned long long
17   _plat__ClockTimeFromStart(
18         void
19         )
20   {
21         unsigned long long currentClock = clock();
22         return ((currentClock - s_initClock) * CLOCK_NOMINAL) / s_adjustRate;
23   }


     C.3.3.3.     _plat__ClockTimeElapsed()

     Get the time elapsed from current to the last time the _plat__ClockTimeElapsed() is called. For the first
     _plat__ClockTimeElapsed() call after a power on event, this call report the elapsed time from power on to
     the current call

24   LIB_EXPORT unsigned long long
25   _plat__ClockTimeElapsed(
26         void


     Family "2.0"                                  TCG Published                                         Page 519
     Level 00 Revision 01.16               Copyright © TCG 2006-2014                            October 30, 2014
     Trusted Platform Module Library                                    Part 4: Supporting Routines

27        )
28   {
29        unsigned long long elapsed;
30        unsigned long long currentClock = clock();
31        elapsed = ((currentClock - s_initClock) * CLOCK_NOMINAL) / s_adjustRate;
32        s_initClock += (elapsed * s_adjustRate) / CLOCK_NOMINAL;
33
34   #ifdef DEBUGGING_TIME
35       // Put this in so that TPM time will pass much faster than real time when
36       // doing debug.
37       // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second
38       // A good value might be 100
39       elapsed *= DEBUG_TIME_MULTIPLIER
40   #endif
41                  return elapsed;
42   }


     C.3.3.4.   _plat__ClockAdjustRate()

     Adjust the clock rate

43   LIB_EXPORT void
44   _plat__ClockAdjustRate(
45        int                adjust         // IN: the adjust number.   It could be positive
46                                          //     or negative
47        )
48   {
49        // We expect the caller should only use a fixed set of constant values to
50        // adjust the rate
51        switch(adjust)
52        {
53            case CLOCK_ADJUST_COARSE:
54                s_adjustRate += CLOCK_ADJUST_COARSE;
55                break;
56            case -CLOCK_ADJUST_COARSE:
57                s_adjustRate -= CLOCK_ADJUST_COARSE;
58                break;
59            case CLOCK_ADJUST_MEDIUM:
60                s_adjustRate += CLOCK_ADJUST_MEDIUM;
61                break;
62            case -CLOCK_ADJUST_MEDIUM:
63                s_adjustRate -= CLOCK_ADJUST_MEDIUM;
64                break;
65            case CLOCK_ADJUST_FINE:
66                s_adjustRate += CLOCK_ADJUST_FINE;
67                break;
68            case -CLOCK_ADJUST_FINE:
69                s_adjustRate -= CLOCK_ADJUST_FINE;
70                break;
71            default:
72                // ignore any other values;
73                break;
74        }
75
76        if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT))
77            s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT;
78        if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT))
79            s_adjustRate = CLOCK_NOMINAL-CLOCK_ADJUST_LIMIT;
80
81        return;
82   }




     Page 520                               TCG Published                             Family "2.0"
     October 30, 2014                  Copyright © TCG 2006-2014          Level 00 Revision 01.16
     Part 4: Supporting Routines                                                       Trusted Platform Module Library


     C.4      Entropy.c

     C.4.1.     Includes

 1   #define _CRT_RAND_S
 2   #include <stdlib.h>
 3   #include <stdint.h>
 4   #include <memory.h>
 5   #include "TpmBuildSwitches.h"


     C.4.2.     Local values

     This is the last 32-bits of hardware entropy produced. We have to check to see that two consecutive 32-
     bit values are not the same because (according to FIPS 140-2, annex C
           “If each call to a RNG produces blocks of n bits (where n > 15), the first n-bit block generated after
           power-up, initialization, or reset shall not be used, but shall be saved for comparison with the next n-
           bit block to be generated. Each subsequent generation of an n-bit block shall be compared with the
           previously generated block. The test shall fail if any two compared n-bit blocks are equal.”

 6   extern uint32_t               lastEntropy;
 7   extern int                    firstValue;


     C.4.3.     _plat__GetEntropy()

     This function is used to get available hardware entropy. In a hardware implementation of this function,
     there would be no call to the system to get entropy. If the caller does not ask for any entropy, then this is
     a startup indication and firstValue should be reset.

     Return Value                       Meaning

     <0                                 hardware failure of the entropy generator, this is sticky
     >= 0                               the returned amount of entropy (bytes)

 8   LIB_EXPORT int32_t
 9   _plat__GetEntropy(
10          unsigned char            *entropy,                  // output buffer
11          uint32_t                  amount                    // amount requested
12   )
13   {
14          uint32_t                rndNum;
15          int                   OK = 1;
16
17          if(amount == 0)
18          {
19              firstValue = 1;
20              return 0;
21          }
22
23          // Only provide entropy 32 bits at a time to test the ability
24          // of the caller to deal with partial results.
25          OK = rand_s(&rndNum) == 0;
26          if(OK)
27          {
28              if(firstValue)
29                   firstValue = 0;
30              else
31                   OK = (rndNum != lastEntropy);
32          }


     Family "2.0"                                    TCG Published                                          Page 521
     Level 00 Revision 01.16                 Copyright © TCG 2006-2014                              October 30, 2014
     Trusted Platform Module Library                               Part 4: Supporting Routines

33       if(OK)
34       {
35           lastEntropy = rndNum;
36           if(amount > sizeof(rndNum))
37               amount = sizeof(rndNum);
38           memcpy(entropy, &rndNum, amount);
39       }
40       return (OK) ? (int32_t)amount : -1;
41   }




     Page 522                               TCG Published                        Family "2.0"
     October 30, 2014                  Copyright © TCG 2006-2014    Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library


     C.5      LocalityPlat.c

     C.5.1.     Includes

 1   #include "PlatformData.h"
 2   #include "TpmError.h"


     C.5.2.     Functions

     C.5.2.1.     _plat__LocalityGet()

     Get the most recent command locality in locality value form. This is an integer value for locality and not a
     locality structure The locality can be 0-4 or 32-255. 5-31 is not allowed.

 3   LIB_EXPORT unsigned char
 4   _plat__LocalityGet(
 5         void
 6         )
 7   {
 8         return s_locality;
 9   }


     C.5.2.2.     _plat__LocalitySet()

     Set the most recent command locality in locality value form

10   LIB_EXPORT void
11   _plat__LocalitySet(
12         unsigned char       locality
13         )
14   {
15         if(locality > 4 && locality < 32)
16             locality = 0;
17         s_locality = locality;
18         return;
19   }


     C.5.2.3.     _plat__IsRsaKeyCacheEnabled()

     This function is used to check if the RSA key cache is enabled or not.

20   LIB_EXPORT int
21   _plat__IsRsaKeyCacheEnabled(
22         void
23         )
24   {
25         return s_RsaKeyCacheEnabled;
26   }




     Family "2.0"                                 TCG Published                                       Page 523
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                 Part 4: Supporting Routines


     C.6      NVMem.c

     C.6.1.     Introduction

     This file contains the NV read and write access methods. This implementation uses RAM/file and does
     not manage the RAM/file as NV blocks. The implementation may become more sophisticated over time.

     C.6.2.     Includes

 1   #include     <memory.h>
 2   #include     <string.h>
 3   #include     "PlatformData.h"
 4   #include     "TpmError.h"
 5   #include     "assert.h"


     C.6.3.     Functions

     C.6.3.1.     _plat__NvErrors()

     This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the
     NV loading process

 6   LIB_EXPORT void
 7   _plat__NvErrors(
 8         BOOL                 recoverable,
 9         BOOL                 unrecoverable
10         )
11   {
12         s_NV_unrecoverable = unrecoverable;
13         s_NV_recoverable = recoverable;
14   }


     C.6.3.2.     _plat__NVEnable()

     Enable NV memory.
     This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the
     integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV
     state would be read in, decrypted and integrity checked.
     The recovery from an integrity failure depends on where the error occurred. It it was in the state that is
     discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go
     into failure mode.

     Return Value                      Meaning

     0                                 if success
     >0                                if receive recoverable error
     <0                                if unrecoverable error

15   LIB_EXPORT int
16   _plat__NVEnable(
17         void                *platParameter       // IN: platform specific parameter
18         )
19   {
20         (platParameter);                              // to keep compiler quiet
21         // Start assuming everything is OK

     Page 524                                        TCG Published                                  Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                  Level 00 Revision 01.16
     Part 4: Supporting Routines                                    Trusted Platform Module Library

22       s_NV_unrecoverable = FALSE;
23       s_NV_recoverable = FALSE;
24
25   #ifdef FILE_BACKED_NV
26
27       if(s_NVFile != NULL) return 0;
28
29       // Try to open an exist NVChip file for read/write
30       if(0 != fopen_s(&s_NVFile, "NVChip", "r+b"))
31           s_NVFile = NULL;
32
33       if(NULL != s_NVFile)
34       {
35           // See if the NVChip file is empty
36           fseek(s_NVFile, 0, SEEK_END);
37           if(0 == ftell(s_NVFile))
38               s_NVFile = NULL;
39       }
40
41       if(s_NVFile == NULL)
42       {
43           // Initialize all the byte in the new file to 0
44           memset(s_NV, 0, NV_MEMORY_SIZE);
45
46              // If NVChip file does not exist, try to create it for read/write
47              fopen_s(&s_NVFile, "NVChip", "w+b");
48              // Start initialize at the end of new file
49              fseek(s_NVFile, 0, SEEK_END);
50              // Write 0s to NVChip file
51              fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
52       }
53       else
54       {
55           // If NVChip file exist, assume the size is correct
56           fseek(s_NVFile, 0, SEEK_END);
57           assert(ftell(s_NVFile) == NV_MEMORY_SIZE);
58           // read NV file data to memory
59           fseek(s_NVFile, 0, SEEK_SET);
60           fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile);
61       }
62   #endif
63       // NV contents have been read and the error checks have been performed. For
64       // simulation purposes, use the signaling interface to indicate if an error is
65       // to be simulated and the type of the error.
66       if(s_NV_unrecoverable)
67           return -1;
68       return s_NV_recoverable;
69   }


     C.6.3.3.    _plat__NVDisable()

     Disable NV memory

70   LIB_EXPORT void
71   _plat__NVDisable(
72       void
73       )
74   {
75   #ifdef     FILE_BACKED_NV
76
77       assert(s_NVFile != NULL);
78       // Close NV file
79       fclose(s_NVFile);
80       // Set file handle to NULL


     Family "2.0"                           TCG Published                                Page 525
     Level 00 Revision 01.16          Copyright © TCG 2006-2014                 October 30, 2014
      Trusted Platform Module Library                                                    Part 4: Supporting Routines

 81        s_NVFile = NULL;
 82
 83   #endif
 84
 85        return;
 86   }


      C.6.3.4.    _plat__IsNvAvailable()

      Check if NV is available

      Return Value                      Meaning

      0                                 NV is available
      1                                 NV is not available due to write failure
      2                                 NV is not available due to rate limit

 87   LIB_EXPORT int
 88   _plat__IsNvAvailable(
 89        void
 90        )
 91   {
 92        // NV is not available if the TPM is in failure mode
 93        if(!s_NvIsAvailable)
 94            return 1;
 95
 96   #ifdef FILE_BACKED_NV
 97       if(s_NVFile == NULL)
 98           return 1;
 99   #endif
100
101        return 0;
102
103   }


      C.6.3.5.    _plat__NvMemoryRead()

      Function: Read a chunk of NV memory

104   LIB_EXPORT void
105   _plat__NvMemoryRead(
106        unsigned int           startOffset,       // IN: read start
107        unsigned int           size,              // IN: size of bytes to read
108        void                  *data               // OUT: data buffer
109        )
110   {
111        assert(startOffset + size <= NV_MEMORY_SIZE);
112
113        // Copy data from RAM
114        memcpy(data, &s_NV[startOffset], size);
115        return;
116   }


      C.6.3.6.    _plat__NvIsDifferent()

      This function checks to see if the NV is different from the test value. This is so that NV will not be written if
      it has not changed.




      Page 526                                        TCG Published                                      Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library


      Return Value                  Meaning

      TRUE                          the NV location is different from the test value
      FALSE                         the NV location is the same as the test value

117   LIB_EXPORT BOOL
118   _plat__NvIsDifferent(
119       unsigned int        startOffset,       // IN: read start
120       unsigned int        size,              // IN: size of bytes to read
121       void               *data               // IN: data buffer
122       )
123   {
124       return (memcmp(&s_NV[startOffset], data, size) != 0);
125   }


      C.6.3.7.   _plat__NvMemoryWrite()

      This function is used to update NV memory. The write is to a memory copy of NV. At the end of the
      current command, any changes are written to the actual NV memory.

126   LIB_EXPORT void
127   _plat__NvMemoryWrite(
128       unsigned int        startOffset,       // IN: write start
129       unsigned int        size,              // IN: size of bytes to write
130       void               *data               // OUT: data buffer
131       )
132   {
133       assert(startOffset + size <= NV_MEMORY_SIZE);
134
135       // Copy the data to the NV image
136       memcpy(&s_NV[startOffset], data, size);
137   }


      C.6.3.8.   _plat__NvMemoryMove()

      Function: Move a chunk of NV memory from source to destination This function should ensure that if
      there overlap, the original data is copied before it is written

138   LIB_EXPORT void
139   _plat__NvMemoryMove(
140       unsigned int        sourceOffset,      // IN: source offset
141       unsigned int        destOffset,        // IN: destination offset
142       unsigned int        size               // IN: size of data being moved
143       )
144   {
145       assert(sourceOffset + size <= NV_MEMORY_SIZE);
146       assert(destOffset + size <= NV_MEMORY_SIZE);
147
148       // Move data in RAM
149       memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
150
151       return;
152   }


      C.6.3.9.   _plat__NvCommit()

      Update NV chip



      Family "2.0"                               TCG Published                                           Page 527
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                              October 30, 2014
      Trusted Platform Module Library                                              Part 4: Supporting Routines


      Return Value                      Meaning

      0                                 NV write success
      non-0                             NV write fail

153   LIB_EXPORT int
154   _plat__NvCommit(
155       void
156       )
157   {
158   #ifdef FILE_BACKED_NV
159       // If NV file is not available, return failure
160       if(s_NVFile == NULL)
161           return 1;
162
163       // Write RAM data to NV
164       fseek(s_NVFile, 0, SEEK_SET);
165       fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
166       return 0;
167   #else
168       return 0;
169   #endif
170
171   }


      C.6.3.10. _plat__SetNvAvail()

      Set the current NV state to available. This function is for testing purpose only. It is not part of the
      platform NV logic

172   LIB_EXPORT void
173   _plat__SetNvAvail(
174       void
175       )
176   {
177       s_NvIsAvailable = TRUE;
178       return;
179   }


      C.6.3.11. _plat__ClearNvAvail()

      Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the
      platform NV logic

180   LIB_EXPORT void
181   _plat__ClearNvAvail(
182       void
183       )
184   {
185       s_NvIsAvailable = FALSE;
186       return;
187   }




      Page 528                                          TCG Published                             Family "2.0"
      October 30, 2014                       Copyright © TCG 2006-2014               Level 00 Revision 01.16
     Part 4: Supporting Routines                                     Trusted Platform Module Library


     C.7      PowerPlat.c

     C.7.1.     Includes and Function Prototypes

 1   #include       "PlatformData.h"
 2   #include       "Platform.h"


     C.7.2.     Functions

     C.7.2.1.     _plat__Signal_PowerOn()

     Signal platform power on

 3   LIB_EXPORT int
 4   _plat__Signal_PowerOn(
 5         void
 6         )
 7   {
 8         // Start clock
 9         _plat__ClockReset();
10
11         // Initialize locality
12         s_locality = 0;
13
14         // Command cancel
15          s_isCanceled = FALSE;
16
17         // Need to indicate that we lost power
18         s_powerLost = TRUE;
19
20         return 0;
21   }


     C.7.2.2.     _plat__WasPowerLost()

     Test whether power was lost before a _TPM_Init()

22   LIB_EXPORT BOOL
23   _plat__WasPowerLost(
24         BOOL                 clear
25         )
26   {
27         BOOL        retVal = s_powerLost;
28         if(clear)
29             s_powerLost = FALSE;
30         return retVal;
31   }


     C.7.2.3.     _plat_Signal_Reset()

     This a TPM reset without a power loss.

32   LIB_EXPORT int
33   _plat__Signal_Reset(
34         void
35         )
36   {
37         // Need to reset the clock
38         _plat__ClockReset();

     Family "2.0"                              TCG Published                              Page 529
     Level 00 Revision 01.16             Copyright © TCG 2006-2014               October 30, 2014
     Trusted Platform Module Library                                Part 4: Supporting Routines

39
40       // if we are doing reset but did not have a power failure, then we should
41       // not need to reload NV ...
42       return 0;
43   }


     C.7.2.4.   _plat__Signal_PowerOff()

     Signal platform power off

44   LIB_EXPORT void
45   _plat__Signal_PowerOff(
46       void
47       )
48   {
49       // Prepare NV memory for power off
50       _plat__NVDisable();
51
52       return;
53   }




     Page 530                               TCG Published                         Family "2.0"
     October 30, 2014                  Copyright © TCG 2006-2014      Level 00 Revision 01.16
     Part 4: Supporting Routines                                      Trusted Platform Module Library


     C.8      Platform.h

 1   #ifndef        PLATFORM_H
 2   #define        PLATFORM_H


     C.8.1.     Includes and Defines

 3   #include "bool.h"
 4   #include "stdint.h"
 5   #include "TpmError.h"
 6   #include "TpmBuildSwitches.h"
 7   #define UNREFERENCED(a) ((void)(a))


     C.8.2.     Power Functions

     C.8.2.1.     _plat__Signal_PowerOn

     Signal power on This signal is simulate by a RPC call

 8   LIB_EXPORT int
 9   _plat__Signal_PowerOn(void);


     C.8.2.2.     _plat__Signal_Reset

     Signal reset This signal is simulate by a RPC call

10   LIB_EXPORT int
11   _plat__Signal_Reset(void);


     C.8.2.3.     _plat__WasPowerLost()

     Indicates if the power was lost before a _TPM__Init().

12   LIB_EXPORT BOOL
13   _plat__WasPowerLost(BOOL clear);


     C.8.2.4.     _plat__Signal_PowerOff()

     Signal power off This signal is simulate by a RPC call

14   LIB_EXPORT void
15   _plat__Signal_PowerOff(void);


     C.8.3.     Physical Presence Functions

     C.8.3.1.     _plat__PhysicalPresenceAsserted()

     Check if physical presence is signaled




     Family "2.0"                                 TCG Published                            Page 531
     Level 00 Revision 01.16              Copyright © TCG 2006-2014               October 30, 2014
     Trusted Platform Module Library                                          Part 4: Supporting Routines


     Return Value                      Meaning

     TRUE                              if physical presence is signaled
     FALSE                             if physical presence is not signaled

16   LIB_EXPORT BOOL
17   _plat__PhysicalPresenceAsserted(void);


     C.8.3.2.    _plat__Signal_PhysicalPresenceOn

     Signal physical presence on This signal is simulate by a RPC call

18   LIB_EXPORT void
19   _plat__Signal_PhysicalPresenceOn(void);


     C.8.3.3.    _plat__Signal_PhysicalPresenceOff()

     Signal physical presence off This signal is simulate by a RPC call

20   LIB_EXPORT void
21   _plat__Signal_PhysicalPresenceOff(void);


     C.8.4.     Command Canceling Functions

     C.8.4.1.    _plat__IsCanceled()

     Check if the cancel flag is set

     Return Value                      Meaning

     TRUE                              if cancel flag is set
     FALSE                             if cancel flag is not set

22   LIB_EXPORT BOOL
23   _plat__IsCanceled(void);


     C.8.4.2.    _plat__SetCancel()

     Set cancel flag.

24   LIB_EXPORT void
25   _plat__SetCancel(void);


     C.8.4.3.    _plat__ClearCancel()

     Clear cancel flag

26   LIB_EXPORT void
27   _plat__ClearCancel( void);




     Page 532                                         TCG Published                         Family "2.0"
     October 30, 2014                        Copyright © TCG 2006-2014         Level 00 Revision 01.16
     Part 4: Supporting Routines                                                 Trusted Platform Module Library

     C.8.5.     NV memory functions

     C.8.5.1.    _plat__NvErrors()

     This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the
     NV loading process

28   LIB_EXPORT void
29   _plat__NvErrors(
30        BOOL           recoverable,
31        BOOL           unrecoverable
32        );


     C.8.5.2.    _plat__NVEnable()

     Enable platform NV memory NV memory is automatically enabled at power on event. This function is
     mostly for TPM_Manufacture() to access NV memory without a power on event

     Return Value                     Meaning

     0                                if success
     non-0                            if fail

33   LIB_EXPORT int
34   _plat__NVEnable(
35        void      *platParameter                       // IN: platform specific parameters
36   );


     C.8.5.3.    _plat__NVDisable()

     Disable platform NV memory NV memory is automatically disabled at power off event. This function is
     mostly for TPM_Manufacture() to disable NV memory without a power off event

37   LIB_EXPORT void
38   _plat__NVDisable(void);


     C.8.5.4.    _plat__IsNvAvailable()

     Check if NV is available

     Return Value                     Meaning

     0                                NV is available
     1                                NV is not available due to write failure
     2                                NV is not available due to rate limit

39   LIB_EXPORT int
40   _plat__IsNvAvailable(void);


     C.8.5.5.    _plat__NvCommit()

     Update NV chip




     Family "2.0"                                    TCG Published                                     Page 533
     Level 00 Revision 01.16                    Copyright © TCG 2006-2014                     October 30, 2014
     Trusted Platform Module Library                                                      Part 4: Supporting Routines


     Return Value                      Meaning

     0                                 NV write success
     non-0                             NV write fail

41   LIB_EXPORT int
42   _plat__NvCommit(void);


     C.8.5.6.    _plat__NvMemoryRead()

     Read a chunk of NV memory

43   LIB_EXPORT void
44   _plat__NvMemoryRead(
45        unsigned int              startOffset,                 // IN: read start
46        unsigned int              size,                        // IN: size of bytes to read
47        void                      *data                        // OUT: data buffer
48   );


     C.8.5.7.    _plat__NvIsDifferent()

     This function checks to see if the NV is different from the test value. This is so that NV will not be written if
     it has not changed.

     Return Value                      Meaning

     TRUE                              the NV location is different from the test value
     FALSE                             the NV location is the same as the test value

49   LIB_EXPORT BOOL
50   _plat__NvIsDifferent(
51        unsigned int               startOffset,                 // IN: read start
52        unsigned int               size,                        // IN: size of bytes to compare
53        void                      *data                         // IN: data buffer
54        );


     C.8.5.8.    _plat__NvMemoryWrite()

     Write a chunk of NV memory

55   LIB_EXPORT void
56   _plat__NvMemoryWrite(
57        unsigned int              startOffset,                 // IN: read start
58        unsigned int              size,                        // IN: size of bytes to read
59        void                      *data                        // OUT: data buffer
60   );


     C.8.5.9.    _plat__NvMemoryMove()

     Move a chunk of NV memory from source to destination This function should ensure that if there overlap,
     the original data is copied before it is written

61   LIB_EXPORT void
62   _plat__NvMemoryMove(
63        unsigned int              sourceOffset,                 // IN: source offset
64        unsigned int              destOffset,                   // IN: destination offset
65        unsigned int              size                          // IN: size of data being moved

     Page 534                                          TCG Published                                    Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                      Level 00 Revision 01.16
     Part 4: Supporting Routines                                              Trusted Platform Module Library

66   );


     C.8.5.10. _plat__SetNvAvail()

     Set the current NV state to available. This function is for testing purposes only. It is not part of the
     platform NV logic

67   LIB_EXPORT void
68   _plat__SetNvAvail(void);


     C.8.5.11. _plat__ClearNvAvail()

     Set the current NV state to unavailable. This function is for testing purposes only. It is not part of the
     platform NV logic

69   LIB_EXPORT void
70   _plat__ClearNvAvail(void);


     C.8.6.     Locality Functions

     C.8.6.1.     _plat__LocalityGet()

     Get the most recent command locality in locality value form

71   LIB_EXPORT unsigned char
72   _plat__LocalityGet(void);


     C.8.6.2.     _plat__LocalitySet()

     Set the most recent command locality in locality value form

73   LIB_EXPORT void
74   _plat__LocalitySet(
75        unsigned char      locality
76   );


     C.8.6.3.     _plat__IsRsaKeyCacheEnabled()

     This function is used to check if the RSA key cache is enabled or not.

77   LIB_EXPORT int
78   _plat__IsRsaKeyCacheEnabled(
79        void
80        );


     C.8.7.     Clock Constants and Functions

     Assume that the nominal divisor is 30000

81   #define        CLOCK_NOMINAL                30000

     A 1% change in rate is 300 counts

82   #define        CLOCK_ADJUST_COARSE          300


     Family "2.0"                                TCG Published                                      Page 535
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                                     Part 4: Supporting Routines


     A .1 change in rate is 30 counts

83   #define        CLOCK_ADJUST_MEDIUM            30

     A minimum change in rate is 1 count

84   #define        CLOCK_ADJUST_FINE              1

     The clock tolerance is +/-15% (4500 counts) Allow some guard band (16.7%)

85   #define        CLOCK_ADJUST_LIMIT             5000


     C.8.7.1.    _plat__ClockReset()

     This function sets the current clock time as initial time. This function is called at a power on event to reset
     the clock

86   LIB_EXPORT void
87   _plat__ClockReset(void);


     C.8.7.2.    _plat__ClockTimeFromStart()

     Function returns the compensated                  time   from   the    start   of     the   command      when
     _plat__ClockTimeFromStart() was called.

88   LIB_EXPORT unsigned long long
89   _plat__ClockTimeFromStart(
90        void
91        );


     C.8.7.3.    _plat__ClockTimeElapsed()

     Get the time elapsed from current to the last time the _plat__ClockTimeElapsed() is called. For the first
     _plat__ClockTimeElapsed() call after a power on event, this call report the elapsed time from power on to
     the current call

92   LIB_EXPORT unsigned long long
93   _plat__ClockTimeElapsed(void);


     C.8.7.4.    _plat__ClockAdjustRate()

     Adjust the clock rate

94   LIB_EXPORT void
95   _plat__ClockAdjustRate(
96        int            adjust                    // IN: the adjust number.         It could be
97                                                 // positive or negative
98        );




     Page 536                                      TCG Published                                       Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                     Level 00 Revision 01.16
      Part 4: Supporting Routines                                                     Trusted Platform Module Library

      C.8.8.     Single Function Files

      C.8.8.1.     _plat__GetEntropy()

      This function is used to get available hardware entropy. In a hardware implementation of this function,
      there would be no call to the system to get entropy. If the caller does not ask for any entropy, then this is
      a startup indication and firstValue should be reset.

      Return Value                     Meaning

      <0                               hardware failure of the entropy generator, this is sticky
      >= 0                             the returned amount of entropy (bytes)

 99   LIB_EXPORT int32_t
100   _plat__GetEntropy(
101          unsigned char          *entropy,                  // output buffer
102          uint32_t                amount                    // amount requested
103   );
104   #endif




      Family "2.0"                                  TCG Published                                          Page 537
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                              October 30, 2014
     Trusted Platform Module Library                                                  Part 4: Supporting Routines


     C.9   PlatformData.h

     This file contains the instance data for the Platform module. It is collected in this file so that the state of
     the module is easier to manage.

 1   #ifndef _PLATFORM_DATA_H_
 2   #define _PLATFORM_DATA_H_
 3   #include    "TpmBuildSwitches.h"
 4   #include    "Implementation.h"
 5   #include    "bool.h"

     From Cancel.c Cancel flag. It is initialized as FALSE, which indicate the command is not being canceled

 6   extern BOOL         s_isCanceled;

     From Clock.c This variable records the time when _plat__ClockReset() is called. This mechanism allow
     us to subtract the time when TPM is power off from the total time reported by clock() function

 7   extern unsigned long long          s_initClock;
 8   extern unsigned int                s_adjustRate;

     From LocalityPlat.c Locality of current command

 9   extern unsigned char s_locality;

     From NVMem.c Choose if the NV memory should be backed by RAM or by file. If this macro is defined,
     then a file is used as NV. If it is not defined, then RAM is used to back NV memory. Comment out to use
     RAM.

10   #define FILE_BACKED_NV
11   #if defined FILE_BACKED_NV
12   #include <stdio.h>

     A file to emulate NV storage

13   extern   FILE*                  s_NVFile;
14   #endif
15   extern   unsigned char          s_NV[NV_MEMORY_SIZE];
16   extern   BOOL                   s_NvIsAvailable;
17   extern   BOOL                   s_NV_unrecoverable;
18   extern   BOOL                   s_NV_recoverable;

     From PPPlat.c Physical presence. It is initialized to FALSE

19   extern BOOL         s_physicalPresence;

     From Power

20   extern BOOL             s_powerLost;

     From Entropy.c

21   extern uint32_t        lastEntropy;
22   extern int             firstValue;
23   #endif // _PLATFORM_DATA_H_




     Page 538                                      TCG Published                                      Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
     Part 4: Supporting Routines                                                Trusted Platform Module Library


     C.10 PlatformData.c

     C.10.1. Description

     This file will instance the TPM variables that are not stack allocated. The descriptions for these variables
     is in Global.h for this project.

     C.10.2. Includes

     This include is required to set the NV memory size consistently across all parts of the implementation.

 1   #include        "Implementation.h"
 2   #include        "Platform.h"
 3   #include        "PlatformData.h"

     From Cancel.c

 4   BOOL                      s_isCanceled;

     From Clock.c

 5   unsigned long long        s_initClock;
 6   unsigned int              s_adjustRate;

     From LocalityPlat.c

 7   unsigned char             s_locality;

     From Power.c

 8   BOOL                      s_powerLost;

     From Entropy.c

 9   uint32_t                  lastEntropy;
10   int                       firstValue;

     From NVMem.c

11   #ifdef VTPM
12   #    undef FILE_BACKED_NV
13   #endif
14   #ifdef FILE_BACKED_NV
15   FILE                 *s_NVFile = NULL;
16   #endif
17   unsigned char         s_NV[NV_MEMORY_SIZE];
18   BOOL                  s_NvIsAvailable;
19   BOOL                  s_NV_unrecoverable;
20   BOOL                  s_NV_recoverable;

     From PPPlat.c

21   BOOL   s_physicalPresence;




     Family "2.0"                                 TCG Published                                       Page 539
     Level 00 Revision 01.16              Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                          Part 4: Supporting Routines


     C.11 PPPlat.c

     C.11.1. Description

     This module simulates the physical present interface pins on the TPM.

     C.11.2. Includes

 1   #include "PlatformData.h"


     C.11.3. Functions

     C.11.3.1. _plat__PhysicalPresenceAsserted()

     Check if physical presence is signaled

     Return Value                      Meaning

     TRUE                              if physical presence is signaled
     FALSE                             if physical presence is not signaled

 2   LIB_EXPORT BOOL
 3   _plat__PhysicalPresenceAsserted(
 4       void
 5       )
 6   {
 7       // Do not know how to check physical presence without real hardware.
 8       // so always return TRUE;
 9       return s_physicalPresence;
10   }


     C.11.3.2. _plat__Signal_PhysicalPresenceOn()

     Signal physical presence on

11   LIB_EXPORT void
12   _plat__Signal_PhysicalPresenceOn(
13       void
14       )
15   {
16       s_physicalPresence = TRUE;
17       return;
18   }


     C.11.3.3. _plat__Signal_PhysicalPresenceOff()

     Signal physical presence off

19   LIB_EXPORT void
20   _plat__Signal_PhysicalPresenceOff(
21       void
22       )
23   {
24       s_physicalPresence = FALSE;
25       return;
26   }


     Page 540                                       TCG Published                           Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014          Level 00 Revision 01.16
     Part 4: Supporting Routines                                                         Trusted Platform Module Library


     C.12 Unique.c

     C.12.1. Introduction

     In some implementations of the TPM, the hardware can provide a secret value to the TPM. This secret
     value is statistically unique to the instance of the TPM. Typical uses of this value are to provide
     personalization to the random number generation and as a shared secret between the TPM and the
     manufacturer.

     C.12.2. Includes

 1   #include "stdint.h"
 2   #include "TpmBuildSwitches.h"
 3   const char notReallyUnique[] =
 4           "This is not really a unique value. A real unique value should"
 5           " be generated by the platform.";


     C.12.3. _plat__GetUnique()

     This function is used to access the platform-specific unique value. This function places the unique value
     in the provided buffer (b) and returns the number of bytes transferred. The function will not copy more
     data than bSize.

     NOTE:           If a platform unique value has unequal distribution of uniqueness and bSize is smaller than the size of the
                     unique value, the bSize portion with the most uniqueness should be returned.

 6   LIB_EXPORT uint32_t
 7   _plat__GetUnique(
 8       uint32_t                    which,                // authorities (0) or details
 9       uint32_t                    bSize,                // size of the buffer
10       unsigned char              *b                     // output buffer
11   )
12   {
13       const char                 *from = notReallyUnique;
14       uint32_t                    retVal = 0;
15
16       if(which == 0) // the authorities value
17       {
18           for(retVal = 0;
19               *from != 0 && retVal < bSize;
20               retVal++)
21           {
22               *b++ = *from++;
23           }
24       }
25       else
26       {
27   #define uSize sizeof(notReallyUnique)
28           b = &b[((bSize < uSize) ? bSize : uSize) - 1];
29           for(retVal = 0;
30               *from != 0 && retVal < bSize;
31               retVal++)
32           {
33               *b-- = *from++;
34           }
35       }
36       return retVal;
37   }




     Family "2.0"                                     TCG Published                                                Page 541
     Level 00 Revision 01.16                 Copyright © TCG 2006-2014                                   October 30, 2014
Trusted Platform Module Library                                         Part 4: Supporting Routines


                                           Annex D
                                         (informative)
                                  Remote Procedure Interface

D.1   Introduction

These files provide an RPC interface for a TPM simulation.
The simulation uses two ports: a command port and a hardware simulation port. Only TPM commands
defined in TPM 2.0 Part 3 are sent to the TPM on the command port. The hardware simulation port is
used to simulate hardware events such as power on/off and locality; and indications such as
_TPM_HashStart.




Page 542                                    TCG Published                             Family "2.0"
October 30, 2014                    Copyright © TCG 2006-2014            Level 00 Revision 01.16
     Part 4: Supporting Routines                                            Trusted Platform Module Library



     D.2      TpmTcpProtocol.h

     D.2.1.    Introduction

     TPM commands are communicated as BYTE streams on a TCP connection. The TPM command
     protocol is enveloped with the interface protocol described in this file. The command is indicated by a
     UINT32 with one of the values below. Most commands take no parameters return no TPM errors. In
     these cases the TPM interface protocol acknowledges that command processing is complete by returning
     a UINT32=0. The command TPM_SIGNAL_HASH_DATA takes a UINT32-prepended variable length
     BYTE array and the interface protocol acknowledges command completion with a UINT32=0. Most TPM
     commands are enveloped using the TPM_SEND_COMMAND interface command. The parameters are
     as indicated below. The interface layer also appends a UIN32=0 to the TPM response for regularity.

     D.2.2.    Typedefs and Defines

 1   #ifndef        TCP_TPM_PROTOCOL_H
 2   #define        TCP_TPM_PROTOCOL_H

     TPM Commands. All commands acknowledge processing by returning a UINT32 == 0 except where
     noted

 3   #define    TPM_SIGNAL_POWER_ON         1
 4   #define    TPM_SIGNAL_POWER_OFF        2
 5   #define    TPM_SIGNAL_PHYS_PRES_ON     3
 6   #define    TPM_SIGNAL_PHYS_PRES_OFF    4
 7   #define    TPM_SIGNAL_HASH_START       5
 8   #define    TPM_SIGNAL_HASH_DATA        6
 9              // {UINT32 BufferSize, BYTE[BufferSize] Buffer}
10   #define    TPM_SIGNAL_HASH_END         7
11   #define    TPM_SEND_COMMAND            8
12              // {BYTE Locality, UINT32 InBufferSize, BYTE[InBufferSize] InBuffer} ->
13              //     {UINT32 OutBufferSize, BYTE[OutBufferSize] OutBuffer}
14   #define    TPM_SIGNAL_CANCEL_ON        9
15   #define    TPM_SIGNAL_CANCEL_OFF       10
16   #define    TPM_SIGNAL_NV_ON            11
17   #define    TPM_SIGNAL_NV_OFF           12
18   #define    TPM_SIGNAL_KEY_CACHE_ON     13
19   #define    TPM_SIGNAL_KEY_CACHE_OFF    14
20   #define    TPM_REMOTE_HANDSHAKE        15
21   #define    TPM_SET_ALTERNATIVE_RESULT 16
22   #define    TPM_SIGNAL_RESET            17
23   #define    TPM_SESSION_END             20
24   #define    TPM_STOP                    21
25   #define    TPM_GET_COMMAND_RESPONSE_SIZES 25
26   #define    TPM_TEST_FAILURE_MODE      30
27   enum TpmEndPointInfo
28   {
29       tpmPlatformAvailable = 0x01,
30       tpmUsesTbs = 0x02,
31       tpmInRawMode = 0x04,
32       tpmSupportsPP = 0x08
33   };
34
35   // Existing RPC interface type definitions retained so that the implementation
36   // can be re-used
37   typedef struct
38   {
39       unsigned long BufferSize;
40       unsigned char *Buffer;
41   } _IN_BUFFER;

     Family "2.0"                               TCG Published                                    Page 543
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                       October 30, 2014
     Trusted Platform Module Library                                          Part 4: Supporting Routines

42
43   typedef unsigned char *_OUTPUT_BUFFER;
44
45   typedef struct
46   {
47       uint32_t             BufferSize;
48       _OUTPUT_BUFFER       Buffer;
49   } _OUT_BUFFER;
50
51   //** TPM Command Function Prototypes
52   void _rpc__Signal_PowerOn(BOOL isReset);
53   void _rpc__Signal_PowerOff();
54   void _rpc__ForceFailureMode();
55   void _rpc__Signal_PhysicalPresenceOn();
56   void _rpc__Signal_PhysicalPresenceOff();
57   void _rpc__Signal_Hash_Start();
58   void _rpc__Signal_Hash_Data(
59       _IN_BUFFER input
60   );
61   void _rpc__Signal_HashEnd();
62   void _rpc__Send_Command(
63       unsigned char   locality,
64       _IN_BUFFER       request,
65       _OUT_BUFFER      *response
66   );
67   void _rpc__Signal_CancelOn();
68   void _rpc__Signal_CancelOff();
69   void _rpc__Signal_NvOn();
70   void _rpc__Signal_NvOff();
71   BOOL _rpc__InjectEPS(
72       const char* seed,
73       int seedSize
74   );

     start the TPM server on the indicated socket. The TPM is single-threaded and will accept connections
     first-come-first-served. Once a connection is dropped another client can connect.

75   BOOL TpmServer(SOCKET ServerSocket);
76   #endif




     Page 544                                  TCG Published                                Family "2.0"
     October 30, 2014                   Copyright © TCG 2006-2014               Level 00 Revision 01.16
     Part 4: Supporting Routines                                      Trusted Platform Module Library


     D.3      TcpServer.c

     D.3.1.     Description

     This file contains the socket interface to a TPM simulator.

     D.3.2.     Includes, Locals, Defines and Function Prototypes

 1   #include <stdio.h>
 2   #include <windows.h>
 3   #include <winsock.h>
 4   #include "string.h"
 5   #include <stdlib.h>
 6   #include <stdint.h>
 7   #include "TpmTcpProtocol.h"
 8   BOOL ReadBytes(SOCKET s, char* buffer, int NumBytes);
 9   BOOL ReadVarBytes(SOCKET s, char* buffer, UINT32* BytesReceived, int MaxLen);
10   BOOL WriteVarBytes(SOCKET s, char *buffer, int BytesToSend);
11   BOOL WriteBytes(SOCKET s, char* buffer, int NumBytes);
12   BOOL WriteUINT32(SOCKET s, UINT32 val);
13   #ifndef __IGNORE_STATE__
14   static UINT32 ServerVersion = 1;
15   #define MAX_BUFFER 1048576
16   char InputBuffer[MAX_BUFFER];        //The input data buffer for the simulator.
17   char OutputBuffer[MAX_BUFFER];       //The output data buffer for the simulator.
18   struct {
19       UINT32      largestCommandSize;
20       UINT32      largestCommand;
21       UINT32      largestResponseSize;
22       UINT32      largestResponse;
23   } CommandResponseSizes = {0};
24   #endif // __IGNORE_STATE___


     D.3.3.     Functions

     D.3.3.1.     CreateSocket()

     This function creates a socket listening on PortNumber.

25   static int
26   CreateSocket(
27         int                      PortNumber,
28         SOCKET                  *listenSocket
29         )
30   {
31         WSADATA                  wsaData;
32         struct                   sockaddr_in MyAddress;
33
34         int res;
35
36         // Initialize Winsock
37         res = WSAStartup(MAKEWORD(2,2), &wsaData);
38         if (res != 0)
39         {
40             printf("WSAStartup failed with error: %d\n", res);
41             return -1;
42         }
43
44         // create listening socket
45         *listenSocket = socket(PF_INET, SOCK_STREAM, 0);


     Family "2.0"                                 TCG Published                            Page 545
     Level 00 Revision 01.16              Copyright © TCG 2006-2014               October 30, 2014
      Trusted Platform Module Library                                       Part 4: Supporting Routines

 46       if(INVALID_SOCKET == *listenSocket)
 47       {
 48           printf("Cannot create server listen socket.         Error is 0x%x\n",
 49                   WSAGetLastError());
 50           return -1;
 51       }
 52
 53       // bind the listening socket to the specified port
 54       ZeroMemory(&MyAddress, sizeof(MyAddress));
 55       MyAddress.sin_port=htons((short) PortNumber);
 56       MyAddress.sin_family=AF_INET;
 57
 58       res= bind(*listenSocket,(struct sockaddr*) &MyAddress,sizeof(MyAddress));
 59       if(res==SOCKET_ERROR)
 60       {
 61           printf("Bind error. Error is 0x%x\n", WSAGetLastError());
 62           return -1;
 63       };
 64
 65       // listen/wait for server connections
 66       res= listen(*listenSocket,3);
 67       if(res==SOCKET_ERROR)
 68       {
 69           printf("Listen error. Error is 0x%x\n", WSAGetLastError());
 70           return -1;
 71       };
 72
 73       return 0;
 74   }


      D.3.3.2.   PlatformServer()

      This function processes incoming platform requests.

 75   BOOL
 76   PlatformServer(
 77       SOCKET               s
 78       )
 79   {
 80       BOOL                      ok = TRUE;
 81       UINT32                    length = 0;
 82       UINT32                    Command;
 83
 84       for(;;)
 85       {
 86           ok = ReadBytes(s, (char*) &Command, 4);
 87           // client disconnected (or other error). We stop processing this client
 88           // and return to our caller who can stop the server or listen for another
 89           // connection.
 90           if(!ok) return TRUE;
 91           Command = ntohl(Command);
 92           switch(Command)
 93           {
 94               case TPM_SIGNAL_POWER_ON:
 95                   _rpc__Signal_PowerOn(FALSE);
 96                   break;
 97
 98                 case TPM_SIGNAL_POWER_OFF:
 99                     _rpc__Signal_PowerOff();
100                     break;
101
102                 case TPM_SIGNAL_RESET:
103                     _rpc__Signal_PowerOn(TRUE);
104                     break;


      Page 546                                    TCG Published                           Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014           Level 00 Revision 01.16
      Part 4: Supporting Routines                                                 Trusted Platform Module Library

105
106                  case TPM_SIGNAL_PHYS_PRES_ON:
107                      _rpc__Signal_PhysicalPresenceOn();
108                      break;
109
110                  case TPM_SIGNAL_PHYS_PRES_OFF:
111                      _rpc__Signal_PhysicalPresenceOff();
112                      break;
113
114                  case TPM_SIGNAL_CANCEL_ON:
115                      _rpc__Signal_CancelOn();
116                      break;
117
118                  case TPM_SIGNAL_CANCEL_OFF:
119                      _rpc__Signal_CancelOff();
120                      break;
121
122                  case TPM_SIGNAL_NV_ON:
123                      _rpc__Signal_NvOn();
124                      break;
125
126                  case TPM_SIGNAL_NV_OFF:
127                      _rpc__Signal_NvOff();
128                      break;
129
130                  case TPM_SESSION_END:
131                      // Client signaled end-of-session
132                      return TRUE;
133
134                  case TPM_STOP:
135                      // Client requested the simulator to exit
136                      return FALSE;
137
138                  case TPM_TEST_FAILURE_MODE:
139                      _rpc__ForceFailureMode();
140                      break;
141
142                  case TPM_GET_COMMAND_RESPONSE_SIZES:
143                      ok = WriteVarBytes(s, (char *)&CommandResponseSizes,
144                                         sizeof(CommandResponseSizes));
145                      memset(&CommandResponseSizes, 0, sizeof(CommandResponseSizes));
146                      if(!ok)
147                          return TRUE;
148                      break;
149
150                  default:
151                      printf("Unrecognized platform interface command %d\n", Command);
152                      WriteUINT32(s, 1);
153                      return TRUE;
154              }
155              WriteUINT32(s,0);
156        }
157        return FALSE;
158   }


      D.3.3.3.    PlatformSvcRoutine()

      This function is called to set up the socket interfaces to listen for commands.

159   DWORD WINAPI
160   PlatformSvcRoutine(
161        LPVOID               port
162        )
163   {


      Family "2.0"                                 TCG Published                                       Page 547
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                         October 30, 2014
      Trusted Platform Module Library                                            Part 4: Supporting Routines

164       int                      PortNumber = (int)(INT_PTR) port;
165       SOCKET                   listenSocket, serverSocket;
166       struct                   sockaddr_in HerAddress;
167       int                      res;
168       int                      length;
169       BOOL                     continueServing;
170
171       res = CreateSocket(PortNumber, &listenSocket);
172       if(res != 0)
173       {
174           printf("Create platform service socket fail\n");
175           return res;
176       }
177
178       // Loop accepting connections one-by-one until we are killed or asked to stop
179       // Note the platform service is single-threaded so we don't listen for a new
180       // connection until the prior connection drops.
181       do
182       {
183           printf("Platform server listening on port %d\n", PortNumber);
184
185              // blocking accept
186              length = sizeof(HerAddress);
187              serverSocket = accept(listenSocket,
188                                    (struct sockaddr*) &HerAddress,
189                                    &length);
190              if(serverSocket == SOCKET_ERROR)
191              {
192                  printf("Accept error. Error is 0x%x\n", WSAGetLastError());
193                  return -1;
194              };
195              printf("Client accepted\n");
196
197              // normal behavior on client disconnection is to wait for a new client
198              // to connect
199              continueServing = PlatformServer(serverSocket);
200              closesocket(serverSocket);
201       }
202       while(continueServing);
203
204       return 0;
205   }


      D.3.3.4.    PlatformSignalService()

      This function starts a new thread waiting for platform signals. Platform signals are processed one at a
      time in the order in which they are received.

206   int
207   PlatformSignalService(
208       int                 PortNumber
209       )
210   {
211       HANDLE                   hPlatformSvc;
212       int                      ThreadId;
213       int                      port = PortNumber;
214
215       // Create service thread for platform signals
216       hPlatformSvc = CreateThread(NULL, 0,
217                                   (LPTHREAD_START_ROUTINE)PlatformSvcRoutine,
218                                   (LPVOID) (INT_PTR) port, 0, (LPDWORD)&ThreadId);
219       if(hPlatformSvc == NULL)
220       {
221           printf("Thread Creation failed\n");

      Page 548                                   TCG Published                                  Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                           Trusted Platform Module Library

222              return -1;
223       }
224
225       return 0;
226   }


      D.3.3.5.    RegularCommandService()

      This funciton services regular commands.

227   int
228   RegularCommandService(
229       int                 PortNumber
230       )
231   {
232       SOCKET                     listenSocket;
233       SOCKET                     serverSocket;
234       struct                     sockaddr_in HerAddress;
235
236       int res, length;
237       BOOL continueServing;
238
239       res = CreateSocket(PortNumber, &listenSocket);
240       if(res != 0)
241       {
242           printf("Create platform service socket fail\n");
243           return res;
244       }
245
246       // Loop accepting connections one-by-one until we are killed or asked to stop
247       // Note the TPM command service is single-threaded so we don't listen for
248       // a new connection until the prior connection drops.
249       do
250       {
251           printf("TPM command server listening on port %d\n", PortNumber);
252
253              // blocking accept
254              length = sizeof(HerAddress);
255              serverSocket = accept(listenSocket,
256                                    (struct sockaddr*) &HerAddress,
257                                    &length);
258              if(serverSocket ==SOCKET_ERROR)
259              {
260                  printf("Accept error. Error is 0x%x\n", WSAGetLastError());
261                  return -1;
262              };
263              printf("Client accepted\n");
264
265              // normal behavior on client disconnection is to wait for a new client
266              // to connect
267              continueServing = TpmServer(serverSocket);
268              closesocket(serverSocket);
269       }
270       while(continueServing);
271
272       return 0;
273   }


      D.3.3.6.    StartTcpServer()

      Main entry-point to the TCP server. The server listens on port specified. Note that there is no way to
      specify the network interface in this implementation.


      Family "2.0"                               TCG Published                                    Page 549
      Level 00 Revision 01.16             Copyright © TCG 2006-2014                      October 30, 2014
      Trusted Platform Module Library                                               Part 4: Supporting Routines

274   int
275   StartTcpServer(
276       int                  PortNumber
277       )
278   {
279       int                       res;
280
281       // Start Platform Signal Processing Service
282       res = PlatformSignalService(PortNumber+1);
283       if (res != 0)
284       {
285           printf("PlatformSignalService failed\n");
286           return res;
287       }
288
289       // Start Regular/DRTM TPM command service
290       res = RegularCommandService(PortNumber);
291       if (res != 0)
292       {
293           printf("RegularCommandService failed\n");
294           return res;
295       }
296
297       return 0;
298   }


      D.3.3.7.   ReadBytes()

      This function reads the indicated number of bytes (NumBytes) into buffer from the indicated socket.

299   BOOL
300   ReadBytes(
301       SOCKET               s,
302       char                *buffer,
303       int                  NumBytes
304       )
305   {
306       int                       res;
307       int                       numGot = 0;
308
309       while(numGot<NumBytes)
310       {
311           res = recv(s, buffer+numGot, NumBytes-numGot, 0);
312           if(res == -1)
313           {
314               printf("Receive error. Error is 0x%x\n", WSAGetLastError());
315               return FALSE;
316           }
317           if(res==0)
318           {
319               return FALSE;
320           }
321           numGot+=res;
322       }
323       return TRUE;
324   }


      D.3.3.8.   WriteBytes()

      This function will send the indicated number of bytes (NumBytes) to the indicated socket

325   BOOL
326   WriteBytes(

      Page 550                                    TCG Published                                   Family "2.0"
      October 30, 2014                     Copyright © TCG 2006-2014                 Level 00 Revision 01.16
      Part 4: Supporting Routines                                           Trusted Platform Module Library

327       SOCKET              s,
328       char               *buffer,
329       int                 NumBytes
330       )
331   {
332       int                   res;
333       int                   numSent = 0;
334       while(numSent<NumBytes)
335       {
336           res = send(s, buffer+numSent, NumBytes-numSent, 0);
337           if(res == -1)
338           {
339               if(WSAGetLastError() == 0x2745)
340               {
341                   printf("Client disconnected\n");
342               }
343               else
344               {
345                   printf("Send error. Error is 0x%x\n", WSAGetLastError());
346               }
347               return FALSE;
348           }
349           numSent+=res;
350       }
351       return TRUE;
352   }


      D.3.3.9.   WriteUINT32()

      Send 4 bytes containing hton(1)

353   BOOL
354   WriteUINT32(
355       SOCKET              s,
356       UINT32              val
357       )
358   {
359       UINT32 netVal = htonl(val);
360       return WriteBytes(s, (char*) &netVal, 4);
361   }


      D.3.3.10. ReadVarBytes()

      Get a UINT32-length-prepended binary array. Note that the 4-byte length is in network byte order (big-
      endian).

362   BOOL
363   ReadVarBytes(
364       SOCKET              s,
365       char               *buffer,
366       UINT32             *BytesReceived,
367       int                 MaxLen
368       )
369   {
370       int                       length;
371       BOOL                      res;
372
373       res = ReadBytes(s, (char*) &length, 4);
374       if(!res) return res;
375       length = ntohl(length);
376       *BytesReceived = length;
377       if(length>MaxLen)
378       {

      Family "2.0"                              TCG Published                                    Page 551
      Level 00 Revision 01.16            Copyright © TCG 2006-2014                       October 30, 2014
      Trusted Platform Module Library                                            Part 4: Supporting Routines

379            printf("Buffer too big.       Client says %d\n", length);
380            return FALSE;
381       }
382       if(length==0) return TRUE;
383       res = ReadBytes(s, buffer, length);
384       if(!res) return res;
385       return TRUE;
386   }


      D.3.3.11. WriteVarBytes()

      Send a UINT32-length-prepended binary array. Note that the 4-byte length is in network byte order (big-
      endian).

387   BOOL
388   WriteVarBytes(
389       SOCKET              s,
390       char               *buffer,
391       int                 BytesToSend
392       )
393   {
394       UINT32                   netLength = htonl(BytesToSend);
395       BOOL res;
396
397       res = WriteBytes(s, (char*) &netLength, 4);
398       if(!res) return res;
399       res = WriteBytes(s, buffer, BytesToSend);
400       if(!res) return res;
401       return TRUE;
402   }


      D.3.3.12. TpmServer()

      Processing incoming TPM command requests using the protocol / interface defined above.

403   BOOL
404   TpmServer(
405       SOCKET              s
406       )
407   {
408       UINT32                   length;
409       UINT32                   Command;
410       BYTE                     locality;
411       BOOL                     ok;
412       int                      result;
413       int                      clientVersion;
414       _IN_BUFFER               InBuffer;
415       _OUT_BUFFER              OutBuffer;
416
417       for(;;)
418       {
419           ok = ReadBytes(s, (char*) &Command, 4);
420           // client disconnected (or other error). We stop processing this client
421           // and return to our caller who can stop the server or listen for another
422           // connection.
423           if(!ok)
424               return TRUE;
425           Command = ntohl(Command);
426           switch(Command)
427           {
428               case TPM_SIGNAL_HASH_START:
429                   _rpc__Signal_Hash_Start();
430                   break;

      Page 552                                   TCG Published                                  Family "2.0"
      October 30, 2014                    Copyright © TCG 2006-2014                Level 00 Revision 01.16
      Part 4: Supporting Routines                                    Trusted Platform Module Library

431
432                  case TPM_SIGNAL_HASH_END:
433                      _rpc__Signal_HashEnd();
434                      break;
435
436                  case TPM_SIGNAL_HASH_DATA:
437                      ok = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
438                      if(!ok) return TRUE;
439                      InBuffer.Buffer = (BYTE*) InputBuffer;
440                      InBuffer.BufferSize = length;
441                      _rpc__Signal_Hash_Data(InBuffer);
442                      break;
443
444                  case TPM_SEND_COMMAND:
445                      ok = ReadBytes(s, (char*) &locality, 1);
446                      if(!ok)
447                          return TRUE;
448
449                      ok = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
450                      if(!ok)
451                          return TRUE;
452                      InBuffer.Buffer = (BYTE*) InputBuffer;
453                      InBuffer.BufferSize = length;
454                      OutBuffer.BufferSize = MAX_BUFFER;
455                      OutBuffer.Buffer = (_OUTPUT_BUFFER) OutputBuffer;
456                      // record the number of bytes in the command if it is the largest
457                      // we have seen so far.
458                      if(InBuffer.BufferSize > CommandResponseSizes.largestCommandSize)
459                      {
460                          CommandResponseSizes.largestCommandSize = InBuffer.BufferSize;
461                          memcpy(&CommandResponseSizes.largestCommand,
462                                 &InputBuffer[6], sizeof(UINT32));
463                      }
464
465                      _rpc__Send_Command(locality, InBuffer, &OutBuffer);
466                      // record the number of bytes in the response if it is the largest
467                      // we have seen so far.
468                      if(OutBuffer.BufferSize > CommandResponseSizes.largestResponseSize)
469                      {
470                          CommandResponseSizes.largestResponseSize
471                              = OutBuffer.BufferSize;
472                          memcpy(&CommandResponseSizes.largestResponse,
473                                 &OutputBuffer[6], sizeof(UINT32));
474                      }
475                      ok = WriteVarBytes(s,
476                                         (char*) OutBuffer.Buffer,
477                                         OutBuffer.BufferSize);
478                      if(!ok)
479                          return TRUE;
480                      break;
481
482                  case TPM_REMOTE_HANDSHAKE:
483                      ok = ReadBytes(s, (char*)&clientVersion, 4);
484                      if(!ok)
485                          return TRUE;
486                      if( clientVersion == 0 )
487                      {
488                          printf("Unsupported client version (0).\n");
489                          return TRUE;
490                      }
491                      ok &= WriteUINT32(s, ServerVersion);
492                      ok &= WriteUINT32(s,
493                                     tpmInRawMode | tpmPlatformAvailable | tpmSupportsPP);
494                      break;
495
496                  case TPM_SET_ALTERNATIVE_RESULT:

      Family "2.0"                           TCG Published                                Page 553
      Level 00 Revision 01.16          Copyright © TCG 2006-2014                   October 30, 2014
      Trusted Platform Module Library                                   Part 4: Supporting Routines

497                      ok = ReadBytes(s, (char*)&result, 4);
498                      if(!ok)
499                          return TRUE;
500                      // Alternative result is not applicable to the simulator.
501                      break;
502
503                 case TPM_SESSION_END:
504                     // Client signaled end-of-session
505                     return TRUE;
506
507                 case TPM_STOP:
508                     // Client requested the simulator to exit
509                     return FALSE;
510                 default:
511                     printf("Unrecognized TPM interface command %d\n", Command);
512                     return TRUE;
513            }
514            ok = WriteUINT32(s,0);
515            if(!ok)
516                return TRUE;
517       }
518       return FALSE;
519   }




      Page 554                               TCG Published                            Family "2.0"
      October 30, 2014                  Copyright © TCG 2006-2014         Level 00 Revision 01.16
     Part 4: Supporting Routines                                              Trusted Platform Module Library


     D.4      TPMCmdp.c

     D.4.1.     Description

     This file contains the functions that process the commands received on the control port or the command
     port of the simulator. The control port is used to allow simulation of hardware events (such as,
     _TPM_Hash_Start()) to test the simulated TPM's reaction to those events. This improves code coverage
     of the testing.

     D.4.2.     Includes and Data Definitions

 1   #define _SWAP_H         // Preclude inclusion of unnecessary simulator header
 2   #include <stdlib.h>
 3   #include <stdio.h>
 4   #include <stdint.h>
 5   #include <setjmp.h>
 6   #include "bool.h"
 7   #include "Platform.h"
 8   #include "ExecCommand_fp.h"
 9   #include "Manufacture_fp.h"
10   #include "DRTM_fp.h"
11   #include "_TPM_Init_fp.h"
12   #include "TpmFail_fp.h"
13   #include <windows.h>
14   #include "TpmTcpProtocol.h"
15   static BOOL     s_isPowerOn = FALSE;


     D.4.3.     Functions

     D.4.3.1.     Signal_PowerOn()

     This function processes a power-on indicataion. Amoung other things, it calls the _TPM_Init() hangler.

16   void
17   _rpc__Signal_PowerOn(
18         BOOL          isReset
19         )
20   {
21         // if power is on and this is not a call to do TPM reset then return
22         if(s_isPowerOn && !isReset)
23             return;
24
25         // If this is a reset but power is not on, then return
26         if(isReset && !s_isPowerOn)
27             return;
28
29         // Pass power on signal to platform
30         if(isReset)
31             _plat__Signal_Reset();
32         else
33             _plat__Signal_PowerOn();
34
35         // Pass power on signal to TPM
36         _TPM_Init();
37
38         // Set state as power on
39         s_isPowerOn = TRUE;
40   }



     Family "2.0"                                TCG Published                                      Page 555
     Level 00 Revision 01.16             Copyright © TCG 2006-2014                          October 30, 2014
     Trusted Platform Module Library                                                  Part 4: Supporting Routines

     D.4.3.2.    Signal_PowerOff()

     This function processes the power off indication. Its primary funtion is to set a flag indicating that the next
     power on indication should cause _TPM_Init() to be called.

41   void
42   _rpc__Signal_PowerOff(
43        void
44        )
45   {
46        if(!s_isPowerOn) return;
47
48        // Pass power off signal to platform
49        _plat__Signal_PowerOff();
50
51        s_isPowerOn = FALSE;
52
53        return;
54   }


     D.4.3.3.    _rpc__ForceFailureMode()

     This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM code such
     that the next call to TPM2_SelfTest() will result in a failure, putting the TPM into Failure Mode.

55   void
56   _rpc__ForceFailureMode(
57        void
58        )
59   {
60        SetForceFailureMode();
61   }


     D.4.3.4.    _rpc__Signal_PhysicalPresenceOn()

     This function is called to simulate activation of the physical presence pin.

62   void
63   _rpc__Signal_PhysicalPresenceOn(
64        void
65        )
66   {
67        // If TPM is power off, reject this signal
68        if(!s_isPowerOn) return;
69
70        // Pass physical presence on to platform
71        _plat__Signal_PhysicalPresenceOn();
72
73        return;
74   }


     D.4.3.5.    _rpc__Signal_PhysicalPresenceOff()

     This function is called to simulate deactivation of the physical presence pin.

75   void
76   _rpc__Signal_PhysicalPresenceOff(
77        void
78        )
79   {

     Page 556                                      TCG Published                                      Family "2.0"
     October 30, 2014                       Copyright © TCG 2006-2014                   Level 00 Revision 01.16
      Part 4: Supporting Routines                                                   Trusted Platform Module Library

 80        // If TPM is power off, reject this signal
 81        if(!s_isPowerOn) return;
 82
 83        // Pass physical presence off to platform
 84        _plat__Signal_PhysicalPresenceOff();
 85
 86        return;
 87   }


      D.4.3.6.    _rpc__Signal_Hash_Start()

      This function is called to simulate a _TPM_Hash_Start() event. It will call

 88   void
 89   _rpc__Signal_Hash_Start(
 90        void
 91        )
 92   {
 93        // If TPM is power off, reject this signal
 94        if(!s_isPowerOn) return;
 95
 96        // Pass _TPM_Hash_Start signal to TPM
 97        Signal_Hash_Start();
 98        return;
 99   }


      D.4.3.7.    _rpc__Signal_Hash_Data()

      This function is called to simulate a _TPM_Hash_Data() event.

100   void
101   _rpc__Signal_Hash_Data(
102        _IN_BUFFER           input
103        )
104   {
105        // If TPM is power off, reject this signal
106        if(!s_isPowerOn) return;
107
108        // Pass _TPM_Hash_Data signal to TPM
109        Signal_Hash_Data(input.BufferSize, input.Buffer);
110        return;
111   }


      D.4.3.8.    _rpc__Signal_HashEnd()

      This function is called to simulate a _TPM_Hash_End() event.

112   void
113   _rpc__Signal_HashEnd(
114        void
115        )
116   {
117        // If TPM is power off, reject this signal
118        if(!s_isPowerOn) return;
119
120        // Pass _TPM_HashEnd signal to TPM
121        Signal_Hash_End();
122        return;
123   }

      Command interface Entry of a RPC call

      Family "2.0"                                 TCG Published                                         Page 557
      Level 00 Revision 01.16               Copyright © TCG 2006-2014                           October 30, 2014
      Trusted Platform Module Library                                                Part 4: Supporting Routines

124   void
125   _rpc__Send_Command(
126       unsigned char        locality,
127       _IN_BUFFER           request,
128       _OUT_BUFFER         *response
129       )
130   {
131       // If TPM is power off, reject any commands.
132       if(!s_isPowerOn) {
133           response->BufferSize = 0;
134           return;
135       }
136       // Set the locality of the command so that it doesn't change during the command
137       _plat__LocalitySet(locality);
138       // Do implementation-specific command dispatch
139       ExecuteCommand(request.BufferSize, request.Buffer,
140                              &response->BufferSize, &response->Buffer);
141       return;
142
143   }


      D.4.3.9.   _rpc__Signal_CancelOn()

      This function is used to turn on the indication to cancel a command in process. An executing command is
      not interrupted. The command code may perodically check this indication to see if it should abort the
      current command processing and returned TPM_RC_CANCELLED.

144   void
145   _rpc__Signal_CancelOn(
146       void
147       )
148   {
149       // If TPM is power off, reject this signal
150       if(!s_isPowerOn) return;
151
152       // Set the platform canceling flag.
153       _plat__SetCancel();
154
155       return;
156   }


      D.4.3.10. _rpc__Signal_CancelOff()

      This function is used to turn off the indication to cancel a command in process.

157   void
158   _rpc__Signal_CancelOff(
159       void
160       )
161   {
162       // If TPM is power off, reject this signal
163       if(!s_isPowerOn) return;
164
165       // Set the platform canceling flag.
166       _plat__ClearCancel();
167
168       return;
169   }




      Page 558                                     TCG Published                                    Family "2.0"
      October 30, 2014                      Copyright © TCG 2006-2014                    Level 00 Revision 01.16
      Part 4: Supporting Routines                                                Trusted Platform Module Library

      D.4.3.11. _rpc__Signal_NvOn()

      In a system where the NV memory used by the TPM is not within the TPM, the NV may not always be
      available. This function turns on the indicator that indicates that NV is available.

170   void
171   _rpc__Signal_NvOn(
172       void
173       )
174   {
175       // If TPM is power off, reject this signal
176       if(!s_isPowerOn) return;
177
178       _plat__SetNvAvail();
179       return;
180   }


      D.4.3.12. _rpc__Signal_NvOff()

      This function is used to set the indication that NV memory is no longer available.

181   void
182   _rpc__Signal_NvOff(
183       void
184       )
185   {
186       // If TPM is power off, reject this signal
187       if(!s_isPowerOn) return;
188
189       _plat__ClearNvAvail();
190       return;
191   }


      D.4.3.13. _rpc__Shutdown()

      This function is used to stop the TPM simulator.

192   void
193   _rpc__Shutdown(
194       void
195       )
196   {
197       RPC_STATUS status;
198
199       // Stop TPM
200       TPM_TearDown();
201
202       status = RpcMgmtStopServerListening(NULL);
203       if (status != RPC_S_OK)
204       {
205           printf_s("RpcMgmtStopServerListening returned: 0x%x\n", status);
206           exit(status);
207       }
208
209       status = RpcServerUnregisterIf(NULL, NULL, FALSE);
210       if (status != RPC_S_OK)
211       {
212           printf_s("RpcServerUnregisterIf returned 0x%x\n", status);
213           exit(status);
214       }
215   }


      Family "2.0"                                 TCG Published                                      Page 559
      Level 00 Revision 01.16              Copyright © TCG 2006-2014                         October 30, 2014
     Trusted Platform Module Library                                       Part 4: Supporting Routines


     D.5      TPMCmds.c

     D.5.1.     Description

     This file contains the entry point for the simulator.

     D.5.2.     Includes, Defines, Data Definitions, and Function Prototypes

 1   #include <stdlib.h>
 2   #include <stdio.h>
 3   #include <stdint.h>
 4   #include <ctype.h>
 5   #include <windows.h>
 6   #include <strsafe.h>
 7   #include "string.h"
 8   #include "TpmTcpProtocol.h"
 9   #include "..\tpm\include\TpmBuildSwitches.h"
10   #include "..\tpm\include\prototypes\Manufacture_fp.h"
11   #define PURPOSE \
12   "TPM Reference Simulator.\nCopyright Microsoft 2010, 2011.\n"
13   #define DEFAULT_TPM_PORT 2321
14   void* MainPointer;
15   int _plat__NVEnable(void* platParameters);
16   void _plat__NVDisable();
17   int StartTcpServer(int PortNumber);


     D.5.3.     Functions

     D.5.3.1.     Usage()

     This function prints the proper calling sequence for the simulator.

18   void
19   Usage(
20         char                      *pszProgramName
21         )
22   {
23         fprintf_s(stderr, "%s", PURPOSE);
24         fprintf_s(stderr, "Usage:\n");
25         fprintf_s(stderr, "%s         - Starts the TPM server listening on port %d\n",
26                   pszProgramName, DEFAULT_TPM_PORT);
27         fprintf_s(stderr,
28                   "%s PortNum - Starts the TPM server listening on port PortNum\n",
29                   pszProgramName);
30         fprintf_s(stderr, "%s ?       - This message\n", pszProgramName);
31         exit(1);
32   }


     D.5.3.2.     main()

     This is the main entry point for the simulator.
     main: register the interface, start listening for clients

33   void __cdecl
34   main(
35         int                  argc,
36         char                *argv[]
37         )

     Page 560                                          TCG Published                      Family "2.0"
     October 30, 2014                         Copyright © TCG 2006-2014        Level 00 Revision 01.16
     Part 4: Supporting Routines                                Trusted Platform Module Library

38   {
39       int portNum = DEFAULT_TPM_PORT;
40       if(argc>2)
41       {
42           Usage(argv[0]);
43       }
44
45       if(argc==2)
46       {
47           if(strcmp(argv[1], "?") ==0)
48           {
49               Usage(argv[0]);
50           }
51           portNum = atoi(argv[1]);
52           if(portNum <=0 || portNum>65535)
53           {
54               Usage(argv[0]);
55           }
56       }
57       _plat__NVEnable(NULL);
58       if(TPM_Manufacture(1) != 0)
59       {
60           exit(1);
61       }
62       // Coverage test - repeated manufacturing attempt
63       if(TPM_Manufacture(0) != 1)
64       {
65           exit(2);
66       }
67       // Coverage test - re-manufacturing
68       TPM_TearDown();
69       if(TPM_Manufacture(1) != 0)
70       {
71           exit(3);
72       }
73       // Disable NV memory
74       _plat__NVDisable();
75
76       StartTcpServer(portNum);
77       return;
78   }




     Family "2.0"                          TCG Published                             Page 561
     Level 00 Revision 01.16        Copyright © TCG 2006-2014               October 30, 2014