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 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 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 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 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 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 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 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(¶meters->p.b, data->p, sizeof(parameters->p.t.buffer)); 1332 1333 // Copy a value 1334 MemoryCopy2B(¶meters->a.b, data->a, sizeof(parameters->a.t.buffer)); 1335 1336 // Copy b value 1337 MemoryCopy2B(¶meters->b.b, data->b, sizeof(parameters->b.t.buffer)); 1338 1339 // Copy Gx value 1340 MemoryCopy2B(¶meters->gX.b, data->x, sizeof(parameters->gX.t.buffer)); 1341 1342 // Copy Gy value 1343 MemoryCopy2B(¶meters->gY.b, data->y, sizeof(parameters->gY.t.buffer)); 1344 1345 // Copy n value 1346 MemoryCopy2B(¶meters->n.b, data->n, sizeof(parameters->n.t.buffer)); 1347 1348 // Copy h value 1349 MemoryCopy2B(¶meters->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< (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 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 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 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 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 3 #include 4 #include 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 2 #include 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 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 2 #include 3 #include 4 #include "string.h" 5 #include 6 #include 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(numGotMaxLen) 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 3 #include 4 #include 5 #include 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 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 2 #include 3 #include 4 #include 5 #include 6 #include 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