| Trusted Platform Module Library |
| Part 4: Supporting Routines |
| |
| Family "2.0" |
| |
| Level 00 Revision 01.16 |
| |
| October 30, 2014 |
| |
| Published |
| |
| |
| |
| |
| Contact: admin@trustedcomputinggroup.org |
| |
| |
| |
| |
| TCG Published |
| Copyright © TCG 2006-2014 |
| |
| |
| |
| |
| TCG |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Licenses and Notices |
| |
| 1. Copyright Licenses: |
| Trusted Computing Group (TCG) grants to the user of the source code in this specification (the |
| “Source Code”) a worldwide, irrevocable, nonexclusive, royalty free, copyright license to |
| reproduce, create derivative works, distribute, display and perform the Source Code and |
| derivative works thereof, and to grant others the rights granted herein. |
| The TCG grants to the user of the other parts of the specification (other than the Source Code) |
| the rights to reproduce, distribute, display, and perform the specification solely for the purpose |
| of developing products based on such documents. |
| 2. Source Code Distribution Conditions: |
| Redistributions of Source Code must retain the above copyright licenses, this list of conditions |
| and the following disclaimers. |
| Redistributions in binary form must reproduce the above copyright licenses, this list of |
| conditions and the following disclaimers in the documentation and/or other materials provided |
| with the distribution. |
| 3. Disclaimers: |
| THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF LICENSE OR |
| WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH RESPECT TO PATENT RIGHTS |
| HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) THAT MAY BE NECESSARY TO IMPLEMENT |
| THIS SPECIFICATION OR OTHERWISE. Contact TCG Administration |
| (admin@trustedcomputinggroup.org) for information on specification licensing rights available |
| through TCG membership agreements. |
| THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES |
| WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A |
| PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF INTELLECTUAL |
| PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF ANY PROPOSAL, |
| SPECIFICATION OR SAMPLE. |
| Without limitation, TCG and its members and licensors disclaim all liability, including liability for |
| infringement of any proprietary rights, relating to use of information in this specification and to |
| the implementation of this specification, and TCG disclaims all liability for cost of procurement |
| of substitute goods or services, lost profits, loss of use, loss of data or any incidental, |
| consequential, direct, indirect, or special damages, whether under contract, tort, warranty or |
| otherwise, arising in any way out of use or reliance upon this specification or any information |
| herein. |
| Any marks and brands contained herein are the property of their respective owner. |
| |
| |
| |
| |
| Page ii TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| CONTENTS |
| 1 Scope ................................................................................................................................... 1 |
| 2 Terms and definitions ........................................................................................................... 1 |
| 3 Symbols and abbreviated terms ............................................................................................ 1 |
| 4 Automation ........................................................................................................................... 1 |
| 4.1 Configuration Parser ................................................................................................... 1 |
| 4.2 Structure Parser .......................................................................................................... 2 |
| 4.2.1 Introduction .......................................................................................................... 2 |
| 4.2.2 Unmarshaling Code Prototype .............................................................................. 2 |
| 4.2.2.1 Simple Types and Structures .......................................................................... 2 |
| 4.2.2.2 Union Types ................................................................................................... 3 |
| 4.2.2.3 Null Types ...................................................................................................... 3 |
| 4.2.2.4 Arrays ............................................................................................................. 3 |
| 4.2.3 Marshaling Code Function Prototypes .................................................................. 4 |
| 4.2.3.1 Simple Types and Structures .......................................................................... 4 |
| 4.2.3.2 Union Types ................................................................................................... 4 |
| 4.2.3.3 Arrays ............................................................................................................. 4 |
| 4.3 Command Parser ........................................................................................................ 5 |
| 4.4 Portability .................................................................................................................... 5 |
| 5 Header Files ......................................................................................................................... 6 |
| 5.1 Introduction ................................................................................................................. 6 |
| 5.2 BaseTypes.h ............................................................................................................... 6 |
| 5.3 bits.h ........................................................................................................................... 7 |
| 5.4 bool.h .......................................................................................................................... 8 |
| 5.5 Capabilities.h .............................................................................................................. 8 |
| 5.6 TPMB.h ....................................................................................................................... 8 |
| 5.7 TpmError.h .................................................................................................................. 9 |
| 5.8 Global.h ...................................................................................................................... 9 |
| 5.8.1 Description ........................................................................................................... 9 |
| 5.8.2 Includes ............................................................................................................... 9 |
| 5.8.3 Defines and Types ............................................................................................. 10 |
| 5.8.3.1 Unreferenced Parameter .............................................................................. 10 |
| 5.8.3.2 Crypto Self-Test Values ................................................................................ 10 |
| 5.8.3.3 Hash and HMAC State Structures ................................................................. 10 |
| 5.8.3.4 Other Types .................................................................................................. 11 |
| 5.8.4 Loaded Object Structures ................................................................................... 11 |
| 5.8.4.1 Description ................................................................................................... 11 |
| 5.8.4.2 OBJECT_ATTRIBUTES ................................................................................ 11 |
| 5.8.4.3 OBJECT Structure ........................................................................................ 12 |
| 5.8.4.4 HASH_OBJECT Structure ............................................................................. 12 |
| 5.8.4.5 ANY_OBJECT .............................................................................................. 13 |
| 5.8.5 AUTH_DUP Types .............................................................................................. 13 |
| 5.8.6 Active Session Context ....................................................................................... 13 |
| 5.8.6.1 Description ................................................................................................... 13 |
| 5.8.6.2 SESSION_ATTRIBUTES .............................................................................. 13 |
| 5.8.6.3 SESSION Structure ...................................................................................... 14 |
| 5.8.7 PCR ................................................................................................................... 15 |
| 5.8.7.1 PCR_SAVE Structure ................................................................................... 15 |
| |
| Family "2.0" TCG Published Page iii |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.8.7.2 PCR_POLICY ............................................................................................... 16 |
| 5.8.7.3 PCR_AUTHVALUE ....................................................................................... 16 |
| 5.8.8 Startup ............................................................................................................... 16 |
| 5.8.8.1 SHUTDOWN_NONE ..................................................................................... 16 |
| 5.8.8.2 STARTUP_TYPE .......................................................................................... 16 |
| 5.8.9 NV ...................................................................................................................... 16 |
| 5.8.9.1 NV_RESERVE .............................................................................................. 16 |
| 5.8.9.2 NV_INDEX .................................................................................................... 18 |
| 5.8.10 COMMIT_INDEX_MASK ..................................................................................... 18 |
| 5.8.11 RAM Global Values ............................................................................................ 18 |
| 5.8.11.1 Description ................................................................................................... 18 |
| 5.8.11.2 g_rcIndex ..................................................................................................... 18 |
| 5.8.11.3 g_exclusiveAuditSession .............................................................................. 18 |
| 5.8.11.4 g_time .......................................................................................................... 18 |
| 5.8.11.5 g_phEnable .................................................................................................. 18 |
| 5.8.11.6 g_pceReConfig ............................................................................................. 19 |
| 5.8.11.7 g_DRTMHandle ............................................................................................ 19 |
| 5.8.11.8 g_DrtmPreStartup ......................................................................................... 19 |
| 5.8.11.9 g_StartupLocality3 ........................................................................................ 19 |
| 5.8.11.10 g_updateNV ................................................................................................. 19 |
| 5.8.11.11 g_clearOrderly .............................................................................................. 19 |
| 5.8.11.12 g_prevOrderlyState ...................................................................................... 20 |
| 5.8.11.13 g_nvOk ......................................................................................................... 20 |
| 5.8.11.14 g_platformUnique ......................................................................................... 20 |
| 5.8.12 Persistent Global Values .................................................................................... 20 |
| 5.8.12.1 Description ................................................................................................... 20 |
| 5.8.12.2 PERSISTENT_DATA .................................................................................... 20 |
| 5.8.12.3 ORDERLY_DATA ......................................................................................... 22 |
| 5.8.12.4 STATE_CLEAR_DATA ................................................................................. 23 |
| 5.8.12.5 State Reset Data .......................................................................................... 24 |
| 5.8.13 Global Macro Definitions .................................................................................... 25 |
| 5.8.14 Private data ........................................................................................................ 25 |
| 5.9 Tpm.h ........................................................................................................................ 29 |
| 5.10 swap.h ...................................................................................................................... 30 |
| 5.11 InternalRoutines.h ..................................................................................................... 31 |
| 5.12 TpmBuildSwitches.h .................................................................................................. 32 |
| 5.13 VendorString.h .......................................................................................................... 33 |
| 6 Main ................................................................................................................................... 35 |
| 6.1 CommandDispatcher() ............................................................................................... 35 |
| 6.2 ExecCommand.c ....................................................................................................... 35 |
| 6.2.1 Introduction ........................................................................................................ 35 |
| 6.2.2 Includes ............................................................................................................. 35 |
| 6.2.3 ExecuteCommand() ............................................................................................ 35 |
| 6.3 ParseHandleBuffer() .................................................................................................. 41 |
| 6.4 SessionProcess.c ...................................................................................................... 42 |
| 6.4.1 Introduction ........................................................................................................ 42 |
| 6.4.2 Includes and Data Definitions ............................................................................. 42 |
| 6.4.3 Authorization Support Functions ......................................................................... 42 |
| 6.4.3.1 IsDAExempted() ........................................................................................... 42 |
| 6.4.3.2 IncrementLockout() ....................................................................................... 43 |
| |
| Page iv TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 6.4.3.3 IsSessionBindEntity() ................................................................................... 44 |
| 6.4.3.4 IsPolicySessionRequired() ............................................................................ 45 |
| 6.4.3.5 IsAuthValueAvailable() ................................................................................. 46 |
| 6.4.3.6 IsAuthPolicyAvailable() ................................................................................. 48 |
| 6.4.4 Session Parsing Functions ................................................................................. 49 |
| 6.4.4.1 ComputeCpHash() ........................................................................................ 49 |
| 6.4.4.2 CheckPWAuthSession() ................................................................................ 50 |
| 6.4.4.3 ComputeCommandHMAC() ........................................................................... 51 |
| 6.4.4.4 CheckSessionHMAC() .................................................................................. 53 |
| 6.4.4.5 CheckPolicyAuthSession() ............................................................................ 53 |
| 6.4.4.6 RetrieveSessionData() .................................................................................. 56 |
| 6.4.4.7 CheckLockedOut() ........................................................................................ 59 |
| 6.4.4.8 CheckAuthSession() ..................................................................................... 60 |
| 6.4.4.9 CheckCommandAudit() ................................................................................. 62 |
| 6.4.4.10 ParseSessionBuffer() .................................................................................... 63 |
| 6.4.4.11 CheckAuthNoSession() ................................................................................. 65 |
| 6.4.5 Response Session Processing ........................................................................... 66 |
| 6.4.5.1 Introduction .................................................................................................. 66 |
| 6.4.5.2 ComputeRpHash() ........................................................................................ 66 |
| 6.4.5.3 InitAuditSession() ......................................................................................... 67 |
| 6.4.5.4 Audit() .......................................................................................................... 67 |
| 6.4.5.5 CommandAudit() ........................................................................................... 68 |
| 6.4.5.6 UpdateAuditSessionStatus() ......................................................................... 69 |
| 6.4.5.7 ComputeResponseHMAC() ........................................................................... 70 |
| 6.4.5.8 BuildSingleResponseAuth() .......................................................................... 71 |
| 6.4.5.9 UpdateTPMNonce() ...................................................................................... 72 |
| 6.4.5.10 UpdateInternalSession() ............................................................................... 72 |
| 6.4.5.11 BuildResponseSession() ............................................................................... 73 |
| 7 Command Support Functions .............................................................................................. 76 |
| 7.1 Introduction ............................................................................................................... 76 |
| 7.2 Attestation Command Support (Attest_spt.c) ............................................................. 76 |
| 7.2.1 Includes ............................................................................................................. 76 |
| 7.2.2 Functions ........................................................................................................... 76 |
| 7.2.2.1 FillInAttestInfo() ............................................................................................ 76 |
| 7.2.2.2 SignAttestInfo() ............................................................................................ 77 |
| 7.3 Context Management Command Support (Context_spt.c) .......................................... 79 |
| 7.3.1 Includes ............................................................................................................. 79 |
| 7.3.2 Functions ........................................................................................................... 79 |
| 7.3.2.1 ComputeContextProtectionKey() ................................................................... 79 |
| 7.3.2.2 ComputeContextIntegrity() ............................................................................ 80 |
| 7.3.2.3 SequenceDataImportExport() ........................................................................ 81 |
| 7.4 Policy Command Support (Policy_spt.c) .................................................................... 81 |
| 7.4.1 PolicyParameterChecks() ................................................................................... 81 |
| 7.4.2 PolicyContextUpdate() ........................................................................................ 82 |
| 7.5 NV Command Support (NV_spt.c) ............................................................................. 83 |
| 7.5.1 Includes ............................................................................................................. 83 |
| 7.5.2 Fuctions ............................................................................................................. 83 |
| 7.5.2.1 NvReadAccessChecks() ............................................................................... 83 |
| 7.5.2.2 NvWriteAccessChecks() ............................................................................... 84 |
| 7.6 Object Command Support (Object_spt.c) ................................................................... 85 |
| |
| Family "2.0" TCG Published Page v |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 7.6.1 Includes ............................................................................................................. 85 |
| 7.6.2 Local Functions .................................................................................................. 86 |
| 7.6.2.1 EqualCryptSet() ............................................................................................ 86 |
| 7.6.2.2 GetIV2BSize() .............................................................................................. 86 |
| 7.6.2.3 ComputeProtectionKeyParms() ..................................................................... 87 |
| 7.6.2.4 ComputeOuterIntegrity() ............................................................................... 88 |
| 7.6.2.5 ComputeInnerIntegrity() ................................................................................ 89 |
| 7.6.2.6 ProduceInnerIntegrity() ................................................................................. 89 |
| 7.6.2.7 CheckInnerIntegrity() .................................................................................... 90 |
| 7.6.3 Public Functions ................................................................................................. 90 |
| 7.6.3.1 AreAttributesForParent() ............................................................................... 90 |
| 7.6.3.2 SchemeChecks() .......................................................................................... 91 |
| 7.6.3.3 PublicAttributesValidation()........................................................................... 94 |
| 7.6.3.4 FillInCreationData() ...................................................................................... 95 |
| 7.6.3.5 GetSeedForKDF() ......................................................................................... 97 |
| 7.6.3.6 ProduceOuterWrap() ..................................................................................... 97 |
| 7.6.3.7 UnwrapOuter() .............................................................................................. 99 |
| 7.6.3.8 SensitiveToPrivate() ................................................................................... 100 |
| 7.6.3.9 PrivateToSensitive() ................................................................................... 101 |
| 7.6.3.10 SensitiveToDuplicate()................................................................................ 103 |
| 7.6.3.11 DuplicateToSensitive()................................................................................ 105 |
| 7.6.3.12 SecretToCredential() .................................................................................. 107 |
| 7.6.3.13 CredentialToSecret() .................................................................................. 108 |
| 8 Subsystem........................................................................................................................ 109 |
| 8.1 CommandAudit.c ..................................................................................................... 109 |
| 8.1.1 Introduction ...................................................................................................... 109 |
| 8.1.2 Includes ........................................................................................................... 109 |
| 8.1.3 Functions ......................................................................................................... 109 |
| 8.1.3.1 CommandAuditPreInstall_Init() ................................................................... 109 |
| 8.1.3.2 CommandAuditStartup() ............................................................................. 109 |
| 8.1.3.3 CommandAuditSet() ................................................................................... 110 |
| 8.1.3.4 CommandAuditClear() ................................................................................ 110 |
| 8.1.3.5 CommandAuditIsRequired() ........................................................................ 111 |
| 8.1.3.6 CommandAuditCapGetCCList() .................................................................. 111 |
| 8.1.3.7 CommandAuditGetDigest ............................................................................ 112 |
| 8.2 DA.c ........................................................................................................................ 113 |
| 8.2.1 Introduction ...................................................................................................... 113 |
| 8.2.2 Includes and Data Definitions ........................................................................... 113 |
| 8.2.3 Functions ......................................................................................................... 113 |
| 8.2.3.1 DAPreInstall_Init() ...................................................................................... 113 |
| 8.2.3.2 DAStartup() ................................................................................................ 114 |
| 8.2.3.3 DARegisterFailure() .................................................................................... 114 |
| 8.2.3.4 DASelfHeal() .............................................................................................. 115 |
| 8.3 Hierarchy.c .............................................................................................................. 116 |
| 8.3.1 Introduction ...................................................................................................... 116 |
| 8.3.2 Includes ........................................................................................................... 116 |
| 8.3.3 Functions ......................................................................................................... 116 |
| 8.3.3.1 HierarchyPreInstall() ................................................................................... 116 |
| 8.3.3.2 HierarchyStartup() ...................................................................................... 117 |
| 8.3.3.3 HierarchyGetProof() ................................................................................... 118 |
| 8.3.3.4 HierarchyGetPrimarySeed() ........................................................................ 118 |
| 8.3.3.5 HierarchyIsEnabled() .................................................................................. 119 |
| |
| Page vi TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.4 NV.c ........................................................................................................................ 119 |
| 8.4.1 Introduction ...................................................................................................... 119 |
| 8.4.2 Includes, Defines and Data Definitions ............................................................. 119 |
| 8.4.3 NV Utility Functions .......................................................................................... 120 |
| 8.4.3.1 NvCheckState() .......................................................................................... 120 |
| 8.4.3.2 NvIsAvailable() ........................................................................................... 120 |
| 8.4.3.3 NvCommit ................................................................................................... 120 |
| 8.4.3.4 NvReadMaxCount() .................................................................................... 121 |
| 8.4.3.5 NvWriteMaxCount() .................................................................................... 121 |
| 8.4.4 NV Index and Persistent Object Access Functions ............................................ 121 |
| 8.4.4.1 Introduction ................................................................................................ 121 |
| 8.4.4.2 NvNext() ..................................................................................................... 121 |
| 8.4.4.3 NvGetEnd() ................................................................................................ 122 |
| 8.4.4.4 NvGetFreeByte ........................................................................................... 122 |
| 8.4.4.5 NvGetEvictObjectSize................................................................................. 123 |
| 8.4.4.6 NvGetCounterSize ...................................................................................... 123 |
| 8.4.4.7 NvTestSpace() ............................................................................................ 123 |
| 8.4.4.8 NvAdd() ...................................................................................................... 124 |
| 8.4.4.9 NvDelete() .................................................................................................. 124 |
| 8.4.5 RAM-based NV Index Data Access Functions ................................................... 125 |
| 8.4.5.1 Introduction ................................................................................................ 125 |
| 8.4.5.2 NvTestRAMSpace() .................................................................................... 125 |
| 8.4.5.3 NvGetRamIndexOffset ................................................................................ 126 |
| 8.4.5.4 NvAddRAM() .............................................................................................. 126 |
| 8.4.5.5 NvDeleteRAM() .......................................................................................... 127 |
| 8.4.6 Utility Functions ................................................................................................ 128 |
| 8.4.6.1 NvInitStatic() .............................................................................................. 128 |
| 8.4.6.2 NvInit() ....................................................................................................... 129 |
| 8.4.6.3 NvReadReserved() ..................................................................................... 129 |
| 8.4.6.4 NvWriteReserved() ..................................................................................... 130 |
| 8.4.6.5 NvReadPersistent() .................................................................................... 130 |
| 8.4.6.6 NvIsPlatformPersistentHandle() .................................................................. 131 |
| 8.4.6.7 NvIsOwnerPersistentHandle() ..................................................................... 131 |
| 8.4.6.8 NvNextIndex() ............................................................................................ 131 |
| 8.4.6.9 NvNextEvict() ............................................................................................. 132 |
| 8.4.6.10 NvFindHandle() .......................................................................................... 132 |
| 8.4.6.11 NvPowerOn() .............................................................................................. 133 |
| 8.4.6.12 NvStateSave() ............................................................................................ 133 |
| 8.4.6.13 NvEntityStartup() ........................................................................................ 134 |
| 8.4.7 NV Access Functions ....................................................................................... 135 |
| 8.4.7.1 Introduction ................................................................................................ 135 |
| 8.4.7.2 NvIsUndefinedIndex() ................................................................................. 135 |
| 8.4.7.3 NvIndexIsAccessible() ................................................................................ 136 |
| 8.4.7.4 NvIsUndefinedEvictHandle() ....................................................................... 137 |
| 8.4.7.5 NvGetEvictObject() ..................................................................................... 138 |
| 8.4.7.6 NvGetIndexInfo() ........................................................................................ 138 |
| 8.4.7.7 NvInitialCounter() ....................................................................................... 139 |
| 8.4.7.8 NvGetIndexData() ....................................................................................... 139 |
| 8.4.7.9 NvGetIntIndexData() ................................................................................... 140 |
| 8.4.7.10 NvWriteIndexInfo() ...................................................................................... 141 |
| 8.4.7.11 NvWriteIndexData() .................................................................................... 142 |
| 8.4.7.12 NvGetName() ............................................................................................. 143 |
| 8.4.7.13 NvDefineIndex().......................................................................................... 143 |
| |
| Family "2.0" TCG Published Page vii |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.4.7.14 NvAddEvictObject() .................................................................................... 144 |
| 8.4.7.15 NvDeleteEntity() ......................................................................................... 145 |
| 8.4.7.16 NvFlushHierarchy() ..................................................................................... 146 |
| 8.4.7.17 NvSetGlobalLock()...................................................................................... 147 |
| 8.4.7.18 InsertSort() ................................................................................................. 148 |
| 8.4.7.19 NvCapGetPersistent() ................................................................................. 149 |
| 8.4.7.20 NvCapGetIndex() ........................................................................................ 150 |
| 8.4.7.21 NvCapGetIndexNumber() ............................................................................ 151 |
| 8.4.7.22 NvCapGetPersistentNumber() .................................................................... 151 |
| 8.4.7.23 NvCapGetPersistentAvail() ......................................................................... 151 |
| 8.4.7.24 NvCapGetCounterNumber() ........................................................................ 151 |
| 8.4.7.25 NvCapGetCounterAvail() ............................................................................ 152 |
| 8.5 Object.c................................................................................................................... 153 |
| 8.5.1 Introduction ...................................................................................................... 153 |
| 8.5.2 Includes and Data Definitions ........................................................................... 153 |
| 8.5.3 Functions ......................................................................................................... 153 |
| 8.5.3.1 ObjectStartup() ........................................................................................... 153 |
| 8.5.3.2 ObjectCleanupEvict() .................................................................................. 153 |
| 8.5.3.3 ObjectIsPresent() ....................................................................................... 154 |
| 8.5.3.4 ObjectIsSequence() .................................................................................... 154 |
| 8.5.3.5 ObjectGet() ................................................................................................. 155 |
| 8.5.3.6 ObjectGetName() ........................................................................................ 155 |
| 8.5.3.7 ObjectGetNameAlg() ................................................................................... 155 |
| 8.5.3.8 ObjectGetQualifiedName() .......................................................................... 156 |
| 8.5.3.9 ObjectDataGetHierarchy() .......................................................................... 156 |
| 8.5.3.10 ObjectGetHierarchy() .................................................................................. 156 |
| 8.5.3.11 ObjectAllocateSlot() .................................................................................... 157 |
| 8.5.3.12 ObjectLoad()............................................................................................... 157 |
| 8.5.3.13 AllocateSequenceSlot() .............................................................................. 160 |
| 8.5.3.14 ObjectCreateHMACSequence() .................................................................. 160 |
| 8.5.3.15 ObjectCreateHashSequence() .................................................................... 161 |
| 8.5.3.16 ObjectCreateEventSequence() ................................................................... 161 |
| 8.5.3.17 ObjectTerminateEvent() .............................................................................. 162 |
| 8.5.3.18 ObjectContextLoad() ................................................................................... 163 |
| 8.5.3.19 ObjectFlush() .............................................................................................. 163 |
| 8.5.3.20 ObjectFlushHierarchy() ............................................................................... 163 |
| 8.5.3.21 ObjectLoadEvict() ....................................................................................... 164 |
| 8.5.3.22 ObjectComputeName() ............................................................................... 165 |
| 8.5.3.23 ObjectComputeQualifiedName() ................................................................. 166 |
| 8.5.3.24 ObjectDataIsStorage() ................................................................................ 166 |
| 8.5.3.25 ObjectIsStorage() ....................................................................................... 167 |
| 8.5.3.26 ObjectCapGetLoaded() ............................................................................... 167 |
| 8.5.3.27 ObjectCapGetTransientAvail() .................................................................... 168 |
| 8.6 PCR.c ..................................................................................................................... 168 |
| 8.6.1 Introduction ...................................................................................................... 168 |
| 8.6.2 Includes, Defines, and Data Definitions ............................................................ 168 |
| 8.6.3 Functions ......................................................................................................... 169 |
| 8.6.3.1 PCRBelongsAuthGroup() ............................................................................ 169 |
| 8.6.3.2 PCRBelongsPolicyGroup() .......................................................................... 169 |
| 8.6.3.3 PCRBelongsTCBGroup() ............................................................................ 170 |
| 8.6.3.4 PCRPolicyIsAvailable() ............................................................................... 170 |
| 8.6.3.5 PCRGetAuthValue() .................................................................................... 171 |
| 8.6.3.6 PCRGetAuthPolicy() ................................................................................... 171 |
| 8.6.3.7 PCRSimStart() ............................................................................................ 172 |
| 8.6.3.8 GetSavedPcrPointer() ................................................................................. 172 |
| |
| Page viii TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.6.3.9 PcrIsAllocated() .......................................................................................... 173 |
| 8.6.3.10 GetPcrPointer() .......................................................................................... 174 |
| 8.6.3.11 IsPcrSelected() ........................................................................................... 175 |
| 8.6.3.12 FilterPcr() ................................................................................................... 175 |
| 8.6.3.13 PcrDrtm() .................................................................................................... 176 |
| 8.6.3.14 PCRStartup() .............................................................................................. 176 |
| 8.6.3.15 PCRStateSave() ......................................................................................... 177 |
| 8.6.3.16 PCRIsStateSaved() .................................................................................... 178 |
| 8.6.3.17 PCRIsResetAllowed() ................................................................................. 179 |
| 8.6.3.18 PCRChanged() ........................................................................................... 179 |
| 8.6.3.19 PCRIsExtendAllowed() ............................................................................... 179 |
| 8.6.3.20 PCRExtend() .............................................................................................. 180 |
| 8.6.3.21 PCRComputeCurrentDigest() ...................................................................... 181 |
| 8.6.3.22 PCRRead() ................................................................................................. 181 |
| 8.6.3.23 PcrWrite() ................................................................................................... 183 |
| 8.6.3.24 PCRAllocate() ............................................................................................. 183 |
| 8.6.3.25 PCRSetValue() ........................................................................................... 185 |
| 8.6.3.26 PCRResetDynamics ................................................................................... 185 |
| 8.6.3.27 PCRCapGetAllocation() .............................................................................. 186 |
| 8.6.3.28 PCRSetSelectBit() ...................................................................................... 186 |
| 8.6.3.29 PCRGetProperty() ...................................................................................... 187 |
| 8.6.3.30 PCRCapGetProperties() ............................................................................. 188 |
| 8.6.3.31 PCRCapGetHandles() ................................................................................. 189 |
| 8.7 PP.c ........................................................................................................................ 190 |
| 8.7.1 Introduction ...................................................................................................... 190 |
| 8.7.2 Includes ........................................................................................................... 190 |
| 8.7.3 Functions ......................................................................................................... 190 |
| 8.7.3.1 PhysicalPresencePreInstall_Init() ............................................................... 190 |
| 8.7.3.2 PhysicalPresenceCommandSet() ................................................................ 191 |
| 8.7.3.3 PhysicalPresenceCommandClear() ............................................................. 191 |
| 8.7.3.4 PhysicalPresenceIsRequired() .................................................................... 192 |
| 8.7.3.5 PhysicalPresenceCapGetCCList() .............................................................. 192 |
| 8.8 Session.c ................................................................................................................ 193 |
| 8.8.1 Introduction ...................................................................................................... 193 |
| 8.8.2 Includes, Defines, and Local Variables ............................................................. 194 |
| 8.8.3 File Scope Function -- ContextIdSetOldest() ..................................................... 194 |
| 8.8.4 Startup Function -- SessionStartup() ................................................................ 195 |
| 8.8.5 Access Functions ............................................................................................. 196 |
| 8.8.5.1 SessionIsLoaded() ...................................................................................... 196 |
| 8.8.5.2 SessionIsSaved() ....................................................................................... 196 |
| 8.8.5.3 SessionPCRValueIsCurrent() ...................................................................... 197 |
| 8.8.5.4 SessionGet() .............................................................................................. 197 |
| 8.8.6 Utility Functions ................................................................................................ 198 |
| 8.8.6.1 ContextIdSessionCreate() ........................................................................... 198 |
| 8.8.6.2 SessionCreate().......................................................................................... 199 |
| 8.8.6.3 SessionContextSave() ................................................................................ 201 |
| 8.8.6.4 SessionContextLoad() ................................................................................ 202 |
| 8.8.6.5 SessionFlush() ........................................................................................... 204 |
| 8.8.6.6 SessionComputeBoundEntity() ................................................................... 204 |
| 8.8.6.7 SessionInitPolicyData()............................................................................... 205 |
| 8.8.6.8 SessionResetPolicyData() .......................................................................... 206 |
| 8.8.6.9 SessionCapGetLoaded() ............................................................................. 206 |
| 8.8.6.10 SessionCapGetSaved() .............................................................................. 207 |
| 8.8.6.11 SessionCapGetLoadedNumber() ................................................................ 208 |
| |
| Family "2.0" TCG Published Page ix |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.8.6.12 SessionCapGetLoadedAvail() ..................................................................... 208 |
| 8.8.6.13 SessionCapGetActiveNumber() .................................................................. 209 |
| 8.8.6.14 SessionCapGetActiveAvail() ....................................................................... 209 |
| 8.9 Time.c ..................................................................................................................... 209 |
| 8.9.1 Introduction ...................................................................................................... 209 |
| 8.9.2 Includes ........................................................................................................... 209 |
| 8.9.3 Functions ......................................................................................................... 210 |
| 8.9.3.1 TimePowerOn() .......................................................................................... 210 |
| 8.9.3.2 TimeStartup() ............................................................................................. 210 |
| 8.9.3.3 TimeUpdateToCurrent() .............................................................................. 211 |
| 8.9.3.4 TimeSetAdjustRate() .................................................................................. 212 |
| 8.9.3.5 TimeGetRange() ......................................................................................... 212 |
| 8.9.3.6 TimeFillInfo ................................................................................................ 213 |
| 9 Support ............................................................................................................................ 214 |
| 9.1 AlgorithmCap.c ........................................................................................................ 214 |
| 9.1.1 Description ....................................................................................................... 214 |
| 9.1.2 Includes and Defines ........................................................................................ 214 |
| 9.1.3 AlgorithmCapGetImplemented() ........................................................................ 215 |
| 9.2 Bits.c ....................................................................................................................... 217 |
| 9.2.1 Introduction ...................................................................................................... 217 |
| 9.2.2 Includes ........................................................................................................... 217 |
| 9.2.3 Functions ......................................................................................................... 217 |
| 9.2.3.1 BitIsSet() .................................................................................................... 217 |
| 9.2.3.2 BitSet() ....................................................................................................... 217 |
| 9.2.3.3 BitClear() .................................................................................................... 218 |
| 9.3 CommandAttributeData.c ........................................................................................ 218 |
| 9.4 CommandCodeAttributes.c ...................................................................................... 224 |
| 9.4.1 Introduction ...................................................................................................... 224 |
| 9.4.2 Includes and Defines ........................................................................................ 224 |
| 9.4.3 Command Attribute Functions .......................................................................... 224 |
| 9.4.3.1 CommandAuthRole() .................................................................................. 224 |
| 9.4.3.2 CommandIsImplemented() .......................................................................... 224 |
| 9.4.3.3 CommandGetAttribute() .............................................................................. 225 |
| 9.4.3.4 EncryptSize() .............................................................................................. 225 |
| 9.4.3.5 DecryptSize().............................................................................................. 226 |
| 9.4.3.6 IsSessionAllowed() ..................................................................................... 226 |
| 9.4.3.7 IsHandleInResponse() ................................................................................ 226 |
| 9.4.3.8 IsWriteOperation() ...................................................................................... 227 |
| 9.4.3.9 IsReadOperation() ...................................................................................... 227 |
| 9.4.3.10 CommandCapGetCCList() .......................................................................... 227 |
| 9.5 DRTM.c ................................................................................................................... 228 |
| 9.5.1 Description ....................................................................................................... 228 |
| 9.5.2 Includes ........................................................................................................... 228 |
| 9.5.3 Functions ......................................................................................................... 229 |
| 9.5.3.1 Signal_Hash_Start() ................................................................................... 229 |
| 9.5.3.2 Signal_Hash_Data() ................................................................................... 229 |
| 9.5.3.3 Signal_Hash_End() ..................................................................................... 229 |
| 9.6 Entity.c .................................................................................................................... 229 |
| 9.6.1 Description ....................................................................................................... 229 |
| 9.6.2 Includes ........................................................................................................... 229 |
| |
| Page x TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.6.3 Functions ......................................................................................................... 230 |
| 9.6.3.1 EntityGetLoadStatus() ................................................................................ 230 |
| 9.6.3.2 EntityGetAuthValue() .................................................................................. 232 |
| 9.6.3.3 EntityGetAuthPolicy() ................................................................................. 233 |
| 9.6.3.4 EntityGetName() ......................................................................................... 234 |
| 9.6.3.5 EntityGetHierarchy() ................................................................................... 235 |
| 9.7 Global.c................................................................................................................... 236 |
| 9.7.1 Description ....................................................................................................... 236 |
| 9.7.2 Includes and Defines ........................................................................................ 236 |
| 9.7.3 Global Data Values .......................................................................................... 236 |
| 9.7.4 Private Values .................................................................................................. 237 |
| 9.7.4.1 SessionProcess.c ....................................................................................... 237 |
| 9.7.4.2 DA.c ........................................................................................................... 237 |
| 9.7.4.3 NV.c ........................................................................................................... 237 |
| 9.7.4.4 Object.c ...................................................................................................... 238 |
| 9.7.4.5 PCR.c ......................................................................................................... 238 |
| 9.7.4.6 Session.c .................................................................................................... 238 |
| 9.7.4.7 Manufacture.c ............................................................................................. 238 |
| 9.7.4.8 Power.c ...................................................................................................... 238 |
| 9.7.4.9 MemoryLib.c ............................................................................................... 238 |
| 9.7.4.10 SelfTest.c ................................................................................................... 238 |
| 9.7.4.11 TpmFail.c ................................................................................................... 238 |
| 9.8 Handle.c .................................................................................................................. 239 |
| 9.8.1 Description ....................................................................................................... 239 |
| 9.8.2 Includes ........................................................................................................... 239 |
| 9.8.3 Functions ......................................................................................................... 239 |
| 9.8.3.1 HandleGetType() ........................................................................................ 239 |
| 9.8.3.2 NextPermanentHandle() ............................................................................. 239 |
| 9.8.3.3 PermanentCapGetHandles() ....................................................................... 240 |
| 9.9 Locality.c ................................................................................................................. 241 |
| 9.9.1 Includes ........................................................................................................... 241 |
| 9.9.2 LocalityGetAttributes() ...................................................................................... 241 |
| 9.10 Manufacture.c ......................................................................................................... 241 |
| 9.10.1 Description ....................................................................................................... 241 |
| 9.10.2 Includes and Data Definitions ........................................................................... 241 |
| 9.10.3 Functions ......................................................................................................... 242 |
| 9.10.3.1 TPM_Manufacture() .................................................................................... 242 |
| 9.10.3.2 TPM_TearDown() ....................................................................................... 243 |
| 9.11 Marshal.c ................................................................................................................ 244 |
| 9.11.1 Introduction ...................................................................................................... 244 |
| 9.11.2 Unmarshal and Marshal a Value ....................................................................... 244 |
| 9.11.3 Unmarshal and Marshal a Union ....................................................................... 245 |
| 9.11.4 Unmarshal and Marshal a Structure .................................................................. 247 |
| 9.11.5 Unmarshal and Marshal an Array ..................................................................... 249 |
| 9.11.6 TPM2B Handling .............................................................................................. 251 |
| 9.12 MemoryLib.c............................................................................................................ 252 |
| 9.12.1 Description ....................................................................................................... 252 |
| 9.12.2 Includes and Data Definitions ........................................................................... 252 |
| 9.12.3 Functions on BYTE Arrays................................................................................ 252 |
| |
| |
| Family "2.0" TCG Published Page xi |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.12.3.1 MemoryMove()............................................................................................ 252 |
| 9.12.3.2 MemoryCopy() ............................................................................................ 253 |
| 9.12.3.3 MemoryEqual() ........................................................................................... 253 |
| 9.12.3.4 MemoryCopy2B() ........................................................................................ 253 |
| 9.12.3.5 MemoryConcat2B() ..................................................................................... 254 |
| 9.12.3.6 Memory2BEqual() ....................................................................................... 254 |
| 9.12.3.7 MemorySet() ............................................................................................... 255 |
| 9.12.3.8 MemoryGetActionInputBuffer().................................................................... 255 |
| 9.12.3.9 MemoryGetActionOutputBuffer() ................................................................. 255 |
| 9.12.3.10 MemoryGetResponseBuffer() ...................................................................... 256 |
| 9.12.3.11 MemoryRemoveTrailingZeros() ................................................................... 256 |
| 9.13 Power.c ................................................................................................................... 256 |
| 9.13.1 Description ....................................................................................................... 256 |
| 9.13.2 Includes and Data Definitions ........................................................................... 256 |
| 9.13.3 Functions ......................................................................................................... 257 |
| 9.13.3.1 TPMInit() .................................................................................................... 257 |
| 9.13.3.2 TPMRegisterStartup() ................................................................................. 257 |
| 9.13.3.3 TPMIsStarted() ........................................................................................... 257 |
| 9.14 PropertyCap.c ......................................................................................................... 257 |
| 9.14.1 Description ....................................................................................................... 257 |
| 9.14.2 Includes ........................................................................................................... 258 |
| 9.14.3 Functions ......................................................................................................... 258 |
| 9.14.3.1 PCRGetProperty() ...................................................................................... 258 |
| 9.14.3.2 TPMCapGetProperties() ............................................................................. 264 |
| 9.15 TpmFail.c ................................................................................................................ 265 |
| 9.15.1 Includes, Defines, and Types ........................................................................... 265 |
| 9.15.2 Typedefs .......................................................................................................... 265 |
| 9.15.3 Local Functions ................................................................................................ 266 |
| 9.15.3.1 MarshalUint16() .......................................................................................... 266 |
| 9.15.3.2 MarshalUint32() .......................................................................................... 266 |
| 9.15.3.3 UnmarshalHeader() .................................................................................... 267 |
| 9.15.4 Public Functions ............................................................................................... 267 |
| 9.15.4.1 SetForceFailureMode() ............................................................................... 267 |
| 9.15.4.2 TpmFail() .................................................................................................... 267 |
| 9.15.5 TpmFailureMode .............................................................................................. 268 |
| 10 Cryptographic Functions ................................................................................................... 272 |
| 10.1 Introduction ............................................................................................................. 272 |
| 10.2 CryptUtil.c ............................................................................................................... 272 |
| 10.2.1 Includes ........................................................................................................... 272 |
| 10.2.2 TranslateCryptErrors() ...................................................................................... 272 |
| 10.2.3 Random Number Generation Functions ............................................................ 273 |
| 10.2.3.1 CryptDrbgGetPutState() .............................................................................. 273 |
| 10.2.3.2 CryptStirRandom() ...................................................................................... 273 |
| 10.2.3.3 CryptGenerateRandom() ............................................................................. 273 |
| 10.2.4 Hash/HMAC Functions ..................................................................................... 274 |
| 10.2.4.1 CryptGetContextAlg() ................................................................................. 274 |
| 10.2.4.2 CryptStartHash()......................................................................................... 274 |
| 10.2.4.3 CryptStartHashSequence() ......................................................................... 275 |
| 10.2.4.4 CryptStartHMAC() ....................................................................................... 275 |
| |
| Page xii TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 10.2.4.5 CryptStartHMACSequence() ....................................................................... 276 |
| 10.2.4.6 CryptStartHMAC2B() .................................................................................. 276 |
| 10.2.4.7 CryptStartHMACSequence2B() ................................................................... 277 |
| 10.2.4.8 CryptUpdateDigest() ................................................................................... 277 |
| 10.2.4.9 CryptUpdateDigest2B() ............................................................................... 278 |
| 10.2.4.10 CryptUpdateDigestInt() ............................................................................... 278 |
| 10.2.4.11 CryptCompleteHash() ................................................................................. 279 |
| 10.2.4.12 CryptCompleteHash2B() ............................................................................. 279 |
| 10.2.4.13 CryptHashBlock() ....................................................................................... 280 |
| 10.2.4.14 CryptCompleteHMAC() ............................................................................... 280 |
| 10.2.4.15 CryptCompleteHMAC2B() ........................................................................... 281 |
| 10.2.4.16 CryptHashStateImportExport() .................................................................... 281 |
| 10.2.4.17 CryptGetHashDigestSize() .......................................................................... 281 |
| 10.2.4.18 CryptGetHashBlockSize() ........................................................................... 282 |
| 10.2.4.19 CryptGetHashAlgByIndex() ......................................................................... 282 |
| 10.2.4.20 CryptSignHMAC() ....................................................................................... 282 |
| 10.2.4.21 CryptHMACVerifySignature() ...................................................................... 283 |
| 10.2.4.22 CryptGenerateKeyedHash() ........................................................................ 283 |
| 10.2.4.23 CryptKDFa() ............................................................................................... 285 |
| 10.2.4.24 CryptKDFaOnce() ....................................................................................... 285 |
| 10.2.4.25 KDFa() ....................................................................................................... 285 |
| 10.2.4.26 CryptKDFe() ............................................................................................... 286 |
| 10.2.5 RSA Functions ................................................................................................. 286 |
| 10.2.5.1 BuildRSA() ................................................................................................. 286 |
| 10.2.5.2 CryptTestKeyRSA() .................................................................................... 286 |
| 10.2.5.3 CryptGenerateKeyRSA() ............................................................................. 287 |
| 10.2.5.4 CryptLoadPrivateRSA() .............................................................................. 288 |
| 10.2.5.5 CryptSelectRSAScheme() ........................................................................... 288 |
| 10.2.5.6 CryptDecryptRSA() ..................................................................................... 289 |
| 10.2.5.7 CryptEncryptRSA() ..................................................................................... 291 |
| 10.2.5.8 CryptSignRSA() .......................................................................................... 292 |
| 10.2.5.9 CryptRSAVerifySignature() ......................................................................... 293 |
| 10.2.6 ECC Functions ................................................................................................. 294 |
| 10.2.6.1 CryptEccGetCurveDataPointer() ................................................................. 294 |
| 10.2.6.2 CryptEccGetKeySizeInBits() ....................................................................... 294 |
| 10.2.6.3 CryptEccGetKeySizeBytes() ....................................................................... 294 |
| 10.2.6.4 CryptEccGetParameter()............................................................................. 294 |
| 10.2.6.5 CryptGetCurveSignScheme() ...................................................................... 295 |
| 10.2.6.6 CryptEccIsPointOnCurve() .......................................................................... 295 |
| 10.2.6.7 CryptNewEccKey() ..................................................................................... 296 |
| 10.2.6.8 CryptEccPointMultiply() .............................................................................. 296 |
| 10.2.6.9 CryptGenerateKeyECC() ............................................................................ 297 |
| 10.2.6.10 CryptSignECC() .......................................................................................... 297 |
| 10.2.6.11 CryptECCVerifySignature() ......................................................................... 298 |
| 10.2.6.12 CryptGenerateR() ....................................................................................... 299 |
| 10.2.6.13 CryptCommit() ............................................................................................ 301 |
| 10.2.6.14 CryptEndCommit() ...................................................................................... 301 |
| 10.2.6.15 CryptCommitCompute() .............................................................................. 301 |
| 10.2.6.16 CryptEccGetParameters() ........................................................................... 302 |
| 10.2.6.17 CryptIsSchemeAnonymous() ....................................................................... 303 |
| 10.2.7 Symmetric Functions ........................................................................................ 303 |
| 10.2.7.1 ParmDecryptSym() ..................................................................................... 303 |
| 10.2.7.2 ParmEncryptSym() ..................................................................................... 304 |
| 10.2.7.3 CryptGenerateNewSymmetric() .................................................................. 305 |
| 10.2.7.4 CryptGenerateKeySymmetric() ................................................................... 306 |
| |
| Family "2.0" TCG Published Page xiii |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 10.2.7.5 CryptXORObfuscation() .............................................................................. 307 |
| 10.2.8 Initialization and shut down .............................................................................. 307 |
| 10.2.8.1 CryptInitUnits() ........................................................................................... 307 |
| 10.2.8.2 CryptStopUnits() ......................................................................................... 308 |
| 10.2.8.3 CryptUtilStartup()........................................................................................ 308 |
| 10.2.9 Algorithm-Independent Functions ..................................................................... 309 |
| 10.2.9.1 Introduction ................................................................................................ 309 |
| 10.2.9.2 CryptIsAsymAlgorithm() .............................................................................. 309 |
| 10.2.9.3 CryptGetSymmetricBlockSize() ................................................................... 309 |
| 10.2.9.4 CryptSymmetricEncrypt() ............................................................................ 310 |
| 10.2.9.5 CryptSymmetricDecrypt() ............................................................................ 311 |
| 10.2.9.6 CryptSecretEncrypt() .................................................................................. 313 |
| 10.2.9.7 CryptSecretDecrypt() .................................................................................. 315 |
| 10.2.9.8 CryptParameterEncryption() ....................................................................... 318 |
| 10.2.9.9 CryptParameterDecryption() ....................................................................... 319 |
| 10.2.9.10 CryptComputeSymmetricUnique() ............................................................... 320 |
| 10.2.9.11 CryptComputeSymValue() .......................................................................... 321 |
| 10.2.9.12 CryptCreateObject() ................................................................................... 321 |
| 10.2.9.13 CryptObjectIsPublicConsistent() ................................................................. 324 |
| 10.2.9.14 CryptObjectPublicPrivateMatch() ................................................................ 325 |
| 10.2.9.15 CryptGetSignHashAlg() .............................................................................. 326 |
| 10.2.9.16 CryptIsSplitSign() ....................................................................................... 327 |
| 10.2.9.17 CryptIsSignScheme() .................................................................................. 327 |
| 10.2.9.18 CryptIsDecryptScheme() ............................................................................. 328 |
| 10.2.9.19 CryptSelectSignScheme() ........................................................................... 328 |
| 10.2.9.20 CryptSign() ................................................................................................. 330 |
| 10.2.9.21 CryptVerifySignature() ................................................................................ 331 |
| 10.2.10 Math functions .................................................................................................. 332 |
| 10.2.10.1 CryptDivide() .............................................................................................. 332 |
| 10.2.10.2 CryptCompare() .......................................................................................... 333 |
| 10.2.10.3 CryptCompareSigned() ............................................................................... 333 |
| 10.2.10.4 CryptGetTestResult .................................................................................... 333 |
| 10.2.11 Capability Support ............................................................................................ 334 |
| 10.2.11.1 CryptCapGetECCCurve() ............................................................................ 334 |
| 10.2.11.2 CryptCapGetEccCurveNumber() ................................................................. 335 |
| 10.2.11.3 CryptAreKeySizesConsistent() .................................................................... 335 |
| 10.2.11.4 CryptAlgSetImplemented() .......................................................................... 336 |
| 10.3 Ticket.c ................................................................................................................... 336 |
| 10.3.1 Introduction ...................................................................................................... 336 |
| 10.3.2 Includes ........................................................................................................... 336 |
| 10.3.3 Functions ......................................................................................................... 336 |
| 10.3.3.1 TicketIsSafe() ............................................................................................. 336 |
| 10.3.3.2 TicketComputeVerified() ............................................................................. 337 |
| 10.3.3.3 TicketComputeAuth() .................................................................................. 337 |
| 10.3.3.4 TicketComputeHashCheck() ....................................................................... 338 |
| 10.3.3.5 TicketComputeCreation() ............................................................................ 339 |
| 10.4 CryptSelfTest.c ....................................................................................................... 339 |
| 10.4.1 Introduction ...................................................................................................... 339 |
| 10.4.2 Functions ......................................................................................................... 340 |
| 10.4.2.1 RunSelfTest() ............................................................................................. 340 |
| 10.4.2.2 CryptSelfTest() ........................................................................................... 340 |
| |
| Page xiv TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 10.4.2.3 CryptIncrementalSelfTest() ......................................................................... 341 |
| 10.4.2.4 CryptInitializeToTest() ................................................................................ 342 |
| 10.4.2.5 CryptTestAlgorithm() .................................................................................. 342 |
| Annex A (informative) Implementation Dependent .................................................................. 344 |
| A.1 Introduction ............................................................................................................. 344 |
| A.2 Implementation.h ..................................................................................................... 344 |
| Annex B (informative) Cryptographic Library Interface ............................................................ 359 |
| B.1 Introduction ............................................................................................................. 359 |
| B.2 Integer Format ........................................................................................................ 359 |
| B.3 CryptoEngine.h ....................................................................................................... 359 |
| B.3.1. Introduction ...................................................................................................... 359 |
| B.3.2. General Purpose Macros .................................................................................. 360 |
| B.3.3. Self-test ........................................................................................................... 360 |
| B.3.4. Hash-related Structures .................................................................................... 360 |
| B.3.5. Asymmetric Structures and Values ................................................................... 362 |
| B.3.5.1. ECC-related Structures ............................................................................... 362 |
| B.3.5.2. RSA-related Structures ............................................................................... 362 |
| B.3.6. Miscelaneous ................................................................................................... 362 |
| B.4 OsslCryptoEngine.h ................................................................................................ 364 |
| B.4.1. Introduction ...................................................................................................... 364 |
| B.4.2. Defines ............................................................................................................. 364 |
| B.5 MathFunctions.c ...................................................................................................... 365 |
| B.5.1. Introduction ...................................................................................................... 365 |
| B.5.2. Externally Accessible Functions ....................................................................... 365 |
| B.5.2.1. _math__Normalize2B() ............................................................................... 365 |
| B.5.2.2. _math__Denormalize2B() ........................................................................... 366 |
| B.5.2.3. _math__sub() ............................................................................................. 366 |
| B.5.2.4. _math__Inc() .............................................................................................. 367 |
| B.5.2.5. _math__Dec() ............................................................................................. 368 |
| B.5.2.6. _math__Mul() ............................................................................................. 368 |
| B.5.2.7. _math__Div() .............................................................................................. 369 |
| B.5.2.8. _math__uComp() ........................................................................................ 370 |
| B.5.2.9. _math__Comp() .......................................................................................... 371 |
| B.5.2.10. _math__ModExp ......................................................................................... 372 |
| B.5.2.11. _math__IsPrime() ....................................................................................... 373 |
| B.6 CpriCryptPri.c .......................................................................................................... 375 |
| B.6.1. Introduction ...................................................................................................... 375 |
| B.6.2. Includes and Locals .......................................................................................... 375 |
| B.6.3. Functions ......................................................................................................... 375 |
| B.6.3.1. TpmFail() .................................................................................................... 375 |
| B.6.3.2. FAILURE_TRAP() ....................................................................................... 375 |
| B.6.3.3. _cpri__InitCryptoUnits() .............................................................................. 375 |
| B.6.3.4. _cpri__StopCryptoUnits()............................................................................ 376 |
| B.6.3.5. _cpri__Startup() .......................................................................................... 376 |
| B.7 CpriRNG.c ............................................................................................................... 377 |
| B.7.1. Introduction ...................................................................................................... 377 |
| B.7.2. Includes ........................................................................................................... 377 |
| B.7.3. Functions ......................................................................................................... 377 |
| B.7.3.1. _cpri__RngStartup() ................................................................................... 377 |
| |
| Family "2.0" TCG Published Page xv |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.7.3.2. _cpri__DrbgGetPutState() .......................................................................... 377 |
| B.7.3.3. _cpri__StirRandom() ................................................................................... 378 |
| B.7.3.4. _cpri__GenerateRandom().......................................................................... 378 |
| B.7.3.4.1. _cpri__GenerateSeededRandom() .............................................................. 379 |
| B.8 CpriHash.c .............................................................................................................. 380 |
| B.8.1. Description ....................................................................................................... 380 |
| B.8.2. Includes, Defines, and Types ........................................................................... 380 |
| B.8.3. Static Functions................................................................................................ 380 |
| B.8.3.1. GetHashServer() ........................................................................................ 380 |
| B.8.3.2. MarshalHashState() .................................................................................... 381 |
| B.8.3.3. GetHashState()........................................................................................... 381 |
| B.8.3.4. GetHashInfoPointer() .................................................................................. 382 |
| B.8.4. Hash Functions ................................................................................................ 382 |
| B.8.4.1. _cpri__HashStartup() .................................................................................. 382 |
| B.8.4.2. _cpri__GetHashAlgByIndex() ...................................................................... 382 |
| B.8.4.3. _cpri__GetHashBlockSize() ........................................................................ 383 |
| B.8.4.4. _cpri__GetHashDER .................................................................................. 383 |
| B.8.4.5. _cpri__GetDigestSize() ............................................................................... 383 |
| B.8.4.6. _cpri__GetContextAlg() .............................................................................. 384 |
| B.8.4.7. _cpri__CopyHashState ............................................................................... 384 |
| B.8.4.8. _cpri__StartHash() ..................................................................................... 384 |
| B.8.4.9. _cpri__UpdateHash() .................................................................................. 385 |
| B.8.4.10. _cpri__CompleteHash() .............................................................................. 386 |
| B.8.4.11. _cpri__ImportExportHashState() ................................................................. 387 |
| B.8.4.12. _cpri__HashBlock() .................................................................................... 388 |
| B.8.5. HMAC Functions .............................................................................................. 389 |
| B.8.5.1. _cpri__StartHMAC ...................................................................................... 389 |
| B.8.5.2. _cpri_CompleteHMAC() .............................................................................. 390 |
| B.8.6. Mask and Key Generation Functions ................................................................ 390 |
| B.8.6.1. _crypi_MGF1() ............................................................................................ 390 |
| B.8.6.2. _cpri_KDFa() .............................................................................................. 392 |
| B.8.6.3. _cpri__KDFe() ............................................................................................ 394 |
| B.9 CpriHashData.c ....................................................................................................... 396 |
| B.10 CpriMisc.c ............................................................................................................... 397 |
| B.10.1. Includes ........................................................................................................... 397 |
| B.10.2. Functions ......................................................................................................... 397 |
| B.10.2.1. BnTo2B() .................................................................................................... 397 |
| B.10.2.2. Copy2B() .................................................................................................... 397 |
| B.10.2.3. BnFrom2B() ................................................................................................ 398 |
| B.11 CpriSym.c ............................................................................................................... 399 |
| B.11.1. Introduction ...................................................................................................... 399 |
| B.11.2. Includes, Defines, and Typedefs ....................................................................... 399 |
| B.11.3. Utility Functions ................................................................................................ 399 |
| B.11.3.1. _cpri_SymStartup() ..................................................................................... 399 |
| B.11.3.2. _cpri__GetSymmetricBlockSize() ................................................................ 399 |
| B.11.4. AES Encryption ................................................................................................ 400 |
| B.11.4.1. _cpri__AESEncryptCBC() ........................................................................... 400 |
| B.11.4.2. _cpri__AESDecryptCBC() ........................................................................... 401 |
| B.11.4.3. _cpri__AESEncryptCFB() ........................................................................... 402 |
| |
| Page xvi TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| B.11.4.4. _cpri__AESDecryptCFB() ........................................................................... 403 |
| B.11.4.5. _cpri__AESEncryptCTR() ........................................................................... 404 |
| B.11.4.6. _cpri__AESDecryptCTR() ........................................................................... 405 |
| B.11.4.7. _cpri__AESEncryptECB() ........................................................................... 405 |
| B.11.4.8. _cpri__AESDecryptECB() ........................................................................... 406 |
| B.11.4.9. _cpri__AESEncryptOFB() ........................................................................... 406 |
| B.11.4.10. _cpri__AESDecryptOFB() ........................................................................... 407 |
| B.11.5. SM4 Encryption ................................................................................................ 408 |
| B.11.5.1. _cpri__SM4EncryptCBC() ........................................................................... 408 |
| B.11.5.2. _cpri__SM4DecryptCBC() ........................................................................... 409 |
| B.11.5.3. _cpri__SM4EncryptCFB() ........................................................................... 410 |
| B.11.5.4. _cpri__SM4DecryptCFB() ........................................................................... 410 |
| B.11.5.5. _cpri__SM4EncryptCTR() ........................................................................... 411 |
| B.11.5.6. _cpri__SM4DecryptCTR() ........................................................................... 412 |
| B.11.5.7. _cpri__SM4EncryptECB() ........................................................................... 413 |
| B.11.5.8. _cpri__SM4DecryptECB() ........................................................................... 413 |
| B.11.5.9. _cpri__SM4EncryptOFB() ........................................................................... 414 |
| B.11.5.10. _cpri__SM4DecryptOFB() ........................................................................... 415 |
| B.12 RSA Files ................................................................................................................ 416 |
| B.12.1. CpriRSA.c ........................................................................................................ 416 |
| B.12.1.1. Introduction ................................................................................................ 416 |
| B.12.1.2. Includes ...................................................................................................... 416 |
| B.12.1.3. Local Functions .......................................................................................... 416 |
| B.12.1.3.1. RsaPrivateExponent() ............................................................................ 416 |
| B.12.1.3.2. _cpri__TestKeyRSA() ............................................................................. 418 |
| B.12.1.3.3. RSAEP() ................................................................................................ 420 |
| B.12.1.3.4. RSADP() ................................................................................................ 420 |
| B.12.1.3.5. OaepEncode() ........................................................................................ 421 |
| B.12.1.3.6. OaepDecode() ........................................................................................ 423 |
| B.12.1.3.7. PKSC1v1_5Encode() .............................................................................. 425 |
| B.12.1.3.8. RSAES_Decode() ................................................................................... 425 |
| B.12.1.3.9. PssEncode() ........................................................................................... 426 |
| B.12.1.3.10. PssDecode() ........................................................................................ 427 |
| B.12.1.3.11. PKSC1v1_5SignEncode() ..................................................................... 429 |
| B.12.1.3.12. RSASSA_Decode()............................................................................... 430 |
| B.12.1.4. Externally Accessible Functions .................................................................. 431 |
| B.12.1.4.1. _cpri__RsaStartup() ............................................................................... 431 |
| B.12.1.4.2. _cpri__EncryptRSA() .............................................................................. 431 |
| B.12.1.4.3. _cpri__DecryptRSA() .............................................................................. 433 |
| B.12.1.4.4. _cpri__SignRSA() ................................................................................... 434 |
| B.12.1.4.5. _cpri__ValidateSignatureRSA() .............................................................. 435 |
| B.12.1.4.6. _cpri__GenerateKeyRSA() ..................................................................... 435 |
| B.12.2. Alternative RSA Key Generation ....................................................................... 440 |
| B.12.2.1. Introduction ................................................................................................ 440 |
| B.12.2.2. RSAKeySieve.h .......................................................................................... 440 |
| B.12.2.3. RSAKeySieve.c .......................................................................................... 443 |
| B.12.2.3.1. Includes and defines .............................................................................. 443 |
| B.12.2.3.2. Bit Manipulation Functions ..................................................................... 443 |
| B.12.2.3.3. Miscellaneous Functions ........................................................................ 445 |
| B.12.2.3.4. Public Function ...................................................................................... 455 |
| B.12.2.4. RSAData.c .................................................................................................. 459 |
| B.13 Elliptic Curve Files .................................................................................................. 471 |
| Family "2.0" TCG Published Page xvii |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.13.1. CpriDataEcc.h .................................................................................................. 471 |
| B.13.2. CpriDataEcc.c .................................................................................................. 472 |
| B.13.3. CpriECC.c ........................................................................................................ 479 |
| B.13.3.1. Includes and Defines .................................................................................. 479 |
| B.13.3.2. Functions .................................................................................................... 479 |
| B.13.3.2.1. _cpri__EccStartup() ................................................................................ 479 |
| B.13.3.2.2. _cpri__GetCurveIdByIndex() .................................................................. 479 |
| B.13.3.2.3. _cpri__EccGetParametersByCurveId() ................................................... 479 |
| B.13.3.2.4. Point2B() ................................................................................................ 480 |
| B.13.3.2.5. EccCurveInit() ........................................................................................ 481 |
| B.13.3.2.6. PointFrom2B() ........................................................................................ 482 |
| B.13.3.2.7. EccInitPoint2B() ..................................................................................... 482 |
| B.13.3.2.8. PointMul() .............................................................................................. 483 |
| B.13.3.2.9. GetRandomPrivate() ............................................................................... 483 |
| B.13.3.2.10. Mod2B() ............................................................................................... 484 |
| B.13.3.2.11. _cpri__EccPointMultiply ....................................................................... 484 |
| B.13.3.2.12. ClearPoint2B() ...................................................................................... 486 |
| B.13.3.2.13. _cpri__EccCommitCompute() ............................................................... 486 |
| B.13.3.2.14. _cpri__EccIsPointOnCurve() ................................................................ 489 |
| B.13.3.2.15. _cpri__GenerateKeyEcc() ..................................................................... 490 |
| B.13.3.2.16. _cpri__GetEphemeralEcc() ................................................................... 492 |
| B.13.3.2.17. SignEcdsa().......................................................................................... 492 |
| B.13.3.2.18. EcDaa() ................................................................................................ 495 |
| B.13.3.2.19. SchnorrEcc() ........................................................................................ 496 |
| B.13.3.2.20. SignSM2() ............................................................................................ 499 |
| B.13.3.2.21. _cpri__SignEcc() .................................................................................. 502 |
| B.13.3.2.22. ValidateSignatureEcdsa() ..................................................................... 502 |
| B.13.3.2.23. ValidateSignatureEcSchnorr() .............................................................. 505 |
| B.13.3.2.24. ValidateSignatueSM2Dsa() ................................................................... 506 |
| B.13.3.2.25. _cpri__ValidateSignatureEcc() ............................................................. 508 |
| B.13.3.2.26. avf1() ................................................................................................... 509 |
| B.13.3.2.27. C_2_2_MQV() ...................................................................................... 509 |
| B.13.3.2.28. avfSm2() .............................................................................................. 512 |
| B.13.3.2.29. C_2_2_ECDH() .................................................................................... 514 |
| B.13.3.2.30. _cpri__C_2_2_KeyExchange() ............................................................. 515 |
| Annex C (informative) Simulation Environment ....................................................................... 517 |
| C.1 Introduction ............................................................................................................. 517 |
| C.2 Cancel.c .................................................................................................................. 517 |
| C.2.1. Introduction ...................................................................................................... 517 |
| C.2.2. Includes, Typedefs, Structures, and Defines ..................................................... 517 |
| C.2.3. Functions ......................................................................................................... 517 |
| C.2.3.1. _plat__IsCanceled() ................................................................................... 517 |
| C.2.3.2. _plat__SetCancel() ..................................................................................... 517 |
| C.2.3.3. _plat__ClearCancel() .................................................................................. 518 |
| C.3 Clock.c .................................................................................................................... 519 |
| C.3.1. Introduction ...................................................................................................... 519 |
| C.3.2. Includes and Data Definitions ........................................................................... 519 |
| C.3.3. Functions ......................................................................................................... 519 |
| C.3.3.1. _plat__ClockReset() ................................................................................... 519 |
| C.3.3.2. _plat__ClockTimeFromStart() ..................................................................... 519 |
| C.3.3.3. _plat__ClockTimeElapsed() ........................................................................ 519 |
| C.3.3.4. _plat__ClockAdjustRate() ........................................................................... 520 |
| C.4 Entropy.c ................................................................................................................. 521 |
| |
| Page xviii TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| C.4.1. Includes ........................................................................................................... 521 |
| C.4.2. Local values ..................................................................................................... 521 |
| C.4.3. _plat__GetEntropy() ......................................................................................... 521 |
| C.5 LocalityPlat.c ........................................................................................................... 523 |
| C.5.1. Includes ........................................................................................................... 523 |
| C.5.2. Functions ......................................................................................................... 523 |
| C.5.2.1. _plat__LocalityGet() ................................................................................... 523 |
| C.5.2.2. _plat__LocalitySet() .................................................................................... 523 |
| C.5.2.3. _plat__IsRsaKeyCacheEnabled() ............................................................... 523 |
| C.6 NVMem.c ................................................................................................................ 524 |
| C.6.1. Introduction ...................................................................................................... 524 |
| C.6.2. Includes ........................................................................................................... 524 |
| C.6.3. Functions ......................................................................................................... 524 |
| C.6.3.1. _plat__NvErrors() ....................................................................................... 524 |
| C.6.3.2. _plat__NVEnable() ..................................................................................... 524 |
| C.6.3.3. _plat__NVDisable() .................................................................................... 525 |
| C.6.3.4. _plat__IsNvAvailable() ................................................................................ 526 |
| C.6.3.5. _plat__NvMemoryRead() ............................................................................ 526 |
| C.6.3.6. _plat__NvIsDifferent() ................................................................................. 526 |
| C.6.3.7. _plat__NvMemoryWrite() ............................................................................ 527 |
| C.6.3.8. _plat__NvMemoryMove() ............................................................................ 527 |
| C.6.3.9. _plat__NvCommit() ..................................................................................... 527 |
| C.6.3.10. _plat__SetNvAvail() .................................................................................... 528 |
| C.6.3.11. _plat__ClearNvAvail() ................................................................................. 528 |
| C.7 PowerPlat.c ............................................................................................................. 529 |
| C.7.1. Includes and Function Prototypes ..................................................................... 529 |
| C.7.2. Functions ......................................................................................................... 529 |
| C.7.2.1. _plat__Signal_PowerOn() ........................................................................... 529 |
| C.7.2.2. _plat__WasPowerLost() .............................................................................. 529 |
| C.7.2.3. _plat_Signal_Reset() .................................................................................. 529 |
| C.7.2.4. _plat__Signal_PowerOff() ........................................................................... 530 |
| C.8 Platform.h ............................................................................................................... 531 |
| C.8.1. Includes and Defines ........................................................................................ 531 |
| C.8.2. Power Functions ............................................................................................... 531 |
| C.8.2.1. _plat__Signal_PowerOn ............................................................................. 531 |
| C.8.2.2. _plat__Signal_Reset ................................................................................... 531 |
| C.8.2.3. _plat__WasPowerLost() .............................................................................. 531 |
| C.8.2.4. _plat__Signal_PowerOff() ........................................................................... 531 |
| C.8.3. Physical Presence Functions ............................................................................ 531 |
| C.8.3.1. _plat__PhysicalPresenceAsserted() ............................................................ 531 |
| C.8.3.2. _plat__Signal_PhysicalPresenceOn............................................................ 532 |
| C.8.3.3. _plat__Signal_PhysicalPresenceOff() ......................................................... 532 |
| C.8.4. Command Canceling Functions ........................................................................ 532 |
| C.8.4.1. _plat__IsCanceled() ................................................................................... 532 |
| C.8.4.2. _plat__SetCancel() ..................................................................................... 532 |
| C.8.4.3. _plat__ClearCancel() .................................................................................. 532 |
| C.8.5. NV memory functions ....................................................................................... 533 |
| C.8.5.1. _plat__NvErrors() ....................................................................................... 533 |
| C.8.5.2. _plat__NVEnable() ..................................................................................... 533 |
| |
| Family "2.0" TCG Published Page xix |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| C.8.5.3. _plat__NVDisable() .................................................................................... 533 |
| C.8.5.4. _plat__IsNvAvailable() ................................................................................ 533 |
| C.8.5.5. _plat__NvCommit() ..................................................................................... 533 |
| C.8.5.6. _plat__NvMemoryRead() ............................................................................ 534 |
| C.8.5.7. _plat__NvIsDifferent() ................................................................................. 534 |
| C.8.5.8. _plat__NvMemoryWrite() ............................................................................ 534 |
| C.8.5.9. _plat__NvMemoryMove() ............................................................................ 534 |
| C.8.5.10. _plat__SetNvAvail() .................................................................................... 535 |
| C.8.5.11. _plat__ClearNvAvail() ................................................................................. 535 |
| C.8.6. Locality Functions ............................................................................................ 535 |
| C.8.6.1. _plat__LocalityGet() ................................................................................... 535 |
| C.8.6.2. _plat__LocalitySet() .................................................................................... 535 |
| C.8.6.3. _plat__IsRsaKeyCacheEnabled() ............................................................... 535 |
| C.8.7. Clock Constants and Functions ........................................................................ 535 |
| C.8.7.1. _plat__ClockReset() ................................................................................... 536 |
| C.8.7.2. _plat__ClockTimeFromStart() ..................................................................... 536 |
| C.8.7.3. _plat__ClockTimeElapsed() ........................................................................ 536 |
| C.8.7.4. _plat__ClockAdjustRate() ........................................................................... 536 |
| C.8.8. Single Function Files ........................................................................................ 537 |
| C.8.8.1. _plat__GetEntropy() ................................................................................... 537 |
| C.9 PlatformData.h ........................................................................................................ 538 |
| C.10 PlatformData.c ........................................................................................................ 539 |
| C.10.1. Description ....................................................................................................... 539 |
| C.10.2. Includes ........................................................................................................... 539 |
| C.11 PPPlat.c .................................................................................................................. 540 |
| C.11.1. Description ....................................................................................................... 540 |
| C.11.2. Includes ........................................................................................................... 540 |
| C.11.3. Functions ......................................................................................................... 540 |
| C.11.3.1. _plat__PhysicalPresenceAsserted() ............................................................ 540 |
| C.11.3.2. _plat__Signal_PhysicalPresenceOn() ......................................................... 540 |
| C.11.3.3. _plat__Signal_PhysicalPresenceOff() ......................................................... 540 |
| C.12 Unique.c .................................................................................................................. 541 |
| C.12.1. Introduction ...................................................................................................... 541 |
| C.12.2. Includes ........................................................................................................... 541 |
| C.12.3. _plat__GetUnique() .......................................................................................... 541 |
| Annex D (informative) Remote Procedure Interface ................................................................ 542 |
| D.1 Introduction ............................................................................................................. 542 |
| D.2 TpmTcpProtocol.h ................................................................................................... 543 |
| D.2.1. Introduction ...................................................................................................... 543 |
| D.2.2. Typedefs and Defines ....................................................................................... 543 |
| D.3 TcpServer.c ............................................................................................................. 545 |
| D.3.1. Description ....................................................................................................... 545 |
| D.3.2. Includes, Locals, Defines and Function Prototypes ........................................... 545 |
| D.3.3. Functions ......................................................................................................... 545 |
| D.3.3.1. CreateSocket() ........................................................................................... 545 |
| D.3.3.2. PlatformServer() ......................................................................................... 546 |
| D.3.3.3. PlatformSvcRoutine() .................................................................................. 547 |
| D.3.3.4. PlatformSignalService() .............................................................................. 548 |
| D.3.3.5. RegularCommandService() ......................................................................... 549 |
| |
| Page xx TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| D.3.3.6. StartTcpServer() ......................................................................................... 549 |
| D.3.3.7. ReadBytes() ............................................................................................... 550 |
| D.3.3.8. WriteBytes() ............................................................................................... 550 |
| D.3.3.9. WriteUINT32() ............................................................................................ 551 |
| D.3.3.10. ReadVarBytes() .......................................................................................... 551 |
| D.3.3.11. WriteVarBytes() .......................................................................................... 552 |
| D.3.3.12. TpmServer() ............................................................................................... 552 |
| D.4 TPMCmdp.c ............................................................................................................ 555 |
| D.4.1. Description ....................................................................................................... 555 |
| D.4.2. Includes and Data Definitions ........................................................................... 555 |
| D.4.3. Functions ......................................................................................................... 555 |
| D.4.3.1. Signal_PowerOn() ...................................................................................... 555 |
| D.4.3.2. Signal_PowerOff() ...................................................................................... 556 |
| D.4.3.3. _rpc__ForceFailureMode() .......................................................................... 556 |
| D.4.3.4. _rpc__Signal_PhysicalPresenceOn() .......................................................... 556 |
| D.4.3.5. _rpc__Signal_PhysicalPresenceOff() .......................................................... 556 |
| D.4.3.6. _rpc__Signal_Hash_Start() ......................................................................... 557 |
| D.4.3.7. _rpc__Signal_Hash_Data() ......................................................................... 557 |
| D.4.3.8. _rpc__Signal_HashEnd() ............................................................................ 557 |
| D.4.3.9. _rpc__Signal_CancelOn() ........................................................................... 558 |
| D.4.3.10. _rpc__Signal_CancelOff() ........................................................................... 558 |
| D.4.3.11. _rpc__Signal_NvOn() ................................................................................. 559 |
| D.4.3.12. _rpc__Signal_NvOff() ................................................................................. 559 |
| D.4.3.13. _rpc__Shutdown() ...................................................................................... 559 |
| D.5 TPMCmds.c............................................................................................................. 560 |
| D.5.1. Description ....................................................................................................... 560 |
| D.5.2. Includes, Defines, Data Definitions, and Function Prototypes ........................... 560 |
| D.5.3. Functions ......................................................................................................... 560 |
| D.5.3.1. Usage() ...................................................................................................... 560 |
| D.5.3.2. main() ......................................................................................................... 560 |
| |
| |
| |
| |
| Family "2.0" TCG Published Page xxi |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Trusted Platform Module Library |
| Part 4: Supporting Routines |
| |
| 1 Scope |
| |
| This part contains C code that describes the algorithms and methods used by the command code in TPM |
| 2.0 Part 3. The code in this document augments TPM 2.0 Part 2 and TPM 2.0 Part 3 to provide a |
| complete description of a TPM, including the supporting framework for the code that performs the |
| command actions. |
| Any TPM 2.0 Part 4 code may be replaced by code that provides similar results when interfacing to the |
| action code in TPM 2.0 Part 3. The behavior of code in this document that is not included in an annex is |
| normative, as observed at the interfaces with TPM 2.0 Part 3 code. Code in an annex is provided for |
| completeness, that is, to allow a full implementation of the specification from the provided code. |
| The code in parts 3 and 4 is written to define the behavior of a compliant TPM. In some cases (e.g., |
| firmware update), it is not possible to provide a compliant implementation. In those cases, any |
| implementation provided by the vendor that meets the general description of the function provided in TPM |
| 2.0 Part 3 would be compliant. |
| The code in parts 3 and 4 is not written to meet any particular level of conformance nor does this |
| specification require that a TPM meet any particular level of conformance. |
| |
| |
| 2 Terms and definitions |
| |
| For the purposes of this document, the terms and definitions given in TPM 2.0 Part 1 apply. |
| |
| |
| 3 Symbols and abbreviated terms |
| |
| For the purposes of this document, the symbols and abbreviated terms given in TPM 2.0 Part 1 apply. |
| |
| |
| 4 Automation |
| |
| TPM 2.0 Part 2 and 3 are constructed so that they can be processed by an automated parser. For |
| example, TPM 2.0 Part 2 can be processed to generate header file contents such as structures, typedefs, |
| and enums. TPM 2.0 Part 3 can be processed to generate command and response marshaling and |
| unmarshaling code. |
| The automated processor is not provided to the TCG. It was used to generate the Microsoft Visual Studio |
| TPM simulator files. These files are not specification reference code, but rather design examples. |
| |
| 4.1 Configuration Parser |
| |
| The tables in the TPM 2.0 Part 2 Annexes are constructed so that they can be processed by a program. |
| The program that processes these tables in the TPM 2.0 Part 2 Annexes is called "The TPM 2.0 Part 2 |
| Configuration Parser." |
| The tables in the TPM 2.0 Part 2 Annexes determine the configuration of a TPM implementation. These |
| tables may be modified by an implementer to describe the algorithms and commands to be executed in |
| by a specific implementation as well as to set implementation limits such as the number of PCR, sizes of |
| buffers, etc. |
| The TPM 2.0 Part 2 Configuration Parser produces a set of structures and definitions that are used by the |
| TPM 2.0 Part 2 Structure Parser. |
| |
| |
| |
| Family "2.0" TCG Published Page 1 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 4.2 Structure Parser |
| |
| 4.2.1 Introduction |
| |
| The program that processes the tables in TPM 2.0 Part 2 (other than the table in the annexes) is called |
| "The TPM 2.0 Part 2 Structure Parser." |
| |
| NOTE A Perl script was used to parse the tables in TPM 2.0 Part 2 to produce the header files and unmarshaling code |
| in for the reference implementation. |
| |
| The TPM 2.0 Part 2 Structure Parser takes as input the files produced by the TPM 2.0 Part 2 |
| Configuration Parser and the same TPM 2.0 Part 2 specification that was used as input to the TPM 2.0 |
| Part 2 Configuration Parser. The TPM 2.0 Part 2 Structure Parser will generate all of the C structure |
| constant definitions that are required by the TPM interface. Additionally, the parser will generate |
| unmarshaling code for all structures passed to the TPM, and marshaling code for structures passed from |
| the TPM. |
| The unmarshaling code produced by the parser uses the prototypes defined below. The unmarshaling |
| code will perform validations of the data to ensure that it is compliant with the limitations on the data |
| imposed by the structure definition and use the response code provided in the table if not. |
| |
| EXAMPLE: The definition for a TPMI_RH_PROVISION indicates that the primitive data type is a TPM_HANDLE and the |
| only allowed values are TPM_RH_OWNER and TPM_RH_PLATFORM. The definition also indicates that the |
| TPM shall indicate TPM_RC_HANDLE if the input value is not none of these values. The unmarshaling code |
| will validate that the input value has one of those allowed values and return TPM_RC_HANDLE if not. |
| |
| The sections below describe the function prototypes for the marshaling and unmarshaling code that is |
| automatically generated by the TPM 2.0 Part 2 Structure Parser. These prototypes are described here as |
| the unmarshaling and marshaling of various types occurs in places other than when the command is |
| being parsed or the response is being built. The prototypes and the description of the interface are |
| intended to aid in the comprehension of the code that uses these auto-generated routines. |
| |
| 4.2.2 Unmarshaling Code Prototype |
| |
| 4.2.2.1 Simple Types and Structures |
| |
| The general form for the unmarshaling code for a simple type or a structure is: |
| |
| TPM_RC TYPE_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size); |
| |
| Where: |
| TYPE name of the data type or structure |
| *target location in the TPM memory into which the data from **buffer is placed |
| **buffer location in input buffer containing the most significant octet (MSO) of |
| *target |
| *size number of octets remaining in **buffer |
| When the data is successfully unmarshaled, the called routine will return TPM_RC_SUCCESS. |
| Otherwise, it will return a Format-One response code (see TPM 2.0 Part 2). |
| If the data is successfully unmarshaled, *buffer is advanced point to the first octet of the next parameter |
| in the input buffer and size is reduced by the number of octets removed from the buffer. |
| When the data type is a simple type, the parser will generate code that will unmarshal the underlying type |
| and then perform checks on the type as indicated by the type definition. |
| |
| |
| Page 2 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| When the data type is a structure, the parser will generate code that unmarshals each of the structure |
| elements in turn and performs any additional parameter checks as indicated by the data type. |
| |
| 4.2.2.2 Union Types |
| |
| When a union is defined, an extra parameter is defined for the unmarshaling code. This parameter is the |
| selector for the type. The unmarshaling code for the union will unmarshal the type indicated by the |
| selector. |
| The function prototype for a union has the form: |
| |
| TPM_RC TYPE_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size, UINT32 selector); |
| |
| where: |
| TYPE name of the union type or structure |
| *target location in the TPM memory into which the data from **buffer is placed |
| **buffer location in input buffer containing the most significant octet (MSO) of |
| *target |
| *size number of octets remaining in **buffer |
| selector union selector that determines what will be unmarshaled into *target |
| |
| |
| 4.2.2.3 Null Types |
| |
| In some cases, the structure definition allows an optional “null” value. The “null” value allows the use of |
| the same C type for the entity even though it does not always have the same members. |
| For example, the TPMI_ALG_HASH data type is used in many places. In some cases, TPM_ALG_NULL |
| is permitted and in some cases it is not. If two different data types had to be defined, the interfaces and |
| code would become more complex because of the number of cast operations that would be necessary. |
| Rather than encumber the code, the “null” value is defined and the unmarshaling code is given a flag to |
| indicate if this instance of the type accepts the “null” parameter or not. When the data type has a “null” |
| value, the function prototype is |
| |
| TPM_RC TYPE_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size, bool flag); |
| |
| The parser detects when the type allows a “null” value and will always include flag in any call to |
| unmarshal that type. |
| |
| 4.2.2.4 Arrays |
| |
| Any data type may be included in an array. The function prototype use to unmarshal an array for a TYPE is |
| |
| TPM_RC TYPE_Array_Unmarshal(TYPE *target, BYTE **buffer, INT32 *size,INT32 count); |
| |
| The generated code for an array uses a count-limited loop within which it calls the unmarshaling code for |
| TYPE. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 3 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 4.2.3 Marshaling Code Function Prototypes |
| |
| 4.2.3.1 Simple Types and Structures |
| |
| The general form for the unmarshaling code for a simple type or a structure is: |
| |
| UINT16 TYPE_Marshal(TYPE *source, BYTE **buffer, INT32 *size); |
| |
| Where: |
| TYPE name of the data type or structure |
| *source location in the TPM memory containing the value that is to be marshaled |
| in to the designated buffer |
| **buffer location in the output buffer where the first octet of the TYPE is to be |
| placed |
| *size number of octets remaining in **buffer. If size is a NULL pointer, then |
| no data is marshaled and the routine will compute the size of the |
| memory required to marshal the indicated type |
| When the data is successfully marshaled, the called routine will return the number of octets marshaled |
| into **buffer. |
| If the data is successfully marshaled, *buffer is advanced point to the first octet of the next location in |
| the output buffer and *size is reduced by the number of octets placed in the buffer. |
| When the data type is a simple type, the parser will generate code that will marshal the underlying type. |
| The presumption is that the TPM internal structures are consistent and correct so the marshaling code |
| does not validate that the data placed in the buffer has a permissible value. |
| When the data type is a structure, the parser will generate code that marshals each of the structure |
| elements in turn. |
| |
| 4.2.3.2 Union Types |
| |
| An extra parameter is defined for the marshaling function of a union. This parameter is the selector for the |
| type. The marshaling code for the union will marshal the type indicated by the selector. |
| The function prototype for a union has the form: |
| |
| UINT16 TYPE_Marshal(TYPE *target, BYTE **buffer, INT32 *size, UINT32 selector); |
| |
| The parameters have a similar meaning as those in 5.2.2.2 but the data movement is from source to |
| buffer. |
| |
| |
| 4.2.3.3 Arrays |
| |
| Any type may be included in an array. The function prototype use to unmarshal an array is: |
| |
| UINT16 TYPE_Array_Marshal(TYPE *source, BYTE **buffer, INT32 *size, INT32 count); |
| |
| The generated code for an array uses a count-limited loop within which it calls the marshaling code for |
| TYPE. |
| |
| |
| |
| |
| Page 4 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 4.3 Command Parser |
| |
| The program that processes the tables in TPM 2.0 Part 3 is called "The TPM 2.0 Part 3 Command |
| Parser." |
| The TPM 2.0 Part 3 Command Parser takes as input a TPM 2.0 Part 3 of the TPM specification and some |
| configuration files produced by the TPM 2.0 Part 2 Configuration Parser. This parser uses the contents of |
| the command and response tables in TPM 2.0 Part 3 to produce unmarshaling code for the command |
| and the marshaling code for the response. Additionally, this parser produces support routines that are |
| used to check that the proper number of authorization values of the proper type have been provided. |
| These support routines are called by the functions in this TPM 2.0 Part 4. |
| |
| 4.4 Portability |
| |
| Where reasonable, the code is written to be portable. There are a few known cases where the code is not |
| portable. Specifically, the handling of bit fields will not always be portable. The bit fields are marshaled |
| and unmarshaled as a simple element of the underlying type. For example, a TPMA_SESSION is defined |
| as a bit field in an octet (BYTE). When sent on the interface a TPMA_SESSION will occupy one octet. |
| When unmarshaled, it is unmarshaled as a UINT8. The ramifications of this are that a TPMA_SESSION |
| th |
| will occupy the 0 octet of the structure in which it is placed regardless of the size of the structure. |
| Many compilers will pad a bit field to some "natural" size for the processor, often 4 octets, meaning that |
| sizeof(TPMA_SESSION) would return 4 rather than 1 (the canonical size of a TPMA_SESSION). |
| th |
| For a little endian machine, padding of bit fields should have little consequence since the 0 octet always |
| th |
| contains the 0 bit of the structure no matter how large the structure. However, for a big endian machine, |
| th |
| the 0 bit will be in the highest numbered octet. When unmarshaling a TPMA_SESSION, the current |
| th th |
| unmarshaling code will place the input octet at the 0 octet of the TPMA_SESSION. Since the 0 octet is |
| most significant octet, this has the effect of shifting all the session attribute bits left by 24 places. |
| As a consequence, someone implementing on a big endian machine should do one of two things: |
| a) allocate all structures as packed to a byte boundary (this may not be possible if the processor does |
| not handle unaligned accesses); or |
| b) modify the code that manipulates bit fields that are not defined as being the alignment size of the |
| system. |
| For many RISC processors, option #2 would be the only choice. This is may not be a terribly daunting |
| task since only two attribute structures are not 32-bits (TPMA_SESSION and TPMA_LOCALITY). |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 5 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| |
| 5 Header Files |
| |
| 5.1 Introduction |
| |
| The files in this section are used to define values that are used in multiple parts of the specification and |
| are not confined to a single module. |
| |
| 5.2 BaseTypes.h |
| |
| 1 #ifndef _BASETYPES_H |
| 2 #define _BASETYPES_H |
| 3 #include "stdint.h" |
| |
| NULL definition |
| |
| 4 #ifndef NULL |
| 5 #define NULL (0) |
| 6 #endif |
| 7 typedef uint8_t UINT8; |
| 8 typedef uint8_t BYTE; |
| 9 typedef int8_t INT8; |
| 10 typedef int BOOL; |
| 11 typedef uint16_t UINT16; |
| 12 typedef int16_t INT16; |
| 13 typedef uint32_t UINT32; |
| 14 typedef int32_t INT32; |
| 15 typedef uint64_t UINT64; |
| 16 typedef int64_t INT64; |
| 17 typedef struct { |
| 18 UINT16 size; |
| 19 BYTE buffer[1]; |
| 20 } TPM2B; |
| 21 #endif |
| |
| |
| |
| |
| Page 6 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 5.3 bits.h |
| |
| 1 #ifndef _BITS_H |
| 2 #define _BITS_H |
| 3 #define CLEAR_BIT(bit, vector) BitClear((bit), (BYTE *)&(vector), sizeof(vector)) |
| 4 #define SET_BIT(bit, vector) BitSet((bit), (BYTE *)&(vector), sizeof(vector)) |
| 5 #define TEST_BIT(bit, vector) BitIsSet((bit), (BYTE *)&(vector), sizeof(vector)) |
| 6 #endif |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 7 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.4 bool.h |
| |
| 1 #ifndef _BOOL_H |
| 2 #define _BOOL_H |
| 3 #if defined(TRUE) |
| 4 #undef TRUE |
| 5 #endif |
| 6 #if defined FALSE |
| 7 #undef FALSE |
| 8 #endif |
| 9 typedef int BOOL; |
| 10 #define FALSE ((BOOL)0) |
| 11 #define TRUE ((BOOL)1) |
| 12 #endif |
| |
| |
| 5.5 Capabilities.h |
| |
| This file contains defines for the number of capability values that will fit into the largest data buffer. |
| These defines are used in various function in the "support" and the "subsystem" code groups. A module |
| that supports a type that is returned by a capability will have a function that returns the capabilities of the |
| type. |
| |
| EXAMPLE PCR.c contains PCRCapGetHandles() and PCRCapGetProperties(). |
| |
| 1 #ifndef _CAPABILITIES_H |
| 2 #define _CAPABILITIES_H |
| 3 #define MAX_CAP_DATA (MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32)) |
| 4 #define MAX_CAP_ALGS (ALG_LAST_VALUE - ALG_FIRST_VALUE + 1) |
| 5 #define MAX_CAP_HANDLES (MAX_CAP_DATA/sizeof(TPM_HANDLE)) |
| 6 #define MAX_CAP_CC ((TPM_CC_LAST - TPM_CC_FIRST) + 1) |
| 7 #define MAX_TPM_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY)) |
| 8 #define MAX_PCR_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT)) |
| 9 #define MAX_ECC_CURVES (MAX_CAP_DATA/sizeof(TPM_ECC_CURVE)) |
| 10 #endif |
| |
| |
| 5.6 TPMB.h |
| |
| This file contains extra TPM2B structures |
| |
| 1 #ifndef _TPMB_H |
| 2 #define _TPMB_H |
| |
| This macro helps avoid having to type in the structure in order to create a new TPM2B type that is used in |
| a function. |
| |
| 3 #define TPM2B_TYPE(name, bytes) \ |
| 4 typedef union { \ |
| 5 struct { \ |
| 6 UINT16 size; \ |
| 7 BYTE buffer[(bytes)]; \ |
| 8 } t; \ |
| 9 TPM2B b; \ |
| 10 } TPM2B_##name |
| |
| Macro to instance and initialize a TPM2B value |
| |
| 11 #define TPM2B_INIT(TYPE, name) \ |
| 12 TPM2B_##TYPE name = {sizeof(name.t.buffer), {0}} |
| 13 #define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes) |
| 14 #endif |
| |
| |
| Page 8 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 5.7 TpmError.h |
| |
| 1 #ifndef _TPM_ERROR_H |
| 2 #define _TPM_ERROR_H |
| 3 #include "TpmBuildSwitches.h" |
| 4 #define FATAL_ERROR_ALLOCATION (1) |
| 5 #define FATAL_ERROR_DIVIDE_ZERO (2) |
| 6 #define FATAL_ERROR_INTERNAL (3) |
| 7 #define FATAL_ERROR_PARAMETER (4) |
| 8 #define FATAL_ERROR_ENTROPY (5) |
| 9 #define FATAL_ERROR_SELF_TEST (6) |
| 10 #define FATAL_ERROR_CRYPTO (7) |
| 11 #define FATAL_ERROR_NV_UNRECOVERABLE (8) |
| 12 #define FATAL_ERROR_REMANUFACTURED (9) // indicates that the TPM has |
| 13 // been re-manufactured after an |
| 14 // unrecoverable NV error |
| 15 #define FATAL_ERROR_DRBG (10) |
| 16 #define FATAL_ERROR_FORCED (666) |
| |
| These are the crypto assertion routines. When a function returns an unexpected and unrecoverable |
| result, the assertion fails and the TpmFail() is called |
| |
| 17 void |
| 18 TpmFail(const char *function, int line, int code); |
| 19 typedef void (*FAIL_FUNCTION)(const char *, int, int); |
| 20 #define FAIL(a) (TpmFail(__FUNCTION__, __LINE__, a)) |
| 21 #if defined(EMPTY_ASSERT) |
| 22 # define pAssert(a) ((void)0) |
| 23 #else |
| 24 # define pAssert(a) (!!(a) ? 1 : (FAIL(FATAL_ERROR_PARAMETER), 0)) |
| 25 #endif |
| 26 #endif // _TPM_ERROR_H |
| |
| |
| 5.8 Global.h |
| |
| 5.8.1 Description |
| |
| This file contains internal global type definitions and data declarations that are need between |
| subsystems. The instantiation of global data is in Global.c. The initialization of global data is in the |
| subsystem that is the primary owner of the data. |
| The first part of this file has the typedefs for structures and other defines used in many portions of the |
| code. After the typedef section, is a section that defines global values that are only present in RAM. The |
| next three sections define the structures for the NV data areas: persistent, orderly, and state save. |
| Additional sections define the data that is used in specific modules. That data is private to the module but |
| is collected here to simplify the management of the instance data. All the data is instanced in Global.c. |
| |
| 5.8.2 Includes |
| |
| 1 #ifndef GLOBAL_H |
| 2 #define GLOBAL_H |
| 3 //#define SELF_TEST |
| 4 #include "TpmBuildSwitches.h" |
| 5 #include "Tpm.h" |
| 6 #include "TPMB.h" |
| 7 #include "CryptoEngine.h" |
| 8 #include <setjmp.h> |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 9 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.8.3 Defines and Types |
| |
| 5.8.3.1 Unreferenced Parameter |
| |
| This define is used to eliminate the compiler warning about an unreferenced parameter. Basically, it tells |
| the compiler that it is not an accident that the parameter is unreferenced. |
| |
| 9 #ifndef UNREFERENCED_PARAMETER |
| 10 # define UNREFERENCED_PARAMETER(a) (a) |
| 11 #endif |
| 12 #include "bits.h" |
| |
| |
| 5.8.3.2 Crypto Self-Test Values |
| |
| Define these values here if the AlgorithmTests() project is not used |
| |
| 13 #ifndef SELF_TEST |
| 14 extern ALGORITHM_VECTOR g_implementedAlgorithms; |
| 15 extern ALGORITHM_VECTOR g_toTest; |
| 16 #else |
| 17 LIB_IMPORT extern ALGORITHM_VECTOR g_implementedAlgorithms; |
| 18 LIB_IMPORT extern ALGORITHM_VECTOR g_toTest; |
| 19 #endif |
| |
| These macros are used in CryptUtil() to invoke the incremental self test. |
| |
| 20 #define TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL) |
| |
| Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting to test a hash with |
| that value, don't do it. |
| |
| 21 #define TEST_HASH(alg) \ |
| 22 if( TEST_BIT(alg, g_toTest) \ |
| 23 && (alg != ALG_NULL_VALUE)) \ |
| 24 CryptTestAlgorithm(alg, NULL) |
| |
| |
| 5.8.3.3 Hash and HMAC State Structures |
| |
| These definitions are for the types that can be in a hash state structure. These types are used in the |
| crypto utilities |
| |
| 25 typedef BYTE HASH_STATE_TYPE; |
| 26 #define HASH_STATE_EMPTY ((HASH_STATE_TYPE) 0) |
| 27 #define HASH_STATE_HASH ((HASH_STATE_TYPE) 1) |
| 28 #define HASH_STATE_HMAC ((HASH_STATE_TYPE) 2) |
| |
| A HASH_STATE structure contains an opaque hash stack state. A caller would use this structure when |
| performing incremental hash operations. The state is updated on each call. If type is an HMAC_STATE, |
| or HMAC_STATE_SEQUENCE then state is followed by the HMAC key in oPad format. |
| |
| 29 typedef struct |
| 30 { |
| 31 CPRI_HASH_STATE state; // hash state |
| 32 HASH_STATE_TYPE type; // type of the context |
| 33 } HASH_STATE; |
| |
| |
| |
| |
| Page 10 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| An HMAC_STATE structure contains an opaque HMAC stack state. A caller would use this structure |
| when performing incremental HMAC operations. This structure contains a hash state and an HMAC key |
| and allows slightly better stack optimization than adding an HMAC key to each hash state. |
| |
| 34 typedef struct |
| 35 { |
| 36 HASH_STATE hashState; // the hash state |
| 37 TPM2B_HASH_BLOCK hmacKey; // the HMAC key |
| 38 } HMAC_STATE; |
| |
| |
| 5.8.3.4 Other Types |
| |
| An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA) |
| |
| 39 typedef BYTE AUTH_VALUE[sizeof(TPMU_HA)]; |
| |
| A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO |
| |
| 40 typedef BYTE TIME_INFO[sizeof(TPMS_TIME_INFO)]; |
| |
| A NAME is a BYTE array that can contain a TPMU_NAME |
| |
| 41 typedef BYTE NAME[sizeof(TPMU_NAME)]; |
| |
| |
| 5.8.4 Loaded Object Structures |
| |
| 5.8.4.1 Description |
| |
| The structures in this section define the object layout as it exists in TPM memory. |
| Two types of objects are defined: an ordinary object such as a key, and a sequence object that may be a |
| hash, HMAC, or event. |
| |
| 5.8.4.2 OBJECT_ATTRIBUTES |
| |
| An OBJECT_ATTRIBUTES structure contains the variable attributes of an object. These properties are |
| not part of the public properties but are used by the TPM in managing the object. An |
| OBJECT_ATTRIBUTES is used in the definition of the OBJECT data type. |
| |
| 42 typedef struct |
| 43 { |
| 44 unsigned publicOnly : 1; //0) SET if only the public portion of |
| 45 // an object is loaded |
| 46 unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS |
| 47 // Hierarchy |
| 48 unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS |
| 49 // Hierarchy |
| 50 unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS |
| 51 // Hierarchy |
| 52 unsigned evict : 1; //4) SET if the object is a platform or |
| 53 // owner evict object. Platform- |
| 54 // evict object belongs to PPS |
| 55 // hierarchy, owner-evict object |
| 56 // belongs to SPS or EPS hierarchy. |
| 57 // This bit is also used to mark a |
| 58 // completed sequence object so it |
| 59 // will be flush when the |
| 60 // SequenceComplete command succeeds. |
| 61 unsigned primary : 1; //5) SET for a primary object |
| |
| Family "2.0" TCG Published Page 11 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 62 unsigned temporary : 1; |
| //6) SET for a temporary object |
| 63 unsigned stClear : 1; |
| //7) SET for an stClear object |
| 64 unsigned hmacSeq : 1; |
| //8) SET for an HMAC sequence object |
| 65 unsigned hashSeq : 1; |
| //9) SET for a hash sequence object |
| 66 unsigned eventSeq : 1; |
| //10) SET for an event sequence object |
| 67 unsigned ticketSafe : 1; |
| //11) SET if a ticket is safe to create |
| 68 // for hash sequence object |
| 69 unsigned firstBlock : 1; //12) SET if the first block of hash |
| 70 // data has been received. It |
| 71 // works with ticketSafe bit |
| 72 unsigned isParent : 1; //13) SET if the key has the proper |
| 73 // attributes to be a parent key |
| 74 unsigned privateExp : 1; //14) SET when the private exponent |
| 75 // of an RSA key has been validated. |
| 76 unsigned reserved : 1; //15) reserved bits. unused. |
| 77 } OBJECT_ATTRIBUTES; |
| |
| |
| 5.8.4.3 OBJECT Structure |
| |
| An OBJECT structure holds the object public, sensitive, and meta-data associated. This structure is |
| implementation dependent. For this implementation, the structure is not optimized for space but rather for |
| clarity of the reference implementation. Other implementations may choose to overlap portions of the |
| structure that are not used simultaneously. These changes would necessitate changes to the source code |
| but those changes would be compatible with the reference implementation. |
| |
| 78 typedef struct |
| 79 { |
| 80 // The attributes field is required to be first followed by the publicArea. |
| 81 // This allows the overlay of the object structure and a sequence structure |
| 82 OBJECT_ATTRIBUTES attributes; // object attributes |
| 83 TPMT_PUBLIC publicArea; // public area of an object |
| 84 TPMT_SENSITIVE sensitive; // sensitive area of an object |
| 85 |
| 86 #ifdef TPM_ALG_RSA |
| 87 TPM2B_PUBLIC_KEY_RSA privateExponent; // Additional field for the private |
| 88 // exponent of an RSA key. |
| 89 #endif |
| 90 TPM2B_NAME qualifiedName; // object qualified name |
| 91 TPMI_DH_OBJECT evictHandle; // if the object is an evict object, |
| 92 // the original handle is kept here. |
| 93 // The 'working' handle will be the |
| 94 // handle of an object slot. |
| 95 |
| 96 TPM2B_NAME name; // Name of the object name. Kept here |
| 97 // to avoid repeatedly computing it. |
| 98 } OBJECT; |
| |
| |
| 5.8.4.4 HASH_OBJECT Structure |
| |
| This structure holds a hash sequence object or an event sequence object. |
| The first four components of this structure are manually set to be the same as the first four components of |
| the object structure. This prevents the object from being inadvertently misused as sequence objects |
| occupy the same memory as a regular object. A debug check is present to make sure that the offsets are |
| what they are supposed to be. |
| |
| 99 typedef struct |
| 100 { |
| 101 OBJECT_ATTRIBUTES attributes; // The attributes of the HASH object |
| 102 TPMI_ALG_PUBLIC type; // algorithm |
| 103 TPMI_ALG_HASH nameAlg; // name algorithm |
| 104 TPMA_OBJECT objectAttributes; // object attributes |
| |
| Page 12 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 105 |
| 106 // The data below is unique to a sequence object |
| 107 TPM2B_AUTH auth; // auth for use of sequence |
| 108 union |
| 109 { |
| 110 HASH_STATE hashState[HASH_COUNT]; |
| 111 HMAC_STATE hmacState; |
| 112 } state; |
| 113 } HASH_OBJECT; |
| |
| |
| 5.8.4.5 ANY_OBJECT |
| |
| This is the union for holding either a sequence object or a regular object. |
| |
| 114 typedef union |
| 115 { |
| 116 OBJECT entity; |
| 117 HASH_OBJECT hash; |
| 118 } ANY_OBJECT; |
| |
| |
| 5.8.5 AUTH_DUP Types |
| |
| These values are used in the authorization processing. |
| |
| 119 typedef UINT32 AUTH_ROLE; |
| 120 #define AUTH_NONE ((AUTH_ROLE)(0)) |
| 121 #define AUTH_USER ((AUTH_ROLE)(1)) |
| 122 #define AUTH_ADMIN ((AUTH_ROLE)(2)) |
| 123 #define AUTH_DUP ((AUTH_ROLE)(3)) |
| |
| |
| 5.8.6 Active Session Context |
| |
| 5.8.6.1 Description |
| |
| The structures in this section define the internal structure of a session context. |
| |
| 5.8.6.2 SESSION_ATTRIBUTES |
| |
| The attributes in the SESSION_ATTRIBUTES structure track the various properties of the session. It |
| maintains most of the tracking state information for the policy session. It is used within the SESSION |
| structure. |
| |
| 124 typedef struct |
| 125 { |
| 126 unsigned isPolicy : 1; //1) SET if the session may only |
| 127 // be used for policy |
| 128 unsigned isAudit : 1; //2) SET if the session is used |
| 129 // for audit |
| 130 unsigned isBound : 1; //3) SET if the session is bound to |
| 131 // with an entity. |
| 132 // This attribute will be CLEAR if |
| 133 // either isPolicy or isAudit is SET. |
| 134 unsigned iscpHashDefined : 1;//4) SET if the cpHash has been defined |
| 135 // This attribute is not SET unless |
| 136 // 'isPolicy' is SET. |
| 137 unsigned isAuthValueNeeded : 1; |
| 138 //5) SET if the authValue is required |
| 139 // for computing the session HMAC. |
| 140 // This attribute is not SET unless |
| |
| Family "2.0" TCG Published Page 13 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 141 // isPolicy is SET. |
| 142 unsigned isPasswordNeeded : 1; |
| 143 //6) SET if a password authValue is |
| 144 // required for authorization |
| 145 // This attribute is not SET unless |
| 146 // isPolicy is SET. |
| 147 unsigned isPPRequired : 1; //7) SET if physical presence is |
| 148 // required to be asserted when the |
| 149 // authorization is checked. |
| 150 // This attribute is not SET unless |
| 151 // isPolicy is SET. |
| 152 unsigned isTrialPolicy : 1; //8) SET if the policy session is |
| 153 // created for trial of the policy's |
| 154 // policyHash generation. |
| 155 // This attribute is not SET unless |
| 156 // isPolicy is SET. |
| 157 unsigned isDaBound : 1; //9) SET if the bind entity had noDA |
| 158 // CLEAR. If this is SET, then an |
| 159 // auth failure using this session |
| 160 // will count against lockout even |
| 161 // if the object being authorized is |
| 162 // exempt from DA. |
| 163 unsigned isLockoutBound : 1; //10)SET if the session is bound to |
| 164 // lockoutAuth. |
| 165 unsigned requestWasBound : 1;//11) SET if the session is being used |
| 166 // with the bind entity. If SET |
| 167 // the authValue will not be use |
| 168 // in the response HMAC computation. |
| 169 unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN |
| 170 // attribute needs to be checked |
| 171 // when the policy is used for |
| 172 // authorization for NV access. |
| 173 // If this is SET for any other |
| 174 // type, the policy will fail. |
| 175 unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is |
| 176 // required to be SET. |
| 177 } SESSION_ATTRIBUTES; |
| |
| |
| 5.8.6.3 SESSION Structure |
| |
| The SESSION structure contains all the context of a session except for the associated contextID. |
| |
| NOTE: The contextID of a session is only relevant when the session context is stored off the TPM. |
| |
| 178 typedef struct |
| 179 { |
| 180 TPM_ALG_ID authHashAlg; // session hash algorithm |
| 181 TPM2B_NONCE nonceTPM; // last TPM-generated nonce for |
| 182 // this session |
| 183 |
| 184 TPMT_SYM_DEF symmetric; // session symmetric algorithm (if any) |
| 185 TPM2B_AUTH sessionKey; // session secret value used for |
| 186 // generating HMAC and encryption keys |
| 187 |
| 188 SESSION_ATTRIBUTES attributes; // session attributes |
| 189 TPM_CC commandCode; // command code (policy session) |
| 190 TPMA_LOCALITY commandLocality; // command locality (policy session) |
| 191 UINT32 pcrCounter; // PCR counter value when PCR is |
| 192 // included (policy session) |
| 193 // If no PCR is included, this |
| 194 // value is 0. |
| 195 |
| 196 UINT64 startTime; // value of TPMS_CLOCK_INFO.clock when |
| 197 // the session was started (policy |
| |
| |
| Page 14 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 198 // session) |
| 199 |
| 200 UINT64 timeOut; // timeout relative to |
| 201 // TPMS_CLOCK_INFO.clock |
| 202 // There is no timeout if this value |
| 203 // is 0. |
| 204 union |
| 205 { |
| 206 TPM2B_NAME boundEntity; // value used to track the entity to |
| 207 // which the session is bound |
| 208 |
| 209 TPM2B_DIGEST cpHash; // the required cpHash value for the |
| 210 // command being authorized |
| 211 |
| 212 } u1; // 'boundEntity' and 'cpHash' may |
| 213 // share the same space to save memory |
| 214 |
| 215 union |
| 216 { |
| 217 TPM2B_DIGEST auditDigest; // audit session digest |
| 218 TPM2B_DIGEST policyDigest; // policyHash |
| 219 |
| 220 } u2; // audit log and policyHash may |
| 221 // share space to save memory |
| 222 } SESSION; |
| |
| |
| 5.8.7 PCR |
| |
| 5.8.7.1 PCR_SAVE Structure |
| |
| The PCR_SAVE structure type contains the PCR data that are saved across power cycles. Only the static |
| PCR are required to be saved across power cycles. The DRTM and resettable PCR are not saved. The |
| number of static and resettable PCR is determined by the platform-specific specification to which the TPM |
| is built. |
| |
| 223 typedef struct |
| 224 { |
| 225 #ifdef TPM_ALG_SHA1 |
| 226 BYTE sha1[NUM_STATIC_PCR][SHA1_DIGEST_SIZE]; |
| 227 #endif |
| 228 #ifdef TPM_ALG_SHA256 |
| 229 BYTE sha256[NUM_STATIC_PCR][SHA256_DIGEST_SIZE]; |
| 230 #endif |
| 231 #ifdef TPM_ALG_SHA384 |
| 232 BYTE sha384[NUM_STATIC_PCR][SHA384_DIGEST_SIZE]; |
| 233 #endif |
| 234 #ifdef TPM_ALG_SHA512 |
| 235 BYTE sha512[NUM_STATIC_PCR][SHA512_DIGEST_SIZE]; |
| 236 #endif |
| 237 #ifdef TPM_ALG_SM3_256 |
| 238 BYTE sm3_256[NUM_STATIC_PCR][SM3_256_DIGEST_SIZE]; |
| 239 #endif |
| 240 |
| 241 // This counter increments whenever the PCR are updated. |
| 242 // NOTE: A platform-specific specification may designate |
| 243 // certain PCR changes as not causing this counter |
| 244 // to increment. |
| 245 UINT32 pcrCounter; |
| 246 |
| 247 } PCR_SAVE; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 15 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.8.7.2 PCR_POLICY |
| |
| This structure holds the PCR policies, one for each group of PCR controlled by policy. |
| |
| 248 typedef struct |
| 249 { |
| 250 TPMI_ALG_HASH hashAlg[NUM_POLICY_PCR_GROUP]; |
| 251 TPM2B_DIGEST a; |
| 252 TPM2B_DIGEST policy[NUM_POLICY_PCR_GROUP]; |
| 253 } PCR_POLICY; |
| |
| |
| 5.8.7.3 PCR_AUTHVALUE |
| |
| This structure holds the PCR policies, one for each group of PCR controlled by policy. |
| |
| 254 typedef struct |
| 255 { |
| 256 TPM2B_DIGEST auth[NUM_AUTHVALUE_PCR_GROUP]; |
| 257 } PCR_AUTHVALUE; |
| |
| |
| 5.8.8 Startup |
| |
| 5.8.8.1 SHUTDOWN_NONE |
| |
| Part 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() and |
| TPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was received. |
| |
| NOTE: This is a reserved value. |
| |
| 258 #define SHUTDOWN_NONE (TPM_SU)(0xFFFF) |
| |
| |
| 5.8.8.2 STARTUP_TYPE |
| |
| This enumeration is the possible startup types. The type is determined by the combination of |
| TPM2_ShutDown() and TPM2_Startup(). |
| |
| 259 typedef enum |
| 260 { |
| 261 SU_RESET, |
| 262 SU_RESTART, |
| 263 SU_RESUME |
| 264 } STARTUP_TYPE; |
| |
| |
| 5.8.9 NV |
| |
| 5.8.9.1 NV_RESERVE |
| |
| This enumeration defines the master list of the elements of a reserved portion of NV. This list includes all |
| the pre-defined data that takes space in NV, either as persistent data or as state save data. The |
| enumerations are used as indexes into an array of offset values. The offset values then are used to index |
| into NV. This is method provides an imperfect analog to an actual NV implementation. |
| |
| 265 typedef enum |
| 266 { |
| 267 // Entries below mirror the PERSISTENT_DATA structure. These values are written |
| 268 // to NV as individual items. |
| 269 // hierarchy |
| |
| Page 16 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 270 NV_DISABLE_CLEAR, |
| 271 NV_OWNER_ALG, |
| 272 NV_ENDORSEMENT_ALG, |
| 273 NV_LOCKOUT_ALG, |
| 274 NV_OWNER_POLICY, |
| 275 NV_ENDORSEMENT_POLICY, |
| 276 NV_LOCKOUT_POLICY, |
| 277 NV_OWNER_AUTH, |
| 278 NV_ENDORSEMENT_AUTH, |
| 279 NV_LOCKOUT_AUTH, |
| 280 |
| 281 NV_EP_SEED, |
| 282 NV_SP_SEED, |
| 283 NV_PP_SEED, |
| 284 |
| 285 NV_PH_PROOF, |
| 286 NV_SH_PROOF, |
| 287 NV_EH_PROOF, |
| 288 |
| 289 // Time |
| 290 NV_TOTAL_RESET_COUNT, |
| 291 NV_RESET_COUNT, |
| 292 |
| 293 // PCR |
| 294 NV_PCR_POLICIES, |
| 295 NV_PCR_ALLOCATED, |
| 296 |
| 297 // Physical Presence |
| 298 NV_PP_LIST, |
| 299 |
| 300 // Dictionary Attack |
| 301 NV_FAILED_TRIES, |
| 302 NV_MAX_TRIES, |
| 303 NV_RECOVERY_TIME, |
| 304 NV_LOCKOUT_RECOVERY, |
| 305 NV_LOCKOUT_AUTH_ENABLED, |
| 306 |
| 307 // Orderly State flag |
| 308 NV_ORDERLY, |
| 309 |
| 310 // Command Audit |
| 311 NV_AUDIT_COMMANDS, |
| 312 NV_AUDIT_HASH_ALG, |
| 313 NV_AUDIT_COUNTER, |
| 314 |
| 315 // Algorithm Set |
| 316 NV_ALGORITHM_SET, |
| 317 |
| 318 NV_FIRMWARE_V1, |
| 319 NV_FIRMWARE_V2, |
| 320 |
| 321 // The entries above are in PERSISTENT_DATA. The entries below represent |
| 322 // structures that are read and written as a unit. |
| 323 |
| 324 // ORDERLY_DATA data structure written on each orderly shutdown |
| 325 NV_ORDERLY_DATA, |
| 326 |
| 327 // STATE_CLEAR_DATA structure written on each Shutdown(STATE) |
| 328 NV_STATE_CLEAR, |
| 329 |
| 330 // STATE_RESET_DATA structure written on each Shutdown(STATE) |
| 331 NV_STATE_RESET, |
| 332 |
| 333 NV_RESERVE_LAST // end of NV reserved data list |
| 334 } NV_RESERVE; |
| |
| |
| Family "2.0" TCG Published Page 17 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.8.9.2 NV_INDEX |
| |
| The NV_INDEX structure defines the internal format for an NV index. The indexData size varies |
| according to the type of the index. In this implementation, all of the index is manipulated as a unit. |
| |
| 335 typedef struct |
| 336 { |
| 337 TPMS_NV_PUBLIC publicArea; |
| 338 TPM2B_AUTH authValue; |
| 339 } NV_INDEX; |
| |
| |
| 5.8.10 COMMIT_INDEX_MASK |
| |
| This is the define for the mask value that is used when manipulating the bits in the commit bit array. The |
| commit counter is a 64-bit value and the low order bits are used to index the commitArray. This mask |
| value is applied to the commit counter to extract the bit number in the array. |
| |
| 340 #ifdef TPM_ALG_ECC |
| 341 #define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1)) |
| 342 #endif |
| |
| |
| 5.8.11 RAM Global Values |
| |
| 5.8.11.1 Description |
| |
| The values in this section are only extant in RAM. They are defined here and instanced in Global.c. |
| |
| 5.8.11.2 g_rcIndex |
| |
| This array is used to contain the array of values that are added to a return code when it is a parameter-, |
| handle-, or session-related error. This is an implementation choice and the same result can be achieved |
| by using a macro. |
| |
| 343 extern const UINT16 g_rcIndex[15]; |
| |
| |
| 5.8.11.3 g_exclusiveAuditSession |
| |
| This location holds the session handle for the current exclusive audit session. If there is no exclusive |
| audit session, the location is set to TPM_RH_UNASSIGNED. |
| |
| 344 extern TPM_HANDLE g_exclusiveAuditSession; |
| |
| |
| 5.8.11.4 g_time |
| |
| This value is the count of milliseconds since the TPM was powered up. This value is initialized at |
| _TPM_Init(). |
| |
| 345 extern UINT64 g_time; |
| |
| |
| 5.8.11.5 g_phEnable |
| |
| This is the platform hierarchy control and determines if the platform hierarchy is available. This value is |
| SET on each TPM2_Startup(). The default value is SET. |
| |
| 346 extern BOOL g_phEnable; |
| |
| Page 18 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 5.8.11.6 g_pceReConfig |
| |
| This value is SET if a TPM2_PCR_Allocate() command successfully executed since the last |
| TPM2_Startup(). If so, then the next shutdown is required to be Shutdown(CLEAR). |
| |
| 347 extern BOOL g_pcrReConfig; |
| |
| |
| 5.8.11.7 g_DRTMHandle |
| |
| This location indicates the sequence object handle that holds the DRTM sequence data. When not used, |
| it is set to TPM_RH_UNASSIGNED. A sequence DRTM sequence is started on either _TPM_Init() or |
| _TPM_Hash_Start(). |
| |
| 348 extern TPMI_DH_OBJECT g_DRTMHandle; |
| |
| |
| 5.8.11.8 g_DrtmPreStartup |
| |
| This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The define |
| for PRE_STARTUP_FLAG is used to add the g_DrtmPreStartup value to gp_orderlyState at shutdown. |
| This hack is to avoid adding another NV variable. |
| |
| 349 extern BOOL g_DrtmPreStartup; |
| 350 #define PRE_STARTUP_FLAG 0x8000 |
| |
| |
| 5.8.11.9 g_StartupLocality3 |
| |
| This value indicates that a TPM2_Startup() occured at locality 3. Otherwise, it at locality 0. The define for |
| STARTUP_LOCALITY_3 is to indicate that the startup was not at locality 0. This hack is to avoid adding |
| another NV variable. |
| |
| 351 extern BOOL g_StartupLocality3; |
| 352 #define STARTUP_LOCALITY_3 0x4000 |
| |
| |
| 5.8.11.10 g_updateNV |
| |
| This flag indicates if NV should be updated at the end of a command. This flag is set to FALSE at the |
| beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand() after the |
| detailed actions of a command complete. If the command execution was successful and this flag is SET, |
| any pending NV writes will be committed to NV. |
| |
| 353 extern BOOL g_updateNV; |
| |
| |
| 5.8.11.11 g_clearOrderly |
| |
| This flag indicates if the execution of a command should cause the orderly state to be cleared. This flag |
| is set to FALSE at the beginning of each command in ExecuteCommand() and is checked in |
| ExecuteCommand() after the detailed actions of a command complete but before the check of |
| g_updateNV. If this flag is TRUE, and the orderly state is not SHUTDOWN_NONE, then the orderly state |
| in NV memory will be changed to SHUTDOWN_NONE. |
| |
| 354 extern BOOL g_clearOrderly; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 19 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.8.11.12 g_prevOrderlyState |
| |
| This location indicates how the TPM was shut down before the most recent TPM2_Startup(). This value, |
| along with the startup type, determines if the TPM should do a TPM Reset, TPM Restart, or TPM |
| Resume. |
| |
| 355 extern TPM_SU g_prevOrderlyState; |
| |
| |
| 5.8.11.13 g_nvOk |
| |
| This value indicates if the NV integrity check was successful or not. If not and the failure was severe, then |
| the TPM would have been put into failure mode after it had been re-manufactured. If the NV failure was in |
| the area where the state-save data is kept, then this variable will have a value of FALSE indicating that a |
| TPM2_Startup(CLEAR) is required. |
| |
| 356 extern BOOL g_nvOk; |
| |
| |
| 5.8.11.14 g_platformUnique |
| |
| This location contains the unique value(s) used to identify the TPM. It is loaded on every |
| _TPM2_Startup() The first value is used to seed the RNG. The second value is used as a vendor |
| authValue. The value used by the RNG would be the value derived from the chip unique value (such as |
| fused) with a dependency on the authorities of the code in the TPM boot path. The second would be |
| derived from the chip unique value with a dependency on the details of the code in the boot path. That is, |
| the first value depends on the various signers of the code and the second depends on what was signed. |
| The TPM vendor should not be able to know the first value but they are expected to know the second. |
| |
| 357 extern TPM2B_AUTH g_platformUniqueAuthorities; // Reserved for RNG |
| 358 extern TPM2B_AUTH g_platformUniqueDetails; // referenced by VENDOR_PERMANENT |
| |
| |
| 5.8.12 Persistent Global Values |
| |
| 5.8.12.1 Description |
| |
| The values in this section are global values that are persistent across power events. The lifetime of the |
| values determines the structure in which the value is placed. |
| |
| 5.8.12.2 PERSISTENT_DATA |
| |
| This structure holds the persistent values that only change as a consequence of a specific Protected |
| Capability and are not affected by TPM power events (TPM2_Startup() or TPM2_Shutdown(). |
| |
| 359 typedef struct |
| 360 { |
| 361 //********************************************************************************* |
| 362 // Hierarchy |
| 363 //********************************************************************************* |
| 364 // The values in this section are related to the hierarchies. |
| 365 |
| 366 BOOL disableClear; // TRUE if TPM2_Clear() using |
| 367 // lockoutAuth is disabled |
| 368 |
| 369 // Hierarchy authPolicies |
| 370 TPMI_ALG_HASH ownerAlg; |
| 371 TPMI_ALG_HASH endorsementAlg; |
| 372 TPMI_ALG_HASH lockoutAlg; |
| 373 TPM2B_DIGEST ownerPolicy; |
| |
| Page 20 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 374 TPM2B_DIGEST endorsementPolicy; |
| 375 TPM2B_DIGEST lockoutPolicy; |
| 376 |
| 377 // Hierarchy authValues |
| 378 TPM2B_AUTH ownerAuth; |
| 379 TPM2B_AUTH endorsementAuth; |
| 380 TPM2B_AUTH lockoutAuth; |
| 381 |
| 382 // Primary Seeds |
| 383 TPM2B_SEED EPSeed; |
| 384 TPM2B_SEED SPSeed; |
| 385 TPM2B_SEED PPSeed; |
| 386 // Note there is a nullSeed in the state_reset memory. |
| 387 |
| 388 // Hierarchy proofs |
| 389 TPM2B_AUTH phProof; |
| 390 TPM2B_AUTH shProof; |
| 391 TPM2B_AUTH ehProof; |
| 392 // Note there is a nullProof in the state_reset memory. |
| 393 |
| 394 //********************************************************************************* |
| 395 // Reset Events |
| 396 //********************************************************************************* |
| 397 // A count that increments at each TPM reset and never get reset during the life |
| 398 // time of TPM. The value of this counter is initialized to 1 during TPM |
| 399 // manufacture process. |
| 400 UINT64 totalResetCount; |
| 401 |
| 402 // This counter increments on each TPM Reset. The counter is reset by |
| 403 // TPM2_Clear(). |
| 404 UINT32 resetCount; |
| 405 |
| 406 //********************************************************************************* |
| 407 // PCR |
| 408 //********************************************************************************* |
| 409 // This structure hold the policies for those PCR that have an update policy. |
| 410 // This implementation only supports a single group of PCR controlled by |
| 411 // policy. If more are required, then this structure would be changed to |
| 412 // an array. |
| 413 PCR_POLICY pcrPolicies; |
| 414 |
| 415 // This structure indicates the allocation of PCR. The structure contains a |
| 416 // list of PCR allocations for each implemented algorithm. If no PCR are |
| 417 // allocated for an algorithm, a list entry still exists but the bit map |
| 418 // will contain no SET bits. |
| 419 TPML_PCR_SELECTION pcrAllocated; |
| 420 |
| 421 //********************************************************************************* |
| 422 // Physical Presence |
| 423 //********************************************************************************* |
| 424 // The PP_LIST type contains a bit map of the commands that require physical |
| 425 // to be asserted when the authorization is evaluated. Physical presence will be |
| 426 // checked if the corresponding bit in the array is SET and if the authorization |
| 427 // handle is TPM_RH_PLATFORM. |
| 428 // |
| 429 // These bits may be changed with TPM2_PP_Commands(). |
| 430 BYTE ppList[((TPM_CC_PP_LAST - TPM_CC_PP_FIRST + 1) + 7)/8]; |
| 431 |
| 432 //********************************************************************************* |
| 433 // Dictionary attack values |
| 434 //********************************************************************************* |
| 435 // These values are used for dictionary attack tracking and control. |
| 436 UINT32 failedTries; // the current count of unexpired |
| 437 // authorization failures |
| 438 |
| 439 UINT32 maxTries; // number of unexpired authorization |
| |
| Family "2.0" TCG Published Page 21 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 440 // failures before the TPM is in |
| 441 // lockout |
| 442 |
| 443 UINT32 recoveryTime; // time between authorization failures |
| 444 // before failedTries is decremented |
| 445 |
| 446 UINT32 lockoutRecovery; // time that must expire between |
| 447 // authorization failures associated |
| 448 // with lockoutAuth |
| 449 |
| 450 BOOL lockOutAuthEnabled; // TRUE if use of lockoutAuth is |
| 451 // allowed |
| 452 |
| 453 //***************************************************************************** |
| 454 // Orderly State |
| 455 //***************************************************************************** |
| 456 // The orderly state for current cycle |
| 457 TPM_SU orderlyState; |
| 458 |
| 459 //***************************************************************************** |
| 460 // Command audit values. |
| 461 //***************************************************************************** |
| 462 BYTE auditComands[((TPM_CC_LAST - TPM_CC_FIRST + 1) + 7) / 8]; |
| 463 TPMI_ALG_HASH auditHashAlg; |
| 464 UINT64 auditCounter; |
| 465 |
| 466 //***************************************************************************** |
| 467 // Algorithm selection |
| 468 //***************************************************************************** |
| 469 // |
| 470 // The 'algorithmSet' value indicates the collection of algorithms that are |
| 471 // currently in used on the TPM. The interpretation of value is vendor dependent. |
| 472 UINT32 algorithmSet; |
| 473 |
| 474 //***************************************************************************** |
| 475 // Firmware version |
| 476 //***************************************************************************** |
| 477 // The firmwareV1 and firmwareV2 values are instanced in TimeStamp.c. This is |
| 478 // a scheme used in development to allow determination of the linker build time |
| 479 // of the TPM. An actual implementation would implement these values in a way that |
| 480 // is consistent with vendor needs. The values are maintained in RAM for simplified |
| 481 // access with a master version in NV. These values are modified in a |
| 482 // vendor-specific way. |
| 483 |
| 484 // g_firmwareV1 contains the more significant 32-bits of the vendor version number. |
| 485 // In the reference implementation, if this value is printed as a hex |
| 486 // value, it will have the format of yyyymmdd |
| 487 UINT32 firmwareV1; |
| 488 |
| 489 // g_firmwareV1 contains the less significant 32-bits of the vendor version number. |
| 490 // In the reference implementation, if this value is printed as a hex |
| 491 // value, it will have the format of 00 hh mm ss |
| 492 UINT32 firmwareV2; |
| 493 |
| 494 } PERSISTENT_DATA; |
| 495 extern PERSISTENT_DATA gp; |
| |
| |
| 5.8.12.3 ORDERLY_DATA |
| |
| The data in this structure is saved to NV on each TPM2_Shutdown(). |
| |
| 496 typedef struct orderly_data |
| 497 { |
| 498 |
| |
| |
| Page 22 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 499 //***************************************************************************** |
| 500 // TIME |
| 501 //***************************************************************************** |
| 502 |
| 503 // Clock has two parts. One is the state save part and one is the NV part. The |
| 504 // state save version is updated on each command. When the clock rolls over, the |
| 505 // NV version is updated. When the TPM starts up, if the TPM was shutdown in and |
| 506 // orderly way, then the sClock value is used to initialize the clock. If the |
| 507 // TPM shutdown was not orderly, then the persistent value is used and the safe |
| 508 // attribute is clear. |
| 509 |
| 510 UINT64 clock; // The orderly version of clock |
| 511 TPMI_YES_NO clockSafe; // Indicates if the clock value is |
| 512 // safe. |
| 513 //********************************************************************************* |
| 514 // DRBG |
| 515 //********************************************************************************* |
| 516 #ifdef _DRBG_STATE_SAVE |
| 517 // This is DRBG state data. This is saved each time the value of clock is |
| 518 // updated. |
| 519 DRBG_STATE drbgState; |
| 520 #endif |
| 521 |
| 522 } ORDERLY_DATA; |
| 523 extern ORDERLY_DATA go; |
| |
| |
| 5.8.12.4 STATE_CLEAR_DATA |
| |
| This structure contains the data that is saved on Shutdown(STATE). and restored on Startup(STATE). |
| The values are set to their default settings on any Startup(Clear). In other words the data is only |
| persistent across TPM Resume. |
| If the comments associated with a parameter indicate a default reset value, the value is applied on each |
| Startup(CLEAR). |
| |
| 524 typedef struct state_clear_data |
| 525 { |
| 526 //***************************************************************************** |
| 527 // Hierarchy Control |
| 528 //***************************************************************************** |
| 529 BOOL shEnable; // default reset is SET |
| 530 BOOL ehEnable; // default reset is SET |
| 531 BOOL phEnableNV; // default reset is SET |
| 532 TPMI_ALG_HASH platformAlg; // default reset is TPM_ALG_NULL |
| 533 TPM2B_DIGEST platformPolicy; // default reset is an Empty Buffer |
| 534 TPM2B_AUTH platformAuth; // default reset is an Empty Buffer |
| 535 |
| 536 //***************************************************************************** |
| 537 // PCR |
| 538 //***************************************************************************** |
| 539 // The set of PCR to be saved on Shutdown(STATE) |
| 540 PCR_SAVE pcrSave; // default reset is 0...0 |
| 541 |
| 542 // This structure hold the authorization values for those PCR that have an |
| 543 // update authorization. |
| 544 // This implementation only supports a single group of PCR controlled by |
| 545 // authorization. If more are required, then this structure would be changed to |
| 546 // an array. |
| 547 PCR_AUTHVALUE pcrAuthValues; |
| 548 |
| 549 } STATE_CLEAR_DATA; |
| 550 extern STATE_CLEAR_DATA gc; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 23 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 5.8.12.5 State Reset Data |
| |
| This structure contains data is that is saved on Shutdown(STATE) and restored on the subsequent |
| Startup(ANY). That is, the data is preserved across TPM Resume and TPM Restart. |
| If a default value is specified in the comments this value is applied on TPM Reset. |
| |
| 551 typedef struct state_reset_data |
| 552 { |
| 553 //***************************************************************************** |
| 554 // Hierarchy Control |
| 555 //***************************************************************************** |
| 556 TPM2B_AUTH nullProof; // The proof value associated with |
| 557 // the TPM_RH_NULL hierarchy. The |
| 558 // default reset value is from the RNG. |
| 559 |
| 560 TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL |
| 561 // hierarchy. The default reset value |
| 562 // is from the RNG. |
| 563 |
| 564 //***************************************************************************** |
| 565 // Context |
| 566 //***************************************************************************** |
| 567 // The 'clearCount' counter is incremented each time the TPM successfully executes |
| 568 // a TPM Resume. The counter is included in each saved context that has 'stClear' |
| 569 // SET (including descendants of keys that have 'stClear' SET). This prevents these |
| 570 // objects from being loaded after a TPM Resume. |
| 571 // If 'clearCount' at its maximum value when the TPM receives a Shutdown(STATE), |
| 572 // the TPM will return TPM_RC_RANGE and the TPM will only accept Shutdown(CLEAR). |
| 573 UINT32 clearCount; // The default reset value is 0. |
| 574 |
| 575 UINT64 objectContextID; // This is the context ID for a saved |
| 576 // object context. The default reset |
| 577 // value is 0. |
| 578 |
| 579 CONTEXT_SLOT contextArray[MAX_ACTIVE_SESSIONS]; |
| 580 // This is the value from which the |
| 581 // 'contextID' is derived. The |
| 582 // default reset value is {0}. |
| 583 |
| 584 CONTEXT_COUNTER contextCounter; // This array contains contains the |
| 585 // values used to track the version |
| 586 // numbers of saved contexts (see |
| 587 // Session.c in for details). The |
| 588 // default reset value is 0. |
| 589 |
| 590 //***************************************************************************** |
| 591 // Command Audit |
| 592 //***************************************************************************** |
| 593 // When an audited command completes, ExecuteCommand() checks the return |
| 594 // value. If it is TPM_RC_SUCCESS, and the command is an audited command, the |
| 595 // TPM will extend the cpHash and rpHash for the command to this value. If this |
| 596 // digest was the Zero Digest before the cpHash was extended, the audit counter |
| 597 // is incremented. |
| 598 |
| 599 TPM2B_DIGEST commandAuditDigest; // This value is set to an Empty Digest |
| 600 // by TPM2_GetCommandAuditDigest() or a |
| 601 // TPM Reset. |
| 602 |
| 603 //***************************************************************************** |
| 604 // Boot counter |
| 605 //***************************************************************************** |
| 606 |
| 607 UINT32 restartCount; // This counter counts TPM Restarts. |
| 608 // The default reset value is 0. |
| |
| |
| Page 24 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 609 |
| 610 //********************************************************************************* |
| 611 // PCR |
| 612 //********************************************************************************* |
| 613 // This counter increments whenever the PCR are updated. This counter is preserved |
| 614 // across TPM Resume even though the PCR are not preserved. This is because |
| 615 // sessions remain active across TPM Restart and the count value in the session |
| 616 // is compared to this counter so this counter must have values that are unique |
| 617 // as long as the sessions are active. |
| 618 // NOTE: A platform-specific specification may designate that certain PCR changes |
| 619 // do not increment this counter to increment. |
| 620 UINT32 pcrCounter; // The default reset value is 0. |
| 621 |
| 622 #ifdef TPM_ALG_ECC |
| 623 |
| 624 //***************************************************************************** |
| 625 // ECDAA |
| 626 //***************************************************************************** |
| 627 UINT64 commitCounter; // This counter increments each time |
| 628 // TPM2_Commit() returns |
| 629 // TPM_RC_SUCCESS. The default reset |
| 630 // value is 0. |
| 631 |
| 632 TPM2B_NONCE commitNonce; // This random value is used to compute |
| 633 // the commit values. The default reset |
| 634 // value is from the RNG. |
| 635 |
| 636 // This implementation relies on the number of bits in g_commitArray being a |
| 637 // power of 2 (8, 16, 32, 64, etc.) and no greater than 64K. |
| 638 BYTE commitArray[16]; // The default reset value is {0}. |
| 639 |
| 640 #endif //TPM_ALG_ECC |
| 641 |
| 642 } STATE_RESET_DATA; |
| 643 extern STATE_RESET_DATA gr; |
| |
| |
| 5.8.13 Global Macro Definitions |
| |
| This macro is used to ensure that a handle, session, or parameter number is only added if the response |
| code is FMT1. |
| |
| 644 #define RcSafeAddToResult(r, v) \ |
| 645 ((r) + (((r) & RC_FMT1) ? (v) : 0)) |
| |
| This macro is used when a parameter is not otherwise referenced in a function. This macro is normally |
| not used by itself but is paired with a pAssert() within a #ifdef pAssert. If pAssert is not defined, then a |
| parameter might not otherwise be referenced. This macro uses the parameter from the perspective of the |
| compiler so it doesn't complain. |
| |
| 646 #define UNREFERENCED(a) ((void)(a)) |
| |
| |
| 5.8.14 Private data |
| |
| 647 #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C |
| |
| From SessionProcess.c |
| The following arrays are used to save command sessions information so that the command |
| handle/session buffer does not have to be preserved for the duration of the command. These arrays are |
| indexed by the session index in accordance with the order of sessions in the session area of the |
| command. |
| |
| Family "2.0" TCG Published Page 25 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Array of the authorization session handles |
| |
| 648 extern TPM_HANDLE s_sessionHandles[MAX_SESSION_NUM]; |
| |
| Array of authorization session attributes |
| |
| 649 extern TPMA_SESSION s_attributes[MAX_SESSION_NUM]; |
| |
| Array of handles authorized by the corresponding authorization sessions; and if none, then |
| TPM_RH_UNASSIGNED value is used |
| |
| 650 extern TPM_HANDLE s_associatedHandles[MAX_SESSION_NUM]; |
| |
| Array of nonces provided by the caller for the corresponding sessions |
| |
| 651 extern TPM2B_NONCE s_nonceCaller[MAX_SESSION_NUM]; |
| |
| Array of authorization values (HMAC's or passwords) for the corresponding sessions |
| |
| 652 extern TPM2B_AUTH s_inputAuthValues[MAX_SESSION_NUM]; |
| |
| Special value to indicate an undefined session index |
| |
| 653 #define UNDEFINED_INDEX (0xFFFF) |
| |
| Index of the session used for encryption of a response parameter |
| |
| 654 extern UINT32 s_encryptSessionIndex; |
| |
| Index of the session used for decryption of a command parameter |
| |
| 655 extern UINT32 s_decryptSessionIndex; |
| |
| Index of a session used for audit |
| |
| 656 extern UINT32 s_auditSessionIndex; |
| |
| The cpHash for an audit session |
| |
| 657 extern TPM2B_DIGEST s_cpHashForAudit; |
| |
| The cpHash for command audit |
| |
| 658 #ifdef TPM_CC_GetCommandAuditDigest |
| 659 extern TPM2B_DIGEST s_cpHashForCommandAudit; |
| 660 #endif |
| |
| Number of authorization sessions present in the command |
| |
| 661 extern UINT32 s_sessionNum; |
| |
| Flag indicating if NV update is pending for the lockOutAuthEnabled or failedTries DA parameter |
| |
| 662 extern BOOL s_DAPendingOnNV; |
| 663 #endif // SESSION_PROCESS_C |
| 664 #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C |
| |
| From DA.c |
| |
| Page 26 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| This variable holds the accumulated time since the last time that failedTries was decremented. This value |
| is in millisecond. |
| |
| 665 extern UINT64 s_selfHealTimer; |
| |
| This variable holds the accumulated time that the lockoutAuth has been blocked. |
| |
| 666 extern UINT64 s_lockoutTimer; |
| 667 #endif // DA_C |
| 668 #if defined NV_C || defined GLOBAL_C |
| |
| From NV.c |
| List of pre-defined address of reserved data |
| |
| 669 extern UINT32 s_reservedAddr[NV_RESERVE_LAST]; |
| |
| List of pre-defined reserved data size in byte |
| |
| 670 extern UINT32 s_reservedSize[NV_RESERVE_LAST]; |
| |
| Size of data in RAM index buffer |
| |
| 671 extern UINT32 s_ramIndexSize; |
| |
| Reserved RAM space for frequently updated NV Index. The data layout in ram buffer is {NV_handle(), |
| size of data, data} for each NV index data stored in RAM |
| |
| 672 extern BYTE s_ramIndex[RAM_INDEX_SPACE]; |
| |
| Address of size of RAM index space in NV |
| |
| 673 extern UINT32 s_ramIndexSizeAddr; |
| |
| Address of NV copy of RAM index space |
| |
| 674 extern UINT32 s_ramIndexAddr; |
| |
| Address of maximum counter value; an auxiliary variable to implement NV counters |
| |
| 675 extern UINT32 s_maxCountAddr; |
| |
| Beginning of NV dynamic area; starts right after the s_maxCountAddr and s_evictHandleMapAddr |
| variables |
| |
| 676 extern UINT32 s_evictNvStart; |
| |
| Beginning of NV dynamic area; also the beginning of the predefined reserved data area. |
| |
| 677 extern UINT32 s_evictNvEnd; |
| |
| NV availability is sampled as the start of each command and stored here so that its value remains |
| consistent during the command execution |
| |
| 678 extern TPM_RC s_NvStatus; |
| 679 #endif |
| 680 #if defined OBJECT_C || defined GLOBAL_C |
| |
| From Object.c |
| |
| Family "2.0" TCG Published Page 27 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| This type is the container for an object. |
| |
| 681 typedef struct |
| 682 { |
| 683 BOOL occupied; |
| 684 ANY_OBJECT object; |
| 685 } OBJECT_SLOT; |
| |
| This is the memory that holds the loaded objects. |
| |
| 686 extern OBJECT_SLOT s_objects[MAX_LOADED_OBJECTS]; |
| 687 #endif // OBJECT_C |
| 688 #if defined PCR_C || defined GLOBAL_C |
| |
| From PCR.c |
| |
| 689 typedef struct |
| 690 { |
| 691 #ifdef TPM_ALG_SHA1 |
| 692 // SHA1 PCR |
| 693 BYTE sha1Pcr[SHA1_DIGEST_SIZE]; |
| 694 #endif |
| 695 #ifdef TPM_ALG_SHA256 |
| 696 // SHA256 PCR |
| 697 BYTE sha256Pcr[SHA256_DIGEST_SIZE]; |
| 698 #endif |
| 699 #ifdef TPM_ALG_SHA384 |
| 700 // SHA384 PCR |
| 701 BYTE sha384Pcr[SHA384_DIGEST_SIZE]; |
| 702 #endif |
| 703 #ifdef TPM_ALG_SHA512 |
| 704 // SHA512 PCR |
| 705 BYTE sha512Pcr[SHA512_DIGEST_SIZE]; |
| 706 #endif |
| 707 #ifdef TPM_ALG_SM3_256 |
| 708 // SHA256 PCR |
| 709 BYTE sm3_256Pcr[SM3_256_DIGEST_SIZE]; |
| 710 #endif |
| 711 } PCR; |
| 712 typedef struct |
| 713 { |
| 714 unsigned int stateSave : 1; // if the PCR value should be |
| 715 // saved in state save |
| 716 unsigned int resetLocality : 5; // The locality that the PCR |
| 717 // can be reset |
| 718 unsigned int extendLocality : 5; // The locality that the PCR |
| 719 // can be extend |
| 720 } PCR_Attributes; |
| 721 extern PCR s_pcrs[IMPLEMENTATION_PCR]; |
| 722 #endif // PCR_C |
| 723 #if defined SESSION_C || defined GLOBAL_C |
| |
| From Session.c |
| Container for HMAC or policy session tracking information |
| |
| 724 typedef struct |
| 725 { |
| 726 BOOL occupied; |
| 727 SESSION session; // session structure |
| 728 } SESSION_SLOT; |
| 729 extern SESSION_SLOT s_sessions[MAX_LOADED_SESSIONS]; |
| |
| |
| |
| |
| Page 28 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| The index in conextArray that has the value of the oldest saved session context. When no context is |
| saved, this will have a value that is greater than or equal to MAX_ACTIVE_SESSIONS. |
| |
| 730 extern UINT32 s_oldestSavedSession; |
| |
| The number of available session slot openings. When this is 1, a session can't be created or loaded if the |
| GAP is maxed out. The exception is that the oldest saved session context can always be loaded |
| (assuming that there is a space in memory to put it) |
| |
| 731 extern int s_freeSessionSlots; |
| 732 #endif // SESSION_C |
| |
| From Manufacture.c |
| |
| 733 extern BOOL g_manufactured; |
| 734 #if defined POWER_C || defined GLOBAL_C |
| |
| From Power.c |
| This value indicates if a TPM2_Startup() commands has been receive since the power on event. This |
| flag is maintained in power simulation module because this is the only place that may reliably set this flag |
| to FALSE. |
| |
| 735 extern BOOL s_initialized; |
| 736 #endif // POWER_C |
| 737 #if defined MEMORY_LIB_C || defined GLOBAL_C |
| |
| The s_actionOutputBuffer should not be modifiable by the host system until the TPM has returned a |
| response code. The s_actionOutputBuffer should not be accessible until response parameter encryption, |
| if any, is complete. |
| |
| 738 extern UINT32 s_actionInputBuffer[1024]; // action input buffer |
| 739 extern UINT32 s_actionOutputBuffer[1024]; // action output buffer |
| 740 extern BYTE s_responseBuffer[MAX_RESPONSE_SIZE];// response buffer |
| 741 #endif // MEMORY_LIB_C |
| |
| From TPMFail.c |
| This value holds the address of the string containing the name of the function in which the failure |
| occurred. This address value isn't useful for anything other than helping the vendor to know in which file |
| the failure occurred. |
| |
| 742 extern jmp_buf g_jumpBuffer; // the jump buffer |
| 743 extern BOOL g_inFailureMode; // Indicates that the TPM is in failure mode |
| 744 extern BOOL g_forceFailureMode; // flag to force failure mode during test |
| 745 #if defined TPM_FAIL_C || defined GLOBAL_C || 1 |
| 746 extern UINT32 s_failFunction; |
| 747 extern UINT32 s_failLine; // the line in the file at which |
| 748 // the error was signaled |
| 749 extern UINT32 s_failCode; // the error code used |
| 750 #endif // TPM_FAIL_C |
| 751 #endif // GLOBAL_H |
| |
| |
| 5.9 Tpm.h |
| |
| Root header file for building any TPM.lib code |
| |
| 1 #ifndef _TPM_H_ |
| 2 #define _TPM_H_ |
| 3 #include "bool.h" |
| |
| |
| Family "2.0" TCG Published Page 29 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 4 #include "Implementation.h" |
| 5 #include "TPM_Types.h" |
| 6 #include "swap.h" |
| 7 #endif // _TPM_H_ |
| |
| |
| 5.10 swap.h |
| |
| 1 #ifndef _SWAP_H |
| 2 #define _SWAP_H |
| 3 #include "Implementation.h" |
| 4 #if NO_AUTO_ALIGN == YES || LITTLE_ENDIAN_TPM == YES |
| |
| The aggregation macros for machines that do not allow unaligned access or for little-endian machines. |
| Aggregate bytes into an UINT |
| |
| 5 #define BYTE_ARRAY_TO_UINT8(b) (UINT8)((b)[0]) |
| 6 #define BYTE_ARRAY_TO_UINT16(b) (UINT16)( ((b)[0] << 8) \ |
| 7 + (b)[1]) |
| 8 #define BYTE_ARRAY_TO_UINT32(b) (UINT32)( ((b)[0] << 24) \ |
| 9 + ((b)[1] << 16) \ |
| 10 + ((b)[2] << 8 ) \ |
| 11 + (b)[3]) |
| 12 #define BYTE_ARRAY_TO_UINT64(b) (UINT64)( ((UINT64)(b)[0] << 56) \ |
| 13 + ((UINT64)(b)[1] << 48) \ |
| 14 + ((UINT64)(b)[2] << 40) \ |
| 15 + ((UINT64)(b)[3] << 32) \ |
| 16 + ((UINT64)(b)[4] << 24) \ |
| 17 + ((UINT64)(b)[5] << 16) \ |
| 18 + ((UINT64)(b)[6] << 8) \ |
| 19 + (UINT64)(b)[7]) |
| |
| Disaggregate a UINT into a byte array |
| |
| 20 #define UINT8_TO_BYTE_ARRAY(i, b) ((b)[0] = (BYTE)(i), i) |
| 21 #define UINT16_TO_BYTE_ARRAY(i, b) ((b)[0] = (BYTE)((i) >> 8), \ |
| 22 (b)[1] = (BYTE) (i), \ |
| 23 (i)) |
| 24 #define UINT32_TO_BYTE_ARRAY(i, b) ((b)[0] = (BYTE)((i) >> 24), \ |
| 25 (b)[1] = (BYTE)((i) >> 16), \ |
| 26 (b)[2] = (BYTE)((i) >> 8), \ |
| 27 (b)[3] = (BYTE) (i), \ |
| 28 (i)) |
| 29 #define UINT64_TO_BYTE_ARRAY(i, b) ((b)[0] = (BYTE)((i) >> 56), \ |
| 30 (b)[1] = (BYTE)((i) >> 48), \ |
| 31 (b)[2] = (BYTE)((i) >> 40), \ |
| 32 (b)[3] = (BYTE)((i) >> 32), \ |
| 33 (b)[4] = (BYTE)((i) >> 24), \ |
| 34 (b)[5] = (BYTE)((i) >> 16), \ |
| 35 (b)[6] = (BYTE)((i) >> 8), \ |
| 36 (b)[7] = (BYTE) (i), \ |
| 37 (i)) |
| 38 #else |
| |
| the big-endian macros for machines that allow unaligned memory access Aggregate a byte array into a |
| UINT |
| |
| 39 #define BYTE_ARRAY_TO_UINT8(b) *((UINT8 *)(b)) |
| 40 #define BYTE_ARRAY_TO_UINT16(b) *((UINT16 *)(b)) |
| 41 #define BYTE_ARRAY_TO_UINT32(b) *((UINT32 *)(b)) |
| 42 #define BYTE_ARRAY_TO_UINT64(b) *((UINT64 *)(b)) |
| |
| Disaggregate a UINT into a byte array |
| |
| Page 30 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 43 #define UINT8_TO_BYTE_ARRAY(i, b) (*((UINT8 *)(b)) = (i)) |
| 44 #define UINT16_TO_BYTE_ARRAY(i, b) (*((UINT16 *)(b)) = (i)) |
| 45 #define UINT32_TO_BYTE_ARRAY(i, b) (*((UINT32 *)(b)) = (i)) |
| 46 #define UINT64_TO_BYTE_ARRAY(i, b) (*((UINT64 *)(b)) = (i)) |
| 47 #endif // NO_AUTO_ALIGN == YES |
| 48 #endif // _SWAP_H |
| |
| |
| 5.11 InternalRoutines.h |
| |
| 1 #ifndef INTERNAL_ROUTINES_H |
| 2 #define INTERNAL_ROUTINES_H |
| |
| NULL definition |
| |
| 3 #ifndef NULL |
| 4 #define NULL (0) |
| 5 #endif |
| |
| UNUSED_PARAMETER |
| |
| 6 #ifndef UNUSED_PARAMETER |
| 7 #define UNUSED_PARAMETER(param) (void)(param); |
| 8 #endif |
| |
| Internal data definition |
| |
| 9 #include "Global.h" |
| 10 #include "VendorString.h" |
| |
| Error Reporting |
| |
| 11 #include "TpmError.h" |
| |
| DRTM functions |
| |
| 12 #include "_TPM_Hash_Start_fp.h" |
| 13 #include "_TPM_Hash_Data_fp.h" |
| 14 #include "_TPM_Hash_End_fp.h" |
| |
| Internal subsystem functions |
| |
| 15 #include "Object_fp.h" |
| 16 #include "Entity_fp.h" |
| 17 #include "Session_fp.h" |
| 18 #include "Hierarchy_fp.h" |
| 19 #include "NV_fp.h" |
| 20 #include "PCR_fp.h" |
| 21 #include "DA_fp.h" |
| 22 #include "TpmFail_fp.h" |
| |
| Internal support functions |
| |
| 23 #include "CommandCodeAttributes_fp.h" |
| 24 #include "MemoryLib_fp.h" |
| 25 #include "marshal_fp.h" |
| 26 #include "Time_fp.h" |
| 27 #include "Locality_fp.h" |
| 28 #include "PP_fp.h" |
| 29 #include "CommandAudit_fp.h" |
| 30 #include "Manufacture_fp.h" |
| 31 #include "Power_fp.h" |
| |
| Family "2.0" TCG Published Page 31 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 32 #include "Handle_fp.h" |
| 33 #include "Commands_fp.h" |
| 34 #include "AlgorithmCap_fp.h" |
| 35 #include "PropertyCap_fp.h" |
| 36 #include "Bits_fp.h" |
| |
| Internal crypto functions |
| |
| 37 #include "Ticket_fp.h" |
| 38 #include "CryptUtil_fp.h" |
| 39 #include "CryptSelfTest_fp.h" |
| 40 #endif |
| |
| |
| 5.12 TpmBuildSwitches.h |
| |
| This file contains the build switches. This contains switches for multiple versions of the crypto-library so |
| some may not apply to your environment. |
| |
| 1 #ifndef _TPM_BUILD_SWITCHES_H |
| 2 #define _TPM_BUILD_SWITCHES_H |
| 3 #define SIMULATION |
| 4 #define FIPS_COMPLIANT |
| |
| Define the alignment macro appropriate for the build environment For MS C compiler |
| |
| 5 #define ALIGN_TO(boundary) __declspec(align(boundary)) |
| |
| For ISO 9899:2011 |
| |
| 6 // #define ALIGN_TO(boundary) _Alignas(boundary) |
| |
| This switch enables the RNG state save and restore |
| |
| 7 #undef _DRBG_STATE_SAVE |
| 8 #define _DRBG_STATE_SAVE // Comment this out if no state save is wanted |
| |
| Set the alignment size for the crypto. It would be nice to set this according to macros automatically |
| defined by the build environment, but that doesn't seem possible because there isn't any simple set for |
| that. So, this is just a plugged value. Your compiler should complain if this alignment isn't possible. |
| |
| NOTE: this value can be set at the command line or just plugged in here. |
| |
| 9 #ifdef CRYPTO_ALIGN_16 |
| 10 # define CRYPTO_ALIGNMENT 16 |
| 11 #elif defined CRYPTO_ALIGN_8 |
| 12 # define CRYPTO_ALIGNMENT 8 |
| 13 #eliF defined CRYPTO_ALIGN_2 |
| 14 # define CRYPTO_ALIGNMENT 2 |
| 15 #elif defined CRTYPO_ALIGN_1 |
| 16 # define CRYPTO_ALIGNMENT 1 |
| 17 #else |
| 18 # define CRYPTO_ALIGNMENT 4 // For 32-bit builds |
| 19 #endif |
| 20 #define CRYPTO_ALIGNED ALIGN_TO(CRYPTO_ALIGNMENT) |
| |
| This macro is used to handle LIB_EXPORT of function and variable names in lieu of a .def file |
| |
| 21 #define LIB_EXPORT __declspec(dllexport) |
| 22 // #define LIB_EXPORT |
| |
| |
| |
| Page 32 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| For import of a variable |
| |
| 23 #define LIB_IMPORT __declspec(dllimport) |
| 24 //#define LIB_IMPORT |
| |
| This is defined to indicate a function that does not return. This is used in static code anlaysis. |
| |
| 25 #define _No_Return_ __declspec(noreturn) |
| 26 //#define _No_Return_ |
| 27 #ifdef SELF_TEST |
| 28 #pragma comment(lib, "algorithmtests.lib") |
| 29 #endif |
| |
| The switches in this group can only be enabled when running a simulation |
| |
| 30 #ifdef SIMULATION |
| 31 # define RSA_KEY_CACHE |
| 32 # define TPM_RNG_FOR_DEBUG |
| 33 #else |
| 34 # undef RSA_KEY_CACHE |
| 35 # undef TPM_RNG_FOR_DEBUG |
| 36 #endif // SIMULATION |
| 37 #define INLINE __inline |
| 38 #endif // _TPM_BUILD_SWITCHES_H |
| |
| |
| 5.13 VendorString.h |
| |
| 1 #ifndef _VENDOR_STRING_H |
| 2 #define _VENDOR_STRING_H |
| |
| Define up to 4-byte values for MANUFACTURER. This value defines the response for |
| TPM_PT_MANUFACTURER in TPM2_GetCapability(). The following line should be un-commented and a |
| vendor specific string should be provided here. |
| |
| 3 #define MANUFACTURER "MSFT" |
| |
| The following #if macro may be deleted after a proper MANUFACTURER is provided. |
| |
| 4 #ifndef MANUFACTURER |
| 5 #error MANUFACTURER is not provided. \ |
| 6 Please modify include\VendorString.h to provide a specific \ |
| 7 manufacturer name. |
| 8 #endif |
| |
| Define up to 4, 4-byte values. The values must each be 4 bytes long and the last value used may contain |
| trailing zeros. These values define the response for TPM_PT_VENDOR_STRING_(1-4) in |
| TPM2_GetCapability(). The following line should be un-commented and a vendor specific string should |
| be provided here. The vendor strings 2-4 may also be defined as appropriately. |
| |
| 9 #define VENDOR_STRING_1 "xCG " |
| 10 #define VENDOR_STRING_2 "fTPM" |
| 11 // #define VENDOR_STRING_3 |
| 12 // #define VENDOR_STRING_4 |
| |
| The following #if macro may be deleted after a proper VENDOR_STRING_1 is provided. |
| |
| 13 #ifndef VENDOR_STRING_1 |
| 14 #error VENDOR_STRING_1 is not provided. \ |
| 15 Please modify include\VendorString.h to provide a vednor specific \ |
| 16 string. |
| |
| |
| Family "2.0" TCG Published Page 33 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 17 #endif |
| |
| the more significant 32-bits of a vendor-specific value indicating the version of the firmware The following |
| line should be un-commented and a vendor specific firmware V1 should be provided here. The |
| FIRMWARE_V2 may also be defined as appropriate. |
| |
| 18 #define FIRMWARE_V1 (0x20140504) |
| |
| the less significant 32-bits of a vendor-specific value indicating the version of the firmware |
| |
| 19 #define FIRMWARE_V2 (0x00200136) |
| |
| The following #if macro may be deleted after a proper FIRMWARE_V1 is provided. |
| |
| 20 #ifndef FIRMWARE_V1 |
| 21 #error FIRMWARE_V1 is not provided. \ |
| 22 Please modify include\VendorString.h to provide a vendor specific firmware \ |
| 23 version |
| 24 #endif |
| 25 #endif |
| |
| |
| |
| |
| Page 34 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| 6 Main |
| |
| 6.1 CommandDispatcher.h |
| |
| In the reference implementation, a program that uses TPM 2.0 Part 3 as input automatically generates |
| the command dispatch code. The function prototype header file (CommandDispatcher_fp.h) is shown |
| here. |
| CommandDispatcher() performs the following operations: |
| unmarshals command parameters from the input buffer; |
| invokes the function that performs the command actions; |
| marshals the returned handles, if any; and |
| marshals the returned parameters, if any, into the output buffer putting in the parameterSize field if |
| authorization sessions are present. |
| |
| 1 #ifndef _COMMANDDISPATCHER_FP_H_ |
| 2 #define _COMMANDDISPATCHER_FP_H_ |
| 3 TPM_RC |
| 4 CommandDispatcher( |
| 5 TPMI_ST_COMMAND_TAG tag, // IN: Input command tag |
| 6 TPM_CC commandCode, // IN: Command code |
| 7 INT32 *parmBufferSize, // IN: size of parameter buffer |
| 8 BYTE *parmBufferStart, // IN: pointer to start of parameter buffer |
| 9 TPM_HANDLE handles[], // IN: handle array |
| 10 UINT32 *responseHandleSize,// OUT: size of handle buffer in response |
| 11 UINT32 *respParmSize // OUT: size of parameter buffer in response |
| 12 ); |
| 13 #endif // _COMMANDDISPATCHER_FP_H_ |
| |
| |
| 6.2 ExecCommand.c |
| |
| 6.2.1 Introduction |
| |
| This file contains the entry function ExecuteCommand() which provides the main control flow for TPM |
| command execution. |
| |
| 6.2.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "HandleProcess_fp.h" |
| 3 #include "SessionProcess_fp.h" |
| 4 #include "CommandDispatcher_fp.h" |
| |
| Uncomment this next #include if doing static command/response buffer sizing |
| |
| 5 // #include "CommandResponseSizes_fp.h" |
| |
| |
| 6.2.3 ExecuteCommand() |
| |
| The function performs the following steps. |
| a) Parses the command header from input buffer. |
| b) Calls ParseHandleBuffer() to parse the handle area of the command. |
| c) Validates that each of the handles references a loaded entity. |
| |
| Family "2.0" TCG Published Page 35 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| d) Calls ParseSessionBuffer() () to: |
| 1) unmarshal and parse the session area; |
| 2) check the authorizations; and |
| 3) when necessary, decrypt a parameter. |
| e) Calls CommandDispatcher() to: |
| 1) unmarshal the command parameters from the command buffer; |
| 2) call the routine that performs the command actions; and |
| 3) marshal the responses into the response buffer. |
| f) If any error occurs in any of the steps above create the error response and return. |
| g) Calls BuildResponseSession() to: |
| 1) when necessary, encrypt a parameter |
| 2) build the response authorization sessions |
| 3) update the audit sessions and nonces |
| h) Assembles handle, parameter and session buffers for response and return. |
| |
| 6 LIB_EXPORT void |
| 7 ExecuteCommand( |
| 8 unsigned int requestSize, // IN: command buffer size |
| 9 unsigned char *request, // IN: command buffer |
| 10 unsigned int *responseSize, // OUT: response buffer size |
| 11 unsigned char **response // OUT: response buffer |
| 12 ) |
| 13 { |
| 14 // Command local variables |
| 15 TPM_ST tag; // these first three variables are the |
| 16 UINT32 commandSize; |
| 17 TPM_CC commandCode = 0; |
| 18 |
| 19 BYTE *parmBufferStart; // pointer to the first byte of an |
| 20 // optional parameter buffer |
| 21 |
| 22 UINT32 parmBufferSize = 0;// number of bytes in parameter area |
| 23 |
| 24 UINT32 handleNum = 0; // number of handles unmarshaled into |
| 25 // the handles array |
| 26 |
| 27 TPM_HANDLE handles[MAX_HANDLE_NUM];// array to hold handles in the |
| 28 // command. Only handles in the handle |
| 29 // area are stored here, not handles |
| 30 // passed as parameters. |
| 31 |
| 32 // Response local variables |
| 33 TPM_RC result; // return code for the command |
| 34 |
| 35 TPM_ST resTag; // tag for the response |
| 36 |
| 37 UINT32 resHandleSize = 0; // size of the handle area in the |
| 38 // response. This is needed so that the |
| 39 // handle area can be skipped when |
| 40 // generating the rpHash. |
| 41 |
| 42 UINT32 resParmSize = 0; // the size of the response parameters |
| 43 // These values go in the rpHash. |
| 44 |
| 45 UINT32 resAuthSize = 0; // size of authorization area in the |
| |
| |
| Page 36 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 46 // response |
| 47 |
| 48 INT32 size; // remaining data to be unmarshaled |
| 49 // or remaining space in the marshaling |
| 50 // buffer |
| 51 |
| 52 BYTE *buffer; // pointer into the buffer being used |
| 53 // for marshaling or unmarshaling |
| 54 |
| 55 UINT32 i; // local temp |
| 56 |
| 57 // This next function call is used in development to size the command and response |
| 58 // buffers. The values printed are the sizes of the internal structures and |
| 59 // not the sizes of the canonical forms of the command response structures. Also, |
| 60 // the sizes do not include the tag, commandCode, requestSize, or the authorization |
| 61 // fields. |
| 62 //CommandResponseSizes(); |
| 63 |
| 64 // Set flags for NV access state. This should happen before any other |
| 65 // operation that may require a NV write. Note, that this needs to be done |
| 66 // even when in failure mode. Otherwise, g_updateNV would stay SET while in |
| 67 // Failure mode and the NB would be written on each call. |
| 68 g_updateNV = FALSE; |
| 69 g_clearOrderly = FALSE; |
| 70 |
| 71 // As of Sept 25, 2013, the failure mode handling has been incorporated in the |
| 72 // reference code. This implementation requires that the system support |
| 73 // setjmp/longjmp. This code is put here because of the complexity being |
| 74 // added to the platform and simulator code to deal with all the variations |
| 75 // of errors. |
| 76 if(g_inFailureMode) |
| 77 { |
| 78 // Do failure mode processing |
| 79 TpmFailureMode (requestSize, request, responseSize, response); |
| 80 return; |
| 81 } |
| 82 if(setjmp(g_jumpBuffer) != 0) |
| 83 { |
| 84 // Get here if we got a longjump putting us into failure mode |
| 85 g_inFailureMode = TRUE; |
| 86 result = TPM_RC_FAILURE; |
| 87 goto Fail; |
| 88 } |
| 89 |
| 90 // Assume that everything is going to work. |
| 91 result = TPM_RC_SUCCESS; |
| 92 |
| 93 // Query platform to get the NV state. The result state is saved internally |
| 94 // and will be reported by NvIsAvailable(). The reference code requires that |
| 95 // accessibility of NV does not change during the execution of a command. |
| 96 // Specifically, if NV is available when the command execution starts and then |
| 97 // is not available later when it is necessary to write to NV, then the TPM |
| 98 // will go into failure mode. |
| 99 NvCheckState(); |
| 100 |
| 101 // Due to the limitations of the simulation, TPM clock must be explicitly |
| 102 // synchronized with the system clock whenever a command is received. |
| 103 // This function call is not necessary in a hardware TPM. However, taking |
| 104 // a snapshot of the hardware timer at the beginning of the command allows |
| 105 // the time value to be consistent for the duration of the command execution. |
| 106 TimeUpdateToCurrent(); |
| 107 |
| 108 // Any command through this function will unceremoniously end the |
| 109 // _TPM_Hash_Data/_TPM_Hash_End sequence. |
| 110 if(g_DRTMHandle != TPM_RH_UNASSIGNED) |
| 111 ObjectTerminateEvent(); |
| |
| Family "2.0" TCG Published Page 37 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 112 |
| 113 // Get command buffer size and command buffer. |
| 114 size = requestSize; |
| 115 buffer = request; |
| 116 |
| 117 // Parse command header: tag, commandSize and commandCode. |
| 118 // First parse the tag. The unmarshaling routine will validate |
| 119 // that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS. |
| 120 result = TPMI_ST_COMMAND_TAG_Unmarshal(&tag, &buffer, &size); |
| 121 if(result != TPM_RC_SUCCESS) |
| 122 goto Cleanup; |
| 123 |
| 124 // Unmarshal the commandSize indicator. |
| 125 result = UINT32_Unmarshal(&commandSize, &buffer, &size); |
| 126 if(result != TPM_RC_SUCCESS) |
| 127 goto Cleanup; |
| 128 |
| 129 // On a TPM that receives bytes on a port, the number of bytes that were |
| 130 // received on that port is requestSize it must be identical to commandSize. |
| 131 // In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed |
| 132 // by the implementation. The check against MAX_COMMAND_SIZE may be redundant |
| 133 // as the input processing (the function that receives the command bytes and |
| 134 // places them in the input buffer) would likely have the input truncated when |
| 135 // it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize. |
| 136 if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE) |
| 137 { |
| 138 result = TPM_RC_COMMAND_SIZE; |
| 139 goto Cleanup; |
| 140 } |
| 141 |
| 142 // Unmarshal the command code. |
| 143 result = TPM_CC_Unmarshal(&commandCode, &buffer, &size); |
| 144 if(result != TPM_RC_SUCCESS) |
| 145 goto Cleanup; |
| 146 |
| 147 // Check to see if the command is implemented. |
| 148 if(!CommandIsImplemented(commandCode)) |
| 149 { |
| 150 result = TPM_RC_COMMAND_CODE; |
| 151 goto Cleanup; |
| 152 } |
| 153 |
| 154 #if FIELD_UPGRADE_IMPLEMENTED == YES |
| 155 // If the TPM is in FUM, then the only allowed command is |
| 156 // TPM_CC_FieldUpgradeData. |
| 157 if(IsFieldUgradeMode() && (commandCode != TPM_CC_FieldUpgradeData)) |
| 158 { |
| 159 result = TPM_RC_UPGRADE; |
| 160 goto Cleanup; |
| 161 } |
| 162 else |
| 163 #endif |
| 164 // Excepting FUM, the TPM only accepts TPM2_Startup() after |
| 165 // _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup() |
| 166 // is no longer allowed. |
| 167 if(( !TPMIsStarted() && commandCode != TPM_CC_Startup) |
| 168 || (TPMIsStarted() && commandCode == TPM_CC_Startup)) |
| 169 { |
| 170 result = TPM_RC_INITIALIZE; |
| 171 goto Cleanup; |
| 172 } |
| 173 |
| 174 // Start regular command process. |
| 175 // Parse Handle buffer. |
| 176 result = ParseHandleBuffer(commandCode, &buffer, &size, handles, &handleNum); |
| 177 if(result != TPM_RC_SUCCESS) |
| |
| Page 38 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 178 goto Cleanup; |
| 179 |
| 180 // Number of handles retrieved from handle area should be less than |
| 181 // MAX_HANDLE_NUM. |
| 182 pAssert(handleNum <= MAX_HANDLE_NUM); |
| 183 |
| 184 // All handles in the handle area are required to reference TPM-resident |
| 185 // entities. |
| 186 for(i = 0; i < handleNum; i++) |
| 187 { |
| 188 result = EntityGetLoadStatus(&handles[i], commandCode); |
| 189 if(result != TPM_RC_SUCCESS) |
| 190 { |
| 191 if(result == TPM_RC_REFERENCE_H0) |
| 192 result = result + i; |
| 193 else |
| 194 result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]); |
| 195 goto Cleanup; |
| 196 } |
| 197 } |
| 198 |
| 199 // Authorization session handling for the command. |
| 200 if(tag == TPM_ST_SESSIONS) |
| 201 { |
| 202 BYTE *sessionBufferStart;// address of the session area first byte |
| 203 // in the input buffer |
| 204 |
| 205 UINT32 authorizationSize; // number of bytes in the session area |
| 206 |
| 207 // Find out session buffer size. |
| 208 result = UINT32_Unmarshal(&authorizationSize, &buffer, &size); |
| 209 if(result != TPM_RC_SUCCESS) |
| 210 goto Cleanup; |
| 211 |
| 212 // Perform sanity check on the unmarshaled value. If it is smaller than |
| 213 // the smallest possible session or larger than the remaining size of |
| 214 // the command, then it is an error. NOTE: This check could pass but the |
| 215 // session size could still be wrong. That will be determined after the |
| 216 // sessions are unmarshaled. |
| 217 if( authorizationSize < 9 |
| 218 || authorizationSize > (UINT32) size) |
| 219 { |
| 220 result = TPM_RC_SIZE; |
| 221 goto Cleanup; |
| 222 } |
| 223 |
| 224 // The sessions, if any, follows authorizationSize. |
| 225 sessionBufferStart = buffer; |
| 226 |
| 227 // The parameters follow the session area. |
| 228 parmBufferStart = sessionBufferStart + authorizationSize; |
| 229 |
| 230 // Any data left over after removing the authorization sessions is |
| 231 // parameter data. If the command does not have parameters, then an |
| 232 // error will be returned if the remaining size is not zero. This is |
| 233 // checked later. |
| 234 parmBufferSize = size - authorizationSize; |
| 235 |
| 236 // The actions of ParseSessionBuffer() are described in the introduction. |
| 237 result = ParseSessionBuffer(commandCode, |
| 238 handleNum, |
| 239 handles, |
| 240 sessionBufferStart, |
| 241 authorizationSize, |
| 242 parmBufferStart, |
| 243 parmBufferSize); |
| |
| Family "2.0" TCG Published Page 39 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 244 if(result != TPM_RC_SUCCESS) |
| 245 goto Cleanup; |
| 246 } |
| 247 else |
| 248 { |
| 249 // Whatever remains in the input buffer is used for the parameters of the |
| 250 // command. |
| 251 parmBufferStart = buffer; |
| 252 parmBufferSize = size; |
| 253 |
| 254 // The command has no authorization sessions. |
| 255 // If the command requires authorizations, then CheckAuthNoSession() will |
| 256 // return an error. |
| 257 result = CheckAuthNoSession(commandCode, handleNum, handles, |
| 258 parmBufferStart, parmBufferSize); |
| 259 if(result != TPM_RC_SUCCESS) |
| 260 goto Cleanup; |
| 261 } |
| 262 |
| 263 // CommandDispatcher returns a response handle buffer and a response parameter |
| 264 // buffer if it succeeds. It will also set the parameterSize field in the |
| 265 // buffer if the tag is TPM_RC_SESSIONS. |
| 266 result = CommandDispatcher(tag, |
| 267 commandCode, |
| 268 (INT32 *) &parmBufferSize, |
| 269 parmBufferStart, |
| 270 handles, |
| 271 &resHandleSize, |
| 272 &resParmSize); |
| 273 if(result != TPM_RC_SUCCESS) |
| 274 goto Cleanup; |
| 275 |
| 276 // Build the session area at the end of the parameter area. |
| 277 BuildResponseSession(tag, |
| 278 commandCode, |
| 279 resHandleSize, |
| 280 resParmSize, |
| 281 &resAuthSize); |
| 282 |
| 283 Cleanup: |
| 284 // This implementation loads an "evict" object to a transient object slot in |
| 285 // RAM whenever an "evict" object handle is used in a command so that the |
| 286 // access to any object is the same. These temporary objects need to be |
| 287 // cleared from RAM whether the command succeeds or fails. |
| 288 ObjectCleanupEvict(); |
| 289 |
| 290 Fail: |
| 291 // The response will contain at least a response header. |
| 292 *responseSize = sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC); |
| 293 |
| 294 // If the command completed successfully, then build the rest of the response. |
| 295 if(result == TPM_RC_SUCCESS) |
| 296 { |
| 297 // Outgoing tag will be the same as the incoming tag. |
| 298 resTag = tag; |
| 299 // The overall response will include the handles, parameters, |
| 300 // and authorizations. |
| 301 *responseSize += resHandleSize + resParmSize + resAuthSize; |
| 302 |
| 303 // Adding parameter size field. |
| 304 if(tag == TPM_ST_SESSIONS) |
| 305 *responseSize += sizeof(UINT32); |
| 306 |
| 307 if( g_clearOrderly == TRUE |
| 308 && gp.orderlyState != SHUTDOWN_NONE) |
| 309 { |
| |
| Page 40 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 310 gp.orderlyState = SHUTDOWN_NONE; |
| 311 NvWriteReserved(NV_ORDERLY, &gp.orderlyState); |
| 312 g_updateNV = TRUE; |
| 313 } |
| 314 } |
| 315 else |
| 316 { |
| 317 // The command failed. |
| 318 // If this was a failure due to a bad command tag, then need to return |
| 319 // a TPM 1.2 compatible response |
| 320 if(result == TPM_RC_BAD_TAG) |
| 321 resTag = TPM_ST_RSP_COMMAND; |
| 322 else |
| 323 // return 2.0 compatible response |
| 324 resTag = TPM_ST_NO_SESSIONS; |
| 325 } |
| 326 // Try to commit all the writes to NV if any NV write happened during this |
| 327 // command execution. This check should be made for both succeeded and failed |
| 328 // commands, because a failed one may trigger a NV write in DA logic as well. |
| 329 // This is the only place in the command execution path that may call the NV |
| 330 // commit. If the NV commit fails, the TPM should be put in failure mode. |
| 331 if(g_updateNV && !g_inFailureMode) |
| 332 { |
| 333 g_updateNV = FALSE; |
| 334 if(!NvCommit()) |
| 335 FAIL(FATAL_ERROR_INTERNAL); |
| 336 } |
| 337 |
| 338 // Marshal the response header. |
| 339 buffer = MemoryGetResponseBuffer(commandCode); |
| 340 TPM_ST_Marshal(&resTag, &buffer, NULL); |
| 341 UINT32_Marshal((UINT32 *)responseSize, &buffer, NULL); |
| 342 pAssert(*responseSize <= MAX_RESPONSE_SIZE); |
| 343 TPM_RC_Marshal(&result, &buffer, NULL); |
| 344 |
| 345 *response = MemoryGetResponseBuffer(commandCode); |
| 346 |
| 347 // Clear unused bit in response buffer. |
| 348 MemorySet(*response + *responseSize, 0, MAX_RESPONSE_SIZE - *responseSize); |
| 349 |
| 350 return; |
| 351 } |
| |
| |
| 6.3 ParseHandleBuffer.h |
| |
| In the reference implementation, the routine for unmarshaling the command handles is automatically |
| generated from TPM 2.0 Part 3 command tables. The prototype header file (HandleProcess_fp.h) is |
| shown here. |
| |
| 1 #ifndef _HANDLEPROCESS_FP_H_ |
| 2 #define _HANDLEPROCESS_FP_H_ |
| 3 TPM_RC |
| 4 ParseHandleBuffer( |
| 5 TPM_CC commandCode, // IN: Command being processed |
| 6 BYTE **handleBufferStart, // IN/OUT: command buffer where handles |
| 7 // are located. Updated as handles |
| 8 // are unmarshaled |
| 9 INT32 *bufferRemainingSize, // IN/OUT: indicates the amount of data |
| 10 // left in the command buffer. |
| 11 // Updated as handles are unmarshaled |
| 12 TPM_HANDLE handles[], // OUT: Array that receives the handles |
| 13 UINT32 *handleCount // OUT: Receives the count of handles |
| 14 ); |
| 15 #endif // _HANDLEPROCESS_FP_H_ |
| |
| Family "2.0" TCG Published Page 41 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 6.4 SessionProcess.c |
| |
| 6.4.1 Introduction |
| |
| This file contains the subsystem that process the authorization sessions including implementation of the |
| Dictionary Attack logic. ExecCommand() uses ParseSessionBuffer() to process the authorization session |
| area of a command and BuildResponseSession() to create the authorization session area of a response. |
| |
| 6.4.2 Includes and Data Definitions |
| |
| 1 #define SESSION_PROCESS_C |
| 2 #include "InternalRoutines.h" |
| 3 #include "SessionProcess_fp.h" |
| 4 #include "Platform.h" |
| |
| |
| 6.4.3 Authorization Support Functions |
| |
| 6.4.3.1 IsDAExempted() |
| |
| This function indicates if a handle is exempted from DA logic. A handle is exempted if it is |
| a) a primary seed handle, |
| b) an object with noDA bit SET, |
| c) an NV Index with TPMA_NV_NO_DA bit SET, or |
| d) a PCR handle. |
| |
| Return Value Meaning |
| |
| TRUE handle is exempted from DA logic |
| FALSE handle is not exempted from DA logic |
| |
| 5 BOOL |
| 6 IsDAExempted( |
| 7 TPM_HANDLE handle // IN: entity handle |
| 8 ) |
| 9 { |
| 10 BOOL result = FALSE; |
| 11 |
| 12 switch(HandleGetType(handle)) |
| 13 { |
| 14 case TPM_HT_PERMANENT: |
| 15 // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from |
| 16 // DA protection. |
| 17 result = (handle != TPM_RH_LOCKOUT); |
| 18 break; |
| 19 |
| 20 // When this function is called, a persistent object will have been loaded |
| 21 // into an object slot and assigned a transient handle. |
| 22 case TPM_HT_TRANSIENT: |
| 23 { |
| 24 OBJECT *object; |
| 25 object = ObjectGet(handle); |
| 26 result = (object->publicArea.objectAttributes.noDA == SET); |
| 27 break; |
| 28 } |
| 29 case TPM_HT_NV_INDEX: |
| 30 { |
| 31 NV_INDEX nvIndex; |
| |
| Page 42 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 32 NvGetIndexInfo(handle, &nvIndex); |
| 33 result = (nvIndex.publicArea.attributes.TPMA_NV_NO_DA == SET); |
| 34 break; |
| 35 } |
| 36 case TPM_HT_PCR: |
| 37 // PCRs are always exempted from DA. |
| 38 result = TRUE; |
| 39 break; |
| 40 default: |
| 41 break; |
| 42 } |
| 43 return result; |
| 44 } |
| |
| |
| 6.4.3.2 IncrementLockout() |
| |
| This function is called after an authorization failure that involves use of an authValue. If the entity |
| referenced by the handle is not exempt from DA protection, then the failedTries counter will be |
| incremented. |
| |
| Error Returns Meaning |
| |
| TPM_RC_AUTH_FAIL authorization failure that caused DA lockout to increment |
| TPM_RC_BAD_AUTH authorization failure did not cause DA lockout to increment |
| |
| 45 static TPM_RC |
| 46 IncrementLockout( |
| 47 UINT32 sessionIndex |
| 48 ) |
| 49 { |
| 50 TPM_HANDLE handle = s_associatedHandles[sessionIndex]; |
| 51 TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; |
| 52 TPM_RC result; |
| 53 SESSION *session = NULL; |
| 54 |
| 55 // Don't increment lockout unless the handle associated with the session |
| 56 // is DA protected or the session is bound to a DA protected entity. |
| 57 if(sessionHandle == TPM_RS_PW) |
| 58 { |
| 59 if(IsDAExempted(handle)) |
| 60 return TPM_RC_BAD_AUTH; |
| 61 |
| 62 } |
| 63 else |
| 64 { |
| 65 session = SessionGet(sessionHandle); |
| 66 // If the session is bound to lockout, then use that as the relevant |
| 67 // handle. This means that an auth failure with a bound session |
| 68 // bound to lockoutAuth will take precedence over any other |
| 69 // lockout check |
| 70 if(session->attributes.isLockoutBound == SET) |
| 71 handle = TPM_RH_LOCKOUT; |
| 72 |
| 73 if( session->attributes.isDaBound == CLEAR |
| 74 && IsDAExempted(handle) |
| 75 ) |
| 76 // If the handle was changed to TPM_RH_LOCKOUT, this will not return |
| 77 // TPM_RC_BAD_AUTH |
| 78 return TPM_RC_BAD_AUTH; |
| 79 |
| 80 } |
| 81 |
| 82 if(handle == TPM_RH_LOCKOUT) |
| |
| Family "2.0" TCG Published Page 43 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 83 { |
| 84 pAssert(gp.lockOutAuthEnabled); |
| 85 gp.lockOutAuthEnabled = FALSE; |
| 86 // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since |
| 87 // the lockout auth will be reset at startup. |
| 88 if(gp.lockoutRecovery != 0) |
| 89 { |
| 90 result = NvIsAvailable(); |
| 91 if(result != TPM_RC_SUCCESS) |
| 92 { |
| 93 // No NV access for now. Put the TPM in pending mode. |
| 94 s_DAPendingOnNV = TRUE; |
| 95 } |
| 96 else |
| 97 { |
| 98 // Update NV. |
| 99 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); |
| 100 g_updateNV = TRUE; |
| 101 } |
| 102 } |
| 103 } |
| 104 else |
| 105 { |
| 106 if(gp.recoveryTime != 0) |
| 107 { |
| 108 gp.failedTries++; |
| 109 result = NvIsAvailable(); |
| 110 if(result != TPM_RC_SUCCESS) |
| 111 { |
| 112 // No NV access for now. Put the TPM in pending mode. |
| 113 s_DAPendingOnNV = TRUE; |
| 114 } |
| 115 else |
| 116 { |
| 117 // Record changes to NV. |
| 118 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 119 g_updateNV = TRUE; |
| 120 } |
| 121 } |
| 122 } |
| 123 |
| 124 // Register a DA failure and reset the timers. |
| 125 DARegisterFailure(handle); |
| 126 |
| 127 return TPM_RC_AUTH_FAIL; |
| 128 } |
| |
| |
| 6.4.3.3 IsSessionBindEntity() |
| |
| This function indicates if the entity associated with the handle is the entity, to which this session is bound. |
| The binding would occur by making the bind parameter in TPM2_StartAuthSession() not equal to |
| TPM_RH_NULL. The binding only occurs if the session is an HMAC session. The bind value is a |
| combination of the Name and the authValue of the entity. |
| |
| Return Value Meaning |
| |
| TRUE handle points to the session start entity |
| FALSE handle does not point to the session start entity |
| |
| 129 static BOOL |
| 130 IsSessionBindEntity( |
| 131 TPM_HANDLE associatedHandle, // IN: handle to be authorized |
| 132 SESSION *session // IN: associated session |
| |
| Page 44 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 133 ) |
| 134 { |
| 135 TPM2B_NAME entity; // The bind value for the entity |
| 136 |
| 137 // If the session is not bound, return FALSE. |
| 138 if(!session->attributes.isBound) |
| 139 return FALSE; |
| 140 |
| 141 // Compute the bind value for the entity. |
| 142 SessionComputeBoundEntity(associatedHandle, &entity); |
| 143 |
| 144 // Compare to the bind value in the session. |
| 145 session->attributes.requestWasBound = |
| 146 Memory2BEqual(&entity.b, &session->u1.boundEntity.b); |
| 147 return session->attributes.requestWasBound; |
| 148 } |
| |
| |
| 6.4.3.4 IsPolicySessionRequired() |
| |
| Checks if a policy session is required for a command. If a command requires DUP or ADMIN role |
| authorization, then the handle that requires that role is the first handle in the command. This simplifies |
| this checking. If a new command is created that requires multiple ADMIN role authorizations, then it will |
| have to be special-cased in this function. A policy session is required if: |
| a) the command requires the DUP role, |
| b) the command requires the ADMIN role and the authorized entity is an object and its adminWithPolicy |
| bit is SET, or |
| c) the command requires the ADMIN role and the authorized entity is a permanent handle or an NV |
| Index. |
| d) The authorized entity is a PCR belonging to a policy group, and has its policy initialized |
| |
| Return Value Meaning |
| |
| TRUE policy session is required |
| FALSE policy session is not required |
| |
| 149 static BOOL |
| 150 IsPolicySessionRequired( |
| 151 TPM_CC commandCode, // IN: command code |
| 152 UINT32 sessionIndex // IN: session index |
| 153 ) |
| 154 { |
| 155 AUTH_ROLE role = CommandAuthRole(commandCode, sessionIndex); |
| 156 TPM_HT type = HandleGetType(s_associatedHandles[sessionIndex]); |
| 157 |
| 158 if(role == AUTH_DUP) |
| 159 return TRUE; |
| 160 |
| 161 if(role == AUTH_ADMIN) |
| 162 { |
| 163 if(type == TPM_HT_TRANSIENT) |
| 164 { |
| 165 OBJECT *object = ObjectGet(s_associatedHandles[sessionIndex]); |
| 166 |
| 167 if(object->publicArea.objectAttributes.adminWithPolicy == CLEAR) |
| 168 return FALSE; |
| 169 } |
| 170 return TRUE; |
| 171 } |
| 172 |
| |
| |
| Family "2.0" TCG Published Page 45 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 173 if(type == TPM_HT_PCR) |
| 174 { |
| 175 if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex])) |
| 176 { |
| 177 TPM2B_DIGEST policy; |
| 178 TPMI_ALG_HASH policyAlg; |
| 179 policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex], |
| 180 &policy); |
| 181 if(policyAlg != TPM_ALG_NULL) |
| 182 return TRUE; |
| 183 } |
| 184 } |
| 185 return FALSE; |
| 186 } |
| |
| |
| 6.4.3.5 IsAuthValueAvailable() |
| |
| This function indicates if authValue is available and allowed for USER role authorization of an entity. |
| This function is similar to IsAuthPolicyAvailable() except that it does not check the size of the authValue |
| as IsAuthPolicyAvailable() does (a null authValue is a valid auth, but a null policy is not a valid policy). |
| This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy. |
| Those checks are assumed to have been performed during the handle unmarshaling. |
| |
| Return Value Meaning |
| |
| TRUE authValue is available |
| FALSE authValue is not available |
| |
| 187 static BOOL |
| 188 IsAuthValueAvailable( |
| 189 TPM_HANDLE handle, // IN: handle of entity |
| 190 TPM_CC commandCode, // IN: commandCode |
| 191 UINT32 sessionIndex // IN: session index |
| 192 ) |
| 193 { |
| 194 BOOL result = FALSE; |
| 195 // If a policy session is required, the entity can not be authorized by |
| 196 // authValue. However, at this point, the policy session requirement should |
| 197 // already have been checked. |
| 198 pAssert(!IsPolicySessionRequired(commandCode, sessionIndex)); |
| 199 |
| 200 switch(HandleGetType(handle)) |
| 201 { |
| 202 case TPM_HT_PERMANENT: |
| 203 switch(handle) |
| 204 { |
| 205 // At this point hierarchy availability has already been |
| 206 // checked so primary seed handles are always available here |
| 207 case TPM_RH_OWNER: |
| 208 case TPM_RH_ENDORSEMENT: |
| 209 case TPM_RH_PLATFORM: |
| 210 #ifdef VENDOR_PERMANENT |
| 211 // This vendor defined handle associated with the |
| 212 // manufacturer's shared secret |
| 213 case VENDOR_PERMANENT: |
| 214 #endif |
| 215 // NullAuth is always available. |
| 216 case TPM_RH_NULL: |
| 217 // At the point when authValue availability is checked, control |
| 218 // path has already passed the DA check so LockOut auth is |
| 219 // always available here |
| 220 case TPM_RH_LOCKOUT: |
| |
| Page 46 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 221 |
| 222 result = TRUE; |
| 223 break; |
| 224 default: |
| 225 // Otherwise authValue is not available. |
| 226 break; |
| 227 } |
| 228 break; |
| 229 case TPM_HT_TRANSIENT: |
| 230 // A persistent object has already been loaded and the internal |
| 231 // handle changed. |
| 232 { |
| 233 OBJECT *object; |
| 234 object = ObjectGet(handle); |
| 235 |
| 236 // authValue is always available for a sequence object. |
| 237 if(ObjectIsSequence(object)) |
| 238 { |
| 239 result = TRUE; |
| 240 break; |
| 241 } |
| 242 // authValue is available for an object if it has its sensitive |
| 243 // portion loaded and |
| 244 // 1. userWithAuth bit is SET, or |
| 245 // 2. ADMIN role is required |
| 246 if( object->attributes.publicOnly == CLEAR |
| 247 && (object->publicArea.objectAttributes.userWithAuth == SET |
| 248 || (CommandAuthRole(commandCode, sessionIndex) == AUTH_ADMIN |
| 249 && object->publicArea.objectAttributes.adminWithPolicy |
| 250 == CLEAR))) |
| 251 result = TRUE; |
| 252 } |
| 253 break; |
| 254 case TPM_HT_NV_INDEX: |
| 255 // NV Index. |
| 256 { |
| 257 NV_INDEX nvIndex; |
| 258 NvGetIndexInfo(handle, &nvIndex); |
| 259 if(IsWriteOperation(commandCode)) |
| 260 { |
| 261 if (nvIndex.publicArea.attributes.TPMA_NV_AUTHWRITE == SET) |
| 262 result = TRUE; |
| 263 |
| 264 } |
| 265 else |
| 266 { |
| 267 if (nvIndex.publicArea.attributes.TPMA_NV_AUTHREAD == SET) |
| 268 result = TRUE; |
| 269 } |
| 270 } |
| 271 break; |
| 272 case TPM_HT_PCR: |
| 273 // PCR handle. |
| 274 // authValue is always allowed for PCR |
| 275 result = TRUE; |
| 276 break; |
| 277 default: |
| 278 // Otherwise, authValue is not available |
| 279 break; |
| 280 } |
| 281 return result; |
| 282 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 47 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 6.4.3.6 IsAuthPolicyAvailable() |
| |
| This function indicates if an authPolicy is available and allowed. |
| This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy. |
| Those checks are assumed to have been performed during the handle unmarshaling. |
| |
| Return Value Meaning |
| |
| TRUE authPolicy is available |
| FALSE authPolicy is not available |
| |
| 283 static BOOL |
| 284 IsAuthPolicyAvailable( |
| 285 TPM_HANDLE handle, // IN: handle of entity |
| 286 TPM_CC commandCode, // IN: commandCode |
| 287 UINT32 sessionIndex // IN: session index |
| 288 ) |
| 289 { |
| 290 BOOL result = FALSE; |
| 291 switch(HandleGetType(handle)) |
| 292 { |
| 293 case TPM_HT_PERMANENT: |
| 294 switch(handle) |
| 295 { |
| 296 // At this point hierarchy availability has already been checked. |
| 297 case TPM_RH_OWNER: |
| 298 if (gp.ownerPolicy.t.size != 0) |
| 299 result = TRUE; |
| 300 break; |
| 301 |
| 302 case TPM_RH_ENDORSEMENT: |
| 303 if (gp.endorsementPolicy.t.size != 0) |
| 304 result = TRUE; |
| 305 break; |
| 306 |
| 307 case TPM_RH_PLATFORM: |
| 308 if (gc.platformPolicy.t.size != 0) |
| 309 result = TRUE; |
| 310 break; |
| 311 case TPM_RH_LOCKOUT: |
| 312 if(gp.lockoutPolicy.t.size != 0) |
| 313 result = TRUE; |
| 314 break; |
| 315 default: |
| 316 break; |
| 317 } |
| 318 break; |
| 319 case TPM_HT_TRANSIENT: |
| 320 { |
| 321 // Object handle. |
| 322 // An evict object would already have been loaded and given a |
| 323 // transient object handle by this point. |
| 324 OBJECT *object = ObjectGet(handle); |
| 325 // Policy authorization is not available for an object with only |
| 326 // public portion loaded. |
| 327 if(object->attributes.publicOnly == CLEAR) |
| 328 { |
| 329 // Policy authorization is always available for an object but |
| 330 // is never available for a sequence. |
| 331 if(!ObjectIsSequence(object)) |
| 332 result = TRUE; |
| 333 } |
| 334 break; |
| |
| Page 48 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 335 } |
| 336 case TPM_HT_NV_INDEX: |
| 337 // An NV Index. |
| 338 { |
| 339 NV_INDEX nvIndex; |
| 340 NvGetIndexInfo(handle, &nvIndex); |
| 341 // If the policy size is not zero, check if policy can be used. |
| 342 if(nvIndex.publicArea.authPolicy.t.size != 0) |
| 343 { |
| 344 // If policy session is required for this handle, always |
| 345 // uses policy regardless of the attributes bit setting |
| 346 if(IsPolicySessionRequired(commandCode, sessionIndex)) |
| 347 result = TRUE; |
| 348 // Otherwise, the presence of the policy depends on the NV |
| 349 // attributes. |
| 350 else if(IsWriteOperation(commandCode)) |
| 351 { |
| 352 if ( nvIndex.publicArea.attributes.TPMA_NV_POLICYWRITE |
| 353 == SET) |
| 354 result = TRUE; |
| 355 } |
| 356 else |
| 357 { |
| 358 if ( nvIndex.publicArea.attributes.TPMA_NV_POLICYREAD |
| 359 == SET) |
| 360 result = TRUE; |
| 361 } |
| 362 } |
| 363 } |
| 364 break; |
| 365 case TPM_HT_PCR: |
| 366 // PCR handle. |
| 367 if(PCRPolicyIsAvailable(handle)) |
| 368 result = TRUE; |
| 369 break; |
| 370 default: |
| 371 break; |
| 372 } |
| 373 return result; |
| 374 } |
| |
| |
| 6.4.4 Session Parsing Functions |
| |
| 6.4.4.1 ComputeCpHash() |
| |
| This function computes the cpHash as defined in Part 2 and described in Part 1. |
| |
| 375 static void |
| 376 ComputeCpHash( |
| 377 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 378 TPM_CC commandCode, // IN: command code |
| 379 UINT32 handleNum, // IN: number of handle |
| 380 TPM_HANDLE handles[], // IN: array of handle |
| 381 UINT32 parmBufferSize, // IN: size of input parameter area |
| 382 BYTE *parmBuffer, // IN: input parameter area |
| 383 TPM2B_DIGEST *cpHash, // OUT: cpHash |
| 384 TPM2B_DIGEST *nameHash // OUT: name hash of command |
| 385 ) |
| 386 { |
| 387 UINT32 i; |
| 388 HASH_STATE hashState; |
| 389 TPM2B_NAME name; |
| 390 |
| |
| |
| Family "2.0" TCG Published Page 49 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 391 // cpHash = hash(commandCode [ || authName1 |
| 392 // [ || authName2 |
| 393 // [ || authName 3 ]]] |
| 394 // [ || parameters]) |
| 395 // A cpHash can contain just a commandCode only if the lone session is |
| 396 // an audit session. |
| 397 |
| 398 // Start cpHash. |
| 399 cpHash->t.size = CryptStartHash(hashAlg, &hashState); |
| 400 |
| 401 // Add commandCode. |
| 402 CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode); |
| 403 |
| 404 // Add authNames for each of the handles. |
| 405 for(i = 0; i < handleNum; i++) |
| 406 { |
| 407 name.t.size = EntityGetName(handles[i], &name.t.name); |
| 408 CryptUpdateDigest2B(&hashState, &name.b); |
| 409 } |
| 410 |
| 411 // Add the parameters. |
| 412 CryptUpdateDigest(&hashState, parmBufferSize, parmBuffer); |
| 413 |
| 414 // Complete the hash. |
| 415 CryptCompleteHash2B(&hashState, &cpHash->b); |
| 416 |
| 417 // If the nameHash is needed, compute it here. |
| 418 if(nameHash != NULL) |
| 419 { |
| 420 // Start name hash. hashState may be reused. |
| 421 nameHash->t.size = CryptStartHash(hashAlg, &hashState); |
| 422 |
| 423 // Adding names. |
| 424 for(i = 0; i < handleNum; i++) |
| 425 { |
| 426 name.t.size = EntityGetName(handles[i], &name.t.name); |
| 427 CryptUpdateDigest2B(&hashState, &name.b); |
| 428 } |
| 429 // Complete hash. |
| 430 CryptCompleteHash2B(&hashState, &nameHash->b); |
| 431 } |
| 432 return; |
| 433 } |
| |
| |
| 6.4.4.2 CheckPWAuthSession() |
| |
| This function validates the authorization provided in a PWAP session. It compares the input value to |
| authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the |
| referenced entities from s_inputAuthValues[] and s_associatedHandles[]. |
| |
| Error Returns Meaning |
| |
| TPM_RC_AUTH_FAIL auth fails and increments DA failure count |
| TPM_RC_BAD_AUTH auth fails but DA does not apply |
| |
| 434 static TPM_RC |
| 435 CheckPWAuthSession( |
| 436 UINT32 sessionIndex // IN: index of session to be processed |
| 437 ) |
| 438 { |
| 439 TPM2B_AUTH authValue; |
| 440 TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; |
| 441 |
| |
| Page 50 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 442 // Strip trailing zeros from the password. |
| 443 MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]); |
| 444 |
| 445 // Get the auth value and size. |
| 446 authValue.t.size = EntityGetAuthValue(associatedHandle, &authValue.t.buffer); |
| 447 |
| 448 // Success if the digests are identical. |
| 449 if(Memory2BEqual(&s_inputAuthValues[sessionIndex].b, &authValue.b)) |
| 450 { |
| 451 return TPM_RC_SUCCESS; |
| 452 } |
| 453 else // if the digests are not identical |
| 454 { |
| 455 // Invoke DA protection if applicable. |
| 456 return IncrementLockout(sessionIndex); |
| 457 } |
| 458 } |
| |
| |
| 6.4.4.3 ComputeCommandHMAC() |
| |
| This function computes the HMAC for an authorization session in a command. |
| |
| 459 static void |
| 460 ComputeCommandHMAC( |
| 461 UINT32 sessionIndex, // IN: index of session to be processed |
| 462 TPM2B_DIGEST *cpHash, // IN: cpHash |
| 463 TPM2B_DIGEST *hmac // OUT: authorization HMAC |
| 464 ) |
| 465 { |
| 466 TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); |
| 467 TPM2B_KEY key; |
| 468 BYTE marshalBuffer[sizeof(TPMA_SESSION)]; |
| 469 BYTE *buffer; |
| 470 UINT32 marshalSize; |
| 471 HMAC_STATE hmacState; |
| 472 TPM2B_NONCE *nonceDecrypt; |
| 473 TPM2B_NONCE *nonceEncrypt; |
| 474 SESSION *session; |
| 475 TPM_HT sessionHandleType = |
| 476 HandleGetType(s_sessionHandles[sessionIndex]); |
| 477 |
| 478 nonceDecrypt = NULL; |
| 479 nonceEncrypt = NULL; |
| 480 |
| 481 // Determine if extra nonceTPM values are going to be required. |
| 482 // If this is the first session (sessionIndex = 0) and it is an authorization |
| 483 // session that uses an HMAC, then check if additional session nonces are to be |
| 484 // included. |
| 485 if( sessionIndex == 0 |
| 486 && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) |
| 487 { |
| 488 // If there is a decrypt session and if this is not the decrypt session, |
| 489 // then an extra nonce may be needed. |
| 490 if( s_decryptSessionIndex != UNDEFINED_INDEX |
| 491 && s_decryptSessionIndex != sessionIndex) |
| 492 { |
| 493 // Will add the nonce for the decrypt session. |
| 494 SESSION *decryptSession |
| 495 = SessionGet(s_sessionHandles[s_decryptSessionIndex]); |
| 496 nonceDecrypt = &decryptSession->nonceTPM; |
| 497 } |
| 498 // Now repeat for the encrypt session. |
| 499 if( s_encryptSessionIndex != UNDEFINED_INDEX |
| 500 && s_encryptSessionIndex != sessionIndex |
| |
| |
| Family "2.0" TCG Published Page 51 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 501 && s_encryptSessionIndex != s_decryptSessionIndex) |
| 502 { |
| 503 // Have to have the nonce for the encrypt session. |
| 504 SESSION *encryptSession |
| 505 = SessionGet(s_sessionHandles[s_encryptSessionIndex]); |
| 506 nonceEncrypt = &encryptSession->nonceTPM; |
| 507 } |
| 508 } |
| 509 |
| 510 // Continue with the HMAC processing. |
| 511 session = SessionGet(s_sessionHandles[sessionIndex]); |
| 512 |
| 513 // Generate HMAC key. |
| 514 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); |
| 515 |
| 516 // Check if the session has an associated handle and if the associated entity |
| 517 // is the one to which the session is bound. If not, add the authValue of |
| 518 // this entity to the HMAC key. |
| 519 // If the session is bound to the object or the session is a policy session |
| 520 // with no authValue required, do not include the authValue in the HMAC key. |
| 521 // Note: For a policy session, its isBound attribute is CLEARED. |
| 522 |
| 523 // If the session isn't used for authorization, then there is no auth value |
| 524 // to add |
| 525 if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) |
| 526 { |
| 527 // used for auth so see if this is a policy session with authValue needed |
| 528 // or an hmac session that is not bound |
| 529 if( sessionHandleType == TPM_HT_POLICY_SESSION |
| 530 && session->attributes.isAuthValueNeeded == SET |
| 531 || sessionHandleType == TPM_HT_HMAC_SESSION |
| 532 && !IsSessionBindEntity(s_associatedHandles[sessionIndex], session) |
| 533 ) |
| 534 { |
| 535 // add the authValue to the HMAC key |
| 536 pAssert((sizeof(AUTH_VALUE) + key.t.size) <= sizeof(key.t.buffer)); |
| 537 key.t.size = key.t.size |
| 538 + EntityGetAuthValue(s_associatedHandles[sessionIndex], |
| 539 (AUTH_VALUE *)&(key.t.buffer[key.t.size])); |
| 540 } |
| 541 } |
| 542 |
| 543 // if the HMAC key size is 0, a NULL string HMAC is allowed |
| 544 if( key.t.size == 0 |
| 545 && s_inputAuthValues[sessionIndex].t.size == 0) |
| 546 { |
| 547 hmac->t.size = 0; |
| 548 return; |
| 549 } |
| 550 |
| 551 // Start HMAC |
| 552 hmac->t.size = CryptStartHMAC2B(session->authHashAlg, &key.b, &hmacState); |
| 553 |
| 554 // Add cpHash |
| 555 CryptUpdateDigest2B(&hmacState, &cpHash->b); |
| 556 |
| 557 // Add nonceCaller |
| 558 CryptUpdateDigest2B(&hmacState, &s_nonceCaller[sessionIndex].b); |
| 559 |
| 560 // Add nonceTPM |
| 561 CryptUpdateDigest2B(&hmacState, &session->nonceTPM.b); |
| 562 |
| 563 // If needed, add nonceTPM for decrypt session |
| 564 if(nonceDecrypt != NULL) |
| 565 CryptUpdateDigest2B(&hmacState, &nonceDecrypt->b); |
| 566 |
| |
| Page 52 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 567 // If needed, add nonceTPM for encrypt session |
| 568 if(nonceEncrypt != NULL) |
| 569 CryptUpdateDigest2B(&hmacState, &nonceEncrypt->b); |
| 570 |
| 571 // Add sessionAttributes |
| 572 buffer = marshalBuffer; |
| 573 marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]), |
| 574 &buffer, NULL); |
| 575 CryptUpdateDigest(&hmacState, marshalSize, marshalBuffer); |
| 576 |
| 577 // Complete the HMAC computation |
| 578 CryptCompleteHMAC2B(&hmacState, &hmac->b); |
| 579 |
| 580 return; |
| 581 } |
| |
| |
| 6.4.4.4 CheckSessionHMAC() |
| |
| This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the |
| expected HMAC value and then compares the result with the HMAC in the authorization session. The |
| authorization is successful if they are the same. |
| If the authorizations are not the same, IncrementLockout() is called. It will return TPM_RC_AUTH_FAIL if |
| the failure caused the failureCount to increment. Otherwise, it will return TPM_RC_BAD_AUTH. |
| |
| Error Returns Meaning |
| |
| TPM_RC_AUTH_FAIL auth failure caused failureCount increment |
| TPM_RC_BAD_AUTH auth failure did not cause failureCount increment |
| |
| 582 static TPM_RC |
| 583 CheckSessionHMAC( |
| 584 UINT32 sessionIndex, // IN: index of session to be processed |
| 585 TPM2B_DIGEST *cpHash // IN: cpHash of the command |
| 586 ) |
| 587 { |
| 588 TPM2B_DIGEST hmac; // authHMAC for comparing |
| 589 |
| 590 // Compute authHMAC |
| 591 ComputeCommandHMAC(sessionIndex, cpHash, &hmac); |
| 592 |
| 593 // Compare the input HMAC with the authHMAC computed above. |
| 594 if(!Memory2BEqual(&s_inputAuthValues[sessionIndex].b, &hmac.b)) |
| 595 { |
| 596 // If an HMAC session has a failure, invoke the anti-hammering |
| 597 // if it applies to the authorized entity or the session. |
| 598 // Otherwise, just indicate that the authorization is bad. |
| 599 return IncrementLockout(sessionIndex); |
| 600 } |
| 601 return TPM_RC_SUCCESS; |
| 602 } |
| |
| |
| 6.4.4.5 CheckPolicyAuthSession() |
| |
| This function is used to validate the authorization in a policy session. This function performs the following |
| comparisons to see if a policy authorization is properly provided. The check are: |
| a) compare policyDigest in session with authPolicy associated with the entity to be authorized; |
| b) compare timeout if applicable; |
| c) compare commandCode if applicable; |
| |
| Family "2.0" TCG Published Page 53 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| d) compare cpHash if applicable; and |
| e) see if PCR values have changed since computed. |
| If all the above checks succeed, the handle is authorized. The order of these comparisons is not |
| important because any failure will result in the same error code. |
| |
| Error Returns Meaning |
| |
| TPM_RC_PCR_CHANGED PCR value is not current |
| TPM_RC_POLICY_FAIL policy session fails |
| TPM_RC_LOCALITY command locality is not allowed |
| TPM_RC_POLICY_CC CC doesn't match |
| TPM_RC_EXPIRED policy session has expired |
| TPM_RC_PP PP is required but not asserted |
| TPM_RC_NV_UNAVAILABLE NV is not available for write |
| TPM_RC_NV_RATE NV is rate limiting |
| |
| 603 static TPM_RC |
| 604 CheckPolicyAuthSession( |
| 605 UINT32 sessionIndex, // IN: index of session to be processed |
| 606 TPM_CC commandCode, // IN: command code |
| 607 TPM2B_DIGEST *cpHash, // IN: cpHash using the algorithm of this |
| 608 // session |
| 609 TPM2B_DIGEST *nameHash // IN: nameHash using the session algorithm |
| 610 ) |
| 611 { |
| 612 TPM_RC result = TPM_RC_SUCCESS; |
| 613 SESSION *session; |
| 614 TPM2B_DIGEST authPolicy; |
| 615 TPMI_ALG_HASH policyAlg; |
| 616 UINT8 locality; |
| 617 |
| 618 // Initialize pointer to the auth session. |
| 619 session = SessionGet(s_sessionHandles[sessionIndex]); |
| 620 |
| 621 // If the command is TPM_RC_PolicySecret(), make sure that |
| 622 // either password or authValue is required |
| 623 if( commandCode == TPM_CC_PolicySecret |
| 624 && session->attributes.isPasswordNeeded == CLEAR |
| 625 && session->attributes.isAuthValueNeeded == CLEAR) |
| 626 return TPM_RC_MODE; |
| 627 |
| 628 // See if the PCR counter for the session is still valid. |
| 629 if( !SessionPCRValueIsCurrent(s_sessionHandles[sessionIndex]) ) |
| 630 return TPM_RC_PCR_CHANGED; |
| 631 |
| 632 // Get authPolicy. |
| 633 policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex], |
| 634 &authPolicy); |
| 635 // Compare authPolicy. |
| 636 if(!Memory2BEqual(&session->u2.policyDigest.b, &authPolicy.b)) |
| 637 return TPM_RC_POLICY_FAIL; |
| 638 |
| 639 // Policy is OK so check if the other factors are correct |
| 640 |
| 641 // Compare policy hash algorithm. |
| 642 if(policyAlg != session->authHashAlg) |
| 643 return TPM_RC_POLICY_FAIL; |
| 644 |
| 645 // Compare timeout. |
| |
| Page 54 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 646 if(session->timeOut != 0) |
| 647 { |
| 648 // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE |
| 649 // or TPM_RC_NV_RATE error may be returned here. |
| 650 result = NvIsAvailable(); |
| 651 if(result != TPM_RC_SUCCESS) |
| 652 return result; |
| 653 |
| 654 if(session->timeOut < go.clock) |
| 655 return TPM_RC_EXPIRED; |
| 656 } |
| 657 |
| 658 // If command code is provided it must match |
| 659 if(session->commandCode != 0) |
| 660 { |
| 661 if(session->commandCode != commandCode) |
| 662 return TPM_RC_POLICY_CC; |
| 663 } |
| 664 else |
| 665 { |
| 666 // If command requires a DUP or ADMIN authorization, the session must have |
| 667 // command code set. |
| 668 AUTH_ROLE role = CommandAuthRole(commandCode, sessionIndex); |
| 669 if(role == AUTH_ADMIN || role == AUTH_DUP) |
| 670 return TPM_RC_POLICY_FAIL; |
| 671 } |
| 672 // Check command locality. |
| 673 { |
| 674 BYTE sessionLocality[sizeof(TPMA_LOCALITY)]; |
| 675 BYTE *buffer = sessionLocality; |
| 676 |
| 677 // Get existing locality setting in canonical form |
| 678 TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); |
| 679 |
| 680 // See if the locality has been set |
| 681 if(sessionLocality[0] != 0) |
| 682 { |
| 683 // If so, get the current locality |
| 684 locality = _plat__LocalityGet(); |
| 685 if (locality < 5) |
| 686 { |
| 687 if( ((sessionLocality[0] & (1 << locality)) == 0) |
| 688 || sessionLocality[0] > 31) |
| 689 return TPM_RC_LOCALITY; |
| 690 } |
| 691 else if (locality > 31) |
| 692 { |
| 693 if(sessionLocality[0] != locality) |
| 694 return TPM_RC_LOCALITY; |
| 695 } |
| 696 else |
| 697 { |
| 698 // Could throw an assert here but a locality error is just |
| 699 // as good. It just means that, whatever the locality is, it isn't |
| 700 // the locality requested so... |
| 701 return TPM_RC_LOCALITY; |
| 702 } |
| 703 } |
| 704 } // end of locality check |
| 705 |
| 706 // Check physical presence. |
| 707 if( session->attributes.isPPRequired == SET |
| 708 && !_plat__PhysicalPresenceAsserted()) |
| 709 return TPM_RC_PP; |
| 710 |
| 711 // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or |
| |
| Family "2.0" TCG Published Page 55 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 712 // DUP role for this handle. |
| 713 if(session->u1.cpHash.b.size != 0) |
| 714 { |
| 715 if(session->attributes.iscpHashDefined) |
| 716 { |
| 717 // Compare cpHash. |
| 718 if(!Memory2BEqual(&session->u1.cpHash.b, &cpHash->b)) |
| 719 return TPM_RC_POLICY_FAIL; |
| 720 } |
| 721 else |
| 722 { |
| 723 // Compare nameHash. |
| 724 // When cpHash is not defined, nameHash is placed in its space. |
| 725 if(!Memory2BEqual(&session->u1.cpHash.b, &nameHash->b)) |
| 726 return TPM_RC_POLICY_FAIL; |
| 727 } |
| 728 } |
| 729 if(session->attributes.checkNvWritten) |
| 730 { |
| 731 NV_INDEX nvIndex; |
| 732 |
| 733 // If this is not an NV index, the policy makes no sense so fail it. |
| 734 if(HandleGetType(s_associatedHandles[sessionIndex])!= TPM_HT_NV_INDEX) |
| 735 return TPM_RC_POLICY_FAIL; |
| 736 |
| 737 // Get the index data |
| 738 NvGetIndexInfo(s_associatedHandles[sessionIndex], &nvIndex); |
| 739 |
| 740 // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state |
| 741 if( (nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) |
| 742 != (session->attributes.nvWrittenState == SET)) |
| 743 return TPM_RC_POLICY_FAIL; |
| 744 } |
| 745 |
| 746 return TPM_RC_SUCCESS; |
| 747 } |
| |
| |
| 6.4.4.6 RetrieveSessionData() |
| |
| This function will unmarshal the sessions in the session area of a command. The values are placed in the |
| arrays that are defined at the beginning of this file. The normal unmarshaling errors are possible. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SUCCSS unmarshaled without error |
| TPM_RC_SIZE the number of bytes unmarshaled is not the same as the value for |
| authorizationSize in the command |
| |
| 748 static TPM_RC |
| 749 RetrieveSessionData ( |
| 750 TPM_CC commandCode, // IN: command code |
| 751 UINT32 *sessionCount, // OUT: number of sessions found |
| 752 BYTE *sessionBuffer, // IN: pointer to the session buffer |
| 753 INT32 bufferSize // IN: size of the session buffer |
| 754 ) |
| 755 { |
| 756 int sessionIndex; |
| 757 int i; |
| 758 TPM_RC result; |
| 759 SESSION *session; |
| 760 TPM_HT sessionType; |
| 761 |
| 762 s_decryptSessionIndex = UNDEFINED_INDEX; |
| |
| Page 56 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 763 s_encryptSessionIndex = UNDEFINED_INDEX; |
| 764 s_auditSessionIndex = UNDEFINED_INDEX; |
| 765 |
| 766 for(sessionIndex = 0; bufferSize > 0; sessionIndex++) |
| 767 { |
| 768 // If maximum allowed number of sessions has been parsed, return a size |
| 769 // error with a session number that is larger than the number of allowed |
| 770 // sessions |
| 771 if(sessionIndex == MAX_SESSION_NUM) |
| 772 return TPM_RC_SIZE + TPM_RC_S + g_rcIndex[sessionIndex+1]; |
| 773 |
| 774 // make sure that the associated handle for each session starts out |
| 775 // unassigned |
| 776 s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; |
| 777 |
| 778 // First parameter: Session handle. |
| 779 result = TPMI_SH_AUTH_SESSION_Unmarshal(&s_sessionHandles[sessionIndex], |
| 780 &sessionBuffer, &bufferSize, TRUE); |
| 781 if(result != TPM_RC_SUCCESS) |
| 782 return result + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 783 |
| 784 // Second parameter: Nonce. |
| 785 result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex], |
| 786 &sessionBuffer, &bufferSize); |
| 787 if(result != TPM_RC_SUCCESS) |
| 788 return result + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 789 |
| 790 // Third parameter: sessionAttributes. |
| 791 result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex], |
| 792 &sessionBuffer, &bufferSize); |
| 793 if(result != TPM_RC_SUCCESS) |
| 794 return result + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 795 |
| 796 // Fourth parameter: authValue (PW or HMAC). |
| 797 result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex], |
| 798 &sessionBuffer, &bufferSize); |
| 799 if(result != TPM_RC_SUCCESS) |
| 800 return result + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 801 |
| 802 if(s_sessionHandles[sessionIndex] == TPM_RS_PW) |
| 803 { |
| 804 // A PWAP session needs additional processing. |
| 805 // Can't have any attributes set other than continueSession bit |
| 806 if( s_attributes[sessionIndex].encrypt |
| 807 || s_attributes[sessionIndex].decrypt |
| 808 || s_attributes[sessionIndex].audit |
| 809 || s_attributes[sessionIndex].auditExclusive |
| 810 || s_attributes[sessionIndex].auditReset |
| 811 ) |
| 812 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 813 |
| 814 // The nonce size must be zero. |
| 815 if(s_nonceCaller[sessionIndex].t.size != 0) |
| 816 return TPM_RC_NONCE + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 817 |
| 818 continue; |
| 819 } |
| 820 // For not password sessions... |
| 821 |
| 822 // Find out if the session is loaded. |
| 823 if(!SessionIsLoaded(s_sessionHandles[sessionIndex])) |
| 824 return TPM_RC_REFERENCE_S0 + sessionIndex; |
| 825 |
| 826 sessionType = HandleGetType(s_sessionHandles[sessionIndex]); |
| 827 session = SessionGet(s_sessionHandles[sessionIndex]); |
| 828 // Check if the session is an HMAC/policy session. |
| |
| Family "2.0" TCG Published Page 57 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 829 if( ( session->attributes.isPolicy == SET |
| 830 && sessionType == TPM_HT_HMAC_SESSION |
| 831 ) |
| 832 || ( session->attributes.isPolicy == CLEAR |
| 833 && sessionType == TPM_HT_POLICY_SESSION |
| 834 ) |
| 835 ) |
| 836 return TPM_RC_HANDLE + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 837 |
| 838 // Check that this handle has not previously been used. |
| 839 for(i = 0; i < sessionIndex; i++) |
| 840 { |
| 841 if(s_sessionHandles[i] == s_sessionHandles[sessionIndex]) |
| 842 return TPM_RC_HANDLE + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 843 } |
| 844 |
| 845 // If the session is used for parameter encryption or audit as well, set |
| 846 // the corresponding indices. |
| 847 |
| 848 // First process decrypt. |
| 849 if(s_attributes[sessionIndex].decrypt) |
| 850 { |
| 851 // Check if the commandCode allows command parameter encryption. |
| 852 if(DecryptSize(commandCode) == 0) |
| 853 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 854 |
| 855 // Encrypt attribute can only appear in one session |
| 856 if(s_decryptSessionIndex != UNDEFINED_INDEX) |
| 857 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 858 |
| 859 // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL |
| 860 if(session->symmetric.algorithm == TPM_ALG_NULL) |
| 861 return TPM_RC_SYMMETRIC + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 862 |
| 863 // All checks passed, so set the index for the session used to decrypt |
| 864 // a command parameter. |
| 865 s_decryptSessionIndex = sessionIndex; |
| 866 } |
| 867 |
| 868 // Now process encrypt. |
| 869 if(s_attributes[sessionIndex].encrypt) |
| 870 { |
| 871 // Check if the commandCode allows response parameter encryption. |
| 872 if(EncryptSize(commandCode) == 0) |
| 873 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 874 |
| 875 // Encrypt attribute can only appear in one session. |
| 876 if(s_encryptSessionIndex != UNDEFINED_INDEX) |
| 877 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 878 |
| 879 // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL |
| 880 if(session->symmetric.algorithm == TPM_ALG_NULL) |
| 881 return TPM_RC_SYMMETRIC + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 882 |
| 883 // All checks passed, so set the index for the session used to encrypt |
| 884 // a response parameter. |
| 885 s_encryptSessionIndex = sessionIndex; |
| 886 } |
| 887 |
| 888 // At last process audit. |
| 889 if(s_attributes[sessionIndex].audit) |
| 890 { |
| 891 // Audit attribute can only appear in one session. |
| 892 if(s_auditSessionIndex != UNDEFINED_INDEX) |
| 893 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 894 |
| |
| Page 58 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 895 // An audit session can not be policy session. |
| 896 if( HandleGetType(s_sessionHandles[sessionIndex]) |
| 897 == TPM_HT_POLICY_SESSION) |
| 898 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 899 |
| 900 // If this is a reset of the audit session, or the first use |
| 901 // of the session as an audit session, it doesn't matter what |
| 902 // the exclusive state is. The session will become exclusive. |
| 903 if( s_attributes[sessionIndex].auditReset == CLEAR |
| 904 && session->attributes.isAudit == SET) |
| 905 { |
| 906 // Not first use or reset. If auditExlusive is SET, then this |
| 907 // session must be the current exclusive session. |
| 908 if( s_attributes[sessionIndex].auditExclusive == SET |
| 909 && g_exclusiveAuditSession != s_sessionHandles[sessionIndex]) |
| 910 return TPM_RC_EXCLUSIVE; |
| 911 } |
| 912 |
| 913 s_auditSessionIndex = sessionIndex; |
| 914 } |
| 915 |
| 916 // Initialize associated handle as undefined. This will be changed when |
| 917 // the handles are processed. |
| 918 s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; |
| 919 |
| 920 } |
| 921 |
| 922 // Set the number of sessions found. |
| 923 *sessionCount = sessionIndex; |
| 924 return TPM_RC_SUCCESS; |
| 925 } |
| |
| |
| 6.4.4.7 CheckLockedOut() |
| |
| This function checks to see if the TPM is in lockout. This function should only be called if the entity being |
| checked is subject to DA protection. The TPM is in lockout if the NV is not available and a DA write is |
| pending. Otherwise the TPM is locked out if checking for lockoutAuth (lockoutAuthCheck == TRUE) and |
| use of lockoutAuth is disabled, or failedTries >= maxTries |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_RATE NV is rate limiting |
| TPM_RC_NV_UNAVAILABLE NV is not available at this time |
| TPM_RC_LOCKOUT TPM is in lockout |
| |
| 926 static TPM_RC |
| 927 CheckLockedOut( |
| 928 BOOL lockoutAuthCheck // IN: TRUE if checking is for lockoutAuth |
| 929 ) |
| 930 { |
| 931 TPM_RC result; |
| 932 |
| 933 // If NV is unavailable, and current cycle state recorded in NV is not |
| 934 // SHUTDOWN_NONE, refuse to check any authorization because we would |
| 935 // not be able to handle a DA failure. |
| 936 result = NvIsAvailable(); |
| 937 if(result != TPM_RC_SUCCESS && gp.orderlyState != SHUTDOWN_NONE) |
| 938 return result; |
| 939 |
| 940 // Check if DA info needs to be updated in NV. |
| 941 if(s_DAPendingOnNV) |
| 942 { |
| |
| Family "2.0" TCG Published Page 59 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 943 // If NV is accessible, ... |
| 944 if(result == TPM_RC_SUCCESS) |
| 945 { |
| 946 // ... write the pending DA data and proceed. |
| 947 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, |
| 948 &gp.lockOutAuthEnabled); |
| 949 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 950 g_updateNV = TRUE; |
| 951 s_DAPendingOnNV = FALSE; |
| 952 } |
| 953 else |
| 954 { |
| 955 // Otherwise no authorization can be checked. |
| 956 return result; |
| 957 } |
| 958 } |
| 959 |
| 960 // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth |
| 961 // is disabled... |
| 962 if(lockoutAuthCheck) |
| 963 { |
| 964 if(gp.lockOutAuthEnabled == FALSE) |
| 965 return TPM_RC_LOCKOUT; |
| 966 } |
| 967 else |
| 968 { |
| 969 // ... or if the number of failed tries has been maxed out. |
| 970 if(gp.failedTries >= gp.maxTries) |
| 971 return TPM_RC_LOCKOUT; |
| 972 } |
| 973 return TPM_RC_SUCCESS; |
| 974 } |
| |
| |
| 6.4.4.8 CheckAuthSession() |
| |
| This function checks that the authorization session properly authorizes the use of the associated handle. |
| |
| Error Returns Meaning |
| |
| TPM_RC_LOCKOUT entity is protected by DA and TPM is in lockout, or TPM is locked out |
| on NV update pending on DA parameters |
| TPM_RC_PP Physical Presence is required but not provided |
| TPM_RC_AUTH_FAIL HMAC or PW authorization failed with DA side-effects (can be a |
| policy session) |
| TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA side-effects (can be a |
| policy session) |
| TPM_RC_POLICY_FAIL if policy session fails |
| TPM_RC_POLICY_CC command code of policy was wrong |
| TPM_RC_EXPIRED the policy session has expired |
| TPM_RC_PCR ??? |
| TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable |
| |
| 975 static TPM_RC |
| 976 CheckAuthSession( |
| 977 TPM_CC commandCode, // IN: commandCode |
| 978 UINT32 sessionIndex, // IN: index of session to be processed |
| 979 TPM2B_DIGEST *cpHash, // IN: cpHash |
| 980 TPM2B_DIGEST *nameHash // IN: nameHash |
| |
| |
| Page 60 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 981 ) |
| 982 { |
| 983 TPM_RC result; |
| 984 SESSION *session = NULL; |
| 985 TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; |
| 986 TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; |
| 987 TPM_HT sessionHandleType = HandleGetType(sessionHandle); |
| 988 |
| 989 pAssert(sessionHandle != TPM_RH_UNASSIGNED); |
| 990 |
| 991 if(sessionHandle != TPM_RS_PW) |
| 992 session = SessionGet(sessionHandle); |
| 993 |
| 994 pAssert(sessionHandleType != TPM_HT_POLICY_SESSION || session != NULL); |
| 995 |
| 996 // If the authorization session is not a policy session, or if the policy |
| 997 // session requires authorization, then check lockout. |
| 998 if( sessionHandleType != TPM_HT_POLICY_SESSION |
| 999 || session->attributes.isAuthValueNeeded |
| 1000 || session->attributes.isPasswordNeeded) |
| 1001 { |
| 1002 // See if entity is subject to lockout. |
| 1003 if(!IsDAExempted(associatedHandle)) |
| 1004 { |
| 1005 // If NV is unavailable, and current cycle state recorded in NV is not |
| 1006 // SHUTDOWN_NONE, refuse to check any authorization because we would |
| 1007 // not be able to handle a DA failure. |
| 1008 result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT); |
| 1009 if(result != TPM_RC_SUCCESS) |
| 1010 return result; |
| 1011 } |
| 1012 } |
| 1013 |
| 1014 if(associatedHandle == TPM_RH_PLATFORM) |
| 1015 { |
| 1016 // If the physical presence is required for this command, check for PP |
| 1017 // assertion. If it isn't asserted, no point going any further. |
| 1018 if( PhysicalPresenceIsRequired(commandCode) |
| 1019 && !_plat__PhysicalPresenceAsserted() |
| 1020 ) |
| 1021 return TPM_RC_PP; |
| 1022 } |
| 1023 // If a policy session is required, make sure that it is being used. |
| 1024 if( IsPolicySessionRequired(commandCode, sessionIndex) |
| 1025 && sessionHandleType != TPM_HT_POLICY_SESSION) |
| 1026 return TPM_RC_AUTH_TYPE; |
| 1027 |
| 1028 // If this is a PW authorization, check it and return. |
| 1029 if(sessionHandle == TPM_RS_PW) |
| 1030 { |
| 1031 if(IsAuthValueAvailable(associatedHandle, commandCode, sessionIndex)) |
| 1032 return CheckPWAuthSession(sessionIndex); |
| 1033 else |
| 1034 return TPM_RC_AUTH_UNAVAILABLE; |
| 1035 } |
| 1036 // If this is a policy session, ... |
| 1037 if(sessionHandleType == TPM_HT_POLICY_SESSION) |
| 1038 { |
| 1039 // ... see if the entity has a policy, ... |
| 1040 if( !IsAuthPolicyAvailable(associatedHandle, commandCode, sessionIndex)) |
| 1041 return TPM_RC_AUTH_UNAVAILABLE; |
| 1042 // ... and check the policy session. |
| 1043 result = CheckPolicyAuthSession(sessionIndex, commandCode, |
| 1044 cpHash, nameHash); |
| 1045 if (result != TPM_RC_SUCCESS) |
| 1046 return result; |
| |
| Family "2.0" TCG Published Page 61 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1047 } |
| 1048 else |
| 1049 { |
| 1050 // For non policy, the entity being accessed must allow authorization |
| 1051 // with an auth value. This is required even if the auth value is not |
| 1052 // going to be used in an HMAC because it is bound. |
| 1053 if(!IsAuthValueAvailable(associatedHandle, commandCode, sessionIndex)) |
| 1054 return TPM_RC_AUTH_UNAVAILABLE; |
| 1055 } |
| 1056 // At this point, the session must be either a policy or an HMAC session. |
| 1057 session = SessionGet(s_sessionHandles[sessionIndex]); |
| 1058 |
| 1059 if( sessionHandleType == TPM_HT_POLICY_SESSION |
| 1060 && session->attributes.isPasswordNeeded == SET) |
| 1061 { |
| 1062 // For policy session that requires a password, check it as PWAP session. |
| 1063 return CheckPWAuthSession(sessionIndex); |
| 1064 } |
| 1065 else |
| 1066 { |
| 1067 // For other policy or HMAC sessions, have its HMAC checked. |
| 1068 return CheckSessionHMAC(sessionIndex, cpHash); |
| 1069 } |
| 1070 } |
| 1071 #ifdef TPM_CC_GetCommandAuditDigest |
| |
| |
| 6.4.4.9 CheckCommandAudit() |
| |
| This function checks if the current command may trigger command audit, and if it is safe to perform the |
| action. |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_UNAVAILABLE NV is not available for write |
| TPM_RC_NV_RATE NV is rate limiting |
| |
| 1072 static TPM_RC |
| 1073 CheckCommandAudit( |
| 1074 TPM_CC commandCode, // IN: Command code |
| 1075 UINT32 handleNum, // IN: number of element in handle array |
| 1076 TPM_HANDLE handles[], // IN: array of handle |
| 1077 BYTE *parmBufferStart, // IN: start of parameter buffer |
| 1078 UINT32 parmBufferSize // IN: size of parameter buffer |
| 1079 ) |
| 1080 { |
| 1081 TPM_RC result = TPM_RC_SUCCESS; |
| 1082 |
| 1083 // If audit is implemented, need to check to see if auditing is being done |
| 1084 // for this command. |
| 1085 if(CommandAuditIsRequired(commandCode)) |
| 1086 { |
| 1087 // If the audit digest is clear and command audit is required, NV must be |
| 1088 // available so that TPM2_GetCommandAuditDigest() is able to increment |
| 1089 // audit counter. If NV is not available, the function bails out to prevent |
| 1090 // the TPM from attempting an operation that would fail anyway. |
| 1091 if( gr.commandAuditDigest.t.size == 0 |
| 1092 || commandCode == TPM_CC_GetCommandAuditDigest) |
| 1093 { |
| 1094 result = NvIsAvailable(); |
| 1095 if(result != TPM_RC_SUCCESS) |
| 1096 return result; |
| 1097 } |
| 1098 ComputeCpHash(gp.auditHashAlg, commandCode, handleNum, |
| |
| Page 62 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1099 handles, parmBufferSize, parmBufferStart, |
| 1100 &s_cpHashForCommandAudit, NULL); |
| 1101 } |
| 1102 |
| 1103 return TPM_RC_SUCCESS; |
| 1104 } |
| 1105 #endif |
| |
| |
| 6.4.4.10 ParseSessionBuffer() |
| |
| This function is the entry function for command session processing. It iterates sessions in session area |
| and reports if the required authorization has been properly provided. It also processes audit session and |
| passes the information of encryption sessions to parameter encryption module. |
| |
| Error Returns Meaning |
| |
| various parsing failure or authorization failure |
| |
| 1106 TPM_RC |
| 1107 ParseSessionBuffer( |
| 1108 TPM_CC commandCode, // IN: Command code |
| 1109 UINT32 handleNum, // IN: number of element in handle array |
| 1110 TPM_HANDLE handles[], // IN: array of handle |
| 1111 BYTE *sessionBufferStart, // IN: start of session buffer |
| 1112 UINT32 sessionBufferSize, // IN: size of session buffer |
| 1113 BYTE *parmBufferStart, // IN: start of parameter buffer |
| 1114 UINT32 parmBufferSize // IN: size of parameter buffer |
| 1115 ) |
| 1116 { |
| 1117 TPM_RC result; |
| 1118 UINT32 i; |
| 1119 INT32 size = 0; |
| 1120 TPM2B_AUTH extraKey; |
| 1121 UINT32 sessionIndex; |
| 1122 SESSION *session; |
| 1123 TPM2B_DIGEST cpHash; |
| 1124 TPM2B_DIGEST nameHash; |
| 1125 TPM_ALG_ID cpHashAlg = TPM_ALG_NULL; // algID for the last computed |
| 1126 // cpHash |
| 1127 |
| 1128 // Check if a command allows any session in its session area. |
| 1129 if(!IsSessionAllowed(commandCode)) |
| 1130 return TPM_RC_AUTH_CONTEXT; |
| 1131 |
| 1132 // Default-initialization. |
| 1133 s_sessionNum = 0; |
| 1134 cpHash.t.size = 0; |
| 1135 |
| 1136 result = RetrieveSessionData(commandCode, &s_sessionNum, |
| 1137 sessionBufferStart, sessionBufferSize); |
| 1138 if(result != TPM_RC_SUCCESS) |
| 1139 return result; |
| 1140 |
| 1141 // There is no command in the TPM spec that has more handles than |
| 1142 // MAX_SESSION_NUM. |
| 1143 pAssert(handleNum <= MAX_SESSION_NUM); |
| 1144 |
| 1145 // Associate the session with an authorization handle. |
| 1146 for(i = 0; i < handleNum; i++) |
| 1147 { |
| 1148 if(CommandAuthRole(commandCode, i) != AUTH_NONE) |
| 1149 { |
| 1150 // If the received session number is less than the number of handle |
| 1151 // that requires authorization, an error should be returned. |
| |
| Family "2.0" TCG Published Page 63 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1152 // Note: for all the TPM 2.0 commands, handles requiring |
| 1153 // authorization come first in a command input. |
| 1154 if(i > (s_sessionNum - 1)) |
| 1155 return TPM_RC_AUTH_MISSING; |
| 1156 |
| 1157 // Record the handle associated with the authorization session |
| 1158 s_associatedHandles[i] = handles[i]; |
| 1159 } |
| 1160 } |
| 1161 |
| 1162 // Consistency checks are done first to avoid auth failure when the command |
| 1163 // will not be executed anyway. |
| 1164 for(sessionIndex = 0; sessionIndex < s_sessionNum; sessionIndex++) |
| 1165 { |
| 1166 // PW session must be an authorization session |
| 1167 if(s_sessionHandles[sessionIndex] == TPM_RS_PW ) |
| 1168 { |
| 1169 if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED) |
| 1170 return TPM_RC_HANDLE + g_rcIndex[sessionIndex]; |
| 1171 } |
| 1172 else |
| 1173 { |
| 1174 session = SessionGet(s_sessionHandles[sessionIndex]); |
| 1175 |
| 1176 // A trial session can not appear in session area, because it cannot |
| 1177 // be used for authorization, audit or encrypt/decrypt. |
| 1178 if(session->attributes.isTrialPolicy == SET) |
| 1179 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 1180 |
| 1181 // See if the session is bound to a DA protected entity |
| 1182 // NOTE: Since a policy session is never bound, a policy is still |
| 1183 // usable even if the object is DA protected and the TPM is in |
| 1184 // lockout. |
| 1185 if(session->attributes.isDaBound == SET) |
| 1186 { |
| 1187 result = CheckLockedOut(session->attributes.isLockoutBound == SET); |
| 1188 if(result != TPM_RC_SUCCESS) |
| 1189 return result; |
| 1190 } |
| 1191 // If the current cpHash is the right one, don't re-compute. |
| 1192 if(cpHashAlg != session->authHashAlg) // different so compute |
| 1193 { |
| 1194 cpHashAlg = session->authHashAlg; // save this new algID |
| 1195 ComputeCpHash(session->authHashAlg, commandCode, handleNum, |
| 1196 handles, parmBufferSize, parmBufferStart, |
| 1197 &cpHash, &nameHash); |
| 1198 } |
| 1199 // If this session is for auditing, save the cpHash. |
| 1200 if(s_attributes[sessionIndex].audit) |
| 1201 s_cpHashForAudit = cpHash; |
| 1202 } |
| 1203 |
| 1204 // if the session has an associated handle, check the auth |
| 1205 if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) |
| 1206 { |
| 1207 result = CheckAuthSession(commandCode, sessionIndex, |
| 1208 &cpHash, &nameHash); |
| 1209 if(result != TPM_RC_SUCCESS) |
| 1210 return RcSafeAddToResult(result, |
| 1211 TPM_RC_S + g_rcIndex[sessionIndex]); |
| 1212 } |
| 1213 else |
| 1214 { |
| 1215 // a session that is not for authorization must either be encrypt, |
| 1216 // decrypt, or audit |
| 1217 if( s_attributes[sessionIndex].audit == CLEAR |
| |
| Page 64 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1218 && s_attributes[sessionIndex].encrypt == CLEAR |
| 1219 && s_attributes[sessionIndex].decrypt == CLEAR) |
| 1220 return TPM_RC_ATTRIBUTES + TPM_RC_S + g_rcIndex[sessionIndex]; |
| 1221 |
| 1222 // check HMAC for encrypt/decrypt/audit only sessions |
| 1223 result = CheckSessionHMAC(sessionIndex, &cpHash); |
| 1224 if(result != TPM_RC_SUCCESS) |
| 1225 return RcSafeAddToResult(result, |
| 1226 TPM_RC_S + g_rcIndex[sessionIndex]); |
| 1227 } |
| 1228 } |
| 1229 |
| 1230 #ifdef TPM_CC_GetCommandAuditDigest |
| 1231 // Check if the command should be audited. |
| 1232 result = CheckCommandAudit(commandCode, handleNum, handles, |
| 1233 parmBufferStart, parmBufferSize); |
| 1234 if(result != TPM_RC_SUCCESS) |
| 1235 return result; // No session number to reference |
| 1236 #endif |
| 1237 |
| 1238 // Decrypt the first parameter if applicable. This should be the last operation |
| 1239 // in session processing. |
| 1240 // If the encrypt session is associated with a handle and the handle's |
| 1241 // authValue is available, then authValue is concatenated with sessionAuth to |
| 1242 // generate encryption key, no matter if the handle is the session bound entity |
| 1243 // or not. |
| 1244 if(s_decryptSessionIndex != UNDEFINED_INDEX) |
| 1245 { |
| 1246 // Get size of the leading size field in decrypt parameter |
| 1247 if( s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED |
| 1248 && IsAuthValueAvailable(s_associatedHandles[s_decryptSessionIndex], |
| 1249 commandCode, |
| 1250 s_decryptSessionIndex) |
| 1251 ) |
| 1252 { |
| 1253 extraKey.b.size= |
| 1254 EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex], |
| 1255 &extraKey.t.buffer); |
| 1256 } |
| 1257 else |
| 1258 { |
| 1259 extraKey.b.size = 0; |
| 1260 } |
| 1261 size = DecryptSize(commandCode); |
| 1262 result = CryptParameterDecryption( |
| 1263 s_sessionHandles[s_decryptSessionIndex], |
| 1264 &s_nonceCaller[s_decryptSessionIndex].b, |
| 1265 parmBufferSize, (UINT16)size, |
| 1266 &extraKey, |
| 1267 parmBufferStart); |
| 1268 if(result != TPM_RC_SUCCESS) |
| 1269 return RcSafeAddToResult(result, |
| 1270 TPM_RC_S + g_rcIndex[s_decryptSessionIndex]); |
| 1271 } |
| 1272 |
| 1273 return TPM_RC_SUCCESS; |
| 1274 } |
| |
| |
| 6.4.4.11 CheckAuthNoSession() |
| |
| Function to process a command with no session associated. The function makes sure all the handles in |
| the command require no authorization. |
| |
| |
| |
| Family "2.0" TCG Published Page 65 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_AUTH_MISSING failure - one or more handles require auth |
| |
| 1275 TPM_RC |
| 1276 CheckAuthNoSession( |
| 1277 TPM_CC commandCode, // IN: Command Code |
| 1278 UINT32 handleNum, // IN: number of handles in command |
| 1279 TPM_HANDLE handles[], // IN: array of handle |
| 1280 BYTE *parmBufferStart, // IN: start of parameter buffer |
| 1281 UINT32 parmBufferSize // IN: size of parameter buffer |
| 1282 ) |
| 1283 { |
| 1284 UINT32 i; |
| 1285 TPM_RC result = TPM_RC_SUCCESS; |
| 1286 |
| 1287 // Check if the commandCode requires authorization |
| 1288 for(i = 0; i < handleNum; i++) |
| 1289 { |
| 1290 if(CommandAuthRole(commandCode, i) != AUTH_NONE) |
| 1291 return TPM_RC_AUTH_MISSING; |
| 1292 } |
| 1293 |
| 1294 #ifdef TPM_CC_GetCommandAuditDigest |
| 1295 // Check if the command should be audited. |
| 1296 result = CheckCommandAudit(commandCode, handleNum, handles, |
| 1297 parmBufferStart, parmBufferSize); |
| 1298 if(result != TPM_RC_SUCCESS) return result; |
| 1299 #endif |
| 1300 |
| 1301 // Initialize number of sessions to be 0 |
| 1302 s_sessionNum = 0; |
| 1303 |
| 1304 return TPM_RC_SUCCESS; |
| 1305 } |
| |
| |
| 6.4.5 Response Session Processing |
| |
| 6.4.5.1 Introduction |
| |
| The following functions build the session area in a response, and handle the audit sessions (if present). |
| |
| 6.4.5.2 ComputeRpHash() |
| |
| Function to compute rpHash (Response Parameter Hash). The rpHash is only computed if there is an |
| HMAC authorization session and the return code is TPM_RC_SUCCESS. |
| |
| 1306 static void |
| 1307 ComputeRpHash( |
| 1308 TPM_ALG_ID hashAlg, // IN: hash algorithm to compute rpHash |
| 1309 TPM_CC commandCode, // IN: commandCode |
| 1310 UINT32 resParmBufferSize, // IN: size of response parameter buffer |
| 1311 BYTE *resParmBuffer, // IN: response parameter buffer |
| 1312 TPM2B_DIGEST *rpHash // OUT: rpHash |
| 1313 ) |
| 1314 { |
| 1315 // The command result in rpHash is always TPM_RC_SUCCESS. |
| 1316 TPM_RC responseCode = TPM_RC_SUCCESS; |
| 1317 HASH_STATE hashState; |
| 1318 |
| 1319 // rpHash := hash(responseCode || commandCode || parameters) |
| |
| Page 66 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1320 |
| 1321 // Initiate hash creation. |
| 1322 rpHash->t.size = CryptStartHash(hashAlg, &hashState); |
| 1323 |
| 1324 // Add hash constituents. |
| 1325 CryptUpdateDigestInt(&hashState, sizeof(TPM_RC), &responseCode); |
| 1326 CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode); |
| 1327 CryptUpdateDigest(&hashState, resParmBufferSize, resParmBuffer); |
| 1328 |
| 1329 // Complete hash computation. |
| 1330 CryptCompleteHash2B(&hashState, &rpHash->b); |
| 1331 |
| 1332 return; |
| 1333 } |
| |
| |
| 6.4.5.3 InitAuditSession() |
| |
| This function initializes the audit data in an audit session. |
| |
| 1334 static void |
| 1335 InitAuditSession( |
| 1336 SESSION *session // session to be initialized |
| 1337 ) |
| 1338 { |
| 1339 // Mark session as an audit session. |
| 1340 session->attributes.isAudit = SET; |
| 1341 |
| 1342 // Audit session can not be bound. |
| 1343 session->attributes.isBound = CLEAR; |
| 1344 |
| 1345 // Size of the audit log is the size of session hash algorithm digest. |
| 1346 session->u2.auditDigest.t.size = CryptGetHashDigestSize(session->authHashAlg); |
| 1347 |
| 1348 // Set the original digest value to be 0. |
| 1349 MemorySet(&session->u2.auditDigest.t.buffer, |
| 1350 0, |
| 1351 session->u2.auditDigest.t.size); |
| 1352 |
| 1353 return; |
| 1354 } |
| |
| |
| 6.4.5.4 Audit() |
| |
| This function updates the audit digest in an audit session. |
| |
| 1355 static void |
| 1356 Audit( |
| 1357 SESSION *auditSession, // IN: loaded audit session |
| 1358 TPM_CC commandCode, // IN: commandCode |
| 1359 UINT32 resParmBufferSize, // IN: size of response parameter buffer |
| 1360 BYTE *resParmBuffer // IN: response parameter buffer |
| 1361 ) |
| 1362 { |
| 1363 TPM2B_DIGEST rpHash; // rpHash for response |
| 1364 HASH_STATE hashState; |
| 1365 |
| 1366 // Compute rpHash |
| 1367 ComputeRpHash(auditSession->authHashAlg, |
| 1368 commandCode, |
| 1369 resParmBufferSize, |
| 1370 resParmBuffer, |
| 1371 &rpHash); |
| 1372 |
| |
| Family "2.0" TCG Published Page 67 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1373 // auditDigestnew := hash (auditDigestold || cpHash || rpHash) |
| 1374 |
| 1375 // Start hash computation. |
| 1376 CryptStartHash(auditSession->authHashAlg, &hashState); |
| 1377 |
| 1378 // Add old digest. |
| 1379 CryptUpdateDigest2B(&hashState, &auditSession->u2.auditDigest.b); |
| 1380 |
| 1381 // Add cpHash and rpHash. |
| 1382 CryptUpdateDigest2B(&hashState, &s_cpHashForAudit.b); |
| 1383 CryptUpdateDigest2B(&hashState, &rpHash.b); |
| 1384 |
| 1385 // Finalize the hash. |
| 1386 CryptCompleteHash2B(&hashState, &auditSession->u2.auditDigest.b); |
| 1387 |
| 1388 return; |
| 1389 } |
| 1390 #ifdef TPM_CC_GetCommandAuditDigest |
| |
| |
| 6.4.5.5 CommandAudit() |
| |
| This function updates the command audit digest. |
| |
| 1391 static void |
| 1392 CommandAudit( |
| 1393 TPM_CC commandCode, // IN: commandCode |
| 1394 UINT32 resParmBufferSize, // IN: size of response parameter buffer |
| 1395 BYTE *resParmBuffer // IN: response parameter buffer |
| 1396 ) |
| 1397 { |
| 1398 if(CommandAuditIsRequired(commandCode)) |
| 1399 { |
| 1400 TPM2B_DIGEST rpHash; // rpHash for response |
| 1401 HASH_STATE hashState; |
| 1402 |
| 1403 // Compute rpHash. |
| 1404 ComputeRpHash(gp.auditHashAlg, commandCode, resParmBufferSize, |
| 1405 resParmBuffer, &rpHash); |
| 1406 |
| 1407 // If the digest.size is one, it indicates the special case of changing |
| 1408 // the audit hash algorithm. For this case, no audit is done on exit. |
| 1409 // NOTE: When the hash algorithm is changed, g_updateNV is set in order to |
| 1410 // force an update to the NV on exit so that the change in digest will |
| 1411 // be recorded. So, it is safe to exit here without setting any flags |
| 1412 // because the digest change will be written to NV when this code exits. |
| 1413 if(gr.commandAuditDigest.t.size == 1) |
| 1414 { |
| 1415 gr.commandAuditDigest.t.size = 0; |
| 1416 return; |
| 1417 } |
| 1418 |
| 1419 // If the digest size is zero, need to start a new digest and increment |
| 1420 // the audit counter. |
| 1421 if(gr.commandAuditDigest.t.size == 0) |
| 1422 { |
| 1423 gr.commandAuditDigest.t.size = CryptGetHashDigestSize(gp.auditHashAlg); |
| 1424 MemorySet(gr.commandAuditDigest.t.buffer, |
| 1425 0, |
| 1426 gr.commandAuditDigest.t.size); |
| 1427 |
| 1428 // Bump the counter and save its value to NV. |
| 1429 gp.auditCounter++; |
| 1430 NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter); |
| 1431 g_updateNV = TRUE; |
| |
| |
| Page 68 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1432 } |
| 1433 |
| 1434 // auditDigestnew := hash (auditDigestold || cpHash || rpHash) |
| 1435 |
| 1436 // Start hash computation. |
| 1437 CryptStartHash(gp.auditHashAlg, &hashState); |
| 1438 |
| 1439 // Add old digest. |
| 1440 CryptUpdateDigest2B(&hashState, &gr.commandAuditDigest.b); |
| 1441 |
| 1442 // Add cpHash |
| 1443 CryptUpdateDigest2B(&hashState, &s_cpHashForCommandAudit.b); |
| 1444 |
| 1445 // Add rpHash |
| 1446 CryptUpdateDigest2B(&hashState, &rpHash.b); |
| 1447 |
| 1448 // Finalize the hash. |
| 1449 CryptCompleteHash2B(&hashState, &gr.commandAuditDigest.b); |
| 1450 } |
| 1451 return; |
| 1452 } |
| 1453 #endif |
| |
| |
| 6.4.5.6 UpdateAuditSessionStatus() |
| |
| Function to update the internal audit related states of a session. It |
| a) initializes the session as audit session and sets it to be exclusive if this is the first time it is used for |
| audit or audit reset was requested; |
| b) reports exclusive audit session; |
| c) extends audit log; and |
| d) clears exclusive audit session if no audit session found in the command. |
| |
| 1454 static void |
| 1455 UpdateAuditSessionStatus( |
| 1456 TPM_CC commandCode, // IN: commandCode |
| 1457 UINT32 resParmBufferSize, // IN: size of response parameter buffer |
| 1458 BYTE *resParmBuffer // IN: response parameter buffer |
| 1459 ) |
| 1460 { |
| 1461 UINT32 i; |
| 1462 TPM_HANDLE auditSession = TPM_RH_UNASSIGNED; |
| 1463 |
| 1464 // Iterate through sessions |
| 1465 for (i = 0; i < s_sessionNum; i++) |
| 1466 { |
| 1467 SESSION *session; |
| 1468 |
| 1469 // PW session do not have a loaded session and can not be an audit |
| 1470 // session either. Skip it. |
| 1471 if(s_sessionHandles[i] == TPM_RS_PW) continue; |
| 1472 |
| 1473 session = SessionGet(s_sessionHandles[i]); |
| 1474 |
| 1475 // If a session is used for audit |
| 1476 if(s_attributes[i].audit == SET) |
| 1477 { |
| 1478 // An audit session has been found |
| 1479 auditSession = s_sessionHandles[i]; |
| 1480 |
| 1481 // If the session has not been an audit session yet, or |
| 1482 // the auditSetting bits indicate a reset, initialize it and set |
| |
| Family "2.0" TCG Published Page 69 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1483 // it to be the exclusive session |
| 1484 if( session->attributes.isAudit == CLEAR |
| 1485 || s_attributes[i].auditReset == SET |
| 1486 ) |
| 1487 { |
| 1488 InitAuditSession(session); |
| 1489 g_exclusiveAuditSession = auditSession; |
| 1490 } |
| 1491 else |
| 1492 { |
| 1493 // Check if the audit session is the current exclusive audit |
| 1494 // session and, if not, clear previous exclusive audit session. |
| 1495 if(g_exclusiveAuditSession != auditSession) |
| 1496 g_exclusiveAuditSession = TPM_RH_UNASSIGNED; |
| 1497 } |
| 1498 |
| 1499 // Report audit session exclusivity. |
| 1500 if(g_exclusiveAuditSession == auditSession) |
| 1501 { |
| 1502 s_attributes[i].auditExclusive = SET; |
| 1503 } |
| 1504 else |
| 1505 { |
| 1506 s_attributes[i].auditExclusive = CLEAR; |
| 1507 } |
| 1508 |
| 1509 // Extend audit log. |
| 1510 Audit(session, commandCode, resParmBufferSize, resParmBuffer); |
| 1511 } |
| 1512 } |
| 1513 |
| 1514 // If no audit session is found in the command, and the command allows |
| 1515 // a session then, clear the current exclusive |
| 1516 // audit session. |
| 1517 if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(commandCode)) |
| 1518 { |
| 1519 g_exclusiveAuditSession = TPM_RH_UNASSIGNED; |
| 1520 } |
| 1521 |
| 1522 return; |
| 1523 } |
| |
| |
| 6.4.5.7 ComputeResponseHMAC() |
| |
| Function to compute HMAC for authorization session in a response. |
| |
| 1524 static void |
| 1525 ComputeResponseHMAC( |
| 1526 UINT32 sessionIndex, // IN: session index to be processed |
| 1527 SESSION *session, // IN: loaded session |
| 1528 TPM_CC commandCode, // IN: commandCode |
| 1529 TPM2B_NONCE *nonceTPM, // IN: nonceTPM |
| 1530 UINT32 resParmBufferSize, // IN: size of response parameter buffer |
| 1531 BYTE *resParmBuffer, // IN: response parameter buffer |
| 1532 TPM2B_DIGEST *hmac // OUT: authHMAC |
| 1533 ) |
| 1534 { |
| 1535 TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); |
| 1536 TPM2B_KEY key; // HMAC key |
| 1537 BYTE marshalBuffer[sizeof(TPMA_SESSION)]; |
| 1538 BYTE *buffer; |
| 1539 UINT32 marshalSize; |
| 1540 HMAC_STATE hmacState; |
| 1541 TPM2B_DIGEST rp_hash; |
| |
| |
| Page 70 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1542 |
| 1543 // Compute rpHash. |
| 1544 ComputeRpHash(session->authHashAlg, commandCode, resParmBufferSize, |
| 1545 resParmBuffer, &rp_hash); |
| 1546 |
| 1547 // Generate HMAC key |
| 1548 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); |
| 1549 |
| 1550 // Check if the session has an associated handle and the associated entity is |
| 1551 // the one that the session is bound to. |
| 1552 // If not bound, add the authValue of this entity to the HMAC key. |
| 1553 if( s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED |
| 1554 && !( HandleGetType(s_sessionHandles[sessionIndex]) |
| 1555 == TPM_HT_POLICY_SESSION |
| 1556 && session->attributes.isAuthValueNeeded == CLEAR) |
| 1557 && !session->attributes.requestWasBound) |
| 1558 { |
| 1559 pAssert((sizeof(AUTH_VALUE) + key.t.size) <= sizeof(key.t.buffer)); |
| 1560 key.t.size = key.t.size + |
| 1561 EntityGetAuthValue(s_associatedHandles[sessionIndex], |
| 1562 (AUTH_VALUE *)&key.t.buffer[key.t.size]); |
| 1563 } |
| 1564 |
| 1565 // if the HMAC key size for a policy session is 0, the response HMAC is |
| 1566 // computed according to the input HMAC |
| 1567 if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION |
| 1568 && key.t.size == 0 |
| 1569 && s_inputAuthValues[sessionIndex].t.size == 0) |
| 1570 { |
| 1571 hmac->t.size = 0; |
| 1572 return; |
| 1573 } |
| 1574 |
| 1575 // Start HMAC computation. |
| 1576 hmac->t.size = CryptStartHMAC2B(session->authHashAlg, &key.b, &hmacState); |
| 1577 |
| 1578 // Add hash components. |
| 1579 CryptUpdateDigest2B(&hmacState, &rp_hash.b); |
| 1580 CryptUpdateDigest2B(&hmacState, &nonceTPM->b); |
| 1581 CryptUpdateDigest2B(&hmacState, &s_nonceCaller[sessionIndex].b); |
| 1582 |
| 1583 // Add session attributes. |
| 1584 buffer = marshalBuffer; |
| 1585 marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL); |
| 1586 CryptUpdateDigest(&hmacState, marshalSize, marshalBuffer); |
| 1587 |
| 1588 // Finalize HMAC. |
| 1589 CryptCompleteHMAC2B(&hmacState, &hmac->b); |
| 1590 |
| 1591 return; |
| 1592 } |
| |
| |
| 6.4.5.8 BuildSingleResponseAuth() |
| |
| Function to compute response for an authorization session. |
| |
| 1593 static void |
| 1594 BuildSingleResponseAuth( |
| 1595 UINT32 sessionIndex, // IN: session index to be processed |
| 1596 TPM_CC commandCode, // IN: commandCode |
| 1597 UINT32 resParmBufferSize, // IN: size of response parameter buffer |
| 1598 BYTE *resParmBuffer, // IN: response parameter buffer |
| 1599 TPM2B_AUTH *auth // OUT: authHMAC |
| 1600 ) |
| |
| |
| Family "2.0" TCG Published Page 71 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1601 { |
| 1602 // For password authorization, field is empty. |
| 1603 if(s_sessionHandles[sessionIndex] == TPM_RS_PW) |
| 1604 { |
| 1605 auth->t.size = 0; |
| 1606 } |
| 1607 else |
| 1608 { |
| 1609 // Fill in policy/HMAC based session response. |
| 1610 SESSION *session = SessionGet(s_sessionHandles[sessionIndex]); |
| 1611 |
| 1612 // If the session is a policy session with isPasswordNeeded SET, the auth |
| 1613 // field is empty. |
| 1614 if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION |
| 1615 && session->attributes.isPasswordNeeded == SET) |
| 1616 auth->t.size = 0; |
| 1617 else |
| 1618 // Compute response HMAC. |
| 1619 ComputeResponseHMAC(sessionIndex, |
| 1620 session, |
| 1621 commandCode, |
| 1622 &session->nonceTPM, |
| 1623 resParmBufferSize, |
| 1624 resParmBuffer, |
| 1625 auth); |
| 1626 } |
| 1627 |
| 1628 return; |
| 1629 } |
| |
| |
| 6.4.5.9 UpdateTPMNonce() |
| |
| Updates TPM nonce in both internal session or response if applicable. |
| |
| 1630 static void |
| 1631 UpdateTPMNonce( |
| 1632 UINT16 noncesSize, // IN: number of elements in 'nonces' array |
| 1633 TPM2B_NONCE nonces[] // OUT: nonceTPM |
| 1634 ) |
| 1635 { |
| 1636 UINT32 i; |
| 1637 pAssert(noncesSize >= s_sessionNum); |
| 1638 for(i = 0; i < s_sessionNum; i++) |
| 1639 { |
| 1640 SESSION *session; |
| 1641 // For PW session, nonce is 0. |
| 1642 if(s_sessionHandles[i] == TPM_RS_PW) |
| 1643 { |
| 1644 nonces[i].t.size = 0; |
| 1645 continue; |
| 1646 } |
| 1647 session = SessionGet(s_sessionHandles[i]); |
| 1648 // Update nonceTPM in both internal session and response. |
| 1649 CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer); |
| 1650 nonces[i] = session->nonceTPM; |
| 1651 } |
| 1652 return; |
| 1653 } |
| |
| |
| 6.4.5.10 UpdateInternalSession() |
| |
| Updates internal sessions: |
| |
| |
| Page 72 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| a) Restarts session time, and |
| b) Clears a policy session since nonce is rolling. |
| |
| 1654 static void |
| 1655 UpdateInternalSession( |
| 1656 void |
| 1657 ) |
| 1658 { |
| 1659 UINT32 i; |
| 1660 for(i = 0; i < s_sessionNum; i++) |
| 1661 { |
| 1662 // For PW session, no update. |
| 1663 if(s_sessionHandles[i] == TPM_RS_PW) continue; |
| 1664 |
| 1665 if(s_attributes[i].continueSession == CLEAR) |
| 1666 { |
| 1667 // Close internal session. |
| 1668 SessionFlush(s_sessionHandles[i]); |
| 1669 } |
| 1670 else |
| 1671 { |
| 1672 // If nonce is rolling in a policy session, the policy related data |
| 1673 // will be re-initialized. |
| 1674 if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION) |
| 1675 { |
| 1676 SESSION *session = SessionGet(s_sessionHandles[i]); |
| 1677 |
| 1678 // When the nonce rolls it starts a new timing interval for the |
| 1679 // policy session. |
| 1680 SessionResetPolicyData(session); |
| 1681 session->startTime = go.clock; |
| 1682 } |
| 1683 } |
| 1684 } |
| 1685 return; |
| 1686 } |
| |
| |
| 6.4.5.11 BuildResponseSession() |
| |
| Function to build Session buffer in a response. |
| |
| 1687 void |
| 1688 BuildResponseSession( |
| 1689 TPM_ST tag, // IN: tag |
| 1690 TPM_CC commandCode, // IN: commandCode |
| 1691 UINT32 resHandleSize, // IN: size of response handle buffer |
| 1692 UINT32 resParmSize, // IN: size of response parameter buffer |
| 1693 UINT32 *resSessionSize // OUT: response session area |
| 1694 ) |
| 1695 { |
| 1696 BYTE *resParmBuffer; |
| 1697 TPM2B_NONCE responseNonces[MAX_SESSION_NUM]; |
| 1698 |
| 1699 // Compute response parameter buffer start. |
| 1700 resParmBuffer = MemoryGetResponseBuffer(commandCode) + sizeof(TPM_ST) + |
| 1701 sizeof(UINT32) + sizeof(TPM_RC) + resHandleSize; |
| 1702 |
| 1703 // For TPM_ST_SESSIONS, there is parameterSize field. |
| 1704 if(tag == TPM_ST_SESSIONS) |
| 1705 resParmBuffer += sizeof(UINT32); |
| 1706 |
| 1707 // Session nonce should be updated before parameter encryption |
| 1708 if(tag == TPM_ST_SESSIONS) |
| |
| Family "2.0" TCG Published Page 73 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1709 { |
| 1710 UpdateTPMNonce(MAX_SESSION_NUM, responseNonces); |
| 1711 |
| 1712 // Encrypt first parameter if applicable. Parameter encryption should |
| 1713 // happen after nonce update and before any rpHash is computed. |
| 1714 // If the encrypt session is associated with a handle, the authValue of |
| 1715 // this handle will be concatenated with sessionAuth to generate |
| 1716 // encryption key, no matter if the handle is the session bound entity |
| 1717 // or not. The authValue is added to sessionAuth only when the authValue |
| 1718 // is available. |
| 1719 if(s_encryptSessionIndex != UNDEFINED_INDEX) |
| 1720 { |
| 1721 UINT32 size; |
| 1722 TPM2B_AUTH extraKey; |
| 1723 |
| 1724 // Get size of the leading size field |
| 1725 if( s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED |
| 1726 && IsAuthValueAvailable(s_associatedHandles[s_encryptSessionIndex], |
| 1727 commandCode, s_encryptSessionIndex) |
| 1728 ) |
| 1729 { |
| 1730 extraKey.b.size = |
| 1731 EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex], |
| 1732 &extraKey.t.buffer); |
| 1733 } |
| 1734 else |
| 1735 { |
| 1736 extraKey.b.size = 0; |
| 1737 } |
| 1738 size = EncryptSize(commandCode); |
| 1739 CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex], |
| 1740 &s_nonceCaller[s_encryptSessionIndex].b, |
| 1741 (UINT16)size, |
| 1742 &extraKey, |
| 1743 resParmBuffer); |
| 1744 |
| 1745 } |
| 1746 |
| 1747 } |
| 1748 // Audit session should be updated first regardless of the tag. |
| 1749 // A command with no session may trigger a change of the exclusivity state. |
| 1750 UpdateAuditSessionStatus(commandCode, resParmSize, resParmBuffer); |
| 1751 |
| 1752 // Audit command. |
| 1753 CommandAudit(commandCode, resParmSize, resParmBuffer); |
| 1754 |
| 1755 // Process command with sessions. |
| 1756 if(tag == TPM_ST_SESSIONS) |
| 1757 { |
| 1758 UINT32 i; |
| 1759 BYTE *buffer; |
| 1760 TPM2B_DIGEST responseAuths[MAX_SESSION_NUM]; |
| 1761 |
| 1762 pAssert(s_sessionNum > 0); |
| 1763 |
| 1764 // Iterate over each session in the command session area, and create |
| 1765 // corresponding sessions for response. |
| 1766 for(i = 0; i < s_sessionNum; i++) |
| 1767 { |
| 1768 BuildSingleResponseAuth( |
| 1769 i, |
| 1770 commandCode, |
| 1771 resParmSize, |
| 1772 resParmBuffer, |
| 1773 &responseAuths[i]); |
| 1774 // Make sure that continueSession is SET on any Password session. |
| |
| Page 74 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1775 // This makes it marginally easier for the management software |
| 1776 // to keep track of the closed sessions. |
| 1777 if( s_attributes[i].continueSession == CLEAR |
| 1778 && s_sessionHandles[i] == TPM_RS_PW) |
| 1779 { |
| 1780 s_attributes[i].continueSession = SET; |
| 1781 } |
| 1782 } |
| 1783 |
| 1784 // Assemble Response Sessions. |
| 1785 *resSessionSize = 0; |
| 1786 buffer = resParmBuffer + resParmSize; |
| 1787 for(i = 0; i < s_sessionNum; i++) |
| 1788 { |
| 1789 *resSessionSize += TPM2B_NONCE_Marshal(&responseNonces[i], |
| 1790 &buffer, NULL); |
| 1791 *resSessionSize += TPMA_SESSION_Marshal(&s_attributes[i], |
| 1792 &buffer, NULL); |
| 1793 *resSessionSize += TPM2B_DIGEST_Marshal(&responseAuths[i], |
| 1794 &buffer, NULL); |
| 1795 } |
| 1796 |
| 1797 // Update internal sessions after completing response buffer computation. |
| 1798 UpdateInternalSession(); |
| 1799 } |
| 1800 else |
| 1801 { |
| 1802 // Process command with no session. |
| 1803 *resSessionSize = 0; |
| 1804 } |
| 1805 |
| 1806 return; |
| 1807 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 75 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| 7 Command Support Functions |
| |
| 7.1 Introduction |
| |
| This clause contains support routines that are called by the command action code in TPM 2.0 Part 3. The |
| functions are grouped by the command group that is supported by the functions. |
| |
| 7.2 Attestation Command Support (Attest_spt.c) |
| |
| 7.2.1 Includes |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "Attest_spt_fp.h" |
| |
| |
| 7.2.2 Functions |
| |
| 7.2.2.1 FillInAttestInfo() |
| |
| Fill in common fields of TPMS_ATTEST structure. |
| |
| Error Returns Meaning |
| |
| TPM_RC_KEY key referenced by signHandle is not a signing key |
| TPM_RC_SCHEME both scheme and key's default scheme are empty; or scheme is |
| empty while key's default scheme requires explicit input scheme (split |
| signing); or non-empty default key scheme differs from scheme |
| |
| 3 TPM_RC |
| 4 FillInAttestInfo( |
| 5 TPMI_DH_OBJECT signHandle, // IN: handle of signing object |
| 6 TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing |
| 7 TPM2B_DATA *data, // IN: qualifying data |
| 8 TPMS_ATTEST *attest // OUT: attest structure |
| 9 ) |
| 10 { |
| 11 TPM_RC result; |
| 12 TPMI_RH_HIERARCHY signHierarhcy; |
| 13 |
| 14 result = CryptSelectSignScheme(signHandle, scheme); |
| 15 if(result != TPM_RC_SUCCESS) |
| 16 return result; |
| 17 |
| 18 // Magic number |
| 19 attest->magic = TPM_GENERATED_VALUE; |
| 20 |
| 21 if(signHandle == TPM_RH_NULL) |
| 22 { |
| 23 BYTE *buffer; |
| 24 // For null sign handle, the QN is TPM_RH_NULL |
| 25 buffer = attest->qualifiedSigner.t.name; |
| 26 attest->qualifiedSigner.t.size = |
| 27 TPM_HANDLE_Marshal(&signHandle, &buffer, NULL); |
| 28 } |
| 29 else |
| 30 { |
| 31 // Certifying object qualified name |
| 32 // if the scheme is anonymous, this is an empty buffer |
| 33 if(CryptIsSchemeAnonymous(scheme->scheme)) |
| |
| Page 76 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 34 attest->qualifiedSigner.t.size = 0; |
| 35 else |
| 36 ObjectGetQualifiedName(signHandle, &attest->qualifiedSigner); |
| 37 } |
| 38 |
| 39 // current clock in plain text |
| 40 TimeFillInfo(&attest->clockInfo); |
| 41 |
| 42 // Firmware version in plain text |
| 43 attest->firmwareVersion = ((UINT64) gp.firmwareV1 << (sizeof(UINT32) * 8)); |
| 44 attest->firmwareVersion += gp.firmwareV2; |
| 45 |
| 46 // Get the hierarchy of sign object. For NULL sign handle, the hierarchy |
| 47 // will be TPM_RH_NULL |
| 48 signHierarhcy = EntityGetHierarchy(signHandle); |
| 49 if(signHierarhcy != TPM_RH_PLATFORM && signHierarhcy != TPM_RH_ENDORSEMENT) |
| 50 { |
| 51 // For sign object is not in platform or endorsement hierarchy, |
| 52 // obfuscate the clock and firmwereVersion information |
| 53 UINT64 obfuscation[2]; |
| 54 TPMI_ALG_HASH hashAlg; |
| 55 |
| 56 // Get hash algorithm |
| 57 if(signHandle == TPM_RH_NULL || signHandle == TPM_RH_OWNER) |
| 58 { |
| 59 hashAlg = CONTEXT_INTEGRITY_HASH_ALG; |
| 60 } |
| 61 else |
| 62 { |
| 63 OBJECT *signObject = NULL; |
| 64 signObject = ObjectGet(signHandle); |
| 65 hashAlg = signObject->publicArea.nameAlg; |
| 66 } |
| 67 KDFa(hashAlg, &gp.shProof.b, "OBFUSCATE", |
| 68 &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL); |
| 69 |
| 70 // Obfuscate data |
| 71 attest->firmwareVersion += obfuscation[0]; |
| 72 attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32); |
| 73 attest->clockInfo.restartCount += (UINT32)obfuscation[1]; |
| 74 } |
| 75 |
| 76 // External data |
| 77 if(CryptIsSchemeAnonymous(scheme->scheme)) |
| 78 attest->extraData.t.size = 0; |
| 79 else |
| 80 { |
| 81 // If we move the data to the attestation structure, then we will not use |
| 82 // it in the signing operation except as part of the signed data |
| 83 attest->extraData = *data; |
| 84 data->t.size = 0; |
| 85 } |
| 86 |
| 87 return TPM_RC_SUCCESS; |
| 88 } |
| |
| |
| 7.2.2.2 SignAttestInfo() |
| |
| Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 77 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_ATTRIBUTES signHandle references not a signing key |
| TPM_RC_SCHEME scheme is not compatible with signHandle type |
| TPM_RC_VALUE digest generated for the given scheme is greater than the modulus of |
| signHandle (for an RSA key); invalid commit status or failed to |
| generate r value (for an ECC key) |
| |
| 89 TPM_RC |
| 90 SignAttestInfo( |
| 91 TPMI_DH_OBJECT signHandle, // IN: handle of sign object |
| 92 TPMT_SIG_SCHEME *scheme, // IN: sign scheme |
| 93 TPMS_ATTEST *certifyInfo, // IN: the data to be signed |
| 94 TPM2B_DATA *qualifyingData, // IN: extra data for the signing proce |
| 95 TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be |
| 96 // signed |
| 97 TPMT_SIGNATURE *signature // OUT: signature |
| 98 ) |
| 99 { |
| 100 TPM_RC result; |
| 101 TPMI_ALG_HASH hashAlg; |
| 102 BYTE *buffer; |
| 103 HASH_STATE hashState; |
| 104 TPM2B_DIGEST digest; |
| 105 |
| 106 // Marshal TPMS_ATTEST structure for hash |
| 107 buffer = attest->t.attestationData; |
| 108 attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL); |
| 109 |
| 110 if(signHandle == TPM_RH_NULL) |
| 111 { |
| 112 signature->sigAlg = TPM_ALG_NULL; |
| 113 } |
| 114 else |
| 115 { |
| 116 // Attestation command may cause the orderlyState to be cleared due to |
| 117 // the reporting of clock info. If this is the case, check if NV is |
| 118 // available first |
| 119 if(gp.orderlyState != SHUTDOWN_NONE) |
| 120 { |
| 121 // The command needs NV update. Check if NV is available. |
| 122 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at |
| 123 // this point |
| 124 result = NvIsAvailable(); |
| 125 if(result != TPM_RC_SUCCESS) |
| 126 return result; |
| 127 } |
| 128 |
| 129 // Compute hash |
| 130 hashAlg = scheme->details.any.hashAlg; |
| 131 digest.t.size = CryptStartHash(hashAlg, &hashState); |
| 132 CryptUpdateDigest(&hashState, attest->t.size, attest->t.attestationData); |
| 133 CryptCompleteHash2B(&hashState, &digest.b); |
| 134 |
| 135 // If there is qualifying data, need to rehash the the data |
| 136 // hash(qualifyingData || hash(attestationData)) |
| 137 if(qualifyingData->t.size != 0) |
| 138 { |
| 139 CryptStartHash(hashAlg, &hashState); |
| 140 CryptUpdateDigest(&hashState, |
| 141 qualifyingData->t.size, |
| 142 qualifyingData->t.buffer); |
| 143 CryptUpdateDigest(&hashState, digest.t.size, digest.t.buffer); |
| 144 CryptCompleteHash2B(&hashState, &digest.b); |
| |
| Page 78 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 145 } |
| 146 |
| 147 // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or |
| 148 // TPM_RC_ATTRIBUTES error may be returned at this point |
| 149 return CryptSign(signHandle, |
| 150 scheme, |
| 151 &digest, |
| 152 signature); |
| 153 } |
| 154 |
| 155 return TPM_RC_SUCCESS; |
| 156 } |
| |
| |
| 7.3 Context Management Command Support (Context_spt.c) |
| |
| 7.3.1 Includes |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "Context_spt_fp.h" |
| |
| |
| 7.3.2 Functions |
| |
| 7.3.2.1 ComputeContextProtectionKey() |
| |
| This function retrieves the symmetric protection key for context encryption It is used by |
| TPM2_ConextSave() and TPM2_ContextLoad() to create the symmetric encryption key and iv |
| |
| 3 void |
| 4 ComputeContextProtectionKey( |
| 5 TPMS_CONTEXT *contextBlob, // IN: context blob |
| 6 TPM2B_SYM_KEY *symKey, // OUT: the symmetric key |
| 7 TPM2B_IV *iv // OUT: the IV. |
| 8 ) |
| 9 { |
| 10 UINT16 symKeyBits; // number of bits in the parent's |
| 11 // symmetric key |
| 12 TPM2B_AUTH *proof = NULL; // the proof value to use. Is null for |
| 13 // everything but a primary object in |
| 14 // the Endorsement Hierarchy |
| 15 |
| 16 BYTE kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF |
| 17 |
| 18 TPM2B_DATA sequence2B, handle2B; |
| 19 |
| 20 // Get proof value |
| 21 proof = HierarchyGetProof(contextBlob->hierarchy); |
| 22 |
| 23 // Get sequence value in 2B format |
| 24 sequence2B.t.size = sizeof(contextBlob->sequence); |
| 25 MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence, |
| 26 sizeof(contextBlob->sequence), |
| 27 sizeof(sequence2B.t.buffer)); |
| 28 |
| 29 // Get handle value in 2B format |
| 30 handle2B.t.size = sizeof(contextBlob->savedHandle); |
| 31 MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle, |
| 32 sizeof(contextBlob->savedHandle), |
| 33 sizeof(handle2B.t.buffer)); |
| 34 |
| 35 // Get the symmetric encryption key size |
| 36 symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; |
| |
| |
| Family "2.0" TCG Published Page 79 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 37 symKeyBits = CONTEXT_ENCRYPT_KEY_BITS; |
| 38 // Get the size of the IV for the algorithm |
| 39 iv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits); |
| 40 |
| 41 // KDFa to generate symmetric key and IV value |
| 42 KDFa(CONTEXT_INTEGRITY_HASH_ALG, &proof->b, "CONTEXT", &sequence2B.b, |
| 43 &handle2B.b, (symKey->t.size + iv->t.size) * 8, kdfResult, NULL); |
| 44 |
| 45 // Copy part of the returned value as the key |
| 46 MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size, |
| 47 sizeof(symKey->t.buffer)); |
| 48 |
| 49 // Copy the rest as the IV |
| 50 MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size, |
| 51 sizeof(iv->t.buffer)); |
| 52 |
| 53 return; |
| 54 } |
| |
| |
| 7.3.2.2 ComputeContextIntegrity() |
| |
| Generate the integrity hash for a context It is used by TPM2_ContextSave() to create an integrity hash |
| and by TPM2_ContextLoad() to compare an integrity hash |
| |
| 55 void |
| 56 ComputeContextIntegrity( |
| 57 TPMS_CONTEXT *contextBlob, // IN: context blob |
| 58 TPM2B_DIGEST *integrity // OUT: integrity |
| 59 ) |
| 60 { |
| 61 HMAC_STATE hmacState; |
| 62 TPM2B_AUTH *proof; |
| 63 UINT16 integritySize; |
| 64 |
| 65 // Get proof value |
| 66 proof = HierarchyGetProof(contextBlob->hierarchy); |
| 67 |
| 68 // Start HMAC |
| 69 integrity->t.size = CryptStartHMAC2B(CONTEXT_INTEGRITY_HASH_ALG, |
| 70 &proof->b, &hmacState); |
| 71 |
| 72 // Compute integrity size at the beginning of context blob |
| 73 integritySize = sizeof(integrity->t.size) + integrity->t.size; |
| 74 |
| 75 // Adding total reset counter so that the context cannot be |
| 76 // used after a TPM Reset |
| 77 CryptUpdateDigestInt(&hmacState, sizeof(gp.totalResetCount), |
| 78 &gp.totalResetCount); |
| 79 |
| 80 // If this is a ST_CLEAR object, add the clear count |
| 81 // so that this contest cannot be loaded after a TPM Restart |
| 82 if(contextBlob->savedHandle == 0x80000002) |
| 83 CryptUpdateDigestInt(&hmacState, sizeof(gr.clearCount), &gr.clearCount); |
| 84 |
| 85 // Adding sequence number to the HMAC to make sure that it doesn't |
| 86 // get changed |
| 87 CryptUpdateDigestInt(&hmacState, sizeof(contextBlob->sequence), |
| 88 &contextBlob->sequence); |
| 89 |
| 90 // Protect the handle |
| 91 CryptUpdateDigestInt(&hmacState, sizeof(contextBlob->savedHandle), |
| 92 &contextBlob->savedHandle); |
| 93 |
| 94 // Adding sensitive contextData, skip the leading integrity area |
| |
| Page 80 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 95 CryptUpdateDigest(&hmacState, contextBlob->contextBlob.t.size - integritySize, |
| 96 contextBlob->contextBlob.t.buffer + integritySize); |
| 97 |
| 98 // Complete HMAC |
| 99 CryptCompleteHMAC2B(&hmacState, &integrity->b); |
| 100 |
| 101 return; |
| 102 } |
| |
| |
| 7.3.2.3 SequenceDataImportExport() |
| |
| This function is used scan through the sequence object and either modify the hash state data for |
| LIB_EXPORT or to import it into the internal format |
| |
| 103 void |
| 104 SequenceDataImportExport( |
| 105 OBJECT *object, // IN: the object containing the sequence data |
| 106 OBJECT *exportObject, // IN/OUT: the object structure that will get |
| 107 // the exported hash state |
| 108 IMPORT_EXPORT direction |
| 109 ) |
| 110 { |
| 111 int count = 1; |
| 112 HASH_OBJECT *internalFmt = (HASH_OBJECT *)object; |
| 113 HASH_OBJECT *externalFmt = (HASH_OBJECT *)exportObject; |
| 114 |
| 115 if(object->attributes.eventSeq) |
| 116 count = HASH_COUNT; |
| 117 for(; count; count--) |
| 118 CryptHashStateImportExport(&internalFmt->state.hashState[count - 1], |
| 119 externalFmt->state.hashState, direction); |
| 120 } |
| |
| |
| 7.4 Policy Command Support (Policy_spt.c) |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "Policy_spt_fp.h" |
| 3 #include "PolicySigned_fp.h" |
| 4 #include "PolicySecret_fp.h" |
| 5 #include "PolicyTicket_fp.h" |
| |
| |
| 7.4.1 PolicyParameterChecks() |
| |
| This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The |
| common parameters are nonceTPM, expiration, and cpHashA. |
| |
| 6 TPM_RC |
| 7 PolicyParameterChecks( |
| 8 SESSION *session, |
| 9 UINT64 authTimeout, |
| 10 TPM2B_DIGEST *cpHashA, |
| 11 TPM2B_NONCE *nonce, |
| 12 TPM_RC nonceParameterNumber, |
| 13 TPM_RC cpHashParameterNumber, |
| 14 TPM_RC expirationParameterNumber |
| 15 ) |
| 16 { |
| 17 TPM_RC result; |
| 18 |
| 19 // Validate that input nonceTPM is correct if present |
| 20 if(nonce != NULL && nonce->t.size != 0) |
| |
| |
| Family "2.0" TCG Published Page 81 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 21 { |
| 22 if(!Memory2BEqual(&nonce->b, &session->nonceTPM.b)) |
| 23 return TPM_RC_NONCE + RC_PolicySigned_nonceTPM; |
| 24 } |
| 25 // If authTimeout is set (expiration != 0... |
| 26 if(authTimeout != 0) |
| 27 { |
| 28 // ...then nonce must be present |
| 29 // nonce present isn't checked in PolicyTicket |
| 30 if(nonce != NULL && nonce->t.size == 0) |
| 31 // This error says that the time has expired but it is pointing |
| 32 // at the nonceTPM value. |
| 33 return TPM_RC_EXPIRED + nonceParameterNumber; |
| 34 |
| 35 // Validate input expiration. |
| 36 // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE |
| 37 // or TPM_RC_NV_RATE error may be returned here. |
| 38 result = NvIsAvailable(); |
| 39 if(result != TPM_RC_SUCCESS) |
| 40 return result; |
| 41 |
| 42 if(authTimeout < go.clock) |
| 43 return TPM_RC_EXPIRED + expirationParameterNumber; |
| 44 } |
| 45 // If the cpHash is present, then check it |
| 46 if(cpHashA != NULL && cpHashA->t.size != 0) |
| 47 { |
| 48 // The cpHash input has to have the correct size |
| 49 if(cpHashA->t.size != session->u2.policyDigest.t.size) |
| 50 return TPM_RC_SIZE + cpHashParameterNumber; |
| 51 |
| 52 // If the cpHash has already been set, then this input value |
| 53 // must match the current value. |
| 54 if( session->u1.cpHash.b.size != 0 |
| 55 && !Memory2BEqual(&cpHashA->b, &session->u1.cpHash.b)) |
| 56 return TPM_RC_CPHASH; |
| 57 } |
| 58 return TPM_RC_SUCCESS; |
| 59 } |
| |
| |
| 7.4.2 PolicyContextUpdate() |
| |
| Update policy hash Update the policyDigest in policy session by extending policyRef and objectName to |
| it. This will also update the cpHash if it is present. |
| |
| 60 void |
| 61 PolicyContextUpdate( |
| 62 TPM_CC commandCode, // IN: command code |
| 63 TPM2B_NAME *name, // IN: name of entity |
| 64 TPM2B_NONCE *ref, // IN: the reference data |
| 65 TPM2B_DIGEST *cpHash, // IN: the cpHash (optional) |
| 66 UINT64 policyTimeout, |
| 67 SESSION *session // IN/OUT: policy session to be updated |
| 68 ) |
| 69 { |
| 70 HASH_STATE hashState; |
| 71 UINT16 policyDigestSize; |
| 72 |
| 73 // Start hash |
| 74 policyDigestSize = CryptStartHash(session->authHashAlg, &hashState); |
| 75 |
| 76 // policyDigest size should always be the digest size of session hash algorithm. |
| 77 pAssert(session->u2.policyDigest.t.size == policyDigestSize); |
| 78 |
| |
| Page 82 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 79 // add old digest |
| 80 CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b); |
| 81 |
| 82 // add commandCode |
| 83 CryptUpdateDigestInt(&hashState, sizeof(commandCode), &commandCode); |
| 84 |
| 85 // add name if applicable |
| 86 if(name != NULL) |
| 87 CryptUpdateDigest2B(&hashState, &name->b); |
| 88 |
| 89 // Complete the digest and get the results |
| 90 CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b); |
| 91 |
| 92 // Start second hash computation |
| 93 CryptStartHash(session->authHashAlg, &hashState); |
| 94 |
| 95 // add policyDigest |
| 96 CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b); |
| 97 |
| 98 // add policyRef |
| 99 if(ref != NULL) |
| 100 CryptUpdateDigest2B(&hashState, &ref->b); |
| 101 |
| 102 // Complete second digest |
| 103 CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b); |
| 104 |
| 105 // Deal with the cpHash. If the cpHash value is present |
| 106 // then it would have already been checked to make sure that |
| 107 // it is compatible with the current value so all we need |
| 108 // to do here is copy it and set the iscoHashDefined attribute |
| 109 if(cpHash != NULL && cpHash->t.size != 0) |
| 110 { |
| 111 session->u1.cpHash = *cpHash; |
| 112 session->attributes.iscpHashDefined = SET; |
| 113 } |
| 114 |
| 115 // update the timeout if it is specified |
| 116 if(policyTimeout!= 0) |
| 117 { |
| 118 // If the timeout has not been set, then set it to the new value |
| 119 if(session->timeOut == 0) |
| 120 session->timeOut = policyTimeout; |
| 121 else if(session->timeOut > policyTimeout) |
| 122 session->timeOut = policyTimeout; |
| 123 } |
| 124 return; |
| 125 } |
| |
| |
| 7.5 NV Command Support (NV_spt.c) |
| |
| 7.5.1 Includes |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "NV_spt_fp.h" |
| |
| |
| 7.5.2 Fuctions |
| |
| 7.5.2.1 NvReadAccessChecks() |
| |
| Common routine for validating a read Used by TPM2_NV_Read(), TPM2_NV_ReadLock() and |
| TPM2_PolicyNV() |
| |
| Family "2.0" TCG Published Page 83 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_AUTHORIZATION autHandle is not allowed to authorize read of the index |
| TPM_RC_NV_LOCKED Read locked |
| TPM_RC_NV_UNINITIALIZED Try to read an uninitialized index |
| |
| 3 TPM_RC |
| 4 NvReadAccessChecks( |
| 5 TPM_HANDLE authHandle, // IN: the handle that provided the |
| 6 // authorization |
| 7 TPM_HANDLE nvHandle // IN: the handle of the NV index to be written |
| 8 ) |
| 9 { |
| 10 NV_INDEX nvIndex; |
| 11 |
| 12 // Get NV index info |
| 13 NvGetIndexInfo(nvHandle, &nvIndex); |
| 14 |
| 15 // This check may be done before doing authorization checks as is done in this |
| 16 // version of the reference code. If not done there, then uncomment the next |
| 17 // three lines. |
| 18 // // If data is read locked, returns an error |
| 19 // if(nvIndex.publicArea.attributes.TPMA_NV_READLOCKED == SET) |
| 20 // return TPM_RC_NV_LOCKED; |
| 21 |
| 22 // If the authorization was provided by the owner or platform, then check |
| 23 // that the attributes allow the read. If the authorization handle |
| 24 // is the same as the index, then the checks were made when the authorization |
| 25 // was checked.. |
| 26 if(authHandle == TPM_RH_OWNER) |
| 27 { |
| 28 // If Owner provided auth then ONWERWRITE must be SET |
| 29 if(! nvIndex.publicArea.attributes.TPMA_NV_OWNERREAD) |
| 30 return TPM_RC_NV_AUTHORIZATION; |
| 31 } |
| 32 else if(authHandle == TPM_RH_PLATFORM) |
| 33 { |
| 34 // If Platform provided auth then PPWRITE must be SET |
| 35 if(!nvIndex.publicArea.attributes.TPMA_NV_PPREAD) |
| 36 return TPM_RC_NV_AUTHORIZATION; |
| 37 } |
| 38 // If neither Owner nor Platform provided auth, make sure that it was |
| 39 // provided by this index. |
| 40 else if(authHandle != nvHandle) |
| 41 return TPM_RC_NV_AUTHORIZATION; |
| 42 |
| 43 // If the index has not been written, then the value cannot be read |
| 44 // NOTE: This has to come after other access checks to make sure that |
| 45 // the proper authorization is given to TPM2_NV_ReadLock() |
| 46 if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR) |
| 47 return TPM_RC_NV_UNINITIALIZED; |
| 48 |
| 49 return TPM_RC_SUCCESS; |
| 50 } |
| |
| |
| 7.5.2.2 NvWriteAccessChecks() |
| |
| Common routine for validating a write Used by TPM2_NV_Write(), TPM2_NV_Increment(), |
| TPM2_SetBits(), and TPM2_NV_WriteLock() |
| |
| |
| |
| |
| Page 84 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_AUTHORIZATION Authorization fails |
| TPM_RC_NV_LOCKED Write locked |
| |
| 51 TPM_RC |
| 52 NvWriteAccessChecks( |
| 53 TPM_HANDLE authHandle, // IN: the handle that provided the |
| 54 // authorization |
| 55 TPM_HANDLE nvHandle // IN: the handle of the NV index to be written |
| 56 ) |
| 57 { |
| 58 NV_INDEX nvIndex; |
| 59 |
| 60 // Get NV index info |
| 61 NvGetIndexInfo(nvHandle, &nvIndex); |
| 62 |
| 63 // This check may be done before doing authorization checks as is done in this |
| 64 // version of the reference code. If not done there, then uncomment the next |
| 65 // three lines. |
| 66 // // If data is write locked, returns an error |
| 67 // if(nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED == SET) |
| 68 // return TPM_RC_NV_LOCKED; |
| 69 |
| 70 // If the authorization was provided by the owner or platform, then check |
| 71 // that the attributes allow the write. If the authorization handle |
| 72 // is the same as the index, then the checks were made when the authorization |
| 73 // was checked.. |
| 74 if(authHandle == TPM_RH_OWNER) |
| 75 { |
| 76 // If Owner provided auth then ONWERWRITE must be SET |
| 77 if(! nvIndex.publicArea.attributes.TPMA_NV_OWNERWRITE) |
| 78 return TPM_RC_NV_AUTHORIZATION; |
| 79 } |
| 80 else if(authHandle == TPM_RH_PLATFORM) |
| 81 { |
| 82 // If Platform provided auth then PPWRITE must be SET |
| 83 if(!nvIndex.publicArea.attributes.TPMA_NV_PPWRITE) |
| 84 return TPM_RC_NV_AUTHORIZATION; |
| 85 } |
| 86 // If neither Owner nor Platform provided auth, make sure that it was |
| 87 // provided by this index. |
| 88 else if(authHandle != nvHandle) |
| 89 return TPM_RC_NV_AUTHORIZATION; |
| 90 |
| 91 return TPM_RC_SUCCESS; |
| 92 } |
| |
| |
| 7.6 Object Command Support (Object_spt.c) |
| |
| 7.6.1 Includes |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "Object_spt_fp.h" |
| 3 #include <Platform.h> |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 85 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 7.6.2 Local Functions |
| |
| 7.6.2.1 EqualCryptSet() |
| |
| Check if the crypto sets in two public areas are equal |
| |
| Error Returns Meaning |
| |
| TPM_RC_ASYMMETRIC mismatched parameters |
| TPM_RC_HASH mismatched name algorithm |
| TPM_RC_TYPE mismatched type |
| |
| 4 static TPM_RC |
| 5 EqualCryptSet( |
| 6 TPMT_PUBLIC *publicArea1, // IN: public area 1 |
| 7 TPMT_PUBLIC *publicArea2 // IN: public area 2 |
| 8 ) |
| 9 { |
| 10 UINT16 size1; |
| 11 UINT16 size2; |
| 12 BYTE params1[sizeof(TPMU_PUBLIC_PARMS)]; |
| 13 BYTE params2[sizeof(TPMU_PUBLIC_PARMS)]; |
| 14 BYTE *buffer; |
| 15 |
| 16 // Compare name hash |
| 17 if(publicArea1->nameAlg != publicArea2->nameAlg) |
| 18 return TPM_RC_HASH; |
| 19 |
| 20 // Compare algorithm |
| 21 if(publicArea1->type != publicArea2->type) |
| 22 return TPM_RC_TYPE; |
| 23 |
| 24 // TPMU_PUBLIC_PARMS field should be identical |
| 25 buffer = params1; |
| 26 size1 = TPMU_PUBLIC_PARMS_Marshal(&publicArea1->parameters, &buffer, |
| 27 NULL, publicArea1->type); |
| 28 buffer = params2; |
| 29 size2 = TPMU_PUBLIC_PARMS_Marshal(&publicArea2->parameters, &buffer, |
| 30 NULL, publicArea2->type); |
| 31 |
| 32 if(size1 != size2 || !MemoryEqual(params1, params2, size1)) |
| 33 return TPM_RC_ASYMMETRIC; |
| 34 |
| 35 return TPM_RC_SUCCESS; |
| 36 } |
| |
| |
| 7.6.2.2 GetIV2BSize() |
| |
| Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive data. It |
| includes both size of size field and size of iv data |
| |
| Return Value Meaning |
| |
| 37 static UINT16 |
| 38 GetIV2BSize( |
| 39 TPM_HANDLE protectorHandle // IN: the protector handle |
| 40 ) |
| 41 { |
| 42 OBJECT *protector = NULL; // Pointer to the protector object |
| 43 TPM_ALG_ID symAlg; |
| |
| |
| Page 86 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 44 UINT16 keyBits; |
| 45 |
| 46 // Determine the symmetric algorithm and size of key |
| 47 if(protectorHandle == TPM_RH_NULL) |
| 48 { |
| 49 // Use the context encryption algorithm and key size |
| 50 symAlg = CONTEXT_ENCRYPT_ALG; |
| 51 keyBits = CONTEXT_ENCRYPT_KEY_BITS; |
| 52 } |
| 53 else |
| 54 { |
| 55 protector = ObjectGet(protectorHandle); |
| 56 symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm; |
| 57 keyBits= protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym; |
| 58 } |
| 59 |
| 60 // The IV size is a UINT16 size field plus the block size of the symmetric |
| 61 // algorithm |
| 62 return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits); |
| 63 } |
| |
| |
| 7.6.2.3 ComputeProtectionKeyParms() |
| |
| This function retrieves the symmetric protection key parameters for the sensitive data The parameters |
| retrieved from this function include encryption algorithm, key size in bit, and a TPM2B_SYM_KEY |
| containing the key material as well as the key size in bytes This function is used for any action that |
| requires encrypting or decrypting of the sensitive area of an object or a credential blob |
| |
| 64 static void |
| 65 ComputeProtectionKeyParms( |
| 66 TPM_HANDLE protectorHandle, // IN: the protector handle |
| 67 TPM_ALG_ID hashAlg, // IN: hash algorithm for KDFa |
| 68 TPM2B_NAME *name, // IN: name of the object |
| 69 TPM2B_SEED *seedIn, // IN: optional seed for duplication blob. |
| 70 // For non duplication blob, this |
| 71 // parameter should be NULL |
| 72 TPM_ALG_ID *symAlg, // OUT: the symmetric algorithm |
| 73 UINT16 *keyBits, // OUT: the symmetric key size in bits |
| 74 TPM2B_SYM_KEY *symKey // OUT: the symmetric key |
| 75 ) |
| 76 { |
| 77 TPM2B_SEED *seed = NULL; |
| 78 OBJECT *protector = NULL; // Pointer to the protector |
| 79 |
| 80 // Determine the algorithms for the KDF and the encryption/decryption |
| 81 // For TPM_RH_NULL, using context settings |
| 82 if(protectorHandle == TPM_RH_NULL) |
| 83 { |
| 84 // Use the context encryption algorithm and key size |
| 85 *symAlg = CONTEXT_ENCRYPT_ALG; |
| 86 symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; |
| 87 *keyBits = CONTEXT_ENCRYPT_KEY_BITS; |
| 88 } |
| 89 else |
| 90 { |
| 91 TPMT_SYM_DEF_OBJECT *symDef; |
| 92 protector = ObjectGet(protectorHandle); |
| 93 symDef = &protector->publicArea.parameters.asymDetail.symmetric; |
| 94 *symAlg = symDef->algorithm; |
| 95 *keyBits= symDef->keyBits.sym; |
| 96 symKey->t.size = (*keyBits + 7) / 8; |
| 97 } |
| 98 |
| 99 // Get seed for KDF |
| |
| Family "2.0" TCG Published Page 87 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 100 seed = GetSeedForKDF(protectorHandle, seedIn); |
| 101 |
| 102 // KDFa to generate symmetric key and IV value |
| 103 KDFa(hashAlg, (TPM2B *)seed, "STORAGE", (TPM2B *)name, NULL, |
| 104 symKey->t.size * 8, symKey->t.buffer, NULL); |
| 105 |
| 106 return; |
| 107 } |
| |
| |
| 7.6.2.4 ComputeOuterIntegrity() |
| |
| The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaled |
| sensitive area. The caller should skip over the area set aside for the integrity value and compute the hash |
| of the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area |
| contents is an array of bytes. |
| |
| 108 static void |
| 109 ComputeOuterIntegrity( |
| 110 TPM2B_NAME *name, // IN: the name of the object |
| 111 TPM_HANDLE protectorHandle, // IN: The handle of the object that |
| 112 // provides protection. For object, it |
| 113 // is parent handle. For credential, it |
| 114 // is the handle of encrypt object. For |
| 115 // a Temporary Object, it is TPM_RH_NULL |
| 116 TPMI_ALG_HASH hashAlg, // IN: algorithm to use for integrity |
| 117 TPM2B_SEED *seedIn, // IN: an external seed may be provided for |
| 118 // duplication blob. For non duplication |
| 119 // blob, this parameter should be NULL |
| 120 UINT32 sensitiveSize, // IN: size of the marshaled sensitive data |
| 121 BYTE *sensitiveData, // IN: sensitive area |
| 122 TPM2B_DIGEST *integrity // OUT: integrity |
| 123 ) |
| 124 { |
| 125 HMAC_STATE hmacState; |
| 126 |
| 127 TPM2B_DIGEST hmacKey; |
| 128 TPM2B_SEED *seed = NULL; |
| 129 |
| 130 // Get seed for KDF |
| 131 seed = GetSeedForKDF(protectorHandle, seedIn); |
| 132 |
| 133 // Determine the HMAC key bits |
| 134 hmacKey.t.size = CryptGetHashDigestSize(hashAlg); |
| 135 |
| 136 // KDFa to generate HMAC key |
| 137 KDFa(hashAlg, (TPM2B *)seed, "INTEGRITY", NULL, NULL, |
| 138 hmacKey.t.size * 8, hmacKey.t.buffer, NULL); |
| 139 |
| 140 // Start HMAC and get the size of the digest which will become the integrity |
| 141 integrity->t.size = CryptStartHMAC2B(hashAlg, &hmacKey.b, &hmacState); |
| 142 |
| 143 // Adding the marshaled sensitive area to the integrity value |
| 144 CryptUpdateDigest(&hmacState, sensitiveSize, sensitiveData); |
| 145 |
| 146 // Adding name |
| 147 CryptUpdateDigest2B(&hmacState, (TPM2B *)name); |
| 148 |
| 149 // Compute HMAC |
| 150 CryptCompleteHMAC2B(&hmacState, &integrity->b); |
| 151 |
| 152 return; |
| 153 } |
| |
| |
| |
| Page 88 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 7.6.2.5 ComputeInnerIntegrity() |
| |
| This function computes the integrity of an inner wrap |
| |
| 154 static void |
| 155 ComputeInnerIntegrity( |
| 156 TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap |
| 157 TPM2B_NAME *name, // IN: the name of the object |
| 158 UINT16 dataSize, // IN: the size of sensitive data |
| 159 BYTE *sensitiveData, // IN: sensitive data |
| 160 TPM2B_DIGEST *integrity // OUT: inner integrity |
| 161 ) |
| 162 { |
| 163 HASH_STATE hashState; |
| 164 |
| 165 // Start hash and get the size of the digest which will become the integrity |
| 166 integrity->t.size = CryptStartHash(hashAlg, &hashState); |
| 167 |
| 168 // Adding the marshaled sensitive area to the integrity value |
| 169 CryptUpdateDigest(&hashState, dataSize, sensitiveData); |
| 170 |
| 171 // Adding name |
| 172 CryptUpdateDigest2B(&hashState, &name->b); |
| 173 |
| 174 // Compute hash |
| 175 CryptCompleteHash2B(&hashState, &integrity->b); |
| 176 |
| 177 return; |
| 178 |
| 179 } |
| |
| |
| 7.6.2.6 ProduceInnerIntegrity() |
| |
| This function produces an inner integrity for regular private, credential or duplication blob It requires the |
| sensitive data being marshaled to the innerBuffer, with the leading bytes reserved for integrity hash. It |
| assume the sensitive data starts at address (innerBuffer + integrity size). This function integrity at the |
| beginning of the inner buffer It returns the total size of buffer with the inner wrap |
| |
| 180 static UINT16 |
| 181 ProduceInnerIntegrity( |
| 182 TPM2B_NAME *name, // IN: the name of the object |
| 183 TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap |
| 184 UINT16 dataSize, // IN: the size of sensitive data, excluding the |
| 185 // leading integrity buffer size |
| 186 BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in |
| 187 // it. At input, the leading bytes of this |
| 188 // buffer is reserved for integrity |
| 189 ) |
| 190 { |
| 191 BYTE *sensitiveData; // pointer to the sensitive data |
| 192 |
| 193 TPM2B_DIGEST integrity; |
| 194 UINT16 integritySize; |
| 195 BYTE *buffer; // Auxiliary buffer pointer |
| 196 |
| 197 // sensitiveData points to the beginning of sensitive data in innerBuffer |
| 198 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); |
| 199 sensitiveData = innerBuffer + integritySize; |
| 200 |
| 201 ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity); |
| 202 |
| 203 // Add integrity at the beginning of inner buffer |
| 204 buffer = innerBuffer; |
| |
| Family "2.0" TCG Published Page 89 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 205 TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); |
| 206 |
| 207 return dataSize + integritySize; |
| 208 } |
| |
| |
| 7.6.2.7 CheckInnerIntegrity() |
| |
| This function check integrity of inner blob |
| |
| Error Returns Meaning |
| |
| TPM_RC_INTEGRITY if the outer blob integrity is bad |
| unmarshal errors unmarshal errors while unmarshaling integrity |
| |
| 209 static TPM_RC |
| 210 CheckInnerIntegrity( |
| 211 TPM2B_NAME *name, // IN: the name of the object |
| 212 TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap |
| 213 UINT16 dataSize, // IN: the size of sensitive data, including the |
| 214 // leading integrity buffer size |
| 215 BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in |
| 216 // it |
| 217 ) |
| 218 { |
| 219 TPM_RC result; |
| 220 |
| 221 TPM2B_DIGEST integrity; |
| 222 TPM2B_DIGEST integrityToCompare; |
| 223 BYTE *buffer; // Auxiliary buffer pointer |
| 224 INT32 size; |
| 225 |
| 226 // Unmarshal integrity |
| 227 buffer = innerBuffer; |
| 228 size = (INT32) dataSize; |
| 229 result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); |
| 230 if(result == TPM_RC_SUCCESS) |
| 231 { |
| 232 // Compute integrity to compare |
| 233 ComputeInnerIntegrity(hashAlg, name, (UINT16) size, buffer, |
| 234 &integrityToCompare); |
| 235 |
| 236 // Compare outer blob integrity |
| 237 if(!Memory2BEqual(&integrity.b, &integrityToCompare.b)) |
| 238 result = TPM_RC_INTEGRITY; |
| 239 } |
| 240 return result; |
| 241 } |
| |
| |
| 7.6.3 Public Functions |
| |
| 7.6.3.1 AreAttributesForParent() |
| |
| This function is called by create, load, and import functions. |
| |
| Return Value Meaning |
| |
| TRUE properties are those of a parent |
| FALSE properties are not those of a parent |
| |
| 242 BOOL |
| |
| Page 90 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 243 AreAttributesForParent( |
| 244 OBJECT *parentObject // IN: parent handle |
| 245 ) |
| 246 { |
| 247 // This function is only called when a parent is needed. Any |
| 248 // time a "parent" is used, it must be authorized. When |
| 249 // the authorization is checked, both the public and sensitive |
| 250 // areas must be loaded. Just make sure... |
| 251 pAssert(parentObject->attributes.publicOnly == CLEAR); |
| 252 |
| 253 if(ObjectDataIsStorage(&parentObject->publicArea)) |
| 254 return TRUE; |
| 255 else |
| 256 return FALSE; |
| 257 } |
| |
| |
| 7.6.3.2 SchemeChecks() |
| |
| This function validates the schemes in the public area of an object. This function is called by |
| TPM2_LoadExternal() and PublicAttributesValidation(). |
| |
| Error Returns Meaning |
| |
| TPM_RC_ASYMMETRIC non-duplicable storage key and its parent have different public |
| parameters |
| TPM_RC_ATTRIBUTES attempt to inject sensitive data for an asymmetric key; or attempt to |
| create a symmetric cipher key that is not a decryption key |
| TPM_RC_HASH non-duplicable storage key and its parent have different name |
| algorithm |
| TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object |
| TPM_RC_KEY invalid key size values in an asymmetric key public area |
| TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID; |
| or hash algorithm is inconsistent with the scheme ID for keyed hash |
| object |
| TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or non-storage |
| key with symmetric algorithm different from TPM_ALG_NULL |
| TPM_RC_TYPE unexpected object type; or non-duplicable storage key and its parent |
| have different types |
| |
| 258 TPM_RC |
| 259 SchemeChecks( |
| 260 BOOL load, // IN: TRUE if load checks, FALSE if |
| 261 // TPM2_Create() |
| 262 TPMI_DH_OBJECT parentHandle, // IN: input parent handle |
| 263 TPMT_PUBLIC *publicArea // IN: public area of the object |
| 264 ) |
| 265 { |
| 266 |
| 267 // Checks for an asymmetric key |
| 268 if(CryptIsAsymAlgorithm(publicArea->type)) |
| 269 { |
| 270 TPMT_ASYM_SCHEME *keyScheme; |
| 271 keyScheme = &publicArea->parameters.asymDetail.scheme; |
| 272 |
| 273 // An asymmetric key can't be injected |
| 274 // This is only checked when creating an object |
| 275 if(!load && (publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)) |
| 276 return TPM_RC_ATTRIBUTES; |
| 277 |
| |
| Family "2.0" TCG Published Page 91 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 278 if(load && !CryptAreKeySizesConsistent(publicArea)) |
| 279 return TPM_RC_KEY; |
| 280 |
| 281 // Keys that are both signing and decrypting must have TPM_ALG_NULL |
| 282 // for scheme |
| 283 if( publicArea->objectAttributes.sign == SET |
| 284 && publicArea->objectAttributes.decrypt == SET |
| 285 && keyScheme->scheme != TPM_ALG_NULL) |
| 286 return TPM_RC_SCHEME; |
| 287 |
| 288 // A restrict sign key must have a non-NULL scheme |
| 289 if( publicArea->objectAttributes.restricted == SET |
| 290 && publicArea->objectAttributes.sign == SET |
| 291 && keyScheme->scheme == TPM_ALG_NULL) |
| 292 return TPM_RC_SCHEME; |
| 293 |
| 294 // Keys must have a valid sign or decrypt scheme, or a TPM_ALG_NULL |
| 295 // scheme |
| 296 // NOTE: The unmarshaling for a public area will unmarshal based on the |
| 297 // object type. If the type is an RSA key, then only RSA schemes will be |
| 298 // allowed because a TPMI_ALG_RSA_SCHEME will be unmarshaled and it |
| 299 // consists only of those algorithms that are allowed with an RSA key. |
| 300 // This means that there is no need to again make sure that the algorithm |
| 301 // is compatible with the object type. |
| 302 if( keyScheme->scheme != TPM_ALG_NULL |
| 303 && ( ( publicArea->objectAttributes.sign == SET |
| 304 && !CryptIsSignScheme(keyScheme->scheme) |
| 305 ) |
| 306 || ( publicArea->objectAttributes.decrypt == SET |
| 307 && !CryptIsDecryptScheme(keyScheme->scheme) |
| 308 ) |
| 309 ) |
| 310 ) |
| 311 return TPM_RC_SCHEME; |
| 312 |
| 313 // Special checks for an ECC key |
| 314 #ifdef TPM_ALG_ECC |
| 315 if(publicArea->type == TPM_ALG_ECC) |
| 316 { |
| 317 TPM_ECC_CURVE curveID = publicArea->parameters.eccDetail.curveID; |
| 318 const TPMT_ECC_SCHEME *curveScheme = CryptGetCurveSignScheme(curveID); |
| 319 // The curveId must be valid or the unmarshaling is busted. |
| 320 pAssert(curveScheme != NULL); |
| 321 |
| 322 // If the curveID requires a specific scheme, then the key must select |
| 323 // the same scheme |
| 324 if(curveScheme->scheme != TPM_ALG_NULL) |
| 325 { |
| 326 if(keyScheme->scheme != curveScheme->scheme) |
| 327 return TPM_RC_SCHEME; |
| 328 // The scheme can allow any hash, or not... |
| 329 if( curveScheme->details.anySig.hashAlg != TPM_ALG_NULL |
| 330 && ( keyScheme->details.anySig.hashAlg |
| 331 != curveScheme->details.anySig.hashAlg |
| 332 ) |
| 333 ) |
| 334 return TPM_RC_SCHEME; |
| 335 } |
| 336 // For now, the KDF must be TPM_ALG_NULL |
| 337 if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL) |
| 338 return TPM_RC_KDF; |
| 339 } |
| 340 #endif |
| 341 |
| 342 // Checks for a storage key (restricted + decryption) |
| 343 if( publicArea->objectAttributes.restricted == SET |
| |
| Page 92 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 344 && publicArea->objectAttributes.decrypt == SET) |
| 345 { |
| 346 // A storage key must have a valid protection key |
| 347 if( publicArea->parameters.asymDetail.symmetric.algorithm |
| 348 == TPM_ALG_NULL) |
| 349 return TPM_RC_SYMMETRIC; |
| 350 |
| 351 // A storage key must have a null scheme |
| 352 if(publicArea->parameters.asymDetail.scheme.scheme != TPM_ALG_NULL) |
| 353 return TPM_RC_SCHEME; |
| 354 |
| 355 // A storage key must match its parent algorithms unless |
| 356 // it is duplicable or a primary (including Temporary Primary Objects) |
| 357 if( HandleGetType(parentHandle) != TPM_HT_PERMANENT |
| 358 && publicArea->objectAttributes.fixedParent == SET |
| 359 ) |
| 360 { |
| 361 // If the object to be created is a storage key, and is fixedParent, |
| 362 // its crypto set has to match its parent's crypto set. TPM_RC_TYPE, |
| 363 // TPM_RC_HASH or TPM_RC_ASYMMETRIC may be returned at this point |
| 364 return EqualCryptSet(publicArea, |
| 365 &(ObjectGet(parentHandle)->publicArea)); |
| 366 } |
| 367 } |
| 368 else |
| 369 { |
| 370 // Non-storage keys must have TPM_ALG_NULL for the symmetric algorithm |
| 371 if( publicArea->parameters.asymDetail.symmetric.algorithm |
| 372 != TPM_ALG_NULL) |
| 373 return TPM_RC_SYMMETRIC; |
| 374 |
| 375 }// End of asymmetric decryption key checks |
| 376 } // End of asymmetric checks |
| 377 |
| 378 // Check for bit attributes |
| 379 else if(publicArea->type == TPM_ALG_KEYEDHASH) |
| 380 { |
| 381 TPMT_KEYEDHASH_SCHEME *scheme |
| 382 = &publicArea->parameters.keyedHashDetail.scheme; |
| 383 // If both sign and decrypt are set the scheme must be TPM_ALG_NULL |
| 384 // and the scheme selected when the key is used. |
| 385 // If neither sign nor decrypt is set, the scheme must be TPM_ALG_NULL |
| 386 // because this is a data object. |
| 387 if( publicArea->objectAttributes.sign |
| 388 == publicArea->objectAttributes.decrypt) |
| 389 { |
| 390 if(scheme->scheme != TPM_ALG_NULL) |
| 391 return TPM_RC_SCHEME; |
| 392 return TPM_RC_SUCCESS; |
| 393 } |
| 394 // If this is a decryption key, make sure that is is XOR and that there |
| 395 // is a KDF |
| 396 else if(publicArea->objectAttributes.decrypt) |
| 397 { |
| 398 if( scheme->scheme != TPM_ALG_XOR |
| 399 || scheme->details.xor.hashAlg == TPM_ALG_NULL) |
| 400 return TPM_RC_SCHEME; |
| 401 if(scheme->details.xor.kdf == TPM_ALG_NULL) |
| 402 return TPM_RC_KDF; |
| 403 return TPM_RC_SUCCESS; |
| 404 |
| 405 } |
| 406 // only supported signing scheme for keyedHash object is HMAC |
| 407 if( scheme->scheme != TPM_ALG_HMAC |
| 408 || scheme->details.hmac.hashAlg == TPM_ALG_NULL) |
| 409 return TPM_RC_SCHEME; |
| |
| Family "2.0" TCG Published Page 93 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 410 |
| 411 // end of the checks for keyedHash |
| 412 return TPM_RC_SUCCESS; |
| 413 } |
| 414 else if (publicArea->type == TPM_ALG_SYMCIPHER) |
| 415 { |
| 416 // Must be a decrypting key and may not be a signing key |
| 417 if( publicArea->objectAttributes.decrypt == CLEAR |
| 418 || publicArea->objectAttributes.sign == SET |
| 419 ) |
| 420 return TPM_RC_ATTRIBUTES; |
| 421 } |
| 422 else |
| 423 return TPM_RC_TYPE; |
| 424 |
| 425 return TPM_RC_SUCCESS; |
| 426 } |
| |
| |
| 7.6.3.3 PublicAttributesValidation() |
| |
| This function validates the values in the public area of an object. This function is called by |
| TPM2_Create(), TPM2_Load(), and TPM2_CreatePrimary() |
| |
| Error Returns Meaning |
| |
| TPM_RC_ASYMMETRIC non-duplicable storage key and its parent have different public |
| parameters |
| TPM_RC_ATTRIBUTES fixedTPM, fixedParent, or encryptedDuplication attributes are |
| inconsistent between themselves or with those of the parent object; |
| inconsistent restricted, decrypt and sign attributes; attempt to inject |
| sensitive data for an asymmetric key; attempt to create a symmetric |
| cipher key that is not a decryption key |
| TPM_RC_HASH non-duplicable storage key and its parent have different name |
| algorithm |
| TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object |
| TPM_RC_KEY invalid key size values in an asymmetric key public area |
| TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID; |
| or hash algorithm is inconsistent with the scheme ID for keyed hash |
| object |
| TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in |
| publicArea |
| TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or non-storage |
| key with symmetric algorithm different from TPM_ALG_NULL |
| TPM_RC_TYPE unexpected object type; or non-duplicable storage key and its parent |
| have different types |
| |
| 427 TPM_RC |
| 428 PublicAttributesValidation( |
| 429 BOOL load, // IN: TRUE if load checks, FALSE if |
| 430 // TPM2_Create() |
| 431 TPMI_DH_OBJECT parentHandle, // IN: input parent handle |
| 432 TPMT_PUBLIC *publicArea // IN: public area of the object |
| 433 ) |
| 434 { |
| 435 OBJECT *parentObject = NULL; |
| 436 |
| 437 if(HandleGetType(parentHandle) != TPM_HT_PERMANENT) |
| 438 parentObject = ObjectGet(parentHandle); |
| |
| Page 94 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 439 |
| 440 // Check authPolicy digest consistency |
| 441 if( publicArea->authPolicy.t.size != 0 |
| 442 && ( publicArea->authPolicy.t.size |
| 443 != CryptGetHashDigestSize(publicArea->nameAlg) |
| 444 ) |
| 445 ) |
| 446 return TPM_RC_SIZE; |
| 447 |
| 448 // If the parent is fixedTPM (including a Primary Object) the object must have |
| 449 // the same value for fixedTPM and fixedParent |
| 450 if( parentObject == NULL |
| 451 || parentObject->publicArea.objectAttributes.fixedTPM == SET) |
| 452 { |
| 453 if( publicArea->objectAttributes.fixedParent |
| 454 != publicArea->objectAttributes.fixedTPM |
| 455 ) |
| 456 return TPM_RC_ATTRIBUTES; |
| 457 } |
| 458 else |
| 459 // The parent is not fixedTPM so the object can't be fixedTPM |
| 460 if(publicArea->objectAttributes.fixedTPM == SET) |
| 461 return TPM_RC_ATTRIBUTES; |
| 462 |
| 463 // A restricted object cannot be both sign and decrypt and it can't be neither |
| 464 // sign nor decrypt |
| 465 if ( publicArea->objectAttributes.restricted == SET |
| 466 && ( publicArea->objectAttributes.decrypt |
| 467 == publicArea->objectAttributes.sign) |
| 468 ) |
| 469 return TPM_RC_ATTRIBUTES; |
| 470 |
| 471 // A fixedTPM object can not have encryptedDuplication bit SET |
| 472 if( publicArea->objectAttributes.fixedTPM == SET |
| 473 && publicArea->objectAttributes.encryptedDuplication == SET) |
| 474 return TPM_RC_ATTRIBUTES; |
| 475 |
| 476 // If a parent object has fixedTPM CLEAR, the child must have the |
| 477 // same encryptedDuplication value as its parent. |
| 478 // Primary objects are considered to have a fixedTPM parent (the seeds). |
| 479 if( ( parentObject != NULL |
| 480 && parentObject->publicArea.objectAttributes.fixedTPM == CLEAR) |
| 481 // Get here if parent is not fixed TPM |
| 482 && ( publicArea->objectAttributes.encryptedDuplication |
| 483 != parentObject->publicArea.objectAttributes.encryptedDuplication |
| 484 ) |
| 485 ) |
| 486 return TPM_RC_ATTRIBUTES; |
| 487 |
| 488 return SchemeChecks(load, parentHandle, publicArea); |
| 489 } |
| |
| |
| 7.6.3.4 FillInCreationData() |
| |
| Fill in creation data for an object. |
| |
| 490 void |
| 491 FillInCreationData( |
| 492 TPMI_DH_OBJECT parentHandle, // IN: handle of parent |
| 493 TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm |
| 494 TPML_PCR_SELECTION *creationPCR, // IN: PCR selection |
| 495 TPM2B_DATA *outsideData, // IN: outside data |
| 496 TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output |
| 497 TPM2B_DIGEST *creationDigest // OUT: creation digest |
| |
| |
| Family "2.0" TCG Published Page 95 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 498 ) |
| 499 { |
| 500 BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; |
| 501 BYTE *buffer; |
| 502 HASH_STATE hashState; |
| 503 |
| 504 // Fill in TPMS_CREATION_DATA in outCreation |
| 505 |
| 506 // Compute PCR digest |
| 507 PCRComputeCurrentDigest(nameHashAlg, creationPCR, |
| 508 &outCreation->t.creationData.pcrDigest); |
| 509 |
| 510 // Put back PCR selection list |
| 511 outCreation->t.creationData.pcrSelect = *creationPCR; |
| 512 |
| 513 // Get locality |
| 514 outCreation->t.creationData.locality |
| 515 = LocalityGetAttributes(_plat__LocalityGet()); |
| 516 |
| 517 outCreation->t.creationData.parentNameAlg = TPM_ALG_NULL; |
| 518 |
| 519 // If the parent is is either a primary seed or TPM_ALG_NULL, then the Name |
| 520 // and QN of the parent are the parent's handle. |
| 521 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) |
| 522 { |
| 523 BYTE *buffer = &outCreation->t.creationData.parentName.t.name[0]; |
| 524 outCreation->t.creationData.parentName.t.size = |
| 525 TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL); |
| 526 |
| 527 // Parent qualified name of a Temporary Object is the same as parent's |
| 528 // name |
| 529 MemoryCopy2B(&outCreation->t.creationData.parentQualifiedName.b, |
| 530 &outCreation->t.creationData.parentName.b, |
| 531 sizeof(outCreation->t.creationData.parentQualifiedName.t.name)); |
| 532 |
| 533 } |
| 534 else // Regular object |
| 535 { |
| 536 OBJECT *parentObject = ObjectGet(parentHandle); |
| 537 |
| 538 // Set name algorithm |
| 539 outCreation->t.creationData.parentNameAlg = |
| 540 parentObject->publicArea.nameAlg; |
| 541 // Copy parent name |
| 542 outCreation->t.creationData.parentName = parentObject->name; |
| 543 |
| 544 // Copy parent qualified name |
| 545 outCreation->t.creationData.parentQualifiedName = |
| 546 parentObject->qualifiedName; |
| 547 } |
| 548 |
| 549 // Copy outside information |
| 550 outCreation->t.creationData.outsideInfo = *outsideData; |
| 551 |
| 552 // Marshal creation data to canonical form |
| 553 buffer = creationBuffer; |
| 554 outCreation->t.size = TPMS_CREATION_DATA_Marshal(&outCreation->t.creationData, |
| 555 &buffer, NULL); |
| 556 |
| 557 // Compute hash for creation field in public template |
| 558 creationDigest->t.size = CryptStartHash(nameHashAlg, &hashState); |
| 559 CryptUpdateDigest(&hashState, outCreation->t.size, creationBuffer); |
| 560 CryptCompleteHash2B(&hashState, &creationDigest->b); |
| 561 |
| 562 return; |
| 563 } |
| |
| Page 96 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 7.6.3.5 GetSeedForKDF() |
| |
| Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. It returns a pointer to |
| the seed |
| |
| 564 TPM2B_SEED* |
| 565 GetSeedForKDF( |
| 566 TPM_HANDLE protectorHandle, // IN: the protector handle |
| 567 TPM2B_SEED *seedIn // IN: the optional input seed |
| 568 ) |
| 569 { |
| 570 OBJECT *protector = NULL; // Pointer to the protector |
| 571 |
| 572 // Get seed for encryption key. Use input seed if provided. |
| 573 // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only |
| 574 // exception that we may not have a loaded object as protector. In such a |
| 575 // case, use nullProof as seed. |
| 576 if(seedIn != NULL) |
| 577 { |
| 578 return seedIn; |
| 579 } |
| 580 else |
| 581 { |
| 582 if(protectorHandle == TPM_RH_NULL) |
| 583 { |
| 584 return (TPM2B_SEED *) &gr.nullProof; |
| 585 } |
| 586 else |
| 587 { |
| 588 protector = ObjectGet(protectorHandle); |
| 589 return (TPM2B_SEED *) &protector->sensitive.seedValue; |
| 590 } |
| 591 } |
| 592 } |
| |
| |
| 7.6.3.6 ProduceOuterWrap() |
| |
| This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data |
| being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv |
| space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address |
| (outerBuffer + integrity size {+ iv size}). This function performs: |
| a) Add IV before sensitive area if required |
| b) encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv |
| c) add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap |
| |
| 593 UINT16 |
| 594 ProduceOuterWrap( |
| 595 TPM_HANDLE protector, // IN: The handle of the object that provides |
| 596 // protection. For object, it is parent |
| 597 // handle. For credential, it is the handle |
| 598 // of encrypt object. |
| 599 TPM2B_NAME *name, // IN: the name of the object |
| 600 TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap |
| 601 TPM2B_SEED *seed, // IN: an external seed may be provided for |
| 602 // duplication blob. For non duplication |
| 603 // blob, this parameter should be NULL |
| 604 BOOL useIV, // IN: indicate if an IV is used |
| 605 UINT16 dataSize, // IN: the size of sensitive data, excluding the |
| 606 // leading integrity buffer size or the |
| 607 // optional iv size |
| 608 BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in |
| |
| Family "2.0" TCG Published Page 97 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 609 // it |
| 610 ) |
| 611 { |
| 612 TPM_ALG_ID symAlg; |
| 613 UINT16 keyBits; |
| 614 TPM2B_SYM_KEY symKey; |
| 615 TPM2B_IV ivRNG; // IV from RNG |
| 616 TPM2B_IV *iv = NULL; |
| 617 UINT16 ivSize = 0; // size of iv area, including the size field |
| 618 |
| 619 BYTE *sensitiveData; // pointer to the sensitive data |
| 620 |
| 621 TPM2B_DIGEST integrity; |
| 622 UINT16 integritySize; |
| 623 BYTE *buffer; // Auxiliary buffer pointer |
| 624 |
| 625 // Compute the beginning of sensitive data. The outer integrity should |
| 626 // always exist if this function function is called to make an outer wrap |
| 627 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); |
| 628 sensitiveData = outerBuffer + integritySize; |
| 629 |
| 630 // If iv is used, adjust the pointer of sensitive data and add iv before it |
| 631 if(useIV) |
| 632 { |
| 633 ivSize = GetIV2BSize(protector); |
| 634 |
| 635 // Generate IV from RNG. The iv data size should be the total IV area |
| 636 // size minus the size of size field |
| 637 ivRNG.t.size = ivSize - sizeof(UINT16); |
| 638 CryptGenerateRandom(ivRNG.t.size, ivRNG.t.buffer); |
| 639 |
| 640 // Marshal IV to buffer |
| 641 buffer = sensitiveData; |
| 642 TPM2B_IV_Marshal(&ivRNG, &buffer, NULL); |
| 643 |
| 644 // adjust sensitive data starting after IV area |
| 645 sensitiveData += ivSize; |
| 646 |
| 647 // Use iv for encryption |
| 648 iv = &ivRNG; |
| 649 } |
| 650 |
| 651 // Compute symmetric key parameters for outer buffer encryption |
| 652 ComputeProtectionKeyParms(protector, hashAlg, name, seed, |
| 653 &symAlg, &keyBits, &symKey); |
| 654 // Encrypt inner buffer in place |
| 655 CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits, |
| 656 TPM_ALG_CFB, symKey.t.buffer, iv, dataSize, |
| 657 sensitiveData); |
| 658 |
| 659 // Compute outer integrity. Integrity computation includes the optional IV |
| 660 // area |
| 661 ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize, |
| 662 outerBuffer + integritySize, &integrity); |
| 663 |
| 664 // Add integrity at the beginning of outer buffer |
| 665 buffer = outerBuffer; |
| 666 TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); |
| 667 |
| 668 // return the total size in outer wrap |
| 669 return dataSize + integritySize + ivSize; |
| 670 |
| 671 } |
| |
| |
| |
| |
| Page 98 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 7.6.3.7 UnwrapOuter() |
| |
| This function remove the outer wrap of a blob containing sensitive data This function performs: |
| a) check integrity of outer blob |
| b) decrypt outer blob |
| |
| Error Returns Meaning |
| |
| TPM_RC_INSUFFICIENT error during sensitive data unmarshaling |
| TPM_RC_INTEGRITY sensitive data integrity is broken |
| TPM_RC_SIZE error during sensitive data unmarshaling |
| TPM_RC_VALUE IV size for CFB does not match the encryption algorithm block size |
| |
| 672 TPM_RC |
| 673 UnwrapOuter( |
| 674 TPM_HANDLE protector, // IN: The handle of the object that provides |
| 675 // protection. For object, it is parent |
| 676 // handle. For credential, it is the handle |
| 677 // of encrypt object. |
| 678 TPM2B_NAME *name, // IN: the name of the object |
| 679 TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap |
| 680 TPM2B_SEED *seed, // IN: an external seed may be provided for |
| 681 // duplication blob. For non duplication |
| 682 // blob, this parameter should be NULL. |
| 683 BOOL useIV, // IN: indicates if an IV is used |
| 684 UINT16 dataSize, // IN: size of sensitive data in outerBuffer, |
| 685 // including the leading integrity buffer |
| 686 // size, and an optional iv area |
| 687 BYTE *outerBuffer // IN/OUT: sensitive data |
| 688 ) |
| 689 { |
| 690 TPM_RC result; |
| 691 TPM_ALG_ID symAlg = TPM_ALG_NULL; |
| 692 TPM2B_SYM_KEY symKey; |
| 693 UINT16 keyBits = 0; |
| 694 TPM2B_IV ivIn; // input IV retrieved from input buffer |
| 695 TPM2B_IV *iv = NULL; |
| 696 |
| 697 BYTE *sensitiveData; // pointer to the sensitive data |
| 698 |
| 699 TPM2B_DIGEST integrityToCompare; |
| 700 TPM2B_DIGEST integrity; |
| 701 INT32 size; |
| 702 |
| 703 // Unmarshal integrity |
| 704 sensitiveData = outerBuffer; |
| 705 size = (INT32) dataSize; |
| 706 result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size); |
| 707 if(result == TPM_RC_SUCCESS) |
| 708 { |
| 709 // Compute integrity to compare |
| 710 ComputeOuterIntegrity(name, protector, hashAlg, seed, |
| 711 (UINT16) size, sensitiveData, |
| 712 &integrityToCompare); |
| 713 |
| 714 // Compare outer blob integrity |
| 715 if(!Memory2BEqual(&integrity.b, &integrityToCompare.b)) |
| 716 return TPM_RC_INTEGRITY; |
| 717 |
| 718 // Get the symmetric algorithm parameters used for encryption |
| 719 ComputeProtectionKeyParms(protector, hashAlg, name, seed, |
| |
| Family "2.0" TCG Published Page 99 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 720 &symAlg, &keyBits, &symKey); |
| 721 |
| 722 // Retrieve IV if it is used |
| 723 if(useIV) |
| 724 { |
| 725 result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size); |
| 726 if(result == TPM_RC_SUCCESS) |
| 727 { |
| 728 // The input iv size for CFB must match the encryption algorithm |
| 729 // block size |
| 730 if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits)) |
| 731 result = TPM_RC_VALUE; |
| 732 else |
| 733 iv = &ivIn; |
| 734 } |
| 735 } |
| 736 } |
| 737 // If no errors, decrypt private in place |
| 738 if(result == TPM_RC_SUCCESS) |
| 739 CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits, |
| 740 TPM_ALG_CFB, symKey.t.buffer, iv, |
| 741 (UINT16) size, sensitiveData); |
| 742 |
| 743 return result; |
| 744 |
| 745 } |
| |
| |
| 7.6.3.8 SensitiveToPrivate() |
| |
| This function prepare the private blob for off the chip storage The operations in this function: |
| a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE |
| b) apply encryption to the sensitive area. |
| c) apply outer integrity computation. |
| |
| 746 void |
| 747 SensitiveToPrivate( |
| 748 TPMT_SENSITIVE *sensitive, // IN: sensitive structure |
| 749 TPM2B_NAME *name, // IN: the name of the object |
| 750 TPM_HANDLE parentHandle, // IN: The parent's handle |
| 751 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This |
| 752 // parameter is used when parentHandle is |
| 753 // NULL, in which case the object is |
| 754 // temporary. |
| 755 TPM2B_PRIVATE *outPrivate // OUT: output private structure |
| 756 ) |
| 757 { |
| 758 BYTE *buffer; // Auxiliary buffer pointer |
| 759 BYTE *sensitiveData; // pointer to the sensitive data |
| 760 UINT16 dataSize; // data blob size |
| 761 TPMI_ALG_HASH hashAlg; // hash algorithm for integrity |
| 762 UINT16 integritySize; |
| 763 UINT16 ivSize; |
| 764 |
| 765 pAssert(name != NULL && name->t.size != 0); |
| 766 |
| 767 // Find the hash algorithm for integrity computation |
| 768 if(parentHandle == TPM_RH_NULL) |
| 769 { |
| 770 // For Temporary Object, using self name algorithm |
| 771 hashAlg = nameAlg; |
| 772 } |
| 773 else |
| |
| Page 100 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 774 { |
| 775 // Otherwise, using parent's name algorithm |
| 776 hashAlg = ObjectGetNameAlg(parentHandle); |
| 777 } |
| 778 |
| 779 // Starting of sensitive data without wrappers |
| 780 sensitiveData = outPrivate->t.buffer; |
| 781 |
| 782 // Compute the integrity size |
| 783 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); |
| 784 |
| 785 // Reserve space for integrity |
| 786 sensitiveData += integritySize; |
| 787 |
| 788 // Get iv size |
| 789 ivSize = GetIV2BSize(parentHandle); |
| 790 |
| 791 // Reserve space for iv |
| 792 sensitiveData += ivSize; |
| 793 |
| 794 // Marshal sensitive area, leaving the leading 2 bytes for size |
| 795 buffer = sensitiveData + sizeof(UINT16); |
| 796 dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); |
| 797 |
| 798 // Adding size before the data area |
| 799 buffer = sensitiveData; |
| 800 UINT16_Marshal(&dataSize, &buffer, NULL); |
| 801 |
| 802 // Adjust the dataSize to include the size field |
| 803 dataSize += sizeof(UINT16); |
| 804 |
| 805 // Adjust the pointer to inner buffer including the iv |
| 806 sensitiveData = outPrivate->t.buffer + ivSize; |
| 807 |
| 808 //Produce outer wrap, including encryption and HMAC |
| 809 outPrivate->t.size = ProduceOuterWrap(parentHandle, name, hashAlg, NULL, |
| 810 TRUE, dataSize, outPrivate->t.buffer); |
| 811 |
| 812 return; |
| 813 } |
| |
| |
| 7.6.3.9 PrivateToSensitive() |
| |
| Unwrap a input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The |
| operations in this function: |
| a) check the integrity HMAC of the input private area |
| b) decrypt the private buffer |
| c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE |
| |
| Error Returns Meaning |
| |
| TPM_RC_INTEGRITY if the private area integrity is bad |
| TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT from input |
| private |
| TPM_RC_VALUE outer wrapper does not have an iV of the correct size |
| |
| 814 TPM_RC |
| 815 PrivateToSensitive( |
| 816 TPM2B_PRIVATE *inPrivate, // IN: input private structure |
| 817 TPM2B_NAME *name, // IN: the name of the object |
| |
| Family "2.0" TCG Published Page 101 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 818 TPM_HANDLE parentHandle, // IN: The parent's handle |
| 819 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is |
| 820 // passed separately because we only pass |
| 821 // name, rather than the whole public area |
| 822 // of the object. This parameter is used in |
| 823 // the following two cases: 1. primary |
| 824 // objects. 2. duplication blob with inner |
| 825 // wrap. In other cases, this parameter |
| 826 // will be ignored |
| 827 TPMT_SENSITIVE *sensitive // OUT: sensitive structure |
| 828 ) |
| 829 { |
| 830 TPM_RC result; |
| 831 |
| 832 BYTE *buffer; |
| 833 INT32 size; |
| 834 BYTE *sensitiveData; // pointer to the sensitive data |
| 835 UINT16 dataSize; |
| 836 UINT16 dataSizeInput; |
| 837 TPMI_ALG_HASH hashAlg; // hash algorithm for integrity |
| 838 OBJECT *parent = NULL; |
| 839 |
| 840 UINT16 integritySize; |
| 841 UINT16 ivSize; |
| 842 |
| 843 // Make sure that name is provided |
| 844 pAssert(name != NULL && name->t.size != 0); |
| 845 |
| 846 // Find the hash algorithm for integrity computation |
| 847 if(parentHandle == TPM_RH_NULL) |
| 848 { |
| 849 // For Temporary Object, using self name algorithm |
| 850 hashAlg = nameAlg; |
| 851 } |
| 852 else |
| 853 { |
| 854 // Otherwise, using parent's name algorithm |
| 855 hashAlg = ObjectGetNameAlg(parentHandle); |
| 856 } |
| 857 |
| 858 // unwrap outer |
| 859 result = UnwrapOuter(parentHandle, name, hashAlg, NULL, TRUE, |
| 860 inPrivate->t.size, inPrivate->t.buffer); |
| 861 if(result != TPM_RC_SUCCESS) |
| 862 return result; |
| 863 |
| 864 // Compute the inner integrity size. |
| 865 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); |
| 866 |
| 867 // Get iv size |
| 868 ivSize = GetIV2BSize(parentHandle); |
| 869 |
| 870 // The starting of sensitive data and data size without outer wrapper |
| 871 sensitiveData = inPrivate->t.buffer + integritySize + ivSize; |
| 872 dataSize = inPrivate->t.size - integritySize - ivSize; |
| 873 |
| 874 // Unmarshal input data size |
| 875 buffer = sensitiveData; |
| 876 size = (INT32) dataSize; |
| 877 result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); |
| 878 if(result == TPM_RC_SUCCESS) |
| 879 { |
| 880 if((dataSizeInput + sizeof(UINT16)) != dataSize) |
| 881 result = TPM_RC_SENSITIVE; |
| 882 else |
| 883 { |
| |
| Page 102 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 884 // Unmarshal sensitive buffer to sensitive structure |
| 885 result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); |
| 886 if(result != TPM_RC_SUCCESS || size != 0) |
| 887 { |
| 888 pAssert( (parent == NULL) |
| 889 || parent->publicArea.objectAttributes.fixedTPM == CLEAR); |
| 890 result = TPM_RC_SENSITIVE; |
| 891 } |
| 892 else |
| 893 { |
| 894 // Always remove trailing zeros at load so that it is not necessary |
| 895 // to check |
| 896 // each time auth is checked. |
| 897 MemoryRemoveTrailingZeros(&(sensitive->authValue)); |
| 898 } |
| 899 } |
| 900 } |
| 901 return result; |
| 902 } |
| |
| |
| 7.6.3.10 SensitiveToDuplicate() |
| |
| This function prepare the duplication blob from the sensitive area. The operations in this function: |
| a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE |
| b) apply inner wrap to the sensitive area if required |
| c) apply outer wrap if required |
| |
| 903 void |
| 904 SensitiveToDuplicate( |
| 905 TPMT_SENSITIVE *sensitive, // IN: sensitive structure |
| 906 TPM2B_NAME *name, // IN: the name of the object |
| 907 TPM_HANDLE parentHandle, // IN: The new parent's handle |
| 908 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It |
| 909 // is passed separately because we |
| 910 // only pass name, rather than the |
| 911 // whole public area of the object. |
| 912 TPM2B_SEED *seed, // IN: the external seed. If external |
| 913 // seed is provided with size of 0, |
| 914 // no outer wrap should be applied |
| 915 // to duplication blob. |
| 916 TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the |
| 917 // symmetric key algorithm is NULL, |
| 918 // no inner wrap should be applied. |
| 919 TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be |
| 920 // provided to encrypt the inner |
| 921 // wrap of a duplication blob. May |
| 922 // be generated here if needed. |
| 923 TPM2B_PRIVATE *outPrivate // OUT: output private structure |
| 924 ) |
| 925 { |
| 926 BYTE *buffer; // Auxiliary buffer pointer |
| 927 BYTE *sensitiveData; // pointer to the sensitive data |
| 928 TPMI_ALG_HASH outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap |
| 929 TPMI_ALG_HASH innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap |
| 930 UINT16 dataSize; // data blob size |
| 931 BOOL doInnerWrap = FALSE; |
| 932 BOOL doOuterWrap = FALSE; |
| 933 |
| 934 // Make sure that name is provided |
| 935 pAssert(name != NULL && name->t.size != 0); |
| 936 |
| 937 // Make sure symDef and innerSymKey are not NULL |
| |
| Family "2.0" TCG Published Page 103 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 938 pAssert(symDef != NULL && innerSymKey != NULL); |
| 939 |
| 940 // Starting of sensitive data without wrappers |
| 941 sensitiveData = outPrivate->t.buffer; |
| 942 |
| 943 // Find out if inner wrap is required |
| 944 if(symDef->algorithm != TPM_ALG_NULL) |
| 945 { |
| 946 doInnerWrap = TRUE; |
| 947 // Use self nameAlg as inner hash algorithm |
| 948 innerHash = nameAlg; |
| 949 // Adjust sensitive data pointer |
| 950 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash); |
| 951 } |
| 952 |
| 953 // Find out if outer wrap is required |
| 954 if(seed->t.size != 0) |
| 955 { |
| 956 doOuterWrap = TRUE; |
| 957 // Use parent nameAlg as outer hash algorithm |
| 958 outerHash = ObjectGetNameAlg(parentHandle); |
| 959 // Adjust sensitive data pointer |
| 960 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); |
| 961 } |
| 962 |
| 963 // Marshal sensitive area, leaving the leading 2 bytes for size |
| 964 buffer = sensitiveData + sizeof(UINT16); |
| 965 dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); |
| 966 |
| 967 // Adding size before the data area |
| 968 buffer = sensitiveData; |
| 969 UINT16_Marshal(&dataSize, &buffer, NULL); |
| 970 |
| 971 // Adjust the dataSize to include the size field |
| 972 dataSize += sizeof(UINT16); |
| 973 |
| 974 // Apply inner wrap for duplication blob. It includes both integrity and |
| 975 // encryption |
| 976 if(doInnerWrap) |
| 977 { |
| 978 BYTE *innerBuffer = NULL; |
| 979 BOOL symKeyInput = TRUE; |
| 980 innerBuffer = outPrivate->t.buffer; |
| 981 // Skip outer integrity space |
| 982 if(doOuterWrap) |
| 983 innerBuffer += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); |
| 984 dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, |
| 985 innerBuffer); |
| 986 |
| 987 // Generate inner encryption key if needed |
| 988 if(innerSymKey->t.size == 0) |
| 989 { |
| 990 innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8; |
| 991 CryptGenerateRandom(innerSymKey->t.size, innerSymKey->t.buffer); |
| 992 |
| 993 // TPM generates symmetric encryption. Set the flag to FALSE |
| 994 symKeyInput = FALSE; |
| 995 } |
| 996 else |
| 997 { |
| 998 // assume the input key size should matches the symmetric definition |
| 999 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); |
| 1000 |
| 1001 } |
| 1002 |
| 1003 // Encrypt inner buffer in place |
| |
| Page 104 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1004 CryptSymmetricEncrypt(innerBuffer, symDef->algorithm, |
| 1005 symDef->keyBits.sym, TPM_ALG_CFB, |
| 1006 innerSymKey->t.buffer, NULL, dataSize, |
| 1007 innerBuffer); |
| 1008 |
| 1009 // If the symmetric encryption key is imported, clear the buffer for |
| 1010 // output |
| 1011 if(symKeyInput) |
| 1012 innerSymKey->t.size = 0; |
| 1013 } |
| 1014 |
| 1015 // Apply outer wrap for duplication blob. It includes both integrity and |
| 1016 // encryption |
| 1017 if(doOuterWrap) |
| 1018 { |
| 1019 dataSize = ProduceOuterWrap(parentHandle, name, outerHash, seed, FALSE, |
| 1020 dataSize, outPrivate->t.buffer); |
| 1021 } |
| 1022 |
| 1023 // Data size for output |
| 1024 outPrivate->t.size = dataSize; |
| 1025 |
| 1026 return; |
| 1027 } |
| |
| |
| 7.6.3.11 DuplicateToSensitive() |
| |
| Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The |
| operations in this function: |
| a) check the integrity HMAC of the input private area |
| b) decrypt the private buffer |
| c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE |
| |
| Error Returns Meaning |
| |
| TPM_RC_INSUFFICIENT unmarshaling sensitive data from inPrivate failed |
| TPM_RC_INTEGRITY inPrivate data integrity is broken |
| TPM_RC_SIZE unmarshaling sensitive data from inPrivate failed |
| |
| 1028 TPM_RC |
| 1029 DuplicateToSensitive( |
| 1030 TPM2B_PRIVATE *inPrivate, // IN: input private structure |
| 1031 TPM2B_NAME *name, // IN: the name of the object |
| 1032 TPM_HANDLE parentHandle, // IN: The parent's handle |
| 1033 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. |
| 1034 TPM2B_SEED *seed, // IN: an external seed may be provided. |
| 1035 // If external seed is provided with |
| 1036 // size of 0, no outer wrap is |
| 1037 // applied |
| 1038 TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the |
| 1039 // symmetric key algorithm is NULL, |
| 1040 // no inner wrap is applied |
| 1041 TPM2B_DATA *innerSymKey, // IN: a symmetric key may be provided |
| 1042 // to decrypt the inner wrap of a |
| 1043 // duplication blob. |
| 1044 TPMT_SENSITIVE *sensitive // OUT: sensitive structure |
| 1045 ) |
| 1046 { |
| 1047 TPM_RC result; |
| 1048 |
| |
| Family "2.0" TCG Published Page 105 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1049 BYTE *buffer; |
| 1050 INT32 size; |
| 1051 BYTE *sensitiveData; // pointer to the sensitive data |
| 1052 UINT16 dataSize; |
| 1053 UINT16 dataSizeInput; |
| 1054 |
| 1055 // Make sure that name is provided |
| 1056 pAssert(name != NULL && name->t.size != 0); |
| 1057 |
| 1058 // Make sure symDef and innerSymKey are not NULL |
| 1059 pAssert(symDef != NULL && innerSymKey != NULL); |
| 1060 |
| 1061 // Starting of sensitive data |
| 1062 sensitiveData = inPrivate->t.buffer; |
| 1063 dataSize = inPrivate->t.size; |
| 1064 |
| 1065 // Find out if outer wrap is applied |
| 1066 if(seed->t.size != 0) |
| 1067 { |
| 1068 TPMI_ALG_HASH outerHash = TPM_ALG_NULL; |
| 1069 |
| 1070 // Use parent nameAlg as outer hash algorithm |
| 1071 outerHash = ObjectGetNameAlg(parentHandle); |
| 1072 result = UnwrapOuter(parentHandle, name, outerHash, seed, FALSE, |
| 1073 dataSize, sensitiveData); |
| 1074 if(result != TPM_RC_SUCCESS) |
| 1075 return result; |
| 1076 |
| 1077 // Adjust sensitive data pointer and size |
| 1078 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); |
| 1079 dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(outerHash); |
| 1080 } |
| 1081 // Find out if inner wrap is applied |
| 1082 if(symDef->algorithm != TPM_ALG_NULL) |
| 1083 { |
| 1084 TPMI_ALG_HASH innerHash = TPM_ALG_NULL; |
| 1085 |
| 1086 // assume the input key size should matches the symmetric definition |
| 1087 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); |
| 1088 |
| 1089 // Decrypt inner buffer in place |
| 1090 CryptSymmetricDecrypt(sensitiveData, symDef->algorithm, |
| 1091 symDef->keyBits.sym, TPM_ALG_CFB, |
| 1092 innerSymKey->t.buffer, NULL, dataSize, |
| 1093 sensitiveData); |
| 1094 |
| 1095 // Use self nameAlg as inner hash algorithm |
| 1096 innerHash = nameAlg; |
| 1097 |
| 1098 // Check inner integrity |
| 1099 result = CheckInnerIntegrity(name, innerHash, dataSize, sensitiveData); |
| 1100 if(result != TPM_RC_SUCCESS) |
| 1101 return result; |
| 1102 |
| 1103 // Adjust sensitive data pointer and size |
| 1104 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash); |
| 1105 dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(innerHash); |
| 1106 } |
| 1107 |
| 1108 // Unmarshal input data size |
| 1109 buffer = sensitiveData; |
| 1110 size = (INT32) dataSize; |
| 1111 result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); |
| 1112 if(result == TPM_RC_SUCCESS) |
| 1113 { |
| 1114 if((dataSizeInput + sizeof(UINT16)) != dataSize) |
| |
| Page 106 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1115 result = TPM_RC_SIZE; |
| 1116 else |
| 1117 { |
| 1118 // Unmarshal sensitive buffer to sensitive structure |
| 1119 result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); |
| 1120 // if the results is OK make sure that all the data was unmarshaled |
| 1121 if(result == TPM_RC_SUCCESS && size != 0) |
| 1122 result = TPM_RC_SIZE; |
| 1123 } |
| 1124 } |
| 1125 // Always remove trailing zeros at load so that it is not necessary to check |
| 1126 // each time auth is checked. |
| 1127 if(result == TPM_RC_SUCCESS) |
| 1128 MemoryRemoveTrailingZeros(&(sensitive->authValue)); |
| 1129 return result; |
| 1130 } |
| |
| |
| 7.6.3.12 SecretToCredential() |
| |
| This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this |
| function: |
| a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT |
| b) encrypt the private buffer, excluding the leading integrity HMAC area |
| c) compute integrity HMAC and append to the beginning of the buffer. |
| d) Set the total size of TPM2B_ID_OBJECT buffer |
| |
| 1131 void |
| 1132 SecretToCredential( |
| 1133 TPM2B_DIGEST *secret, // IN: secret information |
| 1134 TPM2B_NAME *name, // IN: the name of the object |
| 1135 TPM2B_SEED *seed, // IN: an external seed. |
| 1136 TPM_HANDLE protector, // IN: The protector's handle |
| 1137 TPM2B_ID_OBJECT *outIDObject // OUT: output credential |
| 1138 ) |
| 1139 { |
| 1140 BYTE *buffer; // Auxiliary buffer pointer |
| 1141 BYTE *sensitiveData; // pointer to the sensitive data |
| 1142 TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap |
| 1143 UINT16 dataSize; // data blob size |
| 1144 |
| 1145 pAssert(secret != NULL && outIDObject != NULL); |
| 1146 |
| 1147 // use protector's name algorithm as outer hash |
| 1148 outerHash = ObjectGetNameAlg(protector); |
| 1149 |
| 1150 // Marshal secret area to credential buffer, leave space for integrity |
| 1151 sensitiveData = outIDObject->t.credential |
| 1152 + sizeof(UINT16) + CryptGetHashDigestSize(outerHash); |
| 1153 |
| 1154 // Marshal secret area |
| 1155 buffer = sensitiveData; |
| 1156 dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL); |
| 1157 |
| 1158 // Apply outer wrap |
| 1159 outIDObject->t.size = ProduceOuterWrap(protector, |
| 1160 name, |
| 1161 outerHash, |
| 1162 seed, |
| 1163 FALSE, |
| 1164 dataSize, |
| 1165 outIDObject->t.credential); |
| |
| Family "2.0" TCG Published Page 107 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1166 return; |
| 1167 } |
| |
| |
| 7.6.3.13 CredentialToSecret() |
| |
| Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The |
| operations in this function: |
| a) check the integrity HMAC of the input credential area |
| b) decrypt the credential buffer |
| c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST |
| |
| Error Returns Meaning |
| |
| TPM_RC_INSUFFICIENT error during credential unmarshaling |
| TPM_RC_INTEGRITY credential integrity is broken |
| TPM_RC_SIZE error during credential unmarshaling |
| TPM_RC_VALUE IV size does not match the encryption algorithm block size |
| |
| 1168 TPM_RC |
| 1169 CredentialToSecret( |
| 1170 TPM2B_ID_OBJECT *inIDObject, // IN: input credential blob |
| 1171 TPM2B_NAME *name, // IN: the name of the object |
| 1172 TPM2B_SEED *seed, // IN: an external seed. |
| 1173 TPM_HANDLE protector, // IN: The protector's handle |
| 1174 TPM2B_DIGEST *secret // OUT: secret information |
| 1175 ) |
| 1176 { |
| 1177 TPM_RC result; |
| 1178 BYTE *buffer; |
| 1179 INT32 size; |
| 1180 TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap |
| 1181 BYTE *sensitiveData; // pointer to the sensitive data |
| 1182 UINT16 dataSize; |
| 1183 |
| 1184 // use protector's name algorithm as outer hash |
| 1185 outerHash = ObjectGetNameAlg(protector); |
| 1186 |
| 1187 // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point |
| 1188 result = UnwrapOuter(protector, name, outerHash, seed, FALSE, |
| 1189 inIDObject->t.size, inIDObject->t.credential); |
| 1190 if(result == TPM_RC_SUCCESS) |
| 1191 { |
| 1192 // Compute the beginning of sensitive data |
| 1193 sensitiveData = inIDObject->t.credential |
| 1194 + sizeof(UINT16) + CryptGetHashDigestSize(outerHash); |
| 1195 dataSize = inIDObject->t.size |
| 1196 - (sizeof(UINT16) + CryptGetHashDigestSize(outerHash)); |
| 1197 |
| 1198 // Unmarshal secret buffer to TPM2B_DIGEST structure |
| 1199 buffer = sensitiveData; |
| 1200 size = (INT32) dataSize; |
| 1201 result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); |
| 1202 // If there were no other unmarshaling errors, make sure that the |
| 1203 // expected amount of data was recovered |
| 1204 if(result == TPM_RC_SUCCESS && size != 0) |
| 1205 return TPM_RC_SIZE; |
| 1206 } |
| 1207 return result; |
| 1208 } |
| |
| |
| Page 108 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| 8 Subsystem |
| |
| 8.1 CommandAudit.c |
| |
| 8.1.1 Introduction |
| |
| This file contains the functions that support command audit. |
| |
| 8.1.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| 8.1.3 Functions |
| |
| 8.1.3.1 CommandAuditPreInstall_Init() |
| |
| This function initializes the command audit list. This function is simulates the behavior of manufacturing. A |
| function is used instead of a structure definition because this is easier than figuring out the initialization |
| value for a bit array. |
| This function would not be implemented outside of a manufacturing or simulation environment. |
| |
| 2 void |
| 3 CommandAuditPreInstall_Init( |
| 4 void |
| 5 ) |
| 6 { |
| 7 // Clear all the audit commands |
| 8 MemorySet(gp.auditComands, 0x00, |
| 9 ((TPM_CC_LAST - TPM_CC_FIRST + 1) + 7) / 8); |
| 10 |
| 11 // TPM_CC_SetCommandCodeAuditStatus always being audited |
| 12 if(CommandIsImplemented(TPM_CC_SetCommandCodeAuditStatus)) |
| 13 CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus); |
| 14 |
| 15 // Set initial command audit hash algorithm to be context integrity hash |
| 16 // algorithm |
| 17 gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG; |
| 18 |
| 19 // Set up audit counter to be 0 |
| 20 gp.auditCounter = 0; |
| 21 |
| 22 // Write command audit persistent data to NV |
| 23 NvWriteReserved(NV_AUDIT_COMMANDS, &gp.auditComands); |
| 24 NvWriteReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg); |
| 25 NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter); |
| 26 |
| 27 return; |
| 28 } |
| |
| |
| 8.1.3.2 CommandAuditStartup() |
| |
| This function clears the command audit digest on a TPM Reset. |
| |
| 29 void |
| 30 CommandAuditStartup( |
| 31 STARTUP_TYPE type // IN: start up type |
| 32 ) |
| |
| Family "2.0" TCG Published Page 109 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 33 { |
| 34 if(type == SU_RESET) |
| 35 { |
| 36 // Reset the digest size to initialize the digest |
| 37 gr.commandAuditDigest.t.size = 0; |
| 38 } |
| 39 |
| 40 } |
| |
| |
| 8.1.3.3 CommandAuditSet() |
| |
| This function will SET the audit flag for a command. This function will not SET the audit flag for a |
| command that is not implemented. This ensures that the audit status is not SET when |
| TPM2_GetCapability() is used to read the list of audited commands. |
| This function is only used by TPM2_SetCommandCodeAuditStatus(). |
| The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to |
| NV after it is setting and clearing bits. |
| |
| Return Value Meaning |
| |
| TRUE the command code audit status was changed |
| FALSE the command code audit status was not changed |
| |
| 41 BOOL |
| 42 CommandAuditSet( |
| 43 TPM_CC commandCode // IN: command code |
| 44 ) |
| 45 { |
| 46 UINT32 bitPos; |
| 47 |
| 48 // Only SET a bit if the corresponding command is implemented |
| 49 if(CommandIsImplemented(commandCode)) |
| 50 { |
| 51 // Can't audit shutdown |
| 52 if(commandCode != TPM_CC_Shutdown) |
| 53 { |
| 54 bitPos = commandCode - TPM_CC_FIRST; |
| 55 if(!BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands))) |
| 56 { |
| 57 // Set bit |
| 58 BitSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)); |
| 59 return TRUE; |
| 60 } |
| 61 } |
| 62 } |
| 63 // No change |
| 64 return FALSE; |
| 65 } |
| |
| |
| 8.1.3.4 CommandAuditClear() |
| |
| This function will CLEAR the audit flag for a command. It will not CLEAR the audit flag for |
| TPM_CC_SetCommandCodeAuditStatus(). |
| This function is only used by TPM2_SetCommandCodeAuditStatus(). |
| The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to |
| NV after it is setting and clearing bits. |
| |
| |
| |
| Page 110 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| TRUE the command code audit status was changed |
| FALSE the command code audit status was not changed |
| |
| 66 BOOL |
| 67 CommandAuditClear( |
| 68 TPM_CC commandCode // IN: command code |
| 69 ) |
| 70 { |
| 71 UINT32 bitPos; |
| 72 |
| 73 // Do nothing if the command is not implemented |
| 74 if(CommandIsImplemented(commandCode)) |
| 75 { |
| 76 // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be |
| 77 // cleared |
| 78 if(commandCode != TPM_CC_SetCommandCodeAuditStatus) |
| 79 { |
| 80 bitPos = commandCode - TPM_CC_FIRST; |
| 81 if(BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands))) |
| 82 { |
| 83 // Clear bit |
| 84 BitClear(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)); |
| 85 return TRUE; |
| 86 } |
| 87 } |
| 88 } |
| 89 // No change |
| 90 return FALSE; |
| 91 } |
| |
| |
| 8.1.3.5 CommandAuditIsRequired() |
| |
| This function indicates if the audit flag is SET for a command. |
| |
| Return Value Meaning |
| |
| TRUE if command is audited |
| FALSE if command is not audited |
| |
| 92 BOOL |
| 93 CommandAuditIsRequired( |
| 94 TPM_CC commandCode // IN: command code |
| 95 ) |
| 96 { |
| 97 UINT32 bitPos; |
| 98 |
| 99 bitPos = commandCode - TPM_CC_FIRST; |
| 100 |
| 101 // Check the bit map. If the bit is SET, command audit is required |
| 102 if((gp.auditComands[bitPos/8] & (1 << (bitPos % 8))) != 0) |
| 103 return TRUE; |
| 104 else |
| 105 return FALSE; |
| 106 |
| 107 } |
| |
| |
| 8.1.3.6 CommandAuditCapGetCCList() |
| |
| This function returns a list of commands that have their audit bit SET. |
| Family "2.0" TCG Published Page 111 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| The list starts at the input commandCode. |
| |
| Return Value Meaning |
| |
| YES if there are more command code available |
| NO all the available command code has been returned |
| |
| 108 TPMI_YES_NO |
| 109 CommandAuditCapGetCCList( |
| 110 TPM_CC commandCode, // IN: start command code |
| 111 UINT32 count, // IN: count of returned TPM_CC |
| 112 TPML_CC *commandList // OUT: list of TPM_CC |
| 113 ) |
| 114 { |
| 115 TPMI_YES_NO more = NO; |
| 116 UINT32 i; |
| 117 |
| 118 // Initialize output handle list |
| 119 commandList->count = 0; |
| 120 |
| 121 // The maximum count of command we may return is MAX_CAP_CC |
| 122 if(count > MAX_CAP_CC) count = MAX_CAP_CC; |
| 123 |
| 124 // If the command code is smaller than TPM_CC_FIRST, start from TPM_CC_FIRST |
| 125 if(commandCode < TPM_CC_FIRST) commandCode = TPM_CC_FIRST; |
| 126 |
| 127 // Collect audit commands |
| 128 for(i = commandCode; i <= TPM_CC_LAST; i++) |
| 129 { |
| 130 if(CommandAuditIsRequired(i)) |
| 131 { |
| 132 if(commandList->count < count) |
| 133 { |
| 134 // If we have not filled up the return list, add this command |
| 135 // code to it |
| 136 commandList->commandCodes[commandList->count] = i; |
| 137 commandList->count++; |
| 138 } |
| 139 else |
| 140 { |
| 141 // If the return list is full but we still have command |
| 142 // available, report this and stop iterating |
| 143 more = YES; |
| 144 break; |
| 145 } |
| 146 } |
| 147 } |
| 148 |
| 149 return more; |
| 150 |
| 151 } |
| |
| |
| 8.1.3.7 CommandAuditGetDigest |
| |
| This command is used to create a digest of the commands being audited. The commands are processed |
| in ascending numeric order with a list of TPM_CC being added to a hash. This operates as if all the |
| audited command codes were concatenated and then hashed. |
| |
| 152 void |
| 153 CommandAuditGetDigest( |
| 154 TPM2B_DIGEST *digest // OUT: command digest |
| 155 ) |
| 156 { |
| |
| Page 112 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 157 TPM_CC i; |
| 158 HASH_STATE hashState; |
| 159 |
| 160 // Start hash |
| 161 digest->t.size = CryptStartHash(gp.auditHashAlg, &hashState); |
| 162 |
| 163 // Add command code |
| 164 for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++) |
| 165 { |
| 166 if(CommandAuditIsRequired(i)) |
| 167 { |
| 168 CryptUpdateDigestInt(&hashState, sizeof(i), &i); |
| 169 } |
| 170 } |
| 171 |
| 172 // Complete hash |
| 173 CryptCompleteHash2B(&hashState, &digest->b); |
| 174 |
| 175 return; |
| 176 } |
| |
| |
| 8.2 DA.c |
| |
| 8.2.1 Introduction |
| |
| This file contains the functions and data definitions relating to the dictionary attack logic. |
| |
| 8.2.2 Includes and Data Definitions |
| |
| 1 #define DA_C |
| 2 #include "InternalRoutines.h" |
| |
| |
| 8.2.3 Functions |
| |
| 8.2.3.1 DAPreInstall_Init() |
| |
| This function initializes the DA parameters to their manufacturer-default values. The default values are |
| determined by a platform-specific specification. |
| This function should not be called outside of a manufacturing or simulation environment. |
| The DA parameters will be restored to these initial values by TPM2_Clear(). |
| |
| 3 void |
| 4 DAPreInstall_Init( |
| 5 void |
| 6 ) |
| 7 { |
| 8 gp.failedTries = 0; |
| 9 gp.maxTries = 3; |
| 10 gp.recoveryTime = 1000; // in seconds (~16.67 minutes) |
| 11 gp.lockoutRecovery = 1000; // in seconds |
| 12 gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled |
| 13 |
| 14 // Record persistent DA parameter changes to NV |
| 15 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 16 NvWriteReserved(NV_MAX_TRIES, &gp.maxTries); |
| 17 NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime); |
| 18 NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery); |
| 19 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); |
| 20 |
| |
| Family "2.0" TCG Published Page 113 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 21 return; |
| 22 } |
| |
| |
| 8.2.3.2 DAStartup() |
| |
| This function is called by TPM2_Startup() to initialize the DA parameters. In the case of Startup(CLEAR), |
| use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, lockoutAuth will not be |
| enabled until the TPM has been continuously powered for the lockoutRecovery time. |
| This function requires that NV be available and not rate limiting. |
| |
| 23 void |
| 24 DAStartup( |
| 25 STARTUP_TYPE type // IN: startup type |
| 26 ) |
| 27 { |
| 28 // For TPM Reset, if lockoutRecovery is 0, enable use of lockoutAuth. |
| 29 if(type == SU_RESET) |
| 30 { |
| 31 if(gp.lockoutRecovery == 0) |
| 32 { |
| 33 gp.lockOutAuthEnabled = TRUE; |
| 34 // Record the changes to NV |
| 35 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); |
| 36 } |
| 37 } |
| 38 |
| 39 // If DA has not been disabled and the previous shutdown is not orderly |
| 40 // failedTries is not already at its maximum then increment 'failedTries' |
| 41 if( gp.recoveryTime != 0 |
| 42 && g_prevOrderlyState == SHUTDOWN_NONE |
| 43 && gp.failedTries < gp.maxTries) |
| 44 { |
| 45 gp.failedTries++; |
| 46 // Record the change to NV |
| 47 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 48 } |
| 49 |
| 50 // Reset self healing timers |
| 51 s_selfHealTimer = g_time; |
| 52 s_lockoutTimer = g_time; |
| 53 |
| 54 return; |
| 55 } |
| |
| |
| 8.2.3.3 DARegisterFailure() |
| |
| This function is called when a authorization failure occurs on an entity that is subject to dictionary-attack |
| protection. When a DA failure is triggered, register the failure by resetting the relevant self-healing timer |
| to the current time. |
| |
| 56 void |
| 57 DARegisterFailure( |
| 58 TPM_HANDLE handle // IN: handle for failure |
| 59 ) |
| 60 { |
| 61 // Reset the timer associated with lockout if the handle is the lockout auth. |
| 62 if(handle == TPM_RH_LOCKOUT) |
| 63 s_lockoutTimer = g_time; |
| 64 else |
| 65 s_selfHealTimer = g_time; |
| 66 |
| |
| |
| Page 114 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 67 return; |
| 68 } |
| |
| |
| 8.2.3.4 DASelfHeal() |
| |
| This function is called to check if sufficient time has passed to allow decrement of failedTries or to re- |
| enable use of lockoutAuth. |
| This function should be called when the time interval is updated. |
| |
| 69 void |
| 70 DASelfHeal( |
| 71 void |
| 72 ) |
| 73 { |
| 74 // Regular auth self healing logic |
| 75 // If no failed authorization tries, do nothing. Otherwise, try to |
| 76 // decrease failedTries |
| 77 if(gp.failedTries != 0) |
| 78 { |
| 79 // if recovery time is 0, DA logic has been disabled. Clear failed tries |
| 80 // immediately |
| 81 if(gp.recoveryTime == 0) |
| 82 { |
| 83 gp.failedTries = 0; |
| 84 // Update NV record |
| 85 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 86 } |
| 87 else |
| 88 { |
| 89 UINT64 decreaseCount; |
| 90 |
| 91 // In the unlikely event that failedTries should become larger than |
| 92 // maxTries |
| 93 if(gp.failedTries > gp.maxTries) |
| 94 gp.failedTries = gp.maxTries; |
| 95 |
| 96 // How much can failedTried be decreased |
| 97 decreaseCount = ((g_time - s_selfHealTimer) / 1000) / gp.recoveryTime; |
| 98 |
| 99 if(gp.failedTries <= (UINT32) decreaseCount) |
| 100 // should not set failedTries below zero |
| 101 gp.failedTries = 0; |
| 102 else |
| 103 gp.failedTries -= (UINT32) decreaseCount; |
| 104 |
| 105 // the cast prevents overflow of the product |
| 106 s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000; |
| 107 if(decreaseCount != 0) |
| 108 // If there was a change to the failedTries, record the changes |
| 109 // to NV |
| 110 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 111 } |
| 112 } |
| 113 |
| 114 // LockoutAuth self healing logic |
| 115 // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we |
| 116 // may enable it |
| 117 if(!gp.lockOutAuthEnabled) |
| 118 { |
| 119 // if lockout authorization recovery time is 0, a reboot is required to |
| 120 // re-enable use of lockout authorization. Self-healing would not |
| 121 // apply in this case. |
| 122 if(gp.lockoutRecovery != 0) |
| |
| |
| Family "2.0" TCG Published Page 115 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 123 { |
| 124 if(((g_time - s_lockoutTimer)/1000) >= gp.lockoutRecovery) |
| 125 { |
| 126 gp.lockOutAuthEnabled = TRUE; |
| 127 // Record the changes to NV |
| 128 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); |
| 129 } |
| 130 } |
| 131 } |
| 132 |
| 133 return; |
| 134 } |
| |
| |
| 8.3 Hierarchy.c |
| |
| 8.3.1 Introduction |
| |
| This file contains the functions used for managing and accessing the hierarchy-related values. |
| |
| 8.3.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| 8.3.3 Functions |
| |
| 8.3.3.1 HierarchyPreInstall() |
| |
| This function performs the initialization functions for the hierarchy when the TPM is simulated. This |
| function should not be called if the TPM is not in a manufacturing mode at the manufacturer, or in a |
| simulated environment. |
| |
| 2 void |
| 3 HierarchyPreInstall_Init( |
| 4 void |
| 5 ) |
| 6 { |
| 7 // Allow lockout clear command |
| 8 gp.disableClear = FALSE; |
| 9 |
| 10 // Initialize Primary Seeds |
| 11 gp.EPSeed.t.size = PRIMARY_SEED_SIZE; |
| 12 CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer); |
| 13 gp.SPSeed.t.size = PRIMARY_SEED_SIZE; |
| 14 CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.SPSeed.t.buffer); |
| 15 gp.PPSeed.t.size = PRIMARY_SEED_SIZE; |
| 16 CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.PPSeed.t.buffer); |
| 17 |
| 18 // Initialize owner, endorsement and lockout auth |
| 19 gp.ownerAuth.t.size = 0; |
| 20 gp.endorsementAuth.t.size = 0; |
| 21 gp.lockoutAuth.t.size = 0; |
| 22 |
| 23 // Initialize owner, endorsement, and lockout policy |
| 24 gp.ownerAlg = TPM_ALG_NULL; |
| 25 gp.ownerPolicy.t.size = 0; |
| 26 gp.endorsementAlg = TPM_ALG_NULL; |
| 27 gp.endorsementPolicy.t.size = 0; |
| 28 gp.lockoutAlg = TPM_ALG_NULL; |
| 29 gp.lockoutPolicy.t.size = 0; |
| 30 |
| |
| Page 116 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 31 // Initialize ehProof, shProof and phProof |
| 32 gp.phProof.t.size = PROOF_SIZE; |
| 33 gp.shProof.t.size = PROOF_SIZE; |
| 34 gp.ehProof.t.size = PROOF_SIZE; |
| 35 CryptGenerateRandom(gp.phProof.t.size, gp.phProof.t.buffer); |
| 36 CryptGenerateRandom(gp.shProof.t.size, gp.shProof.t.buffer); |
| 37 CryptGenerateRandom(gp.ehProof.t.size, gp.ehProof.t.buffer); |
| 38 |
| 39 // Write hierarchy data to NV |
| 40 NvWriteReserved(NV_DISABLE_CLEAR, &gp.disableClear); |
| 41 NvWriteReserved(NV_EP_SEED, &gp.EPSeed); |
| 42 NvWriteReserved(NV_SP_SEED, &gp.SPSeed); |
| 43 NvWriteReserved(NV_PP_SEED, &gp.PPSeed); |
| 44 NvWriteReserved(NV_OWNER_AUTH, &gp.ownerAuth); |
| 45 NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth); |
| 46 NvWriteReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth); |
| 47 NvWriteReserved(NV_OWNER_ALG, &gp.ownerAlg); |
| 48 NvWriteReserved(NV_OWNER_POLICY, &gp.ownerPolicy); |
| 49 NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg); |
| 50 NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy); |
| 51 NvWriteReserved(NV_LOCKOUT_ALG, &gp.lockoutAlg); |
| 52 NvWriteReserved(NV_LOCKOUT_POLICY, &gp.lockoutPolicy); |
| 53 NvWriteReserved(NV_PH_PROOF, &gp.phProof); |
| 54 NvWriteReserved(NV_SH_PROOF, &gp.shProof); |
| 55 NvWriteReserved(NV_EH_PROOF, &gp.ehProof); |
| 56 |
| 57 return; |
| 58 } |
| |
| |
| 8.3.3.2 HierarchyStartup() |
| |
| This function is called at TPM2_Startup() to initialize the hierarchy related values. |
| |
| 59 void |
| 60 HierarchyStartup( |
| 61 STARTUP_TYPE type // IN: start up type |
| 62 ) |
| 63 { |
| 64 // phEnable is SET on any startup |
| 65 g_phEnable = TRUE; |
| 66 |
| 67 // Reset platformAuth, platformPolicy; enable SH and EH at TPM_RESET and |
| 68 // TPM_RESTART |
| 69 if(type != SU_RESUME) |
| 70 { |
| 71 gc.platformAuth.t.size = 0; |
| 72 gc.platformPolicy.t.size = 0; |
| 73 |
| 74 // enable the storage and endorsement hierarchies and the platformNV |
| 75 gc.shEnable = gc.ehEnable = gc.phEnableNV = TRUE; |
| 76 } |
| 77 |
| 78 // nullProof and nullSeed are updated at every TPM_RESET |
| 79 if(type == SU_RESET) |
| 80 { |
| 81 gr.nullProof.t.size = PROOF_SIZE; |
| 82 CryptGenerateRandom(gr.nullProof.t.size, |
| 83 gr.nullProof.t.buffer); |
| 84 gr.nullSeed.t.size = PRIMARY_SEED_SIZE; |
| 85 CryptGenerateRandom(PRIMARY_SEED_SIZE, gr.nullSeed.t.buffer); |
| 86 } |
| 87 |
| 88 return; |
| 89 } |
| |
| |
| Family "2.0" TCG Published Page 117 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.3.3.3 HierarchyGetProof() |
| |
| This function finds the proof value associated with a hierarchy.It returns a pointer to the proof value. |
| |
| 90 TPM2B_AUTH * |
| 91 HierarchyGetProof( |
| 92 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant |
| 93 ) |
| 94 { |
| 95 TPM2B_AUTH *auth = NULL; |
| 96 |
| 97 switch(hierarchy) |
| 98 { |
| 99 case TPM_RH_PLATFORM: |
| 100 // phProof for TPM_RH_PLATFORM |
| 101 auth = &gp.phProof; |
| 102 break; |
| 103 case TPM_RH_ENDORSEMENT: |
| 104 // ehProof for TPM_RH_ENDORSEMENT |
| 105 auth = &gp.ehProof; |
| 106 break; |
| 107 case TPM_RH_OWNER: |
| 108 // shProof for TPM_RH_OWNER |
| 109 auth = &gp.shProof; |
| 110 break; |
| 111 case TPM_RH_NULL: |
| 112 // nullProof for TPM_RH_NULL |
| 113 auth = &gr.nullProof; |
| 114 break; |
| 115 default: |
| 116 pAssert(FALSE); |
| 117 break; |
| 118 } |
| 119 return auth; |
| 120 |
| 121 } |
| |
| |
| 8.3.3.4 HierarchyGetPrimarySeed() |
| |
| This function returns the primary seed of a hierarchy. |
| |
| 122 TPM2B_SEED * |
| 123 HierarchyGetPrimarySeed( |
| 124 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy |
| 125 ) |
| 126 { |
| 127 TPM2B_SEED *seed = NULL; |
| 128 switch(hierarchy) |
| 129 { |
| 130 case TPM_RH_PLATFORM: |
| 131 seed = &gp.PPSeed; |
| 132 break; |
| 133 case TPM_RH_OWNER: |
| 134 seed = &gp.SPSeed; |
| 135 break; |
| 136 case TPM_RH_ENDORSEMENT: |
| 137 seed = &gp.EPSeed; |
| 138 break; |
| 139 case TPM_RH_NULL: |
| 140 return &gr.nullSeed; |
| 141 default: |
| 142 pAssert(FALSE); |
| 143 break; |
| 144 } |
| |
| Page 118 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 145 return seed; |
| 146 } |
| |
| |
| 8.3.3.5 HierarchyIsEnabled() |
| |
| This function checks to see if a hierarchy is enabled. |
| |
| NOTE: The TPM_RH_NULL hierarchy is always enabled. |
| |
| |
| Return Value Meaning |
| |
| TRUE hierarchy is enabled |
| FALSE hierarchy is disabled |
| |
| 147 BOOL |
| 148 HierarchyIsEnabled( |
| 149 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy |
| 150 ) |
| 151 { |
| 152 BOOL enabled = FALSE; |
| 153 |
| 154 switch(hierarchy) |
| 155 { |
| 156 case TPM_RH_PLATFORM: |
| 157 enabled = g_phEnable; |
| 158 break; |
| 159 case TPM_RH_OWNER: |
| 160 enabled = gc.shEnable; |
| 161 break; |
| 162 case TPM_RH_ENDORSEMENT: |
| 163 enabled = gc.ehEnable; |
| 164 break; |
| 165 case TPM_RH_NULL: |
| 166 enabled = TRUE; |
| 167 break; |
| 168 default: |
| 169 pAssert(FALSE); |
| 170 break; |
| 171 } |
| 172 return enabled; |
| 173 } |
| |
| |
| 8.4 NV.c |
| |
| 8.4.1 Introduction |
| |
| The NV memory is divided into two area: dynamic space for user defined NV Indices and evict objects, |
| and reserved space for TPM persistent and state save data. |
| |
| 8.4.2 Includes, Defines and Data Definitions |
| |
| 1 #define NV_C |
| 2 #include "InternalRoutines.h" |
| 3 #include <Platform.h> |
| |
| NV Index/evict object iterator value |
| |
| 4 typedef UINT32 NV_ITER; // type of a NV iterator |
| 5 #define NV_ITER_INIT 0xFFFFFFFF // initial value to start an |
| |
| Family "2.0" TCG Published Page 119 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 6 // iterator |
| |
| |
| 8.4.3 NV Utility Functions |
| |
| 8.4.3.1 NvCheckState() |
| |
| Function to check the NV state by accessing the platform-specific function to get the NV state. The result |
| state is registered in s_NvIsAvailable that will be reported by NvIsAvailable(). |
| This function is called at the beginning of ExecuteCommand() before any potential call to NvIsAvailable(). |
| |
| 7 void |
| 8 NvCheckState(void) |
| 9 { |
| 10 int func_return; |
| 11 |
| 12 func_return = _plat__IsNvAvailable(); |
| 13 if(func_return == 0) |
| 14 { |
| 15 s_NvStatus = TPM_RC_SUCCESS; |
| 16 } |
| 17 else if(func_return == 1) |
| 18 { |
| 19 s_NvStatus = TPM_RC_NV_UNAVAILABLE; |
| 20 } |
| 21 else |
| 22 { |
| 23 s_NvStatus = TPM_RC_NV_RATE; |
| 24 } |
| 25 |
| 26 return; |
| 27 } |
| |
| |
| 8.4.3.2 NvIsAvailable() |
| |
| This function returns the NV availability parameter. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SUCCESS NV is available |
| TPM_RC_NV_RATE NV is unavailable because of rate limit |
| TPM_RC_NV_UNAVAILABLE NV is inaccessible |
| |
| 28 TPM_RC |
| 29 NvIsAvailable( |
| 30 void |
| 31 ) |
| 32 { |
| 33 return s_NvStatus; |
| 34 } |
| |
| |
| 8.4.3.3 NvCommit |
| |
| This is a wrapper for the platform function to commit pending NV writes. |
| |
| 35 BOOL |
| 36 NvCommit( |
| 37 void |
| 38 ) |
| |
| Page 120 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 39 { |
| 40 BOOL success = (_plat__NvCommit() == 0); |
| 41 return success; |
| 42 } |
| |
| |
| 8.4.3.4 NvReadMaxCount() |
| |
| This function returns the max NV counter value. |
| |
| 43 static UINT64 |
| 44 NvReadMaxCount( |
| 45 void |
| 46 ) |
| 47 { |
| 48 UINT64 countValue; |
| 49 _plat__NvMemoryRead(s_maxCountAddr, sizeof(UINT64), &countValue); |
| 50 return countValue; |
| 51 } |
| |
| |
| 8.4.3.5 NvWriteMaxCount() |
| |
| This function updates the max counter value to NV memory. |
| |
| 52 static void |
| 53 NvWriteMaxCount( |
| 54 UINT64 maxCount |
| 55 ) |
| 56 { |
| 57 _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &maxCount); |
| 58 return; |
| 59 } |
| |
| |
| 8.4.4 NV Index and Persistent Object Access Functions |
| |
| 8.4.4.1 Introduction |
| |
| These functions are used to access an NV Index and persistent object memory. In this implementation, |
| the memory is simulated with RAM. The data in dynamic area is organized as a linked list, starting from |
| address s_evictNvStart. The first 4 bytes of a node in this link list is the offset of next node, followed by |
| the data entry. A 0-valued offset value indicates the end of the list. If the data entry area of the last node |
| happens to reach the end of the dynamic area without space left for an additional 4 byte end marker, the |
| end address, s_evictNvEnd, should serve as the mark of list end |
| |
| 8.4.4.2 NvNext() |
| |
| This function provides a method to traverse every data entry in NV dynamic area. |
| To begin with, parameter iter should be initialized to NV_ITER_INIT indicating the first element. Every |
| time this function is called, the value in iter would be adjusted pointing to the next element in traversal. If |
| there is no next element, iter value would be 0. This function returns the address of the 'data entry' |
| pointed by the iter. If there is no more element in the set, a 0 value is returned indicating the end of |
| traversal. |
| |
| 60 static UINT32 |
| 61 NvNext( |
| 62 NV_ITER *iter |
| 63 ) |
| 64 { |
| |
| Family "2.0" TCG Published Page 121 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 65 NV_ITER currentIter; |
| 66 |
| 67 // If iterator is at the beginning of list |
| 68 if(*iter == NV_ITER_INIT) |
| 69 { |
| 70 // Initialize iterator |
| 71 *iter = s_evictNvStart; |
| 72 } |
| 73 |
| 74 // If iterator reaches the end of NV space, or iterator indicates list end |
| 75 if(*iter + sizeof(UINT32) > s_evictNvEnd || *iter == 0) |
| 76 return 0; |
| 77 |
| 78 // Save the current iter offset |
| 79 currentIter = *iter; |
| 80 |
| 81 // Adjust iter pointer pointing to next entity |
| 82 // Read pointer value |
| 83 _plat__NvMemoryRead(*iter, sizeof(UINT32), iter); |
| 84 |
| 85 if(*iter == 0) return 0; |
| 86 |
| 87 return currentIter + sizeof(UINT32); // entity stores after the pointer |
| 88 } |
| |
| |
| 8.4.4.3 NvGetEnd() |
| |
| Function to find the end of the NV dynamic data list |
| |
| 89 static UINT32 |
| 90 NvGetEnd( |
| 91 void |
| 92 ) |
| 93 { |
| 94 NV_ITER iter = NV_ITER_INIT; |
| 95 UINT32 endAddr = s_evictNvStart; |
| 96 UINT32 currentAddr; |
| 97 |
| 98 while((currentAddr = NvNext(&iter)) != 0) |
| 99 endAddr = currentAddr; |
| 100 |
| 101 if(endAddr != s_evictNvStart) |
| 102 { |
| 103 // Read offset |
| 104 endAddr -= sizeof(UINT32); |
| 105 _plat__NvMemoryRead(endAddr, sizeof(UINT32), &endAddr); |
| 106 } |
| 107 |
| 108 return endAddr; |
| 109 } |
| |
| |
| 8.4.4.4 NvGetFreeByte |
| |
| This function returns the number of free octets in NV space. |
| |
| 110 static UINT32 |
| 111 NvGetFreeByte( |
| 112 void |
| 113 ) |
| 114 { |
| 115 return s_evictNvEnd - NvGetEnd(); |
| 116 } |
| |
| |
| Page 122 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.4.4.5 NvGetEvictObjectSize |
| |
| This function returns the size of an evict object in NV space |
| |
| 117 static UINT32 |
| 118 NvGetEvictObjectSize( |
| 119 void |
| 120 ) |
| 121 { |
| 122 return sizeof(TPM_HANDLE) + sizeof(OBJECT) + sizeof(UINT32); |
| 123 } |
| |
| |
| 8.4.4.6 NvGetCounterSize |
| |
| This function returns the size of a counter index in NV space. |
| |
| 124 static UINT32 |
| 125 NvGetCounterSize( |
| 126 void |
| 127 ) |
| 128 { |
| 129 // It takes an offset field, a handle and the sizeof(NV_INDEX) and |
| 130 // sizeof(UINT64) for counter data |
| 131 return sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + sizeof(UINT64) + sizeof(UINT32); |
| 132 } |
| |
| |
| 8.4.4.7 NvTestSpace() |
| |
| This function will test if there is enough space to add a new entity. |
| |
| Return Value Meaning |
| |
| TRUE space available |
| FALSE no enough space |
| |
| 133 static BOOL |
| 134 NvTestSpace( |
| 135 UINT32 size, // IN: size of the entity to be added |
| 136 BOOL isIndex // IN: TRUE if the entity is an index |
| 137 ) |
| 138 { |
| 139 UINT32 remainByte = NvGetFreeByte(); |
| 140 |
| 141 // For NV Index, need to make sure that we do not allocate and Index if this |
| 142 // would mean that the TPM cannot allocate the minimum number of evict |
| 143 // objects. |
| 144 if(isIndex) |
| 145 { |
| 146 // Get the number of persistent objects allocated |
| 147 UINT32 persistentNum = NvCapGetPersistentNumber(); |
| 148 |
| 149 // If we have not allocated the requisite number of evict objects, then we |
| 150 // need to reserve space for them. |
| 151 // NOTE: some of this is not written as simply as it might seem because |
| 152 // the values are all unsigned and subtracting needs to be done carefully |
| 153 // so that an underflow doesn't cause problems. |
| 154 if(persistentNum < MIN_EVICT_OBJECTS) |
| 155 { |
| 156 UINT32 needed = (MIN_EVICT_OBJECTS - persistentNum) |
| 157 * NvGetEvictObjectSize(); |
| 158 if(needed > remainByte) |
| |
| Family "2.0" TCG Published Page 123 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 159 remainByte = 0; |
| 160 else |
| 161 remainByte -= needed; |
| 162 } |
| 163 // if the requisite number of evict objects have been allocated then |
| 164 // no need to reserve additional space |
| 165 } |
| 166 // This checks for the size of the value being added plus the index value. |
| 167 // NOTE: This does not check to see if the end marker can be placed in |
| 168 // memory because the end marker will not be written if it will not fit. |
| 169 return (size + sizeof(UINT32) <= remainByte); |
| 170 } |
| |
| |
| 8.4.4.8 NvAdd() |
| |
| This function adds a new entity to NV. |
| This function requires that there is enough space to add a new entity (i.e., that NvTestSpace() has been |
| called and the available space is at least as large as the required space). |
| |
| 171 static void |
| 172 NvAdd( |
| 173 UINT32 totalSize, // IN: total size needed for this entity For |
| 174 // evict object, totalSize is the same as |
| 175 // bufferSize. For NV Index, totalSize is |
| 176 // bufferSize plus index data size |
| 177 UINT32 bufferSize, // IN: size of initial buffer |
| 178 BYTE *entity // IN: initial buffer |
| 179 ) |
| 180 { |
| 181 UINT32 endAddr; |
| 182 UINT32 nextAddr; |
| 183 UINT32 listEnd = 0; |
| 184 |
| 185 // Get the end of data list |
| 186 endAddr = NvGetEnd(); |
| 187 |
| 188 // Calculate the value of next pointer, which is the size of a pointer + |
| 189 // the entity data size |
| 190 nextAddr = endAddr + sizeof(UINT32) + totalSize; |
| 191 |
| 192 // Write next pointer |
| 193 _plat__NvMemoryWrite(endAddr, sizeof(UINT32), &nextAddr); |
| 194 |
| 195 // Write entity data |
| 196 _plat__NvMemoryWrite(endAddr + sizeof(UINT32), bufferSize, entity); |
| 197 |
| 198 // Write the end of list if it is not going to exceed the NV space |
| 199 if(nextAddr + sizeof(UINT32) <= s_evictNvEnd) |
| 200 _plat__NvMemoryWrite(nextAddr, sizeof(UINT32), &listEnd); |
| 201 |
| 202 // Set the flag so that NV changes are committed before the command completes. |
| 203 g_updateNV = TRUE; |
| 204 } |
| |
| |
| 8.4.4.9 NvDelete() |
| |
| This function is used to delete an NV Index or persistent object from NV memory. |
| |
| 205 static void |
| 206 NvDelete( |
| 207 UINT32 entityAddr // IN: address of entity to be deleted |
| 208 ) |
| |
| Page 124 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 209 { |
| 210 UINT32 next; |
| 211 UINT32 entrySize; |
| 212 UINT32 entryAddr = entityAddr - sizeof(UINT32); |
| 213 UINT32 listEnd = 0; |
| 214 |
| 215 // Get the offset of the next entry. |
| 216 _plat__NvMemoryRead(entryAddr, sizeof(UINT32), &next); |
| 217 |
| 218 // The size of this entry is the difference between the current entry and the |
| 219 // next entry. |
| 220 entrySize = next - entryAddr; |
| 221 |
| 222 // Move each entry after the current one to fill the freed space. |
| 223 // Stop when we have reached the end of all the indexes. There are two |
| 224 // ways to detect the end of the list. The first is to notice that there |
| 225 // is no room for anything else because we are at the end of NV. The other |
| 226 // indication is that we find an end marker. |
| 227 |
| 228 // The loop condition checks for the end of NV. |
| 229 while(next + sizeof(UINT32) <= s_evictNvEnd) |
| 230 { |
| 231 UINT32 size, oldAddr, newAddr; |
| 232 |
| 233 // Now check for the end marker |
| 234 _plat__NvMemoryRead(next, sizeof(UINT32), &oldAddr); |
| 235 if(oldAddr == 0) |
| 236 break; |
| 237 |
| 238 size = oldAddr - next; |
| 239 |
| 240 // Move entry |
| 241 _plat__NvMemoryMove(next, next - entrySize, size); |
| 242 |
| 243 // Update forward link |
| 244 newAddr = oldAddr - entrySize; |
| 245 _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &newAddr); |
| 246 next = oldAddr; |
| 247 } |
| 248 // Mark the end of list |
| 249 _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &listEnd); |
| 250 |
| 251 // Set the flag so that NV changes are committed before the command completes. |
| 252 g_updateNV = TRUE; |
| 253 } |
| |
| |
| 8.4.5 RAM-based NV Index Data Access Functions |
| |
| 8.4.5.1 Introduction |
| |
| The data layout in ram buffer is {size of(NV_handle() + data), NV_handle(), data} for each NV Index data |
| stored in RAM. |
| NV storage is updated when a NV Index is added or deleted. We do NOT updated NV storage when the |
| data is updated/ |
| |
| 8.4.5.2 NvTestRAMSpace() |
| |
| This function indicates if there is enough RAM space to add a data for a new NV Index. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 125 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| TRUE space available |
| FALSE no enough space |
| |
| 254 static BOOL |
| 255 NvTestRAMSpace( |
| 256 UINT32 size // IN: size of the data to be added to RAM |
| 257 ) |
| 258 { |
| 259 BOOL success = ( s_ramIndexSize |
| 260 + size |
| 261 + sizeof(TPM_HANDLE) + sizeof(UINT32) |
| 262 <= RAM_INDEX_SPACE); |
| 263 return success; |
| 264 } |
| |
| |
| 8.4.5.3 NvGetRamIndexOffset |
| |
| This function returns the offset of NV data in the RAM buffer |
| This function requires that NV Index is in RAM. That is, the index must be known to exist. |
| |
| 265 static UINT32 |
| 266 NvGetRAMIndexOffset( |
| 267 TPMI_RH_NV_INDEX handle // IN: NV handle |
| 268 ) |
| 269 { |
| 270 UINT32 currAddr = 0; |
| 271 |
| 272 while(currAddr < s_ramIndexSize) |
| 273 { |
| 274 TPMI_RH_NV_INDEX currHandle; |
| 275 UINT32 currSize; |
| 276 currHandle = * (TPM_HANDLE *) &s_ramIndex[currAddr + sizeof(UINT32)]; |
| 277 |
| 278 // Found a match |
| 279 if(currHandle == handle) |
| 280 |
| 281 // data buffer follows the handle and size field |
| 282 break; |
| 283 |
| 284 currSize = * (UINT32 *) &s_ramIndex[currAddr]; |
| 285 currAddr += sizeof(UINT32) + currSize; |
| 286 } |
| 287 |
| 288 // We assume the index data is existing in RAM space |
| 289 pAssert(currAddr < s_ramIndexSize); |
| 290 return currAddr + sizeof(TPMI_RH_NV_INDEX) + sizeof(UINT32); |
| 291 } |
| |
| |
| 8.4.5.4 NvAddRAM() |
| |
| This function adds a new data area to RAM. |
| This function requires that enough free RAM space is available to add the new data. |
| |
| 292 static void |
| 293 NvAddRAM( |
| 294 TPMI_RH_NV_INDEX handle, // IN: NV handle |
| 295 UINT32 size // IN: size of data |
| 296 ) |
| |
| Page 126 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 297 { |
| 298 // Add data space at the end of reserved RAM buffer |
| 299 * (UINT32 *) &s_ramIndex[s_ramIndexSize] = size + sizeof(TPMI_RH_NV_INDEX); |
| 300 * (TPMI_RH_NV_INDEX *) &s_ramIndex[s_ramIndexSize + sizeof(UINT32)] = handle; |
| 301 s_ramIndexSize += sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX) + size; |
| 302 |
| 303 pAssert(s_ramIndexSize <= RAM_INDEX_SPACE); |
| 304 |
| 305 // Update NV version of s_ramIndexSize |
| 306 _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize); |
| 307 |
| 308 // Write reserved RAM space to NV to reflect the newly added NV Index |
| 309 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); |
| 310 |
| 311 return; |
| 312 } |
| |
| |
| 8.4.5.5 NvDeleteRAM() |
| |
| This function is used to delete a RAM-backed NV Index data area. |
| This function assumes the data of NV Index exists in RAM |
| |
| 313 static void |
| 314 NvDeleteRAM( |
| 315 TPMI_RH_NV_INDEX handle // IN: NV handle |
| 316 ) |
| 317 { |
| 318 UINT32 nodeOffset; |
| 319 UINT32 nextNode; |
| 320 UINT32 size; |
| 321 |
| 322 nodeOffset = NvGetRAMIndexOffset(handle); |
| 323 |
| 324 // Move the pointer back to get the size field of this node |
| 325 nodeOffset -= sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX); |
| 326 |
| 327 // Get node size |
| 328 size = * (UINT32 *) &s_ramIndex[nodeOffset]; |
| 329 |
| 330 // Get the offset of next node |
| 331 nextNode = nodeOffset + sizeof(UINT32) + size; |
| 332 |
| 333 // Move data |
| 334 MemoryMove(s_ramIndex + nodeOffset, s_ramIndex + nextNode, |
| 335 s_ramIndexSize - nextNode, s_ramIndexSize - nextNode); |
| 336 |
| 337 // Update RAM size |
| 338 s_ramIndexSize -= size + sizeof(UINT32); |
| 339 |
| 340 // Update NV version of s_ramIndexSize |
| 341 _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize); |
| 342 |
| 343 // Write reserved RAM space to NV to reflect the newly delete NV Index |
| 344 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); |
| 345 |
| 346 return; |
| 347 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 127 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.4.6 Utility Functions |
| |
| 8.4.6.1 NvInitStatic() |
| |
| This function initializes the static variables used in the NV subsystem. |
| |
| 348 static void |
| 349 NvInitStatic( |
| 350 void |
| 351 ) |
| 352 { |
| 353 UINT16 i; |
| 354 UINT32 reservedAddr; |
| 355 |
| 356 s_reservedSize[NV_DISABLE_CLEAR] = sizeof(gp.disableClear); |
| 357 s_reservedSize[NV_OWNER_ALG] = sizeof(gp.ownerAlg); |
| 358 s_reservedSize[NV_ENDORSEMENT_ALG] = sizeof(gp.endorsementAlg); |
| 359 s_reservedSize[NV_LOCKOUT_ALG] = sizeof(gp.lockoutAlg); |
| 360 s_reservedSize[NV_OWNER_POLICY] = sizeof(gp.ownerPolicy); |
| 361 s_reservedSize[NV_ENDORSEMENT_POLICY] = sizeof(gp.endorsementPolicy); |
| 362 s_reservedSize[NV_LOCKOUT_POLICY] = sizeof(gp.lockoutPolicy); |
| 363 s_reservedSize[NV_OWNER_AUTH] = sizeof(gp.ownerAuth); |
| 364 s_reservedSize[NV_ENDORSEMENT_AUTH] = sizeof(gp.endorsementAuth); |
| 365 s_reservedSize[NV_LOCKOUT_AUTH] = sizeof(gp.lockoutAuth); |
| 366 s_reservedSize[NV_EP_SEED] = sizeof(gp.EPSeed); |
| 367 s_reservedSize[NV_SP_SEED] = sizeof(gp.SPSeed); |
| 368 s_reservedSize[NV_PP_SEED] = sizeof(gp.PPSeed); |
| 369 s_reservedSize[NV_PH_PROOF] = sizeof(gp.phProof); |
| 370 s_reservedSize[NV_SH_PROOF] = sizeof(gp.shProof); |
| 371 s_reservedSize[NV_EH_PROOF] = sizeof(gp.ehProof); |
| 372 s_reservedSize[NV_TOTAL_RESET_COUNT] = sizeof(gp.totalResetCount); |
| 373 s_reservedSize[NV_RESET_COUNT] = sizeof(gp.resetCount); |
| 374 s_reservedSize[NV_PCR_POLICIES] = sizeof(gp.pcrPolicies); |
| 375 s_reservedSize[NV_PCR_ALLOCATED] = sizeof(gp.pcrAllocated); |
| 376 s_reservedSize[NV_PP_LIST] = sizeof(gp.ppList); |
| 377 s_reservedSize[NV_FAILED_TRIES] = sizeof(gp.failedTries); |
| 378 s_reservedSize[NV_MAX_TRIES] = sizeof(gp.maxTries); |
| 379 s_reservedSize[NV_RECOVERY_TIME] = sizeof(gp.recoveryTime); |
| 380 s_reservedSize[NV_LOCKOUT_RECOVERY] = sizeof(gp.lockoutRecovery); |
| 381 s_reservedSize[NV_LOCKOUT_AUTH_ENABLED] = sizeof(gp.lockOutAuthEnabled); |
| 382 s_reservedSize[NV_ORDERLY] = sizeof(gp.orderlyState); |
| 383 s_reservedSize[NV_AUDIT_COMMANDS] = sizeof(gp.auditComands); |
| 384 s_reservedSize[NV_AUDIT_HASH_ALG] = sizeof(gp.auditHashAlg); |
| 385 s_reservedSize[NV_AUDIT_COUNTER] = sizeof(gp.auditCounter); |
| 386 s_reservedSize[NV_ALGORITHM_SET] = sizeof(gp.algorithmSet); |
| 387 s_reservedSize[NV_FIRMWARE_V1] = sizeof(gp.firmwareV1); |
| 388 s_reservedSize[NV_FIRMWARE_V2] = sizeof(gp.firmwareV2); |
| 389 s_reservedSize[NV_ORDERLY_DATA] = sizeof(go); |
| 390 s_reservedSize[NV_STATE_CLEAR] = sizeof(gc); |
| 391 s_reservedSize[NV_STATE_RESET] = sizeof(gr); |
| 392 |
| 393 // Initialize reserved data address. In this implementation, reserved data |
| 394 // is stored at the start of NV memory |
| 395 reservedAddr = 0; |
| 396 for(i = 0; i < NV_RESERVE_LAST; i++) |
| 397 { |
| 398 s_reservedAddr[i] = reservedAddr; |
| 399 reservedAddr += s_reservedSize[i]; |
| 400 } |
| 401 |
| 402 // Initialize auxiliary variable space for index/evict implementation. |
| 403 // Auxiliary variables are stored after reserved data area |
| 404 // RAM index copy starts at the beginning |
| 405 s_ramIndexSizeAddr = reservedAddr; |
| |
| Page 128 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 406 s_ramIndexAddr = s_ramIndexSizeAddr + sizeof(UINT32); |
| 407 |
| 408 // Maximum counter value |
| 409 s_maxCountAddr = s_ramIndexAddr + RAM_INDEX_SPACE; |
| 410 |
| 411 // dynamic memory start |
| 412 s_evictNvStart = s_maxCountAddr + sizeof(UINT64); |
| 413 |
| 414 // dynamic memory ends at the end of NV memory |
| 415 s_evictNvEnd = NV_MEMORY_SIZE; |
| 416 |
| 417 return; |
| 418 } |
| |
| |
| 8.4.6.2 NvInit() |
| |
| This function initializes the NV system at pre-install time. |
| This function should only be called in a manufacturing environment or in a simulation. |
| The layout of NV memory space is an implementation choice. |
| |
| 419 void |
| 420 NvInit( |
| 421 void |
| 422 ) |
| 423 { |
| 424 UINT32 nullPointer = 0; |
| 425 UINT64 zeroCounter = 0; |
| 426 |
| 427 // Initialize static variables |
| 428 NvInitStatic(); |
| 429 |
| 430 // Initialize RAM index space as unused |
| 431 _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &nullPointer); |
| 432 |
| 433 // Initialize max counter value to 0 |
| 434 _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &zeroCounter); |
| 435 |
| 436 // Initialize the next offset of the first entry in evict/index list to 0 |
| 437 _plat__NvMemoryWrite(s_evictNvStart, sizeof(TPM_HANDLE), &nullPointer); |
| 438 |
| 439 return; |
| 440 |
| 441 } |
| |
| |
| 8.4.6.3 NvReadReserved() |
| |
| This function is used to move reserved data from NV memory to RAM. |
| |
| 442 void |
| 443 NvReadReserved( |
| 444 NV_RESERVE type, // IN: type of reserved data |
| 445 void *buffer // OUT: buffer receives the data. |
| 446 ) |
| 447 { |
| 448 // Input type should be valid |
| 449 pAssert(type >= 0 && type < NV_RESERVE_LAST); |
| 450 |
| 451 _plat__NvMemoryRead(s_reservedAddr[type], s_reservedSize[type], buffer); |
| 452 return; |
| 453 } |
| |
| |
| |
| Family "2.0" TCG Published Page 129 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.4.6.4 NvWriteReserved() |
| |
| This function is used to post a reserved data for writing to NV memory. Before the TPM completes the |
| operation, the value will be written. |
| |
| 454 void |
| 455 NvWriteReserved( |
| 456 NV_RESERVE type, // IN: type of reserved data |
| 457 void *buffer // IN: data buffer |
| 458 ) |
| 459 { |
| 460 // Input type should be valid |
| 461 pAssert(type >= 0 && type < NV_RESERVE_LAST); |
| 462 |
| 463 _plat__NvMemoryWrite(s_reservedAddr[type], s_reservedSize[type], buffer); |
| 464 |
| 465 // Set the flag that a NV write happens |
| 466 g_updateNV = TRUE; |
| 467 return; |
| 468 } |
| |
| |
| 8.4.6.5 NvReadPersistent() |
| |
| This function reads persistent data to the RAM copy of the gp structure. |
| |
| 469 void |
| 470 NvReadPersistent( |
| 471 void |
| 472 ) |
| 473 { |
| 474 // Hierarchy persistent data |
| 475 NvReadReserved(NV_DISABLE_CLEAR, &gp.disableClear); |
| 476 NvReadReserved(NV_OWNER_ALG, &gp.ownerAlg); |
| 477 NvReadReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg); |
| 478 NvReadReserved(NV_LOCKOUT_ALG, &gp.lockoutAlg); |
| 479 NvReadReserved(NV_OWNER_POLICY, &gp.ownerPolicy); |
| 480 NvReadReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy); |
| 481 NvReadReserved(NV_LOCKOUT_POLICY, &gp.lockoutPolicy); |
| 482 NvReadReserved(NV_OWNER_AUTH, &gp.ownerAuth); |
| 483 NvReadReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth); |
| 484 NvReadReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth); |
| 485 NvReadReserved(NV_EP_SEED, &gp.EPSeed); |
| 486 NvReadReserved(NV_SP_SEED, &gp.SPSeed); |
| 487 NvReadReserved(NV_PP_SEED, &gp.PPSeed); |
| 488 NvReadReserved(NV_PH_PROOF, &gp.phProof); |
| 489 NvReadReserved(NV_SH_PROOF, &gp.shProof); |
| 490 NvReadReserved(NV_EH_PROOF, &gp.ehProof); |
| 491 |
| 492 // Time persistent data |
| 493 NvReadReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount); |
| 494 NvReadReserved(NV_RESET_COUNT, &gp.resetCount); |
| 495 |
| 496 // PCR persistent data |
| 497 NvReadReserved(NV_PCR_POLICIES, &gp.pcrPolicies); |
| 498 NvReadReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated); |
| 499 |
| 500 // Physical Presence persistent data |
| 501 NvReadReserved(NV_PP_LIST, &gp.ppList); |
| 502 |
| 503 // Dictionary attack values persistent data |
| 504 NvReadReserved(NV_FAILED_TRIES, &gp.failedTries); |
| 505 NvReadReserved(NV_MAX_TRIES, &gp.maxTries); |
| 506 NvReadReserved(NV_RECOVERY_TIME, &gp.recoveryTime); |
| |
| |
| Page 130 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 507 NvReadReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery); |
| 508 NvReadReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); |
| 509 |
| 510 // Orderly State persistent data |
| 511 NvReadReserved(NV_ORDERLY, &gp.orderlyState); |
| 512 |
| 513 // Command audit values persistent data |
| 514 NvReadReserved(NV_AUDIT_COMMANDS, &gp.auditComands); |
| 515 NvReadReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg); |
| 516 NvReadReserved(NV_AUDIT_COUNTER, &gp.auditCounter); |
| 517 |
| 518 // Algorithm selection persistent data |
| 519 NvReadReserved(NV_ALGORITHM_SET, &gp.algorithmSet); |
| 520 |
| 521 // Firmware version persistent data |
| 522 NvReadReserved(NV_FIRMWARE_V1, &gp.firmwareV1); |
| 523 NvReadReserved(NV_FIRMWARE_V2, &gp.firmwareV2); |
| 524 |
| 525 return; |
| 526 } |
| |
| |
| 8.4.6.6 NvIsPlatformPersistentHandle() |
| |
| This function indicates if a handle references a persistent object in the range belonging to the platform. |
| |
| Return Value Meaning |
| |
| TRUE handle references a platform persistent object |
| FALSE handle does not reference platform persistent object and may |
| reference an owner persistent object either |
| |
| 527 BOOL |
| 528 NvIsPlatformPersistentHandle( |
| 529 TPM_HANDLE handle // IN: handle |
| 530 ) |
| 531 { |
| 532 return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST); |
| 533 } |
| |
| |
| 8.4.6.7 NvIsOwnerPersistentHandle() |
| |
| This function indicates if a handle references a persistent object in the range belonging to the owner. |
| |
| Return Value Meaning |
| |
| TRUE handle is owner persistent handle |
| FALSE handle is not owner persistent handle and may not be a persistent |
| handle at all |
| |
| 534 BOOL |
| 535 NvIsOwnerPersistentHandle( |
| 536 TPM_HANDLE handle // IN: handle |
| 537 ) |
| 538 { |
| 539 return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT); |
| 540 } |
| |
| |
| 8.4.6.8 NvNextIndex() |
| |
| This function returns the offset in NV of the next NV Index entry. A value of 0 indicates the end of the list. |
| Family "2.0" TCG Published Page 131 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 541 static UINT32 |
| 542 NvNextIndex( |
| 543 NV_ITER *iter |
| 544 ) |
| 545 { |
| 546 UINT32 addr; |
| 547 TPM_HANDLE handle; |
| 548 |
| 549 while((addr = NvNext(iter)) != 0) |
| 550 { |
| 551 // Read handle |
| 552 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle); |
| 553 if(HandleGetType(handle) == TPM_HT_NV_INDEX) |
| 554 return addr; |
| 555 } |
| 556 |
| 557 pAssert(addr == 0); |
| 558 return addr; |
| 559 } |
| |
| |
| 8.4.6.9 NvNextEvict() |
| |
| This function returns the offset in NV of the next evict object entry. A value of 0 indicates the end of the |
| list. |
| |
| 560 static UINT32 |
| 561 NvNextEvict( |
| 562 NV_ITER *iter |
| 563 ) |
| 564 { |
| 565 UINT32 addr; |
| 566 TPM_HANDLE handle; |
| 567 |
| 568 while((addr = NvNext(iter)) != 0) |
| 569 { |
| 570 // Read handle |
| 571 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle); |
| 572 if(HandleGetType(handle) == TPM_HT_PERSISTENT) |
| 573 return addr; |
| 574 } |
| 575 |
| 576 pAssert(addr == 0); |
| 577 return addr; |
| 578 } |
| |
| |
| 8.4.6.10 NvFindHandle() |
| |
| this function returns the offset in NV memory of the entity associated with the input handle. A value of |
| zero indicates that handle does not exist reference an existing persistent object or defined NV Index. |
| |
| 579 static UINT32 |
| 580 NvFindHandle( |
| 581 TPM_HANDLE handle |
| 582 ) |
| 583 { |
| 584 UINT32 addr; |
| 585 NV_ITER iter = NV_ITER_INIT; |
| 586 |
| 587 while((addr = NvNext(&iter)) != 0) |
| 588 { |
| 589 TPM_HANDLE entityHandle; |
| 590 // Read handle |
| |
| |
| Page 132 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 591 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle); |
| 592 if(entityHandle == handle) |
| 593 return addr; |
| 594 } |
| 595 |
| 596 pAssert(addr == 0); |
| 597 return addr; |
| 598 } |
| |
| |
| 8.4.6.11 NvPowerOn() |
| |
| This function is called at _TPM_Init() to initialize the NV environment. |
| |
| Return Value Meaning |
| |
| TRUE all NV was initialized |
| FALSE the NV containing saved state had an error and |
| TPM2_Startup(CLEAR) is required |
| |
| 599 BOOL |
| 600 NvPowerOn( |
| 601 void |
| 602 ) |
| 603 { |
| 604 int nvError = 0; |
| 605 // If power was lost, need to re-establish the RAM data that is loaded from |
| 606 // NV and initialize the static variables |
| 607 if(_plat__WasPowerLost(TRUE)) |
| 608 { |
| 609 if((nvError = _plat__NVEnable(0)) < 0) |
| 610 FAIL(FATAL_ERROR_NV_UNRECOVERABLE); |
| 611 |
| 612 NvInitStatic(); |
| 613 } |
| 614 |
| 615 return nvError == 0; |
| 616 } |
| |
| |
| 8.4.6.12 NvStateSave() |
| |
| This function is used to cause the memory containing the RAM backed NV Indices to be written to NV. |
| |
| 617 void |
| 618 NvStateSave( |
| 619 void |
| 620 ) |
| 621 { |
| 622 // Write RAM backed NV Index info to NV |
| 623 // No need to save s_ramIndexSize because we save it to NV whenever it is |
| 624 // updated. |
| 625 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); |
| 626 |
| 627 // Set the flag so that an NV write happens before the command completes. |
| 628 g_updateNV = TRUE; |
| 629 |
| 630 return; |
| 631 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 133 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.4.6.13 NvEntityStartup() |
| |
| This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is |
| taken. If the startup is a TPM Reset or a TPM Restart, then this function will: |
| a) clear read/write lock; |
| b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and |
| c) set the lower bits in orderly counters to 1 for a non-orderly startup |
| It is a prerequisite that NV be available for writing before this function is called. |
| |
| 632 void |
| 633 NvEntityStartup( |
| 634 STARTUP_TYPE type // IN: start up type |
| 635 ) |
| 636 { |
| 637 NV_ITER iter = NV_ITER_INIT; |
| 638 UINT32 currentAddr; // offset points to the current entity |
| 639 |
| 640 // Restore RAM index data |
| 641 _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize); |
| 642 _plat__NvMemoryRead(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); |
| 643 |
| 644 // If recovering from state save, do nothing |
| 645 if(type == SU_RESUME) |
| 646 return; |
| 647 |
| 648 // Iterate all the NV Index to clear the locks |
| 649 while((currentAddr = NvNextIndex(&iter)) != 0) |
| 650 { |
| 651 NV_INDEX nvIndex; |
| 652 UINT32 indexAddr; // NV address points to index info |
| 653 TPMA_NV attributes; |
| 654 |
| 655 indexAddr = currentAddr + sizeof(TPM_HANDLE); |
| 656 |
| 657 // Read NV Index info structure |
| 658 _plat__NvMemoryRead(indexAddr, sizeof(NV_INDEX), &nvIndex); |
| 659 attributes = nvIndex.publicArea.attributes; |
| 660 |
| 661 // Clear read/write lock |
| 662 if(attributes.TPMA_NV_READLOCKED == SET) |
| 663 attributes.TPMA_NV_READLOCKED = CLEAR; |
| 664 |
| 665 if( attributes.TPMA_NV_WRITELOCKED == SET |
| 666 && ( attributes.TPMA_NV_WRITTEN == CLEAR |
| 667 || attributes.TPMA_NV_WRITEDEFINE == CLEAR |
| 668 ) |
| 669 ) |
| 670 attributes.TPMA_NV_WRITELOCKED = CLEAR; |
| 671 |
| 672 // Reset NV data for TPMA_NV_CLEAR_STCLEAR |
| 673 if(attributes.TPMA_NV_CLEAR_STCLEAR == SET) |
| 674 { |
| 675 attributes.TPMA_NV_WRITTEN = CLEAR; |
| 676 attributes.TPMA_NV_WRITELOCKED = CLEAR; |
| 677 } |
| 678 |
| 679 // Reset NV data for orderly values that are not counters |
| 680 // NOTE: The function has already exited on a TPM Resume, so the only |
| 681 // things being processed are TPM Restart and TPM Reset |
| 682 if( type == SU_RESET |
| 683 && attributes.TPMA_NV_ORDERLY == SET |
| 684 && attributes.TPMA_NV_COUNTER == CLEAR |
| |
| Page 134 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 685 ) |
| 686 attributes.TPMA_NV_WRITTEN = CLEAR; |
| 687 |
| 688 // Write NV Index info back if it has changed |
| 689 if(*((UINT32 *)&attributes) != *((UINT32 *)&nvIndex.publicArea.attributes)) |
| 690 { |
| 691 nvIndex.publicArea.attributes = attributes; |
| 692 _plat__NvMemoryWrite(indexAddr, sizeof(NV_INDEX), &nvIndex); |
| 693 |
| 694 // Set the flag that a NV write happens |
| 695 g_updateNV = TRUE; |
| 696 } |
| 697 // Set the lower bits in an orderly counter to 1 for a non-orderly startup |
| 698 if( g_prevOrderlyState == SHUTDOWN_NONE |
| 699 && attributes.TPMA_NV_WRITTEN == SET) |
| 700 { |
| 701 if( attributes.TPMA_NV_ORDERLY == SET |
| 702 && attributes.TPMA_NV_COUNTER == SET) |
| 703 { |
| 704 TPMI_RH_NV_INDEX nvHandle; |
| 705 UINT64 counter; |
| 706 |
| 707 // Read NV handle |
| 708 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle); |
| 709 |
| 710 // Read the counter value saved to NV upon the last roll over. |
| 711 // Do not use RAM backed storage for this once. |
| 712 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = CLEAR; |
| 713 NvGetIntIndexData(nvHandle, &nvIndex, &counter); |
| 714 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = SET; |
| 715 |
| 716 // Set the lower bits of counter to 1's |
| 717 counter |= MAX_ORDERLY_COUNT; |
| 718 |
| 719 // Write back to RAM |
| 720 NvWriteIndexData(nvHandle, &nvIndex, 0, sizeof(counter), &counter); |
| 721 |
| 722 // No write to NV because an orderly shutdown will update the |
| 723 // counters. |
| 724 |
| 725 } |
| 726 } |
| 727 } |
| 728 |
| 729 return; |
| 730 |
| 731 } |
| |
| |
| 8.4.7 NV Access Functions |
| |
| 8.4.7.1 Introduction |
| |
| This set of functions provide accessing NV Index and persistent objects based using a handle for |
| reference to the entity. |
| |
| 8.4.7.2 NvIsUndefinedIndex() |
| |
| This function is used to verify that an NV Index is not defined. This is only used by |
| TPM2_NV_DefineSpace(). |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 135 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| TRUE the handle points to an existing NV Index |
| FALSE the handle points to a non-existent Index |
| |
| 732 BOOL |
| 733 NvIsUndefinedIndex( |
| 734 TPMI_RH_NV_INDEX handle // IN: handle |
| 735 ) |
| 736 { |
| 737 UINT32 entityAddr; // offset points to the entity |
| 738 |
| 739 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); |
| 740 |
| 741 // Find the address of index |
| 742 entityAddr = NvFindHandle(handle); |
| 743 |
| 744 // If handle is not found, return TPM_RC_SUCCESS |
| 745 if(entityAddr == 0) |
| 746 return TPM_RC_SUCCESS; |
| 747 |
| 748 // NV Index is defined |
| 749 return TPM_RC_NV_DEFINED; |
| 750 } |
| |
| |
| 8.4.7.3 NvIndexIsAccessible() |
| |
| This function validates that a handle references a defined NV Index and that the Index is currently |
| accessible. |
| |
| Error Returns Meaning |
| |
| TPM_RC_HANDLE the handle points to an undefined NV Index If shEnable is CLEAR, |
| this would include an index created using ownerAuth. If phEnableNV |
| is CLEAR, this would include and index created using platform auth |
| TPM_RC_NV_READLOCKED Index is present but locked for reading and command does not write |
| to the index |
| TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command writes to the |
| index |
| |
| 751 TPM_RC |
| 752 NvIndexIsAccessible( |
| 753 TPMI_RH_NV_INDEX handle, // IN: handle |
| 754 TPM_CC commandCode // IN: the command |
| 755 ) |
| 756 { |
| 757 UINT32 entityAddr; // offset points to the entity |
| 758 NV_INDEX nvIndex; // |
| 759 |
| 760 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); |
| 761 |
| 762 // Find the address of index |
| 763 entityAddr = NvFindHandle(handle); |
| 764 |
| 765 // If handle is not found, return TPM_RC_HANDLE |
| 766 if(entityAddr == 0) |
| 767 return TPM_RC_HANDLE; |
| 768 |
| 769 // Read NV Index info structure |
| 770 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), |
| 771 &nvIndex); |
| |
| Page 136 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 772 |
| 773 if(gc.shEnable == FALSE || gc.phEnableNV == FALSE) |
| 774 { |
| 775 // if shEnable is CLEAR, an ownerCreate NV Index should not be |
| 776 // indicated as present |
| 777 if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR) |
| 778 { |
| 779 if(gc.shEnable == FALSE) |
| 780 return TPM_RC_HANDLE; |
| 781 } |
| 782 // if phEnableNV is CLEAR, a platform created Index should not |
| 783 // be visible |
| 784 else if(gc.phEnableNV == FALSE) |
| 785 return TPM_RC_HANDLE; |
| 786 } |
| 787 |
| 788 // If the Index is write locked and this is an NV Write operation... |
| 789 if( nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED |
| 790 && IsWriteOperation(commandCode)) |
| 791 { |
| 792 // then return a locked indication unless the command is TPM2_NV_WriteLock |
| 793 if(commandCode != TPM_CC_NV_WriteLock) |
| 794 return TPM_RC_NV_LOCKED; |
| 795 return TPM_RC_SUCCESS; |
| 796 } |
| 797 // If the Index is read locked and this is an NV Read operation... |
| 798 if( nvIndex.publicArea.attributes.TPMA_NV_READLOCKED |
| 799 && IsReadOperation(commandCode)) |
| 800 { |
| 801 // then return a locked indication unless the command is TPM2_NV_ReadLock |
| 802 if(commandCode != TPM_CC_NV_ReadLock) |
| 803 return TPM_RC_NV_LOCKED; |
| 804 return TPM_RC_SUCCESS; |
| 805 } |
| 806 |
| 807 // NV Index is accessible |
| 808 return TPM_RC_SUCCESS; |
| 809 } |
| |
| |
| 8.4.7.4 NvIsUndefinedEvictHandle() |
| |
| This function indicates if a handle does not reference an existing persistent object. This function requires |
| that the handle be in the proper range for persistent objects. |
| |
| Return Value Meaning |
| |
| TRUE handle does not reference an existing persistent object |
| FALSE handle does reference an existing persistent object |
| |
| 810 static BOOL |
| 811 NvIsUndefinedEvictHandle( |
| 812 TPM_HANDLE handle // IN: handle |
| 813 ) |
| 814 { |
| 815 UINT32 entityAddr; // offset points to the entity |
| 816 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); |
| 817 |
| 818 // Find the address of evict object |
| 819 entityAddr = NvFindHandle(handle); |
| 820 |
| 821 // If handle is not found, return TRUE |
| 822 if(entityAddr == 0) |
| 823 return TRUE; |
| |
| Family "2.0" TCG Published Page 137 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 824 else |
| 825 return FALSE; |
| 826 } |
| |
| |
| 8.4.7.5 NvGetEvictObject() |
| |
| This function is used to dereference an evict object handle and get a pointer to the object. |
| |
| Error Returns Meaning |
| |
| TPM_RC_HANDLE the handle does not point to an existing persistent object |
| |
| 827 TPM_RC |
| 828 NvGetEvictObject( |
| 829 TPM_HANDLE handle, // IN: handle |
| 830 OBJECT *object // OUT: object data |
| 831 ) |
| 832 { |
| 833 UINT32 entityAddr; // offset points to the entity |
| 834 TPM_RC result = TPM_RC_SUCCESS; |
| 835 |
| 836 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); |
| 837 |
| 838 // Find the address of evict object |
| 839 entityAddr = NvFindHandle(handle); |
| 840 |
| 841 // If handle is not found, return an error |
| 842 if(entityAddr == 0) |
| 843 result = TPM_RC_HANDLE; |
| 844 else |
| 845 // Read evict object |
| 846 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), |
| 847 sizeof(OBJECT), |
| 848 object); |
| 849 |
| 850 // whether there is an error or not, make sure that the evict |
| 851 // status of the object is set so that the slot will get freed on exit |
| 852 object->attributes.evict = SET; |
| 853 |
| 854 return result; |
| 855 } |
| |
| |
| 8.4.7.6 NvGetIndexInfo() |
| |
| This function is used to retrieve the contents of an NV Index. |
| An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different |
| from the default used by the reference code, then this function would be changed to reformat the data into |
| the default format. |
| A prerequisite to calling this function is that the handle must be known to reference a defined NV Index. |
| |
| 856 void |
| 857 NvGetIndexInfo( |
| 858 TPMI_RH_NV_INDEX handle, // IN: handle |
| 859 NV_INDEX *nvIndex // OUT: NV index structure |
| 860 ) |
| 861 { |
| 862 UINT32 entityAddr; // offset points to the entity |
| 863 |
| 864 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); |
| 865 |
| 866 // Find the address of NV index |
| |
| Page 138 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 867 entityAddr = NvFindHandle(handle); |
| 868 pAssert(entityAddr != 0); |
| 869 |
| 870 // This implementation uses the default format so just |
| 871 // read the data in |
| 872 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), |
| 873 nvIndex); |
| 874 |
| 875 return; |
| 876 } |
| |
| |
| 8.4.7.7 NvInitialCounter() |
| |
| This function returns the value to be used when a counter index is initialized. It will scan the NV counters |
| and find the highest value in any active counter. It will use that value as the starting point. If there are no |
| active counters, it will use the value of the previous largest counter. |
| |
| 877 UINT64 |
| 878 NvInitialCounter( |
| 879 void |
| 880 ) |
| 881 { |
| 882 UINT64 maxCount; |
| 883 NV_ITER iter = NV_ITER_INIT; |
| 884 UINT32 currentAddr; |
| 885 |
| 886 // Read the maxCount value |
| 887 maxCount = NvReadMaxCount(); |
| 888 |
| 889 // Iterate all existing counters |
| 890 while((currentAddr = NvNextIndex(&iter)) != 0) |
| 891 { |
| 892 TPMI_RH_NV_INDEX nvHandle; |
| 893 NV_INDEX nvIndex; |
| 894 |
| 895 // Read NV handle |
| 896 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle); |
| 897 |
| 898 // Get NV Index |
| 899 NvGetIndexInfo(nvHandle, &nvIndex); |
| 900 if( nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET |
| 901 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) |
| 902 { |
| 903 UINT64 countValue; |
| 904 // Read counter value |
| 905 NvGetIntIndexData(nvHandle, &nvIndex, &countValue); |
| 906 if(countValue > maxCount) |
| 907 maxCount = countValue; |
| 908 } |
| 909 } |
| 910 // Initialize the new counter value to be maxCount + 1 |
| 911 // A counter is only initialized the first time it is written. The |
| 912 // way to write a counter is with TPM2_NV_INCREMENT(). Since the |
| 913 // "initial" value of a defined counter is the largest count value that |
| 914 // may have existed in this index previously, then the first use would |
| 915 // add one to that value. |
| 916 return maxCount; |
| 917 } |
| |
| |
| 8.4.7.8 NvGetIndexData() |
| |
| This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since |
| counter values are kept in native format, they are converted to canonical form before being returned. |
| Family "2.0" TCG Published Page 139 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| This function requires that the NV Index be defined, and that the required data is within the data range. It |
| also requires that TPMA_NV_WRITTEN of the Index is SET. |
| |
| 918 void |
| 919 NvGetIndexData( |
| 920 TPMI_RH_NV_INDEX handle, // IN: handle |
| 921 NV_INDEX *nvIndex, // IN: RAM image of index header |
| 922 UINT32 offset, // IN: offset of NV data |
| 923 UINT16 size, // IN: size of NV data |
| 924 void *data // OUT: data buffer |
| 925 ) |
| 926 { |
| 927 |
| 928 pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET); |
| 929 |
| 930 if( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET |
| 931 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET) |
| 932 { |
| 933 // Read bit or counter data in canonical form |
| 934 UINT64 dataInInt; |
| 935 NvGetIntIndexData(handle, nvIndex, &dataInInt); |
| 936 UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data); |
| 937 } |
| 938 else |
| 939 { |
| 940 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) |
| 941 { |
| 942 UINT32 ramAddr; |
| 943 |
| 944 // Get data from RAM buffer |
| 945 ramAddr = NvGetRAMIndexOffset(handle); |
| 946 MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size); |
| 947 } |
| 948 else |
| 949 { |
| 950 UINT32 entityAddr; |
| 951 entityAddr = NvFindHandle(handle); |
| 952 // Get data from NV |
| 953 // Skip NV Index info, read data buffer |
| 954 entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset; |
| 955 // Read the data |
| 956 _plat__NvMemoryRead(entityAddr, size, data); |
| 957 } |
| 958 } |
| 959 return; |
| 960 } |
| |
| |
| 8.4.7.9 NvGetIntIndexData() |
| |
| Get data in integer format of a bit or counter NV Index. |
| This function requires that the NV Index is defined and that the NV Index previously has been written. |
| |
| 961 void |
| 962 NvGetIntIndexData( |
| 963 TPMI_RH_NV_INDEX handle, // IN: handle |
| 964 NV_INDEX *nvIndex, // IN: RAM image of NV Index header |
| 965 UINT64 *data // IN: UINT64 pointer for counter or bit |
| 966 ) |
| 967 { |
| 968 // Validate that index has been written and is the right type |
| 969 pAssert( nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET |
| 970 && ( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET |
| 971 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET |
| |
| Page 140 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 972 ) |
| 973 ); |
| 974 |
| 975 // bit and counter value is store in native format for TPM CPU. So we directly |
| 976 // copy the contents of NV to output data buffer |
| 977 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) |
| 978 { |
| 979 UINT32 ramAddr; |
| 980 |
| 981 // Get data from RAM buffer |
| 982 ramAddr = NvGetRAMIndexOffset(handle); |
| 983 MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data)); |
| 984 } |
| 985 else |
| 986 { |
| 987 UINT32 entityAddr; |
| 988 entityAddr = NvFindHandle(handle); |
| 989 |
| 990 // Get data from NV |
| 991 // Skip NV Index info, read data buffer |
| 992 _plat__NvMemoryRead( |
| 993 entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX), |
| 994 sizeof(UINT64), data); |
| 995 } |
| 996 |
| 997 return; |
| 998 } |
| |
| |
| 8.4.7.10 NvWriteIndexInfo() |
| |
| This function is called to queue the write of NV Index data to persistent memory. |
| This function requires that NV Index is defined. |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_RATE NV is rate limiting so retry |
| TPM_RC_NV_UNAVAILABLE NV is not available |
| |
| 999 TPM_RC |
| 1000 NvWriteIndexInfo( |
| 1001 TPMI_RH_NV_INDEX handle, // IN: handle |
| 1002 NV_INDEX *nvIndex // IN: NV Index info to be written |
| 1003 ) |
| 1004 { |
| 1005 UINT32 entryAddr; |
| 1006 TPM_RC result; |
| 1007 |
| 1008 // Get the starting offset for the index in the RAM image of NV |
| 1009 entryAddr = NvFindHandle(handle); |
| 1010 pAssert(entryAddr != 0); |
| 1011 |
| 1012 // Step over the link value |
| 1013 entryAddr = entryAddr + sizeof(TPM_HANDLE); |
| 1014 |
| 1015 // If the index data is actually changed, then a write to NV is required |
| 1016 if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex)) |
| 1017 { |
| 1018 // Make sure that NV is available |
| 1019 result = NvIsAvailable(); |
| 1020 if(result != TPM_RC_SUCCESS) |
| 1021 return result; |
| 1022 _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex); |
| 1023 g_updateNV = TRUE; |
| |
| Family "2.0" TCG Published Page 141 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1024 } |
| 1025 return TPM_RC_SUCCESS; |
| 1026 } |
| |
| |
| 8.4.7.11 NvWriteIndexData() |
| |
| This function is used to write NV index data. |
| This function requires that the NV Index is defined, and the data is within the defined data range for the |
| index. |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_RATE NV is rate limiting so retry |
| TPM_RC_NV_UNAVAILABLE NV is not available |
| |
| 1027 TPM_RC |
| 1028 NvWriteIndexData( |
| 1029 TPMI_RH_NV_INDEX handle, // IN: handle |
| 1030 NV_INDEX *nvIndex, // IN: RAM copy of NV Index |
| 1031 UINT32 offset, // IN: offset of NV data |
| 1032 UINT32 size, // IN: size of NV data |
| 1033 void *data // OUT: data buffer |
| 1034 ) |
| 1035 { |
| 1036 TPM_RC result; |
| 1037 // Validate that write falls within range of the index |
| 1038 pAssert(nvIndex->publicArea.dataSize >= offset + size); |
| 1039 |
| 1040 // Update TPMA_NV_WRITTEN bit if necessary |
| 1041 if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR) |
| 1042 { |
| 1043 nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET; |
| 1044 result = NvWriteIndexInfo(handle, nvIndex); |
| 1045 if(result != TPM_RC_SUCCESS) |
| 1046 return result; |
| 1047 } |
| 1048 |
| 1049 // Check to see if process for an orderly index is required. |
| 1050 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) |
| 1051 { |
| 1052 UINT32 ramAddr; |
| 1053 |
| 1054 // Write data to RAM buffer |
| 1055 ramAddr = NvGetRAMIndexOffset(handle); |
| 1056 MemoryCopy(s_ramIndex + ramAddr + offset, data, size, |
| 1057 sizeof(s_ramIndex) - ramAddr - offset); |
| 1058 |
| 1059 // NV update does not happen for orderly index. Have |
| 1060 // to clear orderlyState to reflect that we have changed the |
| 1061 // NV and an orderly shutdown is required. Only going to do this if we |
| 1062 // are not processing a counter that has just rolled over |
| 1063 if(g_updateNV == FALSE) |
| 1064 g_clearOrderly = TRUE; |
| 1065 } |
| 1066 // Need to process this part if the Index isn't orderly or if it is |
| 1067 // an orderly counter that just rolled over. |
| 1068 if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR) |
| 1069 { |
| 1070 // Processing for an index with TPMA_NV_ORDERLY CLEAR |
| 1071 UINT32 entryAddr = NvFindHandle(handle); |
| 1072 |
| 1073 pAssert(entryAddr != 0); |
| |
| |
| Page 142 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1074 |
| 1075 // Offset into the index to the first byte of the data to be written |
| 1076 entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset; |
| 1077 |
| 1078 // If the data is actually changed, then a write to NV is required |
| 1079 if(_plat__NvIsDifferent(entryAddr, size, data)) |
| 1080 { |
| 1081 // Make sure that NV is available |
| 1082 result = NvIsAvailable(); |
| 1083 if(result != TPM_RC_SUCCESS) |
| 1084 return result; |
| 1085 _plat__NvMemoryWrite(entryAddr, size, data); |
| 1086 g_updateNV = TRUE; |
| 1087 } |
| 1088 } |
| 1089 return TPM_RC_SUCCESS; |
| 1090 } |
| |
| |
| 8.4.7.12 NvGetName() |
| |
| This function is used to compute the Name of an NV Index. |
| The name buffer receives the bytes of the Name and the return value is the number of octets in the |
| Name. |
| This function requires that the NV Index is defined. |
| |
| 1091 UINT16 |
| 1092 NvGetName( |
| 1093 TPMI_RH_NV_INDEX handle, // IN: handle of the index |
| 1094 NAME *name // OUT: name of the index |
| 1095 ) |
| 1096 { |
| 1097 UINT16 dataSize, digestSize; |
| 1098 NV_INDEX nvIndex; |
| 1099 BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)]; |
| 1100 BYTE *buffer; |
| 1101 HASH_STATE hashState; |
| 1102 |
| 1103 // Get NV public info |
| 1104 NvGetIndexInfo(handle, &nvIndex); |
| 1105 |
| 1106 // Marshal public area |
| 1107 buffer = marshalBuffer; |
| 1108 dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, NULL); |
| 1109 |
| 1110 // hash public area |
| 1111 digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState); |
| 1112 CryptUpdateDigest(&hashState, dataSize, marshalBuffer); |
| 1113 |
| 1114 // Complete digest leaving room for the nameAlg |
| 1115 CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]); |
| 1116 |
| 1117 // Include the nameAlg |
| 1118 UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name); |
| 1119 return digestSize + 2; |
| 1120 } |
| |
| |
| 8.4.7.13 NvDefineIndex() |
| |
| This function is used to assign NV memory to an NV Index. |
| |
| |
| |
| Family "2.0" TCG Published Page 143 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_SPACE insufficient NV space |
| |
| 1121 TPM_RC |
| 1122 NvDefineIndex( |
| 1123 TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. |
| 1124 TPM2B_AUTH *authValue // IN: The initial authorization value |
| 1125 ) |
| 1126 { |
| 1127 // The buffer to be written to NV memory |
| 1128 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)]; |
| 1129 |
| 1130 NV_INDEX *nvIndex; // a pointer to the NV_INDEX data in |
| 1131 // nvBuffer |
| 1132 UINT16 entrySize; // size of entry |
| 1133 |
| 1134 entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize; |
| 1135 |
| 1136 // Check if we have enough space to create the NV Index |
| 1137 // In this implementation, the only resource limitation is the available NV |
| 1138 // space. Other implementation may have other limitation on counter or on |
| 1139 // NV slot |
| 1140 if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE; |
| 1141 |
| 1142 // if the index to be defined is RAM backed, check RAM space availability |
| 1143 // as well |
| 1144 if(publicArea->attributes.TPMA_NV_ORDERLY == SET |
| 1145 && !NvTestRAMSpace(publicArea->dataSize)) |
| 1146 return TPM_RC_NV_SPACE; |
| 1147 |
| 1148 // Copy input value to nvBuffer |
| 1149 // Copy handle |
| 1150 * (TPM_HANDLE *) nvBuffer = publicArea->nvIndex; |
| 1151 |
| 1152 // Copy NV_INDEX |
| 1153 nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE)); |
| 1154 nvIndex->publicArea = *publicArea; |
| 1155 nvIndex->authValue = *authValue; |
| 1156 |
| 1157 // Add index to NV memory |
| 1158 NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer); |
| 1159 |
| 1160 // If the data of NV Index is RAM backed, add the data area in RAM as well |
| 1161 if(publicArea->attributes.TPMA_NV_ORDERLY == SET) |
| 1162 NvAddRAM(publicArea->nvIndex, publicArea->dataSize); |
| 1163 |
| 1164 return TPM_RC_SUCCESS; |
| 1165 } |
| |
| |
| 8.4.7.14 NvAddEvictObject() |
| |
| This function is used to assign NV memory to a persistent object. |
| |
| Error Returns Meaning |
| |
| TPM_RC_NV_HANDLE the requested handle is already in use |
| TPM_RC_NV_SPACE insufficient NV space |
| |
| 1166 TPM_RC |
| 1167 NvAddEvictObject( |
| 1168 TPMI_DH_OBJECT evictHandle, // IN: new evict handle |
| |
| |
| Page 144 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1169 OBJECT *object // IN: object to be added |
| 1170 ) |
| 1171 { |
| 1172 // The buffer to be written to NV memory |
| 1173 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)]; |
| 1174 |
| 1175 OBJECT *nvObject; // a pointer to the OBJECT data in |
| 1176 // nvBuffer |
| 1177 UINT16 entrySize; // size of entry |
| 1178 |
| 1179 // evict handle type should match the object hierarchy |
| 1180 pAssert( ( NvIsPlatformPersistentHandle(evictHandle) |
| 1181 && object->attributes.ppsHierarchy == SET) |
| 1182 || ( NvIsOwnerPersistentHandle(evictHandle) |
| 1183 && ( object->attributes.spsHierarchy == SET |
| 1184 || object->attributes.epsHierarchy == SET))); |
| 1185 |
| 1186 // An evict needs 4 bytes of handle + sizeof OBJECT |
| 1187 entrySize = sizeof(TPM_HANDLE) + sizeof(OBJECT); |
| 1188 |
| 1189 // Check if we have enough space to add the evict object |
| 1190 // An evict object needs 8 bytes in index table + sizeof OBJECT |
| 1191 // In this implementation, the only resource limitation is the available NV |
| 1192 // space. Other implementation may have other limitation on evict object |
| 1193 // handle space |
| 1194 if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE; |
| 1195 |
| 1196 // Allocate a new evict handle |
| 1197 if(!NvIsUndefinedEvictHandle(evictHandle)) |
| 1198 return TPM_RC_NV_DEFINED; |
| 1199 |
| 1200 // Copy evict object to nvBuffer |
| 1201 // Copy handle |
| 1202 * (TPM_HANDLE *) nvBuffer = evictHandle; |
| 1203 |
| 1204 // Copy OBJECT |
| 1205 nvObject = (OBJECT *) (nvBuffer + sizeof(TPM_HANDLE)); |
| 1206 *nvObject = *object; |
| 1207 |
| 1208 // Set evict attribute and handle |
| 1209 nvObject->attributes.evict = SET; |
| 1210 nvObject->evictHandle = evictHandle; |
| 1211 |
| 1212 // Add evict to NV memory |
| 1213 NvAdd(entrySize, entrySize, nvBuffer); |
| 1214 |
| 1215 return TPM_RC_SUCCESS; |
| 1216 |
| 1217 } |
| |
| |
| 8.4.7.15 NvDeleteEntity() |
| |
| This function will delete a NV Index or an evict object. |
| This function requires that the index/evict object has been defined. |
| |
| 1218 void |
| 1219 NvDeleteEntity( |
| 1220 TPM_HANDLE handle // IN: handle of entity to be deleted |
| 1221 ) |
| 1222 { |
| 1223 UINT32 entityAddr; // pointer to entity |
| 1224 |
| 1225 entityAddr = NvFindHandle(handle); |
| 1226 pAssert(entityAddr != 0); |
| |
| Family "2.0" TCG Published Page 145 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1227 |
| 1228 if(HandleGetType(handle) == TPM_HT_NV_INDEX) |
| 1229 { |
| 1230 NV_INDEX nvIndex; |
| 1231 |
| 1232 // Read the NV Index info |
| 1233 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), |
| 1234 &nvIndex); |
| 1235 |
| 1236 // If the entity to be deleted is a counter with the maximum counter |
| 1237 // value, record it in NV memory |
| 1238 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET |
| 1239 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) |
| 1240 { |
| 1241 UINT64 countValue; |
| 1242 UINT64 maxCount; |
| 1243 NvGetIntIndexData(handle, &nvIndex, &countValue); |
| 1244 maxCount = NvReadMaxCount(); |
| 1245 if(countValue > maxCount) |
| 1246 NvWriteMaxCount(countValue); |
| 1247 } |
| 1248 // If the NV Index is RAM back, delete the RAM data as well |
| 1249 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET) |
| 1250 NvDeleteRAM(handle); |
| 1251 } |
| 1252 NvDelete(entityAddr); |
| 1253 |
| 1254 return; |
| 1255 |
| 1256 } |
| |
| |
| 8.4.7.16 NvFlushHierarchy() |
| |
| This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected, |
| the function will also delete any NV Index define using ownerAuth. |
| |
| 1257 void |
| 1258 NvFlushHierarchy( |
| 1259 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. |
| 1260 ) |
| 1261 { |
| 1262 NV_ITER iter = NV_ITER_INIT; |
| 1263 UINT32 currentAddr; |
| 1264 |
| 1265 while((currentAddr = NvNext(&iter)) != 0) |
| 1266 { |
| 1267 TPM_HANDLE entityHandle; |
| 1268 |
| 1269 // Read handle information. |
| 1270 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); |
| 1271 |
| 1272 if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX) |
| 1273 { |
| 1274 // Handle NV Index |
| 1275 NV_INDEX nvIndex; |
| 1276 |
| 1277 // If flush endorsement or platform hierarchy, no NV Index would be |
| 1278 // flushed |
| 1279 if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM) |
| 1280 continue; |
| 1281 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), |
| 1282 sizeof(NV_INDEX), &nvIndex); |
| 1283 |
| 1284 // For storage hierarchy, flush OwnerCreated index |
| |
| Page 146 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1285 if( nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR) |
| 1286 { |
| 1287 // Delete the NV Index |
| 1288 NvDelete(currentAddr); |
| 1289 |
| 1290 // Re-iterate from beginning after a delete |
| 1291 iter = NV_ITER_INIT; |
| 1292 |
| 1293 // If the NV Index is RAM back, delete the RAM data as well |
| 1294 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET) |
| 1295 NvDeleteRAM(entityHandle); |
| 1296 } |
| 1297 } |
| 1298 else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT) |
| 1299 { |
| 1300 OBJECT object; |
| 1301 |
| 1302 // Get evict object |
| 1303 NvGetEvictObject(entityHandle, &object); |
| 1304 |
| 1305 // If the evict object belongs to the hierarchy to be flushed |
| 1306 if( ( hierarchy == TPM_RH_PLATFORM |
| 1307 && object.attributes.ppsHierarchy == SET) |
| 1308 || ( hierarchy == TPM_RH_OWNER |
| 1309 && object.attributes.spsHierarchy == SET) |
| 1310 || ( hierarchy == TPM_RH_ENDORSEMENT |
| 1311 && object.attributes.epsHierarchy == SET) |
| 1312 ) |
| 1313 { |
| 1314 // Delete the evict object |
| 1315 NvDelete(currentAddr); |
| 1316 |
| 1317 // Re-iterate from beginning after a delete |
| 1318 iter = NV_ITER_INIT; |
| 1319 } |
| 1320 } |
| 1321 else |
| 1322 { |
| 1323 pAssert(FALSE); |
| 1324 } |
| 1325 } |
| 1326 |
| 1327 return; |
| 1328 } |
| |
| |
| 8.4.7.17 NvSetGlobalLock() |
| |
| This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have |
| TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock(). |
| |
| 1329 void |
| 1330 NvSetGlobalLock( |
| 1331 void |
| 1332 ) |
| 1333 { |
| 1334 NV_ITER iter = NV_ITER_INIT; |
| 1335 UINT32 currentAddr; |
| 1336 |
| 1337 // Check all Indices |
| 1338 while((currentAddr = NvNextIndex(&iter)) != 0) |
| 1339 { |
| 1340 NV_INDEX nvIndex; |
| 1341 |
| 1342 // Read the index data |
| |
| Family "2.0" TCG Published Page 147 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1343 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), |
| 1344 sizeof(NV_INDEX), &nvIndex); |
| 1345 |
| 1346 // See if it should be locked |
| 1347 if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET) |
| 1348 { |
| 1349 |
| 1350 // if so, lock it |
| 1351 nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET; |
| 1352 |
| 1353 _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE), |
| 1354 sizeof(NV_INDEX), &nvIndex); |
| 1355 // Set the flag that a NV write happens |
| 1356 g_updateNV = TRUE; |
| 1357 } |
| 1358 } |
| 1359 |
| 1360 return; |
| 1361 |
| 1362 } |
| |
| |
| 8.4.7.18 InsertSort() |
| |
| Sort a handle into handle list in ascending order. The total handle number in the list should not exceed |
| MAX_CAP_HANDLES |
| |
| 1363 static void |
| 1364 InsertSort( |
| 1365 TPML_HANDLE *handleList, // IN/OUT: sorted handle list |
| 1366 UINT32 count, // IN: maximum count in the handle list |
| 1367 TPM_HANDLE entityHandle // IN: handle to be inserted |
| 1368 ) |
| 1369 { |
| 1370 UINT32 i, j; |
| 1371 UINT32 originalCount; |
| 1372 |
| 1373 // For a corner case that the maximum count is 0, do nothing |
| 1374 if(count == 0) return; |
| 1375 |
| 1376 // For empty list, add the handle at the beginning and return |
| 1377 if(handleList->count == 0) |
| 1378 { |
| 1379 handleList->handle[0] = entityHandle; |
| 1380 handleList->count++; |
| 1381 return; |
| 1382 } |
| 1383 |
| 1384 // Check if the maximum of the list has been reached |
| 1385 originalCount = handleList->count; |
| 1386 if(originalCount < count) |
| 1387 handleList->count++; |
| 1388 |
| 1389 // Insert the handle to the list |
| 1390 for(i = 0; i < originalCount; i++) |
| 1391 { |
| 1392 if(handleList->handle[i] > entityHandle) |
| 1393 { |
| 1394 for(j = handleList->count - 1; j > i; j--) |
| 1395 { |
| 1396 handleList->handle[j] = handleList->handle[j-1]; |
| 1397 } |
| 1398 break; |
| 1399 } |
| 1400 } |
| |
| Page 148 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1401 |
| 1402 // If a slot was found, insert the handle in this position |
| 1403 if(i < originalCount || handleList->count > originalCount) |
| 1404 handleList->handle[i] = entityHandle; |
| 1405 |
| 1406 return; |
| 1407 } |
| |
| |
| 8.4.7.19 NvCapGetPersistent() |
| |
| This function is used to get a list of handles of the persistent objects, starting at handle. |
| Handle must be in valid persistent object handle range, but does not have to reference an existing |
| persistent object. |
| |
| Return Value Meaning |
| |
| YES if there are more handles available |
| NO all the available handles has been returned |
| |
| 1408 TPMI_YES_NO |
| 1409 NvCapGetPersistent( |
| 1410 TPMI_DH_OBJECT handle, // IN: start handle |
| 1411 UINT32 count, // IN: maximum number of returned handle |
| 1412 TPML_HANDLE *handleList // OUT: list of handle |
| 1413 ) |
| 1414 { |
| 1415 TPMI_YES_NO more = NO; |
| 1416 NV_ITER iter = NV_ITER_INIT; |
| 1417 UINT32 currentAddr; |
| 1418 |
| 1419 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); |
| 1420 |
| 1421 // Initialize output handle list |
| 1422 handleList->count = 0; |
| 1423 |
| 1424 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 1425 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 1426 |
| 1427 while((currentAddr = NvNextEvict(&iter)) != 0) |
| 1428 { |
| 1429 TPM_HANDLE entityHandle; |
| 1430 |
| 1431 // Read handle information. |
| 1432 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); |
| 1433 |
| 1434 // Ignore persistent handles that have values less than the input handle |
| 1435 if(entityHandle < handle) |
| 1436 continue; |
| 1437 |
| 1438 // if the handles in the list have reached the requested count, and there |
| 1439 // are still handles need to be inserted, indicate that there are more. |
| 1440 if(handleList->count == count) |
| 1441 more = YES; |
| 1442 |
| 1443 // A handle with a value larger than start handle is a candidate |
| 1444 // for return. Insert sort it to the return list. Insert sort algorithm |
| 1445 // is chosen here for simplicity based on the assumption that the total |
| 1446 // number of NV Indices is small. For an implementation that may allow |
| 1447 // large number of NV Indices, a more efficient sorting algorithm may be |
| 1448 // used here. |
| 1449 InsertSort(handleList, count, entityHandle); |
| 1450 |
| |
| |
| Family "2.0" TCG Published Page 149 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1451 } |
| 1452 return more; |
| 1453 } |
| |
| |
| 8.4.7.20 NvCapGetIndex() |
| |
| This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of |
| NV Indices, but does not have to reference an existing NV Index. |
| |
| Return Value Meaning |
| |
| YES if there are more handles to report |
| NO all the available handles has been reported |
| |
| 1454 TPMI_YES_NO |
| 1455 NvCapGetIndex( |
| 1456 TPMI_DH_OBJECT handle, // IN: start handle |
| 1457 UINT32 count, // IN: maximum number of returned handle |
| 1458 TPML_HANDLE *handleList // OUT: list of handle |
| 1459 ) |
| 1460 { |
| 1461 TPMI_YES_NO more = NO; |
| 1462 NV_ITER iter = NV_ITER_INIT; |
| 1463 UINT32 currentAddr; |
| 1464 |
| 1465 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); |
| 1466 |
| 1467 // Initialize output handle list |
| 1468 handleList->count = 0; |
| 1469 |
| 1470 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 1471 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 1472 |
| 1473 while((currentAddr = NvNextIndex(&iter)) != 0) |
| 1474 { |
| 1475 TPM_HANDLE entityHandle; |
| 1476 |
| 1477 // Read handle information. |
| 1478 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); |
| 1479 |
| 1480 // Ignore index handles that have values less than the 'handle' |
| 1481 if(entityHandle < handle) |
| 1482 continue; |
| 1483 |
| 1484 // if the count of handles in the list has reached the requested count, |
| 1485 // and there are still handles to report, set more. |
| 1486 if(handleList->count == count) |
| 1487 more = YES; |
| 1488 |
| 1489 // A handle with a value larger than start handle is a candidate |
| 1490 // for return. Insert sort it to the return list. Insert sort algorithm |
| 1491 // is chosen here for simplicity based on the assumption that the total |
| 1492 // number of NV Indices is small. For an implementation that may allow |
| 1493 // large number of NV Indices, a more efficient sorting algorithm may be |
| 1494 // used here. |
| 1495 InsertSort(handleList, count, entityHandle); |
| 1496 } |
| 1497 return more; |
| 1498 } |
| |
| |
| |
| |
| Page 150 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.4.7.21 NvCapGetIndexNumber() |
| |
| This function returns the count of NV Indexes currently defined. |
| |
| 1499 UINT32 |
| 1500 NvCapGetIndexNumber( |
| 1501 void |
| 1502 ) |
| 1503 { |
| 1504 UINT32 num = 0; |
| 1505 NV_ITER iter = NV_ITER_INIT; |
| 1506 |
| 1507 while(NvNextIndex(&iter) != 0) num++; |
| 1508 |
| 1509 return num; |
| 1510 } |
| |
| |
| 8.4.7.22 NvCapGetPersistentNumber() |
| |
| Function returns the count of persistent objects currently in NV memory. |
| |
| 1511 UINT32 |
| 1512 NvCapGetPersistentNumber( |
| 1513 void |
| 1514 ) |
| 1515 { |
| 1516 UINT32 num = 0; |
| 1517 NV_ITER iter = NV_ITER_INIT; |
| 1518 |
| 1519 while(NvNextEvict(&iter) != 0) num++; |
| 1520 |
| 1521 return num; |
| 1522 } |
| |
| |
| 8.4.7.23 NvCapGetPersistentAvail() |
| |
| This function returns an estimate of the number of additional persistent objects that could be loaded into |
| NV memory. |
| |
| 1523 UINT32 |
| 1524 NvCapGetPersistentAvail( |
| 1525 void |
| 1526 ) |
| 1527 { |
| 1528 UINT32 availSpace; |
| 1529 UINT32 objectSpace; |
| 1530 |
| 1531 // Compute the available space in NV storage |
| 1532 availSpace = NvGetFreeByte(); |
| 1533 |
| 1534 // Get the space needed to add a persistent object to NV storage |
| 1535 objectSpace = NvGetEvictObjectSize(); |
| 1536 |
| 1537 return availSpace / objectSpace; |
| 1538 } |
| |
| |
| 8.4.7.24 NvCapGetCounterNumber() |
| |
| Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET. |
| |
| |
| |
| Family "2.0" TCG Published Page 151 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1539 UINT32 |
| 1540 NvCapGetCounterNumber( |
| 1541 void |
| 1542 ) |
| 1543 { |
| 1544 NV_ITER iter = NV_ITER_INIT; |
| 1545 UINT32 currentAddr; |
| 1546 UINT32 num = 0; |
| 1547 |
| 1548 while((currentAddr = NvNextIndex(&iter)) != 0) |
| 1549 { |
| 1550 NV_INDEX nvIndex; |
| 1551 |
| 1552 // Get NV Index info |
| 1553 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), |
| 1554 sizeof(NV_INDEX), &nvIndex); |
| 1555 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++; |
| 1556 } |
| 1557 |
| 1558 return num; |
| 1559 } |
| |
| |
| 8.4.7.25 NvCapGetCounterAvail() |
| |
| This function returns an estimate of the number of additional counter type NV Indices that can be defined. |
| |
| 1560 UINT32 |
| 1561 NvCapGetCounterAvail( |
| 1562 void |
| 1563 ) |
| 1564 { |
| 1565 UINT32 availNVSpace; |
| 1566 UINT32 availRAMSpace; |
| 1567 UINT32 counterNVSpace; |
| 1568 UINT32 counterRAMSpace; |
| 1569 UINT32 persistentNum = NvCapGetPersistentNumber(); |
| 1570 |
| 1571 // Get the available space in NV storage |
| 1572 availNVSpace = NvGetFreeByte(); |
| 1573 |
| 1574 if (persistentNum < MIN_EVICT_OBJECTS) |
| 1575 { |
| 1576 // Some space have to be reserved for evict object. Adjust availNVSpace. |
| 1577 UINT32 reserved = (MIN_EVICT_OBJECTS - persistentNum) |
| 1578 * NvGetEvictObjectSize(); |
| 1579 if (reserved > availNVSpace) |
| 1580 availNVSpace = 0; |
| 1581 else |
| 1582 availNVSpace -= reserved; |
| 1583 } |
| 1584 |
| 1585 // Get the space needed to add a counter index to NV storage |
| 1586 counterNVSpace = NvGetCounterSize(); |
| 1587 |
| 1588 // Compute the available space in RAM |
| 1589 availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize; |
| 1590 |
| 1591 // Compute the space needed to add a counter index to RAM storage |
| 1592 // It takes an size field, a handle and sizeof(UINT64) for counter data |
| 1593 counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64); |
| 1594 |
| 1595 // Return the min of counter number in NV and in RAM |
| 1596 if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace) |
| 1597 return availRAMSpace / counterRAMSpace; |
| |
| Page 152 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1598 else |
| 1599 return availNVSpace / counterNVSpace; |
| 1600 } |
| |
| |
| 8.5 Object.c |
| |
| 8.5.1 Introduction |
| |
| This file contains the functions that manage the object store of the TPM. |
| |
| 8.5.2 Includes and Data Definitions |
| |
| 1 #define OBJECT_C |
| 2 #include "InternalRoutines.h" |
| 3 #include <Platform.h> |
| |
| |
| 8.5.3 Functions |
| |
| 8.5.3.1 ObjectStartup() |
| |
| This function is called at TPM2_Startup() to initialize the object subsystem. |
| |
| 4 void |
| 5 ObjectStartup( |
| 6 void |
| 7 ) |
| 8 { |
| 9 UINT32 i; |
| 10 |
| 11 // object slots initialization |
| 12 for(i = 0; i < MAX_LOADED_OBJECTS; i++) |
| 13 { |
| 14 //Set the slot to not occupied |
| 15 s_objects[i].occupied = FALSE; |
| 16 } |
| 17 return; |
| 18 } |
| |
| |
| 8.5.3.2 ObjectCleanupEvict() |
| |
| In this implementation, a persistent object is moved from NV into an object slot for processing. It is |
| flushed after command execution. This function is called from ExecuteCommand(). |
| |
| 19 void |
| 20 ObjectCleanupEvict( |
| 21 void |
| 22 ) |
| 23 { |
| 24 UINT32 i; |
| 25 |
| 26 // This has to be iterated because a command may have two handles |
| 27 // and they may both be persistent. |
| 28 // This could be made to be more efficient so that a search is not needed. |
| 29 for(i = 0; i < MAX_LOADED_OBJECTS; i++) |
| 30 { |
| 31 // If an object is a temporary evict object, flush it from slot |
| 32 if(s_objects[i].object.entity.attributes.evict == SET) |
| 33 s_objects[i].occupied = FALSE; |
| 34 } |
| |
| Family "2.0" TCG Published Page 153 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 35 |
| 36 return; |
| 37 } |
| |
| |
| 8.5.3.3 ObjectIsPresent() |
| |
| This function checks to see if a transient handle references a loaded object. This routine should not be |
| called if the handle is not a transient handle. The function validates that the handle is in the |
| implementation-dependent allowed in range for loaded transient objects. |
| |
| Return Value Meaning |
| |
| TRUE if the handle references a loaded object |
| FALSE if the handle is not an object handle, or it does not reference to a |
| loaded object |
| |
| 38 BOOL |
| 39 ObjectIsPresent( |
| 40 TPMI_DH_OBJECT handle // IN: handle to be checked |
| 41 ) |
| 42 { |
| 43 UINT32 slotIndex; // index of object slot |
| 44 |
| 45 pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); |
| 46 |
| 47 // The index in the loaded object array is found by subtracting the first |
| 48 // object handle number from the input handle number. If the indicated |
| 49 // slot is occupied, then indicate that there is already is a loaded |
| 50 // object associated with the handle. |
| 51 slotIndex = handle - TRANSIENT_FIRST; |
| 52 if(slotIndex >= MAX_LOADED_OBJECTS) |
| 53 return FALSE; |
| 54 |
| 55 return s_objects[slotIndex].occupied; |
| 56 } |
| |
| |
| 8.5.3.4 ObjectIsSequence() |
| |
| This function is used to check if the object is a sequence object. This function should not be called if the |
| handle does not reference a loaded object. |
| |
| Return Value Meaning |
| |
| TRUE object is an HMAC, hash, or event sequence object |
| FALSE object is not an HMAC, hash, or event sequence object |
| |
| 57 BOOL |
| 58 ObjectIsSequence( |
| 59 OBJECT *object // IN: handle to be checked |
| 60 ) |
| 61 { |
| 62 pAssert (object != NULL); |
| 63 if( object->attributes.hmacSeq == SET |
| 64 || object->attributes.hashSeq == SET |
| 65 || object->attributes.eventSeq == SET) |
| 66 return TRUE; |
| 67 else |
| 68 return FALSE; |
| 69 } |
| |
| |
| |
| Page 154 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.5.3.5 ObjectGet() |
| |
| This function is used to find the object structure associated with a handle. |
| This function requires that handle references a loaded object. |
| |
| 70 OBJECT* |
| 71 ObjectGet( |
| 72 TPMI_DH_OBJECT handle // IN: handle of the object |
| 73 ) |
| 74 { |
| 75 pAssert( handle >= TRANSIENT_FIRST |
| 76 && handle - TRANSIENT_FIRST < MAX_LOADED_OBJECTS); |
| 77 pAssert(s_objects[handle - TRANSIENT_FIRST].occupied == TRUE); |
| 78 |
| 79 // In this implementation, the handle is determined by the slot occupied by the |
| 80 // object. |
| 81 return &s_objects[handle - TRANSIENT_FIRST].object.entity; |
| 82 } |
| |
| |
| 8.5.3.6 ObjectGetName() |
| |
| This function is used to access the Name of the object. In this implementation, the Name is computed |
| when the object is loaded and is saved in the internal representation of the object. This function copies |
| the Name data from the object into the buffer at name and returns the number of octets copied. |
| This function requires that handle references a loaded object. |
| |
| 83 UINT16 |
| 84 ObjectGetName( |
| 85 TPMI_DH_OBJECT handle, // IN: handle of the object |
| 86 NAME *name // OUT: name of the object |
| 87 ) |
| 88 { |
| 89 OBJECT *object = ObjectGet(handle); |
| 90 if(object->publicArea.nameAlg == TPM_ALG_NULL) |
| 91 return 0; |
| 92 |
| 93 // Copy the Name data to the output |
| 94 MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME)); |
| 95 return object->name.t.size; |
| 96 } |
| |
| |
| 8.5.3.7 ObjectGetNameAlg() |
| |
| This function is used to get the Name algorithm of a object. |
| This function requires that handle references a loaded object. |
| |
| 97 TPMI_ALG_HASH |
| 98 ObjectGetNameAlg( |
| 99 TPMI_DH_OBJECT handle // IN: handle of the object |
| 100 ) |
| 101 { |
| 102 OBJECT *object = ObjectGet(handle); |
| 103 |
| 104 return object->publicArea.nameAlg; |
| 105 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 155 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.5.3.8 ObjectGetQualifiedName() |
| |
| This function returns the Qualified Name of the object. In this implementation, the Qualified Name is |
| computed when the object is loaded and is saved in the internal representation of the object. The |
| alternative would be to retain the Name of the parent and compute the QN when needed. This would take |
| the same amount of space so it is not recommended that the alternate be used. |
| This function requires that handle references a loaded object. |
| |
| 106 void |
| 107 ObjectGetQualifiedName( |
| 108 TPMI_DH_OBJECT handle, // IN: handle of the object |
| 109 TPM2B_NAME *qualifiedName // OUT: qualified name of the object |
| 110 ) |
| 111 { |
| 112 OBJECT *object = ObjectGet(handle); |
| 113 if(object->publicArea.nameAlg == TPM_ALG_NULL) |
| 114 qualifiedName->t.size = 0; |
| 115 else |
| 116 // Copy the name |
| 117 *qualifiedName = object->qualifiedName; |
| 118 |
| 119 return; |
| 120 } |
| |
| |
| 8.5.3.9 ObjectDataGetHierarchy() |
| |
| This function returns the handle for the hierarchy of an object. |
| |
| 121 TPMI_RH_HIERARCHY |
| 122 ObjectDataGetHierarchy( |
| 123 OBJECT *object // IN :object |
| 124 ) |
| 125 { |
| 126 if(object->attributes.spsHierarchy) |
| 127 { |
| 128 return TPM_RH_OWNER; |
| 129 } |
| 130 else if(object->attributes.epsHierarchy) |
| 131 { |
| 132 return TPM_RH_ENDORSEMENT; |
| 133 } |
| 134 else if(object->attributes.ppsHierarchy) |
| 135 { |
| 136 return TPM_RH_PLATFORM; |
| 137 } |
| 138 else |
| 139 { |
| 140 return TPM_RH_NULL; |
| 141 } |
| 142 |
| 143 } |
| |
| |
| 8.5.3.10 ObjectGetHierarchy() |
| |
| This function returns the handle of the hierarchy to which a handle belongs. This function is similar to |
| ObjectDataGetHierarchy() but this routine takes a handle but ObjectDataGetHierarchy() takes an pointer |
| to an object. |
| This function requires that handle references a loaded object. |
| |
| 144 TPMI_RH_HIERARCHY |
| |
| Page 156 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 145 ObjectGetHierarchy( |
| 146 TPMI_DH_OBJECT handle // IN :object handle |
| 147 ) |
| 148 { |
| 149 OBJECT *object = ObjectGet(handle); |
| 150 |
| 151 return ObjectDataGetHierarchy(object); |
| 152 } |
| |
| |
| 8.5.3.11 ObjectAllocateSlot() |
| |
| This function is used to allocate a slot in internal object array. |
| |
| Return Value Meaning |
| |
| TRUE allocate success |
| FALSE do not have free slot |
| |
| 153 static BOOL |
| 154 ObjectAllocateSlot( |
| 155 TPMI_DH_OBJECT *handle, // OUT: handle of allocated object |
| 156 OBJECT **object // OUT: points to the allocated object |
| 157 ) |
| 158 { |
| 159 UINT32 i; |
| 160 |
| 161 // find an unoccupied handle slot |
| 162 for(i = 0; i < MAX_LOADED_OBJECTS; i++) |
| 163 { |
| 164 if(!s_objects[i].occupied) // If found a free slot |
| 165 { |
| 166 // Mark the slot as occupied |
| 167 s_objects[i].occupied = TRUE; |
| 168 break; |
| 169 } |
| 170 } |
| 171 // If we reach the end of object slot without finding a free one, return |
| 172 // error. |
| 173 if(i == MAX_LOADED_OBJECTS) return FALSE; |
| 174 |
| 175 *handle = i + TRANSIENT_FIRST; |
| 176 *object = &s_objects[i].object.entity; |
| 177 |
| 178 // Initialize the object attributes |
| 179 MemorySet(&((*object)->attributes), 0, sizeof(OBJECT_ATTRIBUTES)); |
| 180 |
| 181 return TRUE; |
| 182 } |
| |
| |
| 8.5.3.12 ObjectLoad() |
| |
| This function loads an object into an internal object structure. If an error is returned, the internal state is |
| unchanged. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 157 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_BINDING if the public and sensitive parts of the object are not matched |
| TPM_RC_KEY if the parameters in the public area of the object are not consistent |
| TPM_RC_OBJECT_MEMORY if there is no free slot for an object |
| TPM_RC_TYPE the public and private parts are not the same type |
| |
| 183 TPM_RC |
| 184 ObjectLoad( |
| 185 TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy to which the object belongs |
| 186 TPMT_PUBLIC *publicArea, // IN: public area |
| 187 TPMT_SENSITIVE *sensitive, // IN: sensitive area (may be null) |
| 188 TPM2B_NAME *name, // IN: object's name (may be null) |
| 189 TPM_HANDLE parentHandle, // IN: handle of parent |
| 190 BOOL skipChecks, // IN: flag to indicate if it is OK to skip |
| 191 // consistency checks. |
| 192 TPMI_DH_OBJECT *handle // OUT: object handle |
| 193 ) |
| 194 { |
| 195 OBJECT *object = NULL; |
| 196 OBJECT *parent = NULL; |
| 197 TPM_RC result = TPM_RC_SUCCESS; |
| 198 TPM2B_NAME parentQN; // Parent qualified name |
| 199 |
| 200 // Try to allocate a slot for new object |
| 201 if(!ObjectAllocateSlot(handle, &object)) |
| 202 return TPM_RC_OBJECT_MEMORY; |
| 203 |
| 204 // Initialize public |
| 205 object->publicArea = *publicArea; |
| 206 if(sensitive != NULL) |
| 207 object->sensitive = *sensitive; |
| 208 |
| 209 // Are the consistency checks needed |
| 210 if(!skipChecks) |
| 211 { |
| 212 // Check if key size matches |
| 213 if(!CryptObjectIsPublicConsistent(&object->publicArea)) |
| 214 { |
| 215 result = TPM_RC_KEY; |
| 216 goto ErrorExit; |
| 217 } |
| 218 if(sensitive != NULL) |
| 219 { |
| 220 // Check if public type matches sensitive type |
| 221 result = CryptObjectPublicPrivateMatch(object); |
| 222 if(result != TPM_RC_SUCCESS) |
| 223 goto ErrorExit; |
| 224 } |
| 225 } |
| 226 object->attributes.publicOnly = (sensitive == NULL); |
| 227 |
| 228 // If 'name' is NULL, then there is nothing left to do for this |
| 229 // object as it has no qualified name and it is not a member of any |
| 230 // hierarchy and it is temporary |
| 231 if(name == NULL || name->t.size == 0) |
| 232 { |
| 233 object->qualifiedName.t.size = 0; |
| 234 object->name.t.size = 0; |
| 235 object->attributes.temporary = SET; |
| 236 return TPM_RC_SUCCESS; |
| 237 } |
| 238 // If parent handle is a permanent handle, it is a primary or temporary |
| |
| Page 158 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 239 // object |
| 240 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) |
| 241 { |
| 242 // initialize QN |
| 243 parentQN.t.size = 4; |
| 244 |
| 245 // for a primary key, parent qualified name is the handle of hierarchy |
| 246 UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name); |
| 247 } |
| 248 else |
| 249 { |
| 250 // Get hierarchy and qualified name of parent |
| 251 ObjectGetQualifiedName(parentHandle, &parentQN); |
| 252 |
| 253 // Check for stClear object |
| 254 parent = ObjectGet(parentHandle); |
| 255 if( publicArea->objectAttributes.stClear == SET |
| 256 || parent->attributes.stClear == SET) |
| 257 object->attributes.stClear = SET; |
| 258 |
| 259 } |
| 260 object->name = *name; |
| 261 |
| 262 // Compute object qualified name |
| 263 ObjectComputeQualifiedName(&parentQN, publicArea->nameAlg, |
| 264 name, &object->qualifiedName); |
| 265 |
| 266 // Any object in TPM_RH_NULL hierarchy is temporary |
| 267 if(hierarchy == TPM_RH_NULL) |
| 268 { |
| 269 object->attributes.temporary = SET; |
| 270 } |
| 271 else if(parentQN.t.size == sizeof(TPM_HANDLE)) |
| 272 { |
| 273 // Otherwise, if the size of parent's qualified name is the size of a |
| 274 // handle, this object is a primary object |
| 275 object->attributes.primary = SET; |
| 276 } |
| 277 switch(hierarchy) |
| 278 { |
| 279 case TPM_RH_PLATFORM: |
| 280 object->attributes.ppsHierarchy = SET; |
| 281 break; |
| 282 case TPM_RH_OWNER: |
| 283 object->attributes.spsHierarchy = SET; |
| 284 break; |
| 285 case TPM_RH_ENDORSEMENT: |
| 286 object->attributes.epsHierarchy = SET; |
| 287 break; |
| 288 case TPM_RH_NULL: |
| 289 break; |
| 290 default: |
| 291 pAssert(FALSE); |
| 292 break; |
| 293 } |
| 294 return TPM_RC_SUCCESS; |
| 295 |
| 296 ErrorExit: |
| 297 ObjectFlush(*handle); |
| 298 return result; |
| 299 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 159 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.5.3.13 AllocateSequenceSlot() |
| |
| This function allocates a sequence slot and initializes the parts that are used by the normal objects so |
| that a sequence object is not inadvertently used for an operation that is not appropriate for a sequence. |
| |
| 300 static BOOL |
| 301 AllocateSequenceSlot( |
| 302 TPM_HANDLE *newHandle, // OUT: receives the allocated handle |
| 303 HASH_OBJECT **object, // OUT: receives pointer to allocated object |
| 304 TPM2B_AUTH *auth // IN: the authValue for the slot |
| 305 ) |
| 306 { |
| 307 OBJECT *objectHash; // the hash as an object |
| 308 |
| 309 if(!ObjectAllocateSlot(newHandle, &objectHash)) |
| 310 return FALSE; |
| 311 |
| 312 *object = (HASH_OBJECT *)objectHash; |
| 313 |
| 314 // Validate that the proper location of the hash state data relative to the |
| 315 // object state data. |
| 316 pAssert(&((*object)->auth) == &objectHash->publicArea.authPolicy); |
| 317 |
| 318 // Set the common values that a sequence object shares with an ordinary object |
| 319 // The type is TPM_ALG_NULL |
| 320 (*object)->type = TPM_ALG_NULL; |
| 321 |
| 322 // This has no name algorithm and the name is the Empty Buffer |
| 323 (*object)->nameAlg = TPM_ALG_NULL; |
| 324 |
| 325 // Clear the attributes |
| 326 MemorySet(&((*object)->objectAttributes), 0, sizeof(TPMA_OBJECT)); |
| 327 |
| 328 // A sequence object is considered to be in the NULL hierarchy so it should |
| 329 // be marked as temporary so that it can't be persisted |
| 330 (*object)->attributes.temporary = SET; |
| 331 |
| 332 // A sequence object is DA exempt. |
| 333 (*object)->objectAttributes.noDA = SET; |
| 334 |
| 335 if(auth != NULL) |
| 336 { |
| 337 MemoryRemoveTrailingZeros(auth); |
| 338 (*object)->auth = *auth; |
| 339 } |
| 340 else |
| 341 (*object)->auth.t.size = 0; |
| 342 return TRUE; |
| 343 } |
| |
| |
| 8.5.3.14 ObjectCreateHMACSequence() |
| |
| This function creates an internal HMAC sequence object. |
| |
| Error Returns Meaning |
| |
| TPM_RC_OBJECT_MEMORY if there is no free slot for an object |
| |
| 344 TPM_RC |
| 345 ObjectCreateHMACSequence( |
| 346 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 347 TPM_HANDLE handle, // IN: the handle associated with sequence |
| 348 // object |
| |
| Page 160 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 349 TPM2B_AUTH *auth, // IN: authValue |
| 350 TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle |
| 351 ) |
| 352 { |
| 353 HASH_OBJECT *hmacObject; |
| 354 OBJECT *keyObject; |
| 355 |
| 356 // Try to allocate a slot for new object |
| 357 if(!AllocateSequenceSlot(newHandle, &hmacObject, auth)) |
| 358 return TPM_RC_OBJECT_MEMORY; |
| 359 |
| 360 // Set HMAC sequence bit |
| 361 hmacObject->attributes.hmacSeq = SET; |
| 362 |
| 363 // Get pointer to the HMAC key object |
| 364 keyObject = ObjectGet(handle); |
| 365 |
| 366 CryptStartHMACSequence2B(hashAlg, &keyObject->sensitive.sensitive.bits.b, |
| 367 &hmacObject->state.hmacState); |
| 368 |
| 369 return TPM_RC_SUCCESS; |
| 370 } |
| |
| |
| 8.5.3.15 ObjectCreateHashSequence() |
| |
| This function creates a hash sequence object. |
| |
| Error Returns Meaning |
| |
| TPM_RC_OBJECT_MEMORY if there is no free slot for an object |
| |
| 371 TPM_RC |
| 372 ObjectCreateHashSequence( |
| 373 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 374 TPM2B_AUTH *auth, // IN: authValue |
| 375 TPMI_DH_OBJECT *newHandle // OUT: sequence object handle |
| 376 ) |
| 377 { |
| 378 HASH_OBJECT *hashObject; |
| 379 |
| 380 // Try to allocate a slot for new object |
| 381 if(!AllocateSequenceSlot(newHandle, &hashObject, auth)) |
| 382 return TPM_RC_OBJECT_MEMORY; |
| 383 |
| 384 // Set hash sequence bit |
| 385 hashObject->attributes.hashSeq = SET; |
| 386 |
| 387 // Start hash for hash sequence |
| 388 CryptStartHashSequence(hashAlg, &hashObject->state.hashState[0]); |
| 389 |
| 390 return TPM_RC_SUCCESS; |
| 391 } |
| |
| |
| 8.5.3.16 ObjectCreateEventSequence() |
| |
| This function creates an event sequence object. |
| |
| Error Returns Meaning |
| |
| TPM_RC_OBJECT_MEMORY if there is no free slot for an object |
| |
| 392 TPM_RC |
| |
| Family "2.0" TCG Published Page 161 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 393 ObjectCreateEventSequence( |
| 394 TPM2B_AUTH *auth, // IN: authValue |
| 395 TPMI_DH_OBJECT *newHandle // OUT: sequence object handle |
| 396 ) |
| 397 { |
| 398 HASH_OBJECT *hashObject; |
| 399 UINT32 count; |
| 400 TPM_ALG_ID hash; |
| 401 |
| 402 // Try to allocate a slot for new object |
| 403 if(!AllocateSequenceSlot(newHandle, &hashObject, auth)) |
| 404 return TPM_RC_OBJECT_MEMORY; |
| 405 |
| 406 // Set the event sequence attribute |
| 407 hashObject->attributes.eventSeq = SET; |
| 408 |
| 409 // Initialize hash states for each implemented PCR algorithms |
| 410 for(count = 0; (hash = CryptGetHashAlgByIndex(count)) != TPM_ALG_NULL; count++) |
| 411 { |
| 412 // If this is a _TPM_Init or _TPM_HashStart, the sequence object will |
| 413 // not leave the TPM so it doesn't need the sequence handling |
| 414 if(auth == NULL) |
| 415 CryptStartHash(hash, &hashObject->state.hashState[count]); |
| 416 else |
| 417 CryptStartHashSequence(hash, &hashObject->state.hashState[count]); |
| 418 } |
| 419 return TPM_RC_SUCCESS; |
| 420 } |
| |
| |
| 8.5.3.17 ObjectTerminateEvent() |
| |
| This function is called to close out the event sequence and clean up the hash context states. |
| |
| 421 void |
| 422 ObjectTerminateEvent( |
| 423 void |
| 424 ) |
| 425 { |
| 426 HASH_OBJECT *hashObject; |
| 427 int count; |
| 428 BYTE buffer[MAX_DIGEST_SIZE]; |
| 429 hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle); |
| 430 |
| 431 // Don't assume that this is a proper sequence object |
| 432 if(hashObject->attributes.eventSeq) |
| 433 { |
| 434 // If it is, close any open hash contexts. This is done in case |
| 435 // the crypto implementation has some context values that need to be |
| 436 // cleaned up (hygiene). |
| 437 // |
| 438 for(count = 0; CryptGetHashAlgByIndex(count) != TPM_ALG_NULL; count++) |
| 439 { |
| 440 CryptCompleteHash(&hashObject->state.hashState[count], 0, buffer); |
| 441 } |
| 442 // Flush sequence object |
| 443 ObjectFlush(g_DRTMHandle); |
| 444 } |
| 445 |
| 446 g_DRTMHandle = TPM_RH_UNASSIGNED; |
| 447 } |
| |
| |
| |
| |
| Page 162 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.5.3.18 ObjectContextLoad() |
| |
| This function loads an object from a saved object context. |
| |
| Error Returns Meaning |
| |
| TPM_RC_OBJECT_MEMORY if there is no free slot for an object |
| |
| 448 TPM_RC |
| 449 ObjectContextLoad( |
| 450 OBJECT *object, // IN: object structure from saved context |
| 451 TPMI_DH_OBJECT *handle // OUT: object handle |
| 452 ) |
| 453 { |
| 454 OBJECT *newObject; |
| 455 |
| 456 // Try to allocate a slot for new object |
| 457 if(!ObjectAllocateSlot(handle, &newObject)) |
| 458 return TPM_RC_OBJECT_MEMORY; |
| 459 |
| 460 // Copy input object data to internal structure |
| 461 *newObject = *object; |
| 462 |
| 463 return TPM_RC_SUCCESS; |
| 464 } |
| |
| |
| 8.5.3.19 ObjectFlush() |
| |
| This function frees an object slot. |
| This function requires that the object is loaded. |
| |
| 465 void |
| 466 ObjectFlush( |
| 467 TPMI_DH_OBJECT handle // IN: handle to be freed |
| 468 ) |
| 469 { |
| 470 UINT32 index = handle - TRANSIENT_FIRST; |
| 471 pAssert(ObjectIsPresent(handle)); |
| 472 |
| 473 // Mark the handle slot as unoccupied |
| 474 s_objects[index].occupied = FALSE; |
| 475 |
| 476 // With no attributes |
| 477 MemorySet((BYTE*)&(s_objects[index].object.entity.attributes), |
| 478 0, sizeof(OBJECT_ATTRIBUTES)); |
| 479 return; |
| 480 } |
| |
| |
| 8.5.3.20 ObjectFlushHierarchy() |
| |
| This function is called to flush all the loaded transient objects associated with a hierarchy when the |
| hierarchy is disabled. |
| |
| 481 void |
| 482 ObjectFlushHierarchy( |
| 483 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush |
| 484 ) |
| 485 { |
| 486 UINT16 i; |
| 487 |
| 488 // iterate object slots |
| |
| Family "2.0" TCG Published Page 163 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 489 for(i = 0; i < MAX_LOADED_OBJECTS; i++) |
| 490 { |
| 491 if(s_objects[i].occupied) // If found an occupied slot |
| 492 { |
| 493 switch(hierarchy) |
| 494 { |
| 495 case TPM_RH_PLATFORM: |
| 496 if(s_objects[i].object.entity.attributes.ppsHierarchy == SET) |
| 497 s_objects[i].occupied = FALSE; |
| 498 break; |
| 499 case TPM_RH_OWNER: |
| 500 if(s_objects[i].object.entity.attributes.spsHierarchy == SET) |
| 501 s_objects[i].occupied = FALSE; |
| 502 break; |
| 503 case TPM_RH_ENDORSEMENT: |
| 504 if(s_objects[i].object.entity.attributes.epsHierarchy == SET) |
| 505 s_objects[i].occupied = FALSE; |
| 506 break; |
| 507 default: |
| 508 pAssert(FALSE); |
| 509 break; |
| 510 } |
| 511 } |
| 512 } |
| 513 |
| 514 return; |
| 515 |
| 516 } |
| |
| |
| 8.5.3.21 ObjectLoadEvict() |
| |
| This function loads a persistent object into a transient object slot. |
| This function requires that handle is associated with a persistent object. |
| |
| Error Returns Meaning |
| |
| TPM_RC_HANDLE the persistent object does not exist or the associated hierarchy is |
| disabled. |
| TPM_RC_OBJECT_MEMORY no object slot |
| |
| 517 TPM_RC |
| 518 ObjectLoadEvict( |
| 519 TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it |
| 520 // will be replace by the loaded object handle |
| 521 TPM_CC commandCode // IN: the command being processed |
| 522 ) |
| 523 { |
| 524 TPM_RC result; |
| 525 TPM_HANDLE evictHandle = *handle; // Save the evict handle |
| 526 OBJECT *object; |
| 527 |
| 528 // If this is an index that references a persistent object created by |
| 529 // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE |
| 530 if(*handle >= PLATFORM_PERSISTENT) |
| 531 { |
| 532 // belongs to platform |
| 533 if(g_phEnable == CLEAR) |
| 534 return TPM_RC_HANDLE; |
| 535 } |
| 536 // belongs to owner |
| 537 else if(gc.shEnable == CLEAR) |
| 538 return TPM_RC_HANDLE; |
| 539 |
| |
| Page 164 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 540 // Try to allocate a slot for an object |
| 541 if(!ObjectAllocateSlot(handle, &object)) |
| 542 return TPM_RC_OBJECT_MEMORY; |
| 543 |
| 544 // Copy persistent object to transient object slot. A TPM_RC_HANDLE |
| 545 // may be returned at this point. This will mark the slot as containing |
| 546 // a transient object so that it will be flushed at the end of the |
| 547 // command |
| 548 result = NvGetEvictObject(evictHandle, object); |
| 549 |
| 550 // Bail out if this failed |
| 551 if(result != TPM_RC_SUCCESS) |
| 552 return result; |
| 553 |
| 554 // check the object to see if it is in the endorsement hierarchy |
| 555 // if it is and this is not a TPM2_EvictControl() command, indicate |
| 556 // that the hierarchy is disabled. |
| 557 // If the associated hierarchy is disabled, make it look like the |
| 558 // handle is not defined |
| 559 if( ObjectDataGetHierarchy(object) == TPM_RH_ENDORSEMENT |
| 560 && gc.ehEnable == CLEAR |
| 561 && commandCode != TPM_CC_EvictControl |
| 562 ) |
| 563 return TPM_RC_HANDLE; |
| 564 |
| 565 return result; |
| 566 } |
| |
| |
| 8.5.3.22 ObjectComputeName() |
| |
| This function computes the Name of an object from its public area. |
| |
| 567 void |
| 568 ObjectComputeName( |
| 569 TPMT_PUBLIC *publicArea, // IN: public area of an object |
| 570 TPM2B_NAME *name // OUT: name of the object |
| 571 ) |
| 572 { |
| 573 TPM2B_PUBLIC marshalBuffer; |
| 574 BYTE *buffer; // auxiliary marshal buffer pointer |
| 575 HASH_STATE hashState; // hash state |
| 576 |
| 577 // if the nameAlg is NULL then there is no name. |
| 578 if(publicArea->nameAlg == TPM_ALG_NULL) |
| 579 { |
| 580 name->t.size = 0; |
| 581 return; |
| 582 } |
| 583 // Start hash stack |
| 584 name->t.size = CryptStartHash(publicArea->nameAlg, &hashState); |
| 585 |
| 586 // Marshal the public area into its canonical form |
| 587 buffer = marshalBuffer.b.buffer; |
| 588 |
| 589 marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL); |
| 590 |
| 591 // Adding public area |
| 592 CryptUpdateDigest2B(&hashState, &marshalBuffer.b); |
| 593 |
| 594 // Complete hash leaving room for the name algorithm |
| 595 CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]); |
| 596 |
| 597 // set the nameAlg |
| 598 UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name); |
| |
| |
| Family "2.0" TCG Published Page 165 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 599 name->t.size += 2; |
| 600 return; |
| 601 } |
| |
| |
| 8.5.3.23 ObjectComputeQualifiedName() |
| |
| This function computes the qualified name of an object. |
| |
| 602 void |
| 603 ObjectComputeQualifiedName( |
| 604 TPM2B_NAME *parentQN, // IN: parent's qualified name |
| 605 TPM_ALG_ID nameAlg, // IN: name hash |
| 606 TPM2B_NAME *name, // IN: name of the object |
| 607 TPM2B_NAME *qualifiedName // OUT: qualified name of the object |
| 608 ) |
| 609 { |
| 610 HASH_STATE hashState; // hash state |
| 611 |
| 612 // QN_A = hash_A (QN of parent || NAME_A) |
| 613 |
| 614 // Start hash |
| 615 qualifiedName->t.size = CryptStartHash(nameAlg, &hashState); |
| 616 |
| 617 // Add parent's qualified name |
| 618 CryptUpdateDigest2B(&hashState, &parentQN->b); |
| 619 |
| 620 // Add self name |
| 621 CryptUpdateDigest2B(&hashState, &name->b); |
| 622 |
| 623 // Complete hash leaving room for the name algorithm |
| 624 CryptCompleteHash(&hashState, qualifiedName->t.size, |
| 625 &qualifiedName->t.name[2]); |
| 626 UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name); |
| 627 qualifiedName->t.size += 2; |
| 628 return; |
| 629 } |
| |
| |
| 8.5.3.24 ObjectDataIsStorage() |
| |
| This function determines if a public area has the attributes associated with a storage key. A storage key is |
| an asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR. |
| |
| Return Value Meaning |
| |
| TRUE if the object is a storage key |
| FALSE if the object is not a storage key |
| |
| 630 BOOL |
| 631 ObjectDataIsStorage( |
| 632 TPMT_PUBLIC *publicArea // IN: public area of the object |
| 633 ) |
| 634 { |
| 635 if( CryptIsAsymAlgorithm(publicArea->type) // must be asymmetric, |
| 636 && publicArea->objectAttributes.restricted == SET // restricted, |
| 637 && publicArea->objectAttributes.decrypt == SET // decryption key |
| 638 && publicArea->objectAttributes.sign == CLEAR // can not be sign key |
| 639 ) |
| 640 return TRUE; |
| 641 else |
| 642 return FALSE; |
| 643 } |
| |
| |
| Page 166 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.5.3.25 ObjectIsStorage() |
| |
| This function determines if an object has the attributes associated with a storage key. A storage key is an |
| asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR. |
| |
| Return Value Meaning |
| |
| TRUE if the object is a storage key |
| FALSE if the object is not a storage key |
| |
| 644 BOOL |
| 645 ObjectIsStorage( |
| 646 TPMI_DH_OBJECT handle // IN: object handle |
| 647 ) |
| 648 { |
| 649 OBJECT *object = ObjectGet(handle); |
| 650 return ObjectDataIsStorage(&object->publicArea); |
| 651 } |
| |
| |
| 8.5.3.26 ObjectCapGetLoaded() |
| |
| This function returns a a list of handles of loaded object, starting from handle. Handle must be in the |
| range of valid transient object handles, but does not have to be the handle of a loaded transient object. |
| |
| Return Value Meaning |
| |
| YES if there are more handles available |
| NO all the available handles has been returned |
| |
| 652 TPMI_YES_NO |
| 653 ObjectCapGetLoaded( |
| 654 TPMI_DH_OBJECT handle, // IN: start handle |
| 655 UINT32 count, // IN: count of returned handles |
| 656 TPML_HANDLE *handleList // OUT: list of handle |
| 657 ) |
| 658 { |
| 659 TPMI_YES_NO more = NO; |
| 660 UINT32 i; |
| 661 |
| 662 pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); |
| 663 |
| 664 // Initialize output handle list |
| 665 handleList->count = 0; |
| 666 |
| 667 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 668 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 669 |
| 670 // Iterate object slots to get loaded object handles |
| 671 for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++) |
| 672 { |
| 673 if(s_objects[i].occupied == TRUE) |
| 674 { |
| 675 // A valid transient object can not be the copy of a persistent object |
| 676 pAssert(s_objects[i].object.entity.attributes.evict == CLEAR); |
| 677 |
| 678 if(handleList->count < count) |
| 679 { |
| 680 // If we have not filled up the return list, add this object |
| 681 // handle to it |
| 682 handleList->handle[handleList->count] = i + TRANSIENT_FIRST; |
| 683 handleList->count++; |
| |
| |
| Family "2.0" TCG Published Page 167 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 684 } |
| 685 else |
| 686 { |
| 687 // If the return list is full but we still have loaded object |
| 688 // available, report this and stop iterating |
| 689 more = YES; |
| 690 break; |
| 691 } |
| 692 } |
| 693 } |
| 694 |
| 695 return more; |
| 696 } |
| |
| |
| 8.5.3.27 ObjectCapGetTransientAvail() |
| |
| This function returns an estimate of the number of additional transient objects that could be loaded into |
| the TPM. |
| |
| 697 UINT32 |
| 698 ObjectCapGetTransientAvail( |
| 699 void |
| 700 ) |
| 701 { |
| 702 UINT32 i; |
| 703 UINT32 num = 0; |
| 704 |
| 705 // Iterate object slot to get the number of unoccupied slots |
| 706 for(i = 0; i < MAX_LOADED_OBJECTS; i++) |
| 707 { |
| 708 if(s_objects[i].occupied == FALSE) num++; |
| 709 } |
| 710 |
| 711 return num; |
| 712 } |
| |
| |
| 8.6 PCR.c |
| |
| 8.6.1 Introduction |
| |
| This function contains the functions needed for PCR access and manipulation. |
| This implementation uses a static allocation for the PCR. The amount of memory is allocated based on |
| the number of PCR in the implementation and the number of implemented hash algorithms. This is not |
| the expected implementation. PCR SPACE DEFINITIONS. |
| In the definitions below, the g_hashPcrMap is a bit array that indicates which of the PCR are |
| implemented. The g_hashPcr array is an array of digests. In this implementation, the space is allocated |
| whether the PCR is implemented or not. |
| |
| 8.6.2 Includes, Defines, and Data Definitions |
| |
| 1 #define PCR_C |
| 2 #include "InternalRoutines.h" |
| 3 #include <Platform.h> |
| |
| The initial value of PCR attributes. The value of these fields should be consistent with PC Client |
| specification In this implementation, we assume the total number of implemented PCR is 24. |
| |
| 4 static const PCR_Attributes s_initAttributes[] = |
| |
| Page 168 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 5 { |
| 6 // PCR 0 - 15, static RTM |
| 7 {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
| 8 {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
| 9 {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
| 10 {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
| 11 |
| 12 {0, 0x0F, 0x1F}, // PCR 16, Debug |
| 13 {0, 0x10, 0x1C}, // PCR 17, Locality 4 |
| 14 {0, 0x10, 0x1C}, // PCR 18, Locality 3 |
| 15 {0, 0x10, 0x0C}, // PCR 19, Locality 2 |
| 16 {0, 0x14, 0x0E}, // PCR 20, Locality 1 |
| 17 {0, 0x14, 0x04}, // PCR 21, Dynamic OS |
| 18 {0, 0x14, 0x04}, // PCR 22, Dynamic OS |
| 19 {0, 0x0F, 0x1F}, // PCR 23, App specific |
| 20 {0, 0x0F, 0x1F} // PCR 24, testing policy |
| 21 }; |
| |
| |
| 8.6.3 Functions |
| |
| 8.6.3.1 PCRBelongsAuthGroup() |
| |
| This function indicates if a PCR belongs to a group that requires an authValue in order to modify the |
| PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is decided by the |
| platform specification. |
| |
| Return Value Meaning |
| |
| TRUE: PCR belongs an auth group |
| FALSE: PCR does not belong an auth group |
| |
| 22 BOOL |
| 23 PCRBelongsAuthGroup( |
| 24 TPMI_DH_PCR handle, // IN: handle of PCR |
| 25 UINT32 *groupIndex // OUT: group index if PCR belongs a |
| 26 // group that allows authValue. If PCR |
| 27 // does not belong to an auth group, |
| 28 // the value in this parameter is |
| 29 // invalid |
| 30 ) |
| 31 { |
| 32 #if NUM_AUTHVALUE_PCR_GROUP > 0 |
| 33 // Platform specification determines to which auth group a PCR belongs (if |
| 34 // any). In this implementation, we assume there is only |
| 35 // one auth group which contains PCR[20-22]. If the platform specification |
| 36 // requires differently, the implementation should be changed accordingly |
| 37 if(handle >= 20 && handle <= 22) |
| 38 { |
| 39 *groupIndex = 0; |
| 40 return TRUE; |
| 41 } |
| 42 |
| 43 #endif |
| 44 return FALSE; |
| 45 } |
| |
| |
| 8.6.3.2 PCRBelongsPolicyGroup() |
| |
| This function indicates if a PCR belongs to a group that requires a policy authorization in order to modify |
| the PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is decided by the |
| platform specification. |
| Family "2.0" TCG Published Page 169 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| TRUE: PCR belongs a policy group |
| FALSE: PCR does not belong a policy group |
| |
| 46 BOOL |
| 47 PCRBelongsPolicyGroup( |
| 48 TPMI_DH_PCR handle, // IN: handle of PCR |
| 49 UINT32 *groupIndex // OUT: group index if PCR belongs a group that |
| 50 // allows policy. If PCR does not belong to |
| 51 // a policy group, the value in this |
| 52 // parameter is invalid |
| 53 ) |
| 54 { |
| 55 #if NUM_POLICY_PCR_GROUP > 0 |
| 56 // Platform specification decides if a PCR belongs to a policy group and |
| 57 // belongs to which group. In this implementation, we assume there is only |
| 58 // one policy group which contains PCR20-22. If the platform specification |
| 59 // requires differently, the implementation should be changed accordingly |
| 60 if(handle >= 20 && handle <= 22) |
| 61 { |
| 62 *groupIndex = 0; |
| 63 return TRUE; |
| 64 } |
| 65 #endif |
| 66 return FALSE; |
| 67 } |
| |
| |
| 8.6.3.3 PCRBelongsTCBGroup() |
| |
| This function indicates if a PCR belongs to the TCB group. |
| |
| Return Value Meaning |
| |
| TRUE: PCR belongs to TCB group |
| FALSE: PCR does not belong to TCB group |
| |
| 68 static BOOL |
| 69 PCRBelongsTCBGroup( |
| 70 TPMI_DH_PCR handle // IN: handle of PCR |
| 71 ) |
| 72 { |
| 73 #if ENABLE_PCR_NO_INCREMENT == YES |
| 74 // Platform specification decides if a PCR belongs to a TCB group. In this |
| 75 // implementation, we assume PCR[20-22] belong to TCB group. If the platform |
| 76 // specification requires differently, the implementation should be |
| 77 // changed accordingly |
| 78 if(handle >= 20 && handle <= 22) |
| 79 return TRUE; |
| 80 |
| 81 #endif |
| 82 return FALSE; |
| 83 } |
| |
| |
| 8.6.3.4 PCRPolicyIsAvailable() |
| |
| This function indicates if a policy is available for a PCR. |
| |
| |
| |
| |
| Page 170 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| TRUE the PCR should be authorized by policy |
| FALSE the PCR does not allow policy |
| |
| 84 BOOL |
| 85 PCRPolicyIsAvailable( |
| 86 TPMI_DH_PCR handle // IN: PCR handle |
| 87 ) |
| 88 { |
| 89 UINT32 groupIndex; |
| 90 |
| 91 return PCRBelongsPolicyGroup(handle, &groupIndex); |
| 92 } |
| |
| |
| 8.6.3.5 PCRGetAuthValue() |
| |
| This function is used to access the authValue of a PCR. If PCR does not belong to an authValue group, |
| an Empty Auth will be returned. |
| |
| 93 void |
| 94 PCRGetAuthValue( |
| 95 TPMI_DH_PCR handle, // IN: PCR handle |
| 96 TPM2B_AUTH *auth // OUT: authValue of PCR |
| 97 ) |
| 98 { |
| 99 UINT32 groupIndex; |
| 100 |
| 101 if(PCRBelongsAuthGroup(handle, &groupIndex)) |
| 102 { |
| 103 *auth = gc.pcrAuthValues.auth[groupIndex]; |
| 104 } |
| 105 else |
| 106 { |
| 107 auth->t.size = 0; |
| 108 } |
| 109 |
| 110 return; |
| 111 } |
| |
| |
| 8.6.3.6 PCRGetAuthPolicy() |
| |
| This function is used to access the authorization policy of a PCR. It sets policy to the authorization policy |
| and returns the hash algorithm for policy If the PCR does not allow a policy, TPM_ALG_NULL is returned. |
| |
| 112 TPMI_ALG_HASH |
| 113 PCRGetAuthPolicy( |
| 114 TPMI_DH_PCR handle, // IN: PCR handle |
| 115 TPM2B_DIGEST *policy // OUT: policy of PCR |
| 116 ) |
| 117 { |
| 118 UINT32 groupIndex; |
| 119 |
| 120 if(PCRBelongsPolicyGroup(handle, &groupIndex)) |
| 121 { |
| 122 *policy = gp.pcrPolicies.policy[groupIndex]; |
| 123 return gp.pcrPolicies.hashAlg[groupIndex]; |
| 124 } |
| 125 else |
| 126 { |
| 127 policy->t.size = 0; |
| |
| Family "2.0" TCG Published Page 171 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 128 return TPM_ALG_NULL; |
| 129 } |
| 130 } |
| |
| |
| 8.6.3.7 PCRSimStart() |
| |
| This function is used to initialize the policies when a TPM is manufactured. This function would only be |
| called in a manufacturing environment or in a TPM simulator. |
| |
| 131 void |
| 132 PCRSimStart( |
| 133 void |
| 134 ) |
| 135 { |
| 136 UINT32 i; |
| 137 for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) |
| 138 { |
| 139 gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; |
| 140 gp.pcrPolicies.policy[i].t.size = 0; |
| 141 } |
| 142 |
| 143 for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++) |
| 144 { |
| 145 gc.pcrAuthValues.auth[i].t.size = 0; |
| 146 } |
| 147 |
| 148 // We need to give an initial configuration on allocated PCR before |
| 149 // receiving any TPM2_PCR_Allocate command to change this configuration |
| 150 // When the simulation environment starts, we allocate all the PCRs |
| 151 for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT; |
| 152 gp.pcrAllocated.count++) |
| 153 { |
| 154 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash |
| 155 = CryptGetHashAlgByIndex(gp.pcrAllocated.count); |
| 156 |
| 157 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect |
| 158 = PCR_SELECT_MAX; |
| 159 for(i = 0; i < PCR_SELECT_MAX; i++) |
| 160 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i] |
| 161 = 0xFF; |
| 162 } |
| 163 |
| 164 // Store the initial configuration to NV |
| 165 NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies); |
| 166 NvWriteReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated); |
| 167 |
| 168 return; |
| 169 } |
| |
| |
| 8.6.3.8 GetSavedPcrPointer() |
| |
| This function returns the address of an array of state saved PCR based on the hash algorithm. |
| |
| Return Value Meaning |
| |
| NULL no such algorithm |
| not NULL pointer to the 0th byte of the 0th PCR |
| |
| 170 static BYTE * |
| 171 GetSavedPcrPointer ( |
| 172 TPM_ALG_ID alg, // IN: algorithm for bank |
| 173 UINT32 pcrIndex // IN: PCR index in PCR_SAVE |
| |
| Page 172 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 174 ) |
| 175 { |
| 176 switch(alg) |
| 177 { |
| 178 #ifdef TPM_ALG_SHA1 |
| 179 case TPM_ALG_SHA1: |
| 180 return gc.pcrSave.sha1[pcrIndex]; |
| 181 break; |
| 182 #endif |
| 183 #ifdef TPM_ALG_SHA256 |
| 184 case TPM_ALG_SHA256: |
| 185 return gc.pcrSave.sha256[pcrIndex]; |
| 186 break; |
| 187 #endif |
| 188 #ifdef TPM_ALG_SHA384 |
| 189 case TPM_ALG_SHA384: |
| 190 return gc.pcrSave.sha384[pcrIndex]; |
| 191 break; |
| 192 #endif |
| 193 |
| 194 #ifdef TPM_ALG_SHA512 |
| 195 case TPM_ALG_SHA512: |
| 196 return gc.pcrSave.sha512[pcrIndex]; |
| 197 break; |
| 198 #endif |
| 199 #ifdef TPM_ALG_SM3_256 |
| 200 case TPM_ALG_SM3_256: |
| 201 return gc.pcrSave.sm3_256[pcrIndex]; |
| 202 break; |
| 203 #endif |
| 204 default: |
| 205 FAIL(FATAL_ERROR_INTERNAL); |
| 206 } |
| 207 //return NULL; // Can't be reached |
| 208 } |
| |
| |
| 8.6.3.9 PcrIsAllocated() |
| |
| This function indicates if a PCR number for the particular hash algorithm is allocated. |
| |
| Return Value Meaning |
| |
| FALSE PCR is not allocated |
| TRUE PCR is allocated |
| |
| 209 BOOL |
| 210 PcrIsAllocated ( |
| 211 UINT32 pcr, // IN: The number of the PCR |
| 212 TPMI_ALG_HASH hashAlg // IN: The PCR algorithm |
| 213 ) |
| 214 { |
| 215 UINT32 i; |
| 216 BOOL allocated = FALSE; |
| 217 |
| 218 if(pcr < IMPLEMENTATION_PCR) |
| 219 { |
| 220 |
| 221 for(i = 0; i < gp.pcrAllocated.count; i++) |
| 222 { |
| 223 if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg) |
| 224 { |
| 225 if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr/8]) |
| 226 & (1 << (pcr % 8))) != 0) |
| |
| |
| Family "2.0" TCG Published Page 173 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 227 allocated = TRUE; |
| 228 else |
| 229 allocated = FALSE; |
| 230 break; |
| 231 } |
| 232 } |
| 233 } |
| 234 return allocated; |
| 235 } |
| |
| |
| 8.6.3.10 GetPcrPointer() |
| |
| This function returns the address of an array of PCR based on the hash algorithm. |
| |
| Return Value Meaning |
| |
| NULL no such algorithm |
| not NULL pointer to the 0th byte of the 0th PCR |
| |
| 236 static BYTE * |
| 237 GetPcrPointer ( |
| 238 TPM_ALG_ID alg, // IN: algorithm for bank |
| 239 UINT32 pcrNumber // IN: PCR number |
| 240 ) |
| 241 { |
| 242 static BYTE *pcr = NULL; |
| 243 |
| 244 if(!PcrIsAllocated(pcrNumber, alg)) |
| 245 return NULL; |
| 246 |
| 247 switch(alg) |
| 248 { |
| 249 #ifdef TPM_ALG_SHA1 |
| 250 case TPM_ALG_SHA1: |
| 251 pcr = s_pcrs[pcrNumber].sha1Pcr; |
| 252 break; |
| 253 #endif |
| 254 #ifdef TPM_ALG_SHA256 |
| 255 case TPM_ALG_SHA256: |
| 256 pcr = s_pcrs[pcrNumber].sha256Pcr; |
| 257 break; |
| 258 #endif |
| 259 #ifdef TPM_ALG_SHA384 |
| 260 case TPM_ALG_SHA384: |
| 261 pcr = s_pcrs[pcrNumber].sha384Pcr; |
| 262 break; |
| 263 #endif |
| 264 #ifdef TPM_ALG_SHA512 |
| 265 case TPM_ALG_SHA512: |
| 266 pcr = s_pcrs[pcrNumber].sha512Pcr; |
| 267 break; |
| 268 #endif |
| 269 #ifdef TPM_ALG_SM3_256 |
| 270 case TPM_ALG_SM3_256: |
| 271 pcr = s_pcrs[pcrNumber].sm3_256Pcr; |
| 272 break; |
| 273 #endif |
| 274 default: |
| 275 pAssert(FALSE); |
| 276 break; |
| 277 } |
| 278 |
| 279 return pcr; |
| |
| |
| Page 174 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 280 } |
| |
| |
| 8.6.3.11 IsPcrSelected() |
| |
| This function indicates if an indicated PCR number is selected by the bit map in selection. |
| |
| Return Value Meaning |
| |
| FALSE PCR is not selected |
| TRUE PCR is selected |
| |
| 281 static BOOL |
| 282 IsPcrSelected ( |
| 283 UINT32 pcr, // IN: The number of the PCR |
| 284 TPMS_PCR_SELECTION *selection // IN: The selection structure |
| 285 ) |
| 286 { |
| 287 BOOL selected = FALSE; |
| 288 if( pcr < IMPLEMENTATION_PCR |
| 289 && ((selection->pcrSelect[pcr/8]) & (1 << (pcr % 8))) != 0) |
| 290 selected = TRUE; |
| 291 |
| 292 return selected; |
| 293 } |
| |
| |
| 8.6.3.12 FilterPcr() |
| |
| This function modifies a PCR selection array based on the implemented PCR. |
| |
| 294 static void |
| 295 FilterPcr( |
| 296 TPMS_PCR_SELECTION *selection // IN: input PCR selection |
| 297 ) |
| 298 { |
| 299 UINT32 i; |
| 300 TPMS_PCR_SELECTION *allocated = NULL; |
| 301 |
| 302 // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR |
| 303 for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++) |
| 304 selection->pcrSelect[i] = 0; |
| 305 |
| 306 // Find the internal configuration for the bank |
| 307 for(i = 0; i < gp.pcrAllocated.count; i++) |
| 308 { |
| 309 if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash) |
| 310 { |
| 311 allocated = &gp.pcrAllocated.pcrSelections[i]; |
| 312 break; |
| 313 } |
| 314 } |
| 315 |
| 316 for (i = 0; i < selection->sizeofSelect; i++) |
| 317 { |
| 318 if(allocated == NULL) |
| 319 { |
| 320 // If the required bank does not exist, clear input selection |
| 321 selection->pcrSelect[i] = 0; |
| 322 } |
| 323 else |
| 324 selection->pcrSelect[i] &= allocated->pcrSelect[i]; |
| 325 } |
| 326 |
| |
| Family "2.0" TCG Published Page 175 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 327 return; |
| 328 } |
| |
| |
| 8.6.3.13 PcrDrtm() |
| |
| This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End(). |
| |
| 329 void |
| 330 PcrDrtm( |
| 331 const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be |
| 332 // modified |
| 333 const TPMI_ALG_HASH hash, // IN: the bank identifier |
| 334 const TPM2B_DIGEST *digest // IN: the digest to modify the PCR |
| 335 ) |
| 336 { |
| 337 BYTE *pcrData = GetPcrPointer(hash, pcrHandle); |
| 338 |
| 339 if(pcrData != NULL) |
| 340 { |
| 341 // Rest the PCR to zeros |
| 342 MemorySet(pcrData, 0, digest->t.size); |
| 343 |
| 344 // if the TPM has not started, then set the PCR to 0...04 and then extend |
| 345 if(!TPMIsStarted()) |
| 346 { |
| 347 pcrData[digest->t.size - 1] = 4; |
| 348 } |
| 349 // Now, extend the value |
| 350 PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer); |
| 351 } |
| 352 } |
| |
| |
| 8.6.3.14 PCRStartup() |
| |
| This function initializes the PCR subsystem at TPM2_Startup(). |
| |
| 353 void |
| 354 PCRStartup( |
| 355 STARTUP_TYPE type, // IN: startup type |
| 356 BYTE locality // IN: startup locality |
| 357 ) |
| 358 { |
| 359 UINT32 pcr, j; |
| 360 UINT32 saveIndex = 0; |
| 361 |
| 362 g_pcrReConfig = FALSE; |
| 363 |
| 364 if(type != SU_RESUME) |
| 365 { |
| 366 // PCR generation counter is cleared at TPM_RESET and TPM_RESTART |
| 367 gr.pcrCounter = 0; |
| 368 } |
| 369 |
| 370 // Initialize/Restore PCR values |
| 371 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
| 372 { |
| 373 // On resume, need to know if this PCR had its state saved or not |
| 374 UINT32 stateSaved = |
| 375 (type == SU_RESUME && s_initAttributes[pcr].stateSave == SET) ? 1 : 0; |
| 376 |
| 377 // If this is the H-CRTM PCR and we are not doing a resume and we |
| 378 // had an H-CRTM event, then we don't change this PCR |
| 379 if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE) |
| |
| Page 176 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 380 continue; |
| 381 |
| 382 // Iterate each hash algorithm bank |
| 383 for(j = 0; j < gp.pcrAllocated.count; j++) |
| 384 { |
| 385 TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash; |
| 386 BYTE *pcrData = GetPcrPointer(hash, pcr); |
| 387 UINT16 pcrSize = CryptGetHashDigestSize(hash); |
| 388 |
| 389 if(pcrData != NULL) |
| 390 { |
| 391 // if state was saved |
| 392 if(stateSaved == 1) |
| 393 { |
| 394 // Restore saved PCR value |
| 395 BYTE *pcrSavedData; |
| 396 pcrSavedData = GetSavedPcrPointer( |
| 397 gp.pcrAllocated.pcrSelections[j].hash, |
| 398 saveIndex); |
| 399 MemoryCopy(pcrData, pcrSavedData, pcrSize, pcrSize); |
| 400 } |
| 401 else |
| 402 // PCR was not restored by state save |
| 403 { |
| 404 // If the reset locality of the PCR is 4, then |
| 405 // the reset value is all one's, otherwise it is |
| 406 // all zero. |
| 407 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
| 408 MemorySet(pcrData, 0xFF, pcrSize); |
| 409 else |
| 410 { |
| 411 MemorySet(pcrData, 0, pcrSize); |
| 412 if(pcr == HCRTM_PCR) |
| 413 pcrData[pcrSize-1] = locality; |
| 414 } |
| 415 } |
| 416 } |
| 417 } |
| 418 saveIndex += stateSaved; |
| 419 } |
| 420 |
| 421 // Reset authValues |
| 422 if(type != SU_RESUME) |
| 423 { |
| 424 for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++) |
| 425 { |
| 426 gc.pcrAuthValues.auth[j].t.size = 0; |
| 427 } |
| 428 } |
| 429 |
| 430 } |
| |
| |
| 8.6.3.15 PCRStateSave() |
| |
| This function is used to save the PCR values that will be restored on TPM Resume. |
| |
| 431 void |
| 432 PCRStateSave( |
| 433 TPM_SU type // IN: startup type |
| 434 ) |
| 435 { |
| 436 UINT32 pcr, j; |
| 437 UINT32 saveIndex = 0; |
| 438 |
| |
| |
| Family "2.0" TCG Published Page 177 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 439 // if state save CLEAR, nothing to be done. Return here |
| 440 if(type == TPM_SU_CLEAR) return; |
| 441 |
| 442 // Copy PCR values to the structure that should be saved to NV |
| 443 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
| 444 { |
| 445 UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0; |
| 446 |
| 447 // Iterate each hash algorithm bank |
| 448 for(j = 0; j < gp.pcrAllocated.count; j++) |
| 449 { |
| 450 BYTE *pcrData; |
| 451 UINT32 pcrSize; |
| 452 |
| 453 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr); |
| 454 |
| 455 if(pcrData != NULL) |
| 456 { |
| 457 pcrSize |
| 458 = CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[j].hash); |
| 459 |
| 460 if(stateSaved == 1) |
| 461 { |
| 462 // Restore saved PCR value |
| 463 BYTE *pcrSavedData; |
| 464 pcrSavedData |
| 465 = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, |
| 466 saveIndex); |
| 467 MemoryCopy(pcrSavedData, pcrData, pcrSize, pcrSize); |
| 468 } |
| 469 } |
| 470 } |
| 471 saveIndex += stateSaved; |
| 472 } |
| 473 |
| 474 return; |
| 475 } |
| |
| |
| 8.6.3.16 PCRIsStateSaved() |
| |
| This function indicates if the selected PCR is a PCR that is state saved on TPM2_Shutdown(STATE). The |
| return value is based on PCR attributes. |
| |
| Return Value Meaning |
| |
| TRUE PCR is state saved |
| FALSE PCR is not state saved |
| |
| 476 BOOL |
| 477 PCRIsStateSaved( |
| 478 TPMI_DH_PCR handle // IN: PCR handle to be extended |
| 479 ) |
| 480 { |
| 481 UINT32 pcr = handle - PCR_FIRST; |
| 482 |
| 483 if(s_initAttributes[pcr].stateSave == SET) |
| 484 return TRUE; |
| 485 else |
| 486 return FALSE; |
| 487 } |
| |
| |
| |
| |
| Page 178 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.6.3.17 PCRIsResetAllowed() |
| |
| This function indicates if a PCR may be reset by the current command locality. The return value is based |
| on PCR attributes, and not the PCR allocation. |
| |
| Return Value Meaning |
| |
| TRUE TPM2_PCR_Reset() is allowed |
| FALSE TPM2_PCR_Reset() is not allowed |
| |
| 488 BOOL |
| 489 PCRIsResetAllowed( |
| 490 TPMI_DH_PCR handle // IN: PCR handle to be extended |
| 491 ) |
| 492 { |
| 493 UINT8 commandLocality; |
| 494 UINT8 localityBits = 1; |
| 495 UINT32 pcr = handle - PCR_FIRST; |
| 496 |
| 497 // Check for the locality |
| 498 commandLocality = _plat__LocalityGet(); |
| 499 |
| 500 #ifdef DRTM_PCR |
| 501 // For a TPM that does DRTM, Reset is not allowed at locality 4 |
| 502 if(commandLocality == 4) |
| 503 return FALSE; |
| 504 #endif |
| 505 |
| 506 localityBits = localityBits << commandLocality; |
| 507 if((localityBits & s_initAttributes[pcr].resetLocality) == 0) |
| 508 return FALSE; |
| 509 else |
| 510 return TRUE; |
| 511 |
| 512 } |
| |
| |
| 8.6.3.18 PCRChanged() |
| |
| This function checks a PCR handle to see if the attributes for the PCR are set so that any change to the |
| PCR causes an increment of the pcrCounter. If it does, then the function increments the counter. |
| |
| 513 void |
| 514 PCRChanged( |
| 515 TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. |
| 516 ) |
| 517 { |
| 518 // For the reference implementation, the only change that does not cause |
| 519 // increment is a change to a PCR in the TCB group. |
| 520 if(!PCRBelongsTCBGroup(pcrHandle)) |
| 521 gr.pcrCounter++; |
| 522 } |
| |
| |
| 8.6.3.19 PCRIsExtendAllowed() |
| |
| This function indicates a PCR may be extended at the current command locality. The return value is |
| based on PCR attributes, and not the PCR allocation. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 179 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| TRUE extend is allowed |
| FALSE extend is not allowed |
| |
| 523 BOOL |
| 524 PCRIsExtendAllowed( |
| 525 TPMI_DH_PCR handle // IN: PCR handle to be extended |
| 526 ) |
| 527 { |
| 528 UINT8 commandLocality; |
| 529 UINT8 localityBits = 1; |
| 530 UINT32 pcr = handle - PCR_FIRST; |
| 531 |
| 532 // Check for the locality |
| 533 commandLocality = _plat__LocalityGet(); |
| 534 localityBits = localityBits << commandLocality; |
| 535 if((localityBits & s_initAttributes[pcr].extendLocality) == 0) |
| 536 return FALSE; |
| 537 else |
| 538 return TRUE; |
| 539 |
| 540 } |
| |
| |
| 8.6.3.20 PCRExtend() |
| |
| This function is used to extend a PCR in a specific bank. |
| |
| 541 void |
| 542 PCRExtend( |
| 543 TPMI_DH_PCR handle, // IN: PCR handle to be extended |
| 544 TPMI_ALG_HASH hash, // IN: hash algorithm of PCR |
| 545 UINT32 size, // IN: size of data to be extended |
| 546 BYTE *data // IN: data to be extended |
| 547 ) |
| 548 { |
| 549 UINT32 pcr = handle - PCR_FIRST; |
| 550 BYTE *pcrData; |
| 551 HASH_STATE hashState; |
| 552 UINT16 pcrSize; |
| 553 |
| 554 pcrData = GetPcrPointer(hash, pcr); |
| 555 |
| 556 // Extend PCR if it is allocated |
| 557 if(pcrData != NULL) |
| 558 { |
| 559 pcrSize = CryptGetHashDigestSize(hash); |
| 560 CryptStartHash(hash, &hashState); |
| 561 CryptUpdateDigest(&hashState, pcrSize, pcrData); |
| 562 CryptUpdateDigest(&hashState, size, data); |
| 563 CryptCompleteHash(&hashState, pcrSize, pcrData); |
| 564 |
| 565 // If PCR does not belong to TCB group, increment PCR counter |
| 566 if(!PCRBelongsTCBGroup(handle)) |
| 567 gr.pcrCounter++; |
| 568 } |
| 569 |
| 570 return; |
| 571 } |
| |
| |
| |
| |
| Page 180 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8.6.3.21 PCRComputeCurrentDigest() |
| |
| This function computes the digest of the selected PCR. |
| As a side-effect, selection is modified so that only the implemented PCR will have their bits still set. |
| |
| 572 void |
| 573 PCRComputeCurrentDigest( |
| 574 TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest |
| 575 TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on |
| 576 // output) |
| 577 TPM2B_DIGEST *digest // OUT: digest |
| 578 ) |
| 579 { |
| 580 HASH_STATE hashState; |
| 581 TPMS_PCR_SELECTION *select; |
| 582 BYTE *pcrData; // will point to a digest |
| 583 UINT32 pcrSize; |
| 584 UINT32 pcr; |
| 585 UINT32 i; |
| 586 |
| 587 // Initialize the hash |
| 588 digest->t.size = CryptStartHash(hashAlg, &hashState); |
| 589 pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX); |
| 590 |
| 591 // Iterate through the list of PCR selection structures |
| 592 for(i = 0; i < selection->count; i++) |
| 593 { |
| 594 // Point to the current selection |
| 595 select = &selection->pcrSelections[i]; // Point to the current selection |
| 596 FilterPcr(select); // Clear out the bits for unimplemented PCR |
| 597 |
| 598 // Need the size of each digest |
| 599 pcrSize = CryptGetHashDigestSize(selection->pcrSelections[i].hash); |
| 600 |
| 601 // Iterate through the selection |
| 602 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
| 603 { |
| 604 if(IsPcrSelected(pcr, select)) // Is this PCR selected |
| 605 { |
| 606 // Get pointer to the digest data for the bank |
| 607 pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); |
| 608 pAssert(pcrData != NULL); |
| 609 CryptUpdateDigest(&hashState, pcrSize, pcrData); // add to digest |
| 610 } |
| 611 } |
| 612 } |
| 613 // Complete hash stack |
| 614 CryptCompleteHash2B(&hashState, &digest->b); |
| 615 |
| 616 return; |
| 617 } |
| |
| |
| 8.6.3.22 PCRRead() |
| |
| This function is used to read a list of selected PCR. If the requested PCR number exceeds the maximum |
| number that can be output, the selection is adjusted to reflect the actual output PCR. |
| |
| 618 void |
| 619 PCRRead( |
| 620 TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on |
| 621 // output) |
| 622 TPML_DIGEST *digest, // OUT: digest |
| 623 UINT32 *pcrCounter // OUT: the current value of PCR generation |
| |
| Family "2.0" TCG Published Page 181 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 624 // number |
| 625 ) |
| 626 { |
| 627 TPMS_PCR_SELECTION *select; |
| 628 BYTE *pcrData; // will point to a digest |
| 629 UINT32 pcr; |
| 630 UINT32 i; |
| 631 |
| 632 digest->count = 0; |
| 633 |
| 634 // Iterate through the list of PCR selection structures |
| 635 for(i = 0; i < selection->count; i++) |
| 636 { |
| 637 // Point to the current selection |
| 638 select = &selection->pcrSelections[i]; // Point to the current selection |
| 639 FilterPcr(select); // Clear out the bits for unimplemented PCR |
| 640 |
| 641 // Iterate through the selection |
| 642 for (pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
| 643 { |
| 644 if(IsPcrSelected(pcr, select)) // Is this PCR selected |
| 645 { |
| 646 // Check if number of digest exceed upper bound |
| 647 if(digest->count > 7) |
| 648 { |
| 649 // Clear rest of the current select bitmap |
| 650 while( pcr < IMPLEMENTATION_PCR |
| 651 // do not round up! |
| 652 && (pcr / 8) < select->sizeofSelect) |
| 653 { |
| 654 // do not round up! |
| 655 select->pcrSelect[pcr/8] &= (BYTE) ~(1 << (pcr % 8)); |
| 656 pcr++; |
| 657 } |
| 658 // Exit inner loop |
| 659 break;; |
| 660 } |
| 661 // Need the size of each digest |
| 662 digest->digests[digest->count].t.size = |
| 663 CryptGetHashDigestSize(selection->pcrSelections[i].hash); |
| 664 |
| 665 // Get pointer to the digest data for the bank |
| 666 pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); |
| 667 pAssert(pcrData != NULL); |
| 668 // Add to the data to digest |
| 669 MemoryCopy(digest->digests[digest->count].t.buffer, |
| 670 pcrData, |
| 671 digest->digests[digest->count].t.size, |
| 672 digest->digests[digest->count].t.size); |
| 673 digest->count++; |
| 674 } |
| 675 } |
| 676 // If we exit inner loop because we have exceed the output upper bound |
| 677 if(digest->count > 7 && pcr < IMPLEMENTATION_PCR) |
| 678 { |
| 679 // Clear rest of the selection |
| 680 while(i < selection->count) |
| 681 { |
| 682 MemorySet(selection->pcrSelections[i].pcrSelect, 0, |
| 683 selection->pcrSelections[i].sizeofSelect); |
| 684 i++; |
| 685 } |
| 686 // exit outer loop |
| 687 break; |
| 688 } |
| 689 } |
| |
| Page 182 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 690 |
| 691 *pcrCounter = gr.pcrCounter; |
| 692 |
| 693 return; |
| 694 } |
| |
| |
| 8.6.3.23 PcrWrite() |
| |
| This function is used by _TPM_Hash_End() to set a PCR to the computed hash of the H-CRTM event. |
| |
| 695 void |
| 696 PcrWrite( |
| 697 TPMI_DH_PCR handle, // IN: PCR handle to be extended |
| 698 TPMI_ALG_HASH hash, // IN: hash algorithm of PCR |
| 699 TPM2B_DIGEST *digest // IN: the new value |
| 700 ) |
| 701 { |
| 702 UINT32 pcr = handle - PCR_FIRST; |
| 703 BYTE *pcrData; |
| 704 |
| 705 // Copy value to the PCR if it is allocated |
| 706 pcrData = GetPcrPointer(hash, pcr); |
| 707 if(pcrData != NULL) |
| 708 { |
| 709 MemoryCopy(pcrData, digest->t.buffer, digest->t.size, digest->t.size); ; |
| 710 } |
| 711 |
| 712 return; |
| 713 } |
| |
| |
| 8.6.3.24 PCRAllocate() |
| |
| This function is used to change the PCR allocation. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SUCCESS allocate success |
| TPM_RC_NO_RESULTS allocate failed |
| TPM_RC_PCR improper allocation |
| |
| 714 TPM_RC |
| 715 PCRAllocate( |
| 716 TPML_PCR_SELECTION *allocate, // IN: required allocation |
| 717 UINT32 *maxPCR, // OUT: Maximum number of PCR |
| 718 UINT32 *sizeNeeded, // OUT: required space |
| 719 UINT32 *sizeAvailable // OUT: available space |
| 720 ) |
| 721 { |
| 722 UINT32 i, j, k; |
| 723 TPML_PCR_SELECTION newAllocate; |
| 724 // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated. |
| 725 BOOL pcrHcrtm = FALSE; |
| 726 BOOL pcrDrtm = FALSE; |
| 727 |
| 728 // Create the expected new PCR allocation based on the existing allocation |
| 729 // and the new input: |
| 730 // 1. if a PCR bank does not appear in the new allocation, the existing |
| 731 // allocation of this PCR bank will be preserved. |
| 732 // 2. if a PCR bank appears multiple times in the new allocation, only the |
| 733 // last one will be in effect. |
| 734 newAllocate = gp.pcrAllocated; |
| |
| Family "2.0" TCG Published Page 183 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 735 for(i = 0; i < allocate->count; i++) |
| 736 { |
| 737 for(j = 0; j < newAllocate.count; j++) |
| 738 { |
| 739 // If hash matches, the new allocation covers the old allocation |
| 740 // for this particular bank. |
| 741 // The assumption is the initial PCR allocation (from manufacture) |
| 742 // has all the supported hash algorithms with an assigned bank |
| 743 // (possibly empty). So there must be a match for any new bank |
| 744 // allocation from the input. |
| 745 if(newAllocate.pcrSelections[j].hash == |
| 746 allocate->pcrSelections[i].hash) |
| 747 { |
| 748 newAllocate.pcrSelections[j] = allocate->pcrSelections[i]; |
| 749 break; |
| 750 } |
| 751 } |
| 752 // The j loop must exit with a match. |
| 753 pAssert(j < newAllocate.count); |
| 754 } |
| 755 |
| 756 // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined) |
| 757 *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes); |
| 758 if(*maxPCR > IMPLEMENTATION_PCR) |
| 759 *maxPCR = IMPLEMENTATION_PCR; |
| 760 |
| 761 // Compute required size for allocation |
| 762 *sizeNeeded = 0; |
| 763 for(i = 0; i < newAllocate.count; i++) |
| 764 { |
| 765 UINT32 digestSize |
| 766 = CryptGetHashDigestSize(newAllocate.pcrSelections[i].hash); |
| 767 #if defined(DRTM_PCR) |
| 768 // Make sure that we end up with at least one DRTM PCR |
| 769 # define PCR_DRTM (PCR_FIRST + DRTM_PCR) // for cosmetics |
| 770 pcrDrtm = pcrDrtm || TEST_BIT(PCR_DRTM, newAllocate.pcrSelections[i]); |
| 771 #else // if DRTM PCR is not required, indicate that the allocation is OK |
| 772 pcrDrtm = TRUE; |
| 773 #endif |
| 774 |
| 775 #if defined(HCRTM_PCR) |
| 776 // and one HCRTM PCR (since this is usually PCR 0...) |
| 777 # define PCR_HCRTM (PCR_FIRST + HCRTM_PCR) |
| 778 pcrHcrtm = pcrDrtm || TEST_BIT(PCR_HCRTM, newAllocate.pcrSelections[i]); |
| 779 #else |
| 780 pcrHcrtm = TRUE; |
| 781 #endif |
| 782 for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++) |
| 783 { |
| 784 BYTE mask = 1; |
| 785 for(k = 0; k < 8; k++) |
| 786 { |
| 787 if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0) |
| 788 *sizeNeeded += digestSize; |
| 789 mask = mask << 1; |
| 790 } |
| 791 } |
| 792 } |
| 793 |
| 794 if(!pcrDrtm || !pcrHcrtm) |
| 795 return TPM_RC_PCR; |
| 796 |
| 797 // In this particular implementation, we always have enough space to |
| 798 // allocate PCR. Different implementation may return a sizeAvailable less |
| 799 // than the sizeNeed. |
| 800 *sizeAvailable = sizeof(s_pcrs); |
| |
| Page 184 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 801 |
| 802 // Save the required allocation to NV. Note that after NV is written, the |
| 803 // PCR allocation in NV is no longer consistent with the RAM data |
| 804 // gp.pcrAllocated. The NV version reflect the allocate after next |
| 805 // TPM_RESET, while the RAM version reflects the current allocation |
| 806 NvWriteReserved(NV_PCR_ALLOCATED, &newAllocate); |
| 807 |
| 808 return TPM_RC_SUCCESS; |
| 809 |
| 810 } |
| |
| |
| 8.6.3.25 PCRSetValue() |
| |
| This function is used to set the designated PCR in all banks to an initial value. The initial value is signed |
| and will be sign extended into the entire PCR. |
| |
| 811 void |
| 812 PCRSetValue( |
| 813 TPM_HANDLE handle, // IN: the handle of the PCR to set |
| 814 INT8 initialValue // IN: the value to set |
| 815 ) |
| 816 { |
| 817 int i; |
| 818 UINT32 pcr = handle - PCR_FIRST; |
| 819 TPMI_ALG_HASH hash; |
| 820 UINT16 digestSize; |
| 821 BYTE *pcrData; |
| 822 |
| 823 // Iterate supported PCR bank algorithms to reset |
| 824 for(i = 0; i < HASH_COUNT; i++) |
| 825 { |
| 826 hash = CryptGetHashAlgByIndex(i); |
| 827 // Prevent runaway |
| 828 if(hash == TPM_ALG_NULL) |
| 829 break; |
| 830 |
| 831 // Get a pointer to the data |
| 832 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); |
| 833 |
| 834 // If the PCR is allocated |
| 835 if(pcrData != NULL) |
| 836 { |
| 837 // And the size of the digest |
| 838 digestSize = CryptGetHashDigestSize(hash); |
| 839 |
| 840 // Set the LSO to the input value |
| 841 pcrData[digestSize - 1] = initialValue; |
| 842 |
| 843 // Sign extend |
| 844 if(initialValue >= 0) |
| 845 MemorySet(pcrData, 0, digestSize - 1); |
| 846 else |
| 847 MemorySet(pcrData, -1, digestSize - 1); |
| 848 } |
| 849 } |
| 850 } |
| |
| |
| 8.6.3.26 PCRResetDynamics |
| |
| This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence. |
| |
| 851 void |
| 852 PCRResetDynamics( |
| |
| Family "2.0" TCG Published Page 185 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 853 void |
| 854 ) |
| 855 { |
| 856 UINT32 pcr, i; |
| 857 |
| 858 // Initialize PCR values |
| 859 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
| 860 { |
| 861 // Iterate each hash algorithm bank |
| 862 for(i = 0; i < gp.pcrAllocated.count; i++) |
| 863 { |
| 864 BYTE *pcrData; |
| 865 UINT32 pcrSize; |
| 866 |
| 867 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); |
| 868 |
| 869 if(pcrData != NULL) |
| 870 { |
| 871 pcrSize = |
| 872 CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[i].hash); |
| 873 |
| 874 // Reset PCR |
| 875 // Any PCR can be reset by locality 4 should be reset to 0 |
| 876 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
| 877 MemorySet(pcrData, 0, pcrSize); |
| 878 } |
| 879 } |
| 880 } |
| 881 return; |
| 882 } |
| |
| |
| 8.6.3.27 PCRCapGetAllocation() |
| |
| This function is used to get the current allocation of PCR banks. |
| |
| Return Value Meaning |
| |
| YES: if the return count is 0 |
| NO: if the return count is not 0 |
| |
| 883 TPMI_YES_NO |
| 884 PCRCapGetAllocation( |
| 885 UINT32 count, // IN: count of return |
| 886 TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list |
| 887 ) |
| 888 { |
| 889 if(count == 0) |
| 890 { |
| 891 pcrSelection->count = 0; |
| 892 return YES; |
| 893 } |
| 894 else |
| 895 { |
| 896 *pcrSelection = gp.pcrAllocated; |
| 897 return NO; |
| 898 } |
| 899 } |
| |
| |
| 8.6.3.28 PCRSetSelectBit() |
| |
| This function sets a bit in a bitmap array. |
| |
| |
| Page 186 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 900 static void |
| 901 PCRSetSelectBit( |
| 902 UINT32 pcr, // IN: PCR number |
| 903 BYTE *bitmap // OUT: bit map to be set |
| 904 ) |
| 905 { |
| 906 bitmap[pcr / 8] |= (1 << (pcr % 8)); |
| 907 return; |
| 908 } |
| |
| |
| 8.6.3.29 PCRGetProperty() |
| |
| This function returns the selected PCR property. |
| |
| Return Value Meaning |
| |
| TRUE the property type is implemented |
| FALSE the property type is not implemented |
| |
| 909 static BOOL |
| 910 PCRGetProperty( |
| 911 TPM_PT_PCR property, |
| 912 TPMS_TAGGED_PCR_SELECT *select |
| 913 ) |
| 914 { |
| 915 UINT32 pcr; |
| 916 UINT32 groupIndex; |
| 917 |
| 918 select->tag = property; |
| 919 // Always set the bitmap to be the size of all PCR |
| 920 select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8; |
| 921 |
| 922 // Initialize bitmap |
| 923 MemorySet(select->pcrSelect, 0, select->sizeofSelect); |
| 924 |
| 925 // Collecting properties |
| 926 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
| 927 { |
| 928 switch(property) |
| 929 { |
| 930 case TPM_PT_PCR_SAVE: |
| 931 if(s_initAttributes[pcr].stateSave == SET) |
| 932 PCRSetSelectBit(pcr, select->pcrSelect); |
| 933 break; |
| 934 case TPM_PT_PCR_EXTEND_L0: |
| 935 if((s_initAttributes[pcr].extendLocality & 0x01) != 0) |
| 936 PCRSetSelectBit(pcr, select->pcrSelect); |
| 937 break; |
| 938 case TPM_PT_PCR_RESET_L0: |
| 939 if((s_initAttributes[pcr].resetLocality & 0x01) != 0) |
| 940 PCRSetSelectBit(pcr, select->pcrSelect); |
| 941 break; |
| 942 case TPM_PT_PCR_EXTEND_L1: |
| 943 if((s_initAttributes[pcr].extendLocality & 0x02) != 0) |
| 944 PCRSetSelectBit(pcr, select->pcrSelect); |
| 945 break; |
| 946 case TPM_PT_PCR_RESET_L1: |
| 947 if((s_initAttributes[pcr].resetLocality & 0x02) != 0) |
| 948 PCRSetSelectBit(pcr, select->pcrSelect); |
| 949 break; |
| 950 case TPM_PT_PCR_EXTEND_L2: |
| 951 if((s_initAttributes[pcr].extendLocality & 0x04) != 0) |
| 952 PCRSetSelectBit(pcr, select->pcrSelect); |
| |
| |
| Family "2.0" TCG Published Page 187 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 953 break; |
| 954 case TPM_PT_PCR_RESET_L2: |
| 955 if((s_initAttributes[pcr].resetLocality & 0x04) != 0) |
| 956 PCRSetSelectBit(pcr, select->pcrSelect); |
| 957 break; |
| 958 case TPM_PT_PCR_EXTEND_L3: |
| 959 if((s_initAttributes[pcr].extendLocality & 0x08) != 0) |
| 960 PCRSetSelectBit(pcr, select->pcrSelect); |
| 961 break; |
| 962 case TPM_PT_PCR_RESET_L3: |
| 963 if((s_initAttributes[pcr].resetLocality & 0x08) != 0) |
| 964 PCRSetSelectBit(pcr, select->pcrSelect); |
| 965 break; |
| 966 case TPM_PT_PCR_EXTEND_L4: |
| 967 if((s_initAttributes[pcr].extendLocality & 0x10) != 0) |
| 968 PCRSetSelectBit(pcr, select->pcrSelect); |
| 969 break; |
| 970 case TPM_PT_PCR_RESET_L4: |
| 971 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
| 972 PCRSetSelectBit(pcr, select->pcrSelect); |
| 973 break; |
| 974 case TPM_PT_PCR_DRTM_RESET: |
| 975 // DRTM reset PCRs are the PCR reset by locality 4 |
| 976 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
| 977 PCRSetSelectBit(pcr, select->pcrSelect); |
| 978 break; |
| 979 #if NUM_POLICY_PCR_GROUP > 0 |
| 980 case TPM_PT_PCR_POLICY: |
| 981 if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex)) |
| 982 PCRSetSelectBit(pcr, select->pcrSelect); |
| 983 break; |
| 984 #endif |
| 985 #if NUM_AUTHVALUE_PCR_GROUP > 0 |
| 986 case TPM_PT_PCR_AUTH: |
| 987 if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex)) |
| 988 PCRSetSelectBit(pcr, select->pcrSelect); |
| 989 break; |
| 990 #endif |
| 991 #if ENABLE_PCR_NO_INCREMENT == YES |
| 992 case TPM_PT_PCR_NO_INCREMENT: |
| 993 if(PCRBelongsTCBGroup(pcr + PCR_FIRST)) |
| 994 PCRSetSelectBit(pcr, select->pcrSelect); |
| 995 break; |
| 996 #endif |
| 997 default: |
| 998 // If property is not supported, stop scanning PCR attributes |
| 999 // and return. |
| 1000 return FALSE; |
| 1001 break; |
| 1002 } |
| 1003 } |
| 1004 return TRUE; |
| 1005 } |
| |
| |
| 8.6.3.30 PCRCapGetProperties() |
| |
| This function returns a list of PCR properties starting at property. |
| |
| |
| |
| |
| Page 188 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| YES: if no more property is available |
| NO: if there are more properties not reported |
| |
| 1006 TPMI_YES_NO |
| 1007 PCRCapGetProperties( |
| 1008 TPM_PT_PCR property, // IN: the starting PCR property |
| 1009 UINT32 count, // IN: count of returned propertie |
| 1010 TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select |
| 1011 ) |
| 1012 { |
| 1013 TPMI_YES_NO more = NO; |
| 1014 UINT32 i; |
| 1015 |
| 1016 // Initialize output property list |
| 1017 select->count = 0; |
| 1018 |
| 1019 // The maximum count of properties we may return is MAX_PCR_PROPERTIES |
| 1020 if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES; |
| 1021 |
| 1022 // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property |
| 1023 // value would never be less than TPM_PT_PCR_FIRST |
| 1024 pAssert(TPM_PT_PCR_FIRST == 0); |
| 1025 |
| 1026 // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property |
| 1027 // implemented on the TPM. |
| 1028 for(i = property; i <= TPM_PT_PCR_LAST; i++) |
| 1029 { |
| 1030 if(select->count < count) |
| 1031 { |
| 1032 // If we have not filled up the return list, add more properties to it |
| 1033 if(PCRGetProperty(i, &select->pcrProperty[select->count])) |
| 1034 // only increment if the property is implemented |
| 1035 select->count++; |
| 1036 } |
| 1037 else |
| 1038 { |
| 1039 // If the return list is full but we still have properties |
| 1040 // available, report this and stop iterating. |
| 1041 more = YES; |
| 1042 break; |
| 1043 } |
| 1044 } |
| 1045 return more; |
| 1046 } |
| |
| |
| 8.6.3.31 PCRCapGetHandles() |
| |
| This function is used to get a list of handles of PCR, started from handle. If handle exceeds the maximum |
| PCR handle range, an empty list will be returned and the return value will be NO. |
| |
| Return Value Meaning |
| |
| YES if there are more handles available |
| NO all the available handles has been returned |
| |
| 1047 TPMI_YES_NO |
| 1048 PCRCapGetHandles( |
| 1049 TPMI_DH_PCR handle, // IN: start handle |
| 1050 UINT32 count, // IN: count of returned handle |
| 1051 TPML_HANDLE *handleList // OUT: list of handle |
| |
| Family "2.0" TCG Published Page 189 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1052 ) |
| 1053 { |
| 1054 TPMI_YES_NO more = NO; |
| 1055 UINT32 i; |
| 1056 |
| 1057 pAssert(HandleGetType(handle) == TPM_HT_PCR); |
| 1058 |
| 1059 // Initialize output handle list |
| 1060 handleList->count = 0; |
| 1061 |
| 1062 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 1063 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 1064 |
| 1065 // Iterate PCR handle range |
| 1066 for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++) |
| 1067 { |
| 1068 if(handleList->count < count) |
| 1069 { |
| 1070 // If we have not filled up the return list, add this PCR |
| 1071 // handle to it |
| 1072 handleList->handle[handleList->count] = i + PCR_FIRST; |
| 1073 handleList->count++; |
| 1074 } |
| 1075 else |
| 1076 { |
| 1077 // If the return list is full but we still have PCR handle |
| 1078 // available, report this and stop iterating |
| 1079 more = YES; |
| 1080 break; |
| 1081 } |
| 1082 } |
| 1083 return more; |
| 1084 } |
| |
| |
| 8.7 PP.c |
| |
| 8.7.1 Introduction |
| |
| This file contains the functions that support the physical presence operations of the TPM. |
| |
| 8.7.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| 8.7.3 Functions |
| |
| 8.7.3.1 PhysicalPresencePreInstall_Init() |
| |
| This function is used to initialize the array of commands that require confirmation with physical presence. |
| The array is an array of bits that has a correspondence with the command code. |
| This command should only ever be executable in a manufacturing setting or in a simulation. |
| |
| 2 void |
| 3 PhysicalPresencePreInstall_Init( |
| 4 void |
| 5 ) |
| 6 { |
| 7 // Clear all the PP commands |
| 8 MemorySet(&gp.ppList, 0, |
| |
| |
| Page 190 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9 ((TPM_CC_PP_LAST - TPM_CC_PP_FIRST + 1) + 7) / 8); |
| 10 |
| 11 // TPM_CC_PP_Commands always requires PP |
| 12 if(CommandIsImplemented(TPM_CC_PP_Commands)) |
| 13 PhysicalPresenceCommandSet(TPM_CC_PP_Commands); |
| 14 |
| 15 // Write PP list to NV |
| 16 NvWriteReserved(NV_PP_LIST, &gp.ppList); |
| 17 |
| 18 return; |
| 19 } |
| |
| |
| 8.7.3.2 PhysicalPresenceCommandSet() |
| |
| This function is used to indicate a command that requires PP confirmation. |
| |
| 20 void |
| 21 PhysicalPresenceCommandSet( |
| 22 TPM_CC commandCode // IN: command code |
| 23 ) |
| 24 { |
| 25 UINT32 bitPos; |
| 26 |
| 27 // Assume command is implemented. It should be checked before this |
| 28 // function is called |
| 29 pAssert(CommandIsImplemented(commandCode)); |
| 30 |
| 31 // If the command is not a PP command, ignore it |
| 32 if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST) |
| 33 return; |
| 34 |
| 35 bitPos = commandCode - TPM_CC_PP_FIRST; |
| 36 |
| 37 // Set bit |
| 38 gp.ppList[bitPos/8] |= 1 << (bitPos % 8); |
| 39 |
| 40 return; |
| 41 } |
| |
| |
| 8.7.3.3 PhysicalPresenceCommandClear() |
| |
| This function is used to indicate a command that no longer requires PP confirmation. |
| |
| 42 void |
| 43 PhysicalPresenceCommandClear( |
| 44 TPM_CC commandCode // IN: command code |
| 45 ) |
| 46 { |
| 47 UINT32 bitPos; |
| 48 |
| 49 // Assume command is implemented. It should be checked before this |
| 50 // function is called |
| 51 pAssert(CommandIsImplemented(commandCode)); |
| 52 |
| 53 // If the command is not a PP command, ignore it |
| 54 if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST) |
| 55 return; |
| 56 |
| 57 // if the input code is TPM_CC_PP_Commands, it can not be cleared |
| 58 if(commandCode == TPM_CC_PP_Commands) |
| 59 return; |
| 60 |
| 61 bitPos = commandCode - TPM_CC_PP_FIRST; |
| |
| Family "2.0" TCG Published Page 191 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 62 |
| 63 // Set bit |
| 64 gp.ppList[bitPos/8] |= (1 << (bitPos % 8)); |
| 65 // Flip it to off |
| 66 gp.ppList[bitPos/8] ^= (1 << (bitPos % 8)); |
| 67 |
| 68 return; |
| 69 } |
| |
| |
| 8.7.3.4 PhysicalPresenceIsRequired() |
| |
| This function indicates if PP confirmation is required for a command. |
| |
| Return Value Meaning |
| |
| TRUE if physical presence is required |
| FALSE if physical presence is not required |
| |
| 70 BOOL |
| 71 PhysicalPresenceIsRequired( |
| 72 TPM_CC commandCode // IN: command code |
| 73 ) |
| 74 { |
| 75 UINT32 bitPos; |
| 76 |
| 77 // if the input commandCode is not a PP command, return FALSE |
| 78 if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST) |
| 79 return FALSE; |
| 80 |
| 81 bitPos = commandCode - TPM_CC_PP_FIRST; |
| 82 |
| 83 // Check the bit map. If the bit is SET, PP authorization is required |
| 84 return ((gp.ppList[bitPos/8] & (1 << (bitPos % 8))) != 0); |
| 85 |
| 86 } |
| |
| |
| 8.7.3.5 PhysicalPresenceCapGetCCList() |
| |
| This function returns a list of commands that require PP confirmation. The list starts from the first |
| implemented command that has a command code that the same or greater than commandCode. |
| |
| Return Value Meaning |
| |
| YES if there are more command codes available |
| NO all the available command codes have been returned |
| |
| 87 TPMI_YES_NO |
| 88 PhysicalPresenceCapGetCCList( |
| 89 TPM_CC commandCode, // IN: start command code |
| 90 UINT32 count, // IN: count of returned TPM_CC |
| 91 TPML_CC *commandList // OUT: list of TPM_CC |
| 92 ) |
| 93 { |
| 94 TPMI_YES_NO more = NO; |
| 95 UINT32 i; |
| 96 |
| 97 // Initialize output handle list |
| 98 commandList->count = 0; |
| 99 |
| 100 // The maximum count of command we may return is MAX_CAP_CC |
| 101 if(count > MAX_CAP_CC) count = MAX_CAP_CC; |
| |
| Page 192 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 102 |
| 103 // Collect PP commands |
| 104 for(i = commandCode; i <= TPM_CC_PP_LAST; i++) |
| 105 { |
| 106 if(PhysicalPresenceIsRequired(i)) |
| 107 { |
| 108 if(commandList->count < count) |
| 109 { |
| 110 // If we have not filled up the return list, add this command |
| 111 // code to it |
| 112 commandList->commandCodes[commandList->count] = i; |
| 113 commandList->count++; |
| 114 } |
| 115 else |
| 116 { |
| 117 // If the return list is full but we still have PP command |
| 118 // available, report this and stop iterating |
| 119 more = YES; |
| 120 break; |
| 121 } |
| 122 } |
| 123 } |
| 124 return more; |
| 125 } |
| |
| |
| 8.8 Session.c |
| |
| 8.8.1 Introduction |
| |
| The code in this file is used to manage the session context counter. The scheme implemented here is a |
| "truncated counter". This scheme allows the TPM to not need TPM_SU_CLEAR for a very long period of |
| time and still not have the context count for a session repeated. |
| The counter (contextCounter)in this implementation is a UINT64 but can be smaller. The "tracking array" |
| (contextArray) only has 16-bits per context. The tracking array is the data that needs to be saved and |
| restored across TPM_SU_STATE so that sessions are not lost when the system enters the sleep state. |
| Also, when the TPM is active, the tracking array is kept in RAM making it important that the number of |
| bytes for each entry be kept as small as possible. |
| The TPM prevents collisions of these truncated values by not allowing a contextID to be assigned if it |
| would be the same as an existing value. Since the array holds 16 bits, after a context has been saved, |
| an additional 2^16-1 contexts may be saved before the count would again match. The normal |
| expectation is that the context will be flushed before its count value is needed again but it is always |
| possible to have long-lived sessions. |
| The contextID is assigned when the context is saved (TPM2_ContextSave()). At that time, the TPM will |
| compare the low-order 16 bits of contextCounter to the existing values in contextArray and if one |
| matches, the TPM will return TPM_RC_CONTEXT_GAP (by construction, the entry that contains the |
| matching value is the oldest context). |
| The expected remediation by the TRM is to load the oldest saved session context (the one found by the |
| TPM), and save it. Since loading the oldest session also eliminates its contextID value from contextArray, |
| there TPM will always be able to load and save the oldest existing context. |
| In the worst case, software may have to load and save several contexts in order to save an additional |
| one. This should happen very infrequently. |
| When the TPM searches contextArray and finds that none of the contextIDs match the low-order 16-bits |
| of contextCount, the TPM can copy the low bits to the contextArray associated with the session, and |
| increment contextCount. |
| |
| |
| |
| Family "2.0" TCG Published Page 193 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| There is one entry in contextArray for each of the active sessions allowed by the TPM implementation. |
| This array contains either a context count, an index, or a value indicating the slot is available (0). |
| The index into the contextArray is the handle for the session with the region selector byte of the session |
| set to zero. If an entry in contextArray contains 0, then the corresponding handle may be assigned to a |
| session. If the entry contains a value that is less than or equal to the number of loaded sessions for the |
| TPM, then the array entry is the slot in which the context is loaded. |
| |
| EXAMPLE: If the TPM allows 8 loaded sessions, then the slot numbers would be 1-8 and a contextArrary value in that |
| range would represent the loaded session. |
| |
| NOTE: When the TPM firmware determines that the array entry is for a loaded session, it will subtract 1 to create the |
| zero-based slot number. |
| |
| There is one significant corner case in this scheme. When the contextCount is equal to a value in the |
| contextArray, the oldest session needs to be recycled or flushed. In order to recycle the session, it must |
| be loaded. To be loaded, there must be an available slot. Rather than require that a spare slot be |
| available all the time, the TPM will check to see if the contextCount is equal to some value in the |
| contextArray when a session is created. This prevents the last session slot from being used when it is |
| likely that a session will need to be recycled. |
| If a TPM with both 1.2 and 2.0 functionality uses this scheme for both 1.2 and 2.0 sessions, and the list of |
| active contexts is read with TPM_GetCapabiltiy(), the TPM will create 32-bit representations of the list that |
| contains 16-bit values (the TPM2_GetCapability() returns a list of handles for active sessions rather than |
| a list of contextID). The full contextID has high-order bits that are either the same as the current |
| contextCount or one less. It is one less if the 16-bits of the contextArray has a value that is larger than |
| the low-order 16 bits of contextCount. |
| |
| 8.8.2 Includes, Defines, and Local Variables |
| |
| 1 #define SESSION_C |
| 2 #include "InternalRoutines.h" |
| 3 #include "Platform.h" |
| 4 #include "SessionProcess_fp.h" |
| |
| |
| 8.8.3 File Scope Function -- ContextIdSetOldest() |
| |
| This function is called when the oldest contextID is being loaded or deleted. Once a saved context |
| becomes the oldest, it stays the oldest until it is deleted. |
| Finding the oldest is a bit tricky. It is not just the numeric comparison of values but is dependent on the |
| value of contextCounter. |
| Assume we have a small contextArray with 8, 4-bit values with values 1 and 2 used to indicate the loaded |
| context slot number. Also assume that the array contains hex values of (0 0 1 0 3 0 9 F) and that the |
| contextCounter is an 8-bit counter with a value of 0x37. Since the low nibble is 7, that means that values |
| above 7 are older than values below it and, in this example, 9 is the oldest value. |
| Note if we subtract the counter value, from each slot that contains a saved contextID we get (- - - - B - 2 - |
| 8) and the oldest entry is now easy to find. |
| |
| 5 static void |
| 6 ContextIdSetOldest( |
| 7 void |
| 8 ) |
| 9 { |
| 10 CONTEXT_SLOT lowBits; |
| 11 CONTEXT_SLOT entry; |
| 12 CONTEXT_SLOT smallest = ((CONTEXT_SLOT) ~0); |
| 13 UINT32 i; |
| |
| |
| Page 194 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 14 |
| 15 // Set oldestSaveContext to a value indicating none assigned |
| 16 s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; |
| 17 |
| 18 lowBits = (CONTEXT_SLOT)gr.contextCounter; |
| 19 for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) |
| 20 { |
| 21 entry = gr.contextArray[i]; |
| 22 |
| 23 // only look at entries that are saved contexts |
| 24 if(entry > MAX_LOADED_SESSIONS) |
| 25 { |
| 26 // Use a less than or equal in case the oldest |
| 27 // is brand new (= lowBits-1) and equal to our initial |
| 28 // value for smallest. |
| 29 if(((CONTEXT_SLOT) (entry - lowBits)) <= smallest) |
| 30 { |
| 31 smallest = (entry - lowBits); |
| 32 s_oldestSavedSession = i; |
| 33 } |
| 34 } |
| 35 } |
| 36 // When we finish, either the s_oldestSavedSession still has its initial |
| 37 // value, or it has the index of the oldest saved context. |
| 38 } |
| |
| |
| 8.8.4 Startup Function -- SessionStartup() |
| |
| This function initializes the session subsystem on TPM2_Startup(). |
| |
| 39 void |
| 40 SessionStartup( |
| 41 STARTUP_TYPE type |
| 42 ) |
| 43 { |
| 44 UINT32 i; |
| 45 |
| 46 // Initialize session slots. At startup, all the in-memory session slots |
| 47 // are cleared and marked as not occupied |
| 48 for(i = 0; i < MAX_LOADED_SESSIONS; i++) |
| 49 s_sessions[i].occupied = FALSE; // session slot is not occupied |
| 50 |
| 51 // The free session slots the number of maximum allowed loaded sessions |
| 52 s_freeSessionSlots = MAX_LOADED_SESSIONS; |
| 53 |
| 54 // Initialize context ID data. On a ST_SAVE or hibernate sequence, it will |
| 55 // scan the saved array of session context counts, and clear any entry that |
| 56 // references a session that was in memory during the state save since that |
| 57 // memory was not preserved over the ST_SAVE. |
| 58 if(type == SU_RESUME || type == SU_RESTART) |
| 59 { |
| 60 // On ST_SAVE we preserve the contexts that were saved but not the ones |
| 61 // in memory |
| 62 for (i = 0; i < MAX_ACTIVE_SESSIONS; i++) |
| 63 { |
| 64 // If the array value is unused or references a loaded session then |
| 65 // that loaded session context is lost and the array entry is |
| 66 // reclaimed. |
| 67 if (gr.contextArray[i] <= MAX_LOADED_SESSIONS) |
| 68 gr.contextArray[i] = 0; |
| 69 } |
| 70 // Find the oldest session in context ID data and set it in |
| 71 // s_oldestSavedSession |
| 72 ContextIdSetOldest(); |
| |
| |
| Family "2.0" TCG Published Page 195 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 73 } |
| 74 else |
| 75 { |
| 76 // For STARTUP_CLEAR, clear out the contextArray |
| 77 for (i = 0; i < MAX_ACTIVE_SESSIONS; i++) |
| 78 gr.contextArray[i] = 0; |
| 79 |
| 80 // reset the context counter |
| 81 gr.contextCounter = MAX_LOADED_SESSIONS + 1; |
| 82 |
| 83 // Initialize oldest saved session |
| 84 s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; |
| 85 } |
| 86 return; |
| 87 } |
| |
| |
| 8.8.5 Access Functions |
| |
| 8.8.5.1 SessionIsLoaded() |
| |
| This function test a session handle references a loaded session. The handle must have previously been |
| checked to make sure that it is a valid handle for an authorization session. |
| |
| NOTE: A PWAP authorization does not have a session. |
| |
| |
| Return Value Meaning |
| |
| TRUE if session is loaded |
| FALSE if it is not loaded |
| |
| 88 BOOL |
| 89 SessionIsLoaded( |
| 90 TPM_HANDLE handle // IN: session handle |
| 91 ) |
| 92 { |
| 93 pAssert( HandleGetType(handle) == TPM_HT_POLICY_SESSION |
| 94 || HandleGetType(handle) == TPM_HT_HMAC_SESSION); |
| 95 |
| 96 handle = handle & HR_HANDLE_MASK; |
| 97 |
| 98 // if out of range of possible active session, or not assigned to a loaded |
| 99 // session return false |
| 100 if( handle >= MAX_ACTIVE_SESSIONS |
| 101 || gr.contextArray[handle] == 0 |
| 102 || gr.contextArray[handle] > MAX_LOADED_SESSIONS |
| 103 ) |
| 104 return FALSE; |
| 105 |
| 106 return TRUE; |
| 107 } |
| |
| |
| 8.8.5.2 SessionIsSaved() |
| |
| This function test a session handle references a saved session. The handle must have previously been |
| checked to make sure that it is a valid handle for an authorization session. |
| |
| NOTE: An password authorization does not have a session. |
| |
| This function requires that the handle be a valid session handle. |
| |
| |
| Page 196 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| TRUE if session is saved |
| FALSE if it is not saved |
| |
| 108 BOOL |
| 109 SessionIsSaved( |
| 110 TPM_HANDLE handle // IN: session handle |
| 111 ) |
| 112 { |
| 113 pAssert( HandleGetType(handle) == TPM_HT_POLICY_SESSION |
| 114 || HandleGetType(handle) == TPM_HT_HMAC_SESSION); |
| 115 |
| 116 handle = handle & HR_HANDLE_MASK; |
| 117 // if out of range of possible active session, or not assigned, or |
| 118 // assigned to a loaded session, return false |
| 119 if( handle >= MAX_ACTIVE_SESSIONS |
| 120 || gr.contextArray[handle] == 0 |
| 121 || gr.contextArray[handle] <= MAX_LOADED_SESSIONS |
| 122 ) |
| 123 return FALSE; |
| 124 |
| 125 return TRUE; |
| 126 } |
| |
| |
| 8.8.5.3 SessionPCRValueIsCurrent() |
| |
| This function is used to check if PCR values have been updated since the last time they were checked in |
| a policy session. |
| This function requires the session is loaded. |
| |
| Return Value Meaning |
| |
| TRUE if PCR value is current |
| FALSE if PCR value is not current |
| |
| 127 BOOL |
| 128 SessionPCRValueIsCurrent( |
| 129 TPMI_SH_POLICY handle // IN: session handle |
| 130 ) |
| 131 { |
| 132 SESSION *session; |
| 133 |
| 134 pAssert(SessionIsLoaded(handle)); |
| 135 |
| 136 session = SessionGet(handle); |
| 137 if( session->pcrCounter != 0 |
| 138 && session->pcrCounter != gr.pcrCounter |
| 139 ) |
| 140 return FALSE; |
| 141 else |
| 142 return TRUE; |
| 143 } |
| |
| |
| 8.8.5.4 SessionGet() |
| |
| This function returns a pointer to the session object associated with a session handle. |
| The function requires that the session is loaded. |
| |
| |
| Family "2.0" TCG Published Page 197 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 144 SESSION * |
| 145 SessionGet( |
| 146 TPM_HANDLE handle // IN: session handle |
| 147 ) |
| 148 { |
| 149 CONTEXT_SLOT sessionIndex; |
| 150 |
| 151 pAssert( HandleGetType(handle) == TPM_HT_POLICY_SESSION |
| 152 || HandleGetType(handle) == TPM_HT_HMAC_SESSION |
| 153 ); |
| 154 |
| 155 pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS); |
| 156 |
| 157 // get the contents of the session array. Because session is loaded, we |
| 158 // should always get a valid sessionIndex |
| 159 sessionIndex = gr.contextArray[handle & HR_HANDLE_MASK] - 1; |
| 160 |
| 161 pAssert(sessionIndex < MAX_LOADED_SESSIONS); |
| 162 |
| 163 return &s_sessions[sessionIndex].session; |
| 164 } |
| |
| |
| 8.8.6 Utility Functions |
| |
| 8.8.6.1 ContextIdSessionCreate() |
| |
| This function is called when a session is created. It will check to see if the current gap would prevent a |
| context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find an |
| open slot in contextArray, set contextArray to the slot. |
| This routine requires that the caller has determined the session array index for the session. |
| |
| return type TPM_RC |
| |
| TPM_RC_SUCCESS context ID was assigned |
| TPM_RC_CONTEXT_GAP can't assign a new contextID until the oldest saved session context is |
| recycled |
| TPM_RC_SESSION_HANDLE there is no slot available in the context array for tracking of this |
| session context |
| |
| 165 static TPM_RC |
| 166 ContextIdSessionCreate ( |
| 167 TPM_HANDLE *handle, // OUT: receives the assigned handle. This will |
| 168 // be an index that must be adjusted by the |
| 169 // caller according to the type of the |
| 170 // session created |
| 171 UINT32 sessionIndex // IN: The session context array entry that will |
| 172 // be occupied by the created session |
| 173 ) |
| 174 { |
| 175 |
| 176 pAssert(sessionIndex < MAX_LOADED_SESSIONS); |
| 177 |
| 178 // check to see if creating the context is safe |
| 179 // Is this going to be an assignment for the last session context |
| 180 // array entry? If so, then there will be no room to recycle the |
| 181 // oldest context if needed. If the gap is not at maximum, then |
| 182 // it will be possible to save a context if it becomes necessary. |
| 183 if( s_oldestSavedSession < MAX_ACTIVE_SESSIONS |
| 184 && s_freeSessionSlots == 1) |
| 185 { |
| 186 // See if the gap is at maximum |
| |
| Page 198 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 187 if( (CONTEXT_SLOT)gr.contextCounter |
| 188 == gr.contextArray[s_oldestSavedSession]) |
| 189 |
| 190 // Note: if this is being used on a TPM.combined, this return |
| 191 // code should be transformed to an appropriate 1.2 error |
| 192 // code for this case. |
| 193 return TPM_RC_CONTEXT_GAP; |
| 194 } |
| 195 |
| 196 // Find an unoccupied entry in the contextArray |
| 197 for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++) |
| 198 { |
| 199 if(gr.contextArray[*handle] == 0) |
| 200 { |
| 201 // indicate that the session associated with this handle |
| 202 // references a loaded session |
| 203 gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex+1); |
| 204 return TPM_RC_SUCCESS; |
| 205 } |
| 206 } |
| 207 return TPM_RC_SESSION_HANDLES; |
| 208 } |
| |
| |
| 8.8.6.2 SessionCreate() |
| |
| This function does the detailed work for starting an authorization session. This is done in a support |
| routine rather than in the action code because the session management may differ in implementations. |
| This implementation uses a fixed memory allocation to hold sessions and a fixed allocation to hold the |
| contextID for the saved contexts. |
| |
| Error Returns Meaning |
| |
| TPM_RC_CONTEXT_GAP need to recycle sessions |
| TPM_RC_SESSION_HANDLE active session space is full |
| TPM_RC_SESSION_MEMORY loaded session space is full |
| |
| 209 TPM_RC |
| 210 SessionCreate( |
| 211 TPM_SE sessionType, // IN: the session type |
| 212 TPMI_ALG_HASH authHash, // IN: the hash algorithm |
| 213 TPM2B_NONCE *nonceCaller, // IN: initial nonceCaller |
| 214 TPMT_SYM_DEF *symmetric, // IN: the symmetric algorithm |
| 215 TPMI_DH_ENTITY bind, // IN: the bind object |
| 216 TPM2B_DATA *seed, // IN: seed data |
| 217 TPM_HANDLE *sessionHandle // OUT: the session handle |
| 218 ) |
| 219 { |
| 220 TPM_RC result = TPM_RC_SUCCESS; |
| 221 CONTEXT_SLOT slotIndex; |
| 222 SESSION *session = NULL; |
| 223 |
| 224 pAssert( sessionType == TPM_SE_HMAC |
| 225 || sessionType == TPM_SE_POLICY |
| 226 || sessionType == TPM_SE_TRIAL); |
| 227 |
| 228 // If there are no open spots in the session array, then no point in searching |
| 229 if(s_freeSessionSlots == 0) |
| 230 return TPM_RC_SESSION_MEMORY; |
| 231 |
| 232 // Find a space for loading a session |
| 233 for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) |
| 234 { |
| |
| Family "2.0" TCG Published Page 199 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 235 // Is this available? |
| 236 if(s_sessions[slotIndex].occupied == FALSE) |
| 237 { |
| 238 session = &s_sessions[slotIndex].session; |
| 239 break; |
| 240 } |
| 241 } |
| 242 // if no spot found, then this is an internal error |
| 243 pAssert (slotIndex < MAX_LOADED_SESSIONS); |
| 244 |
| 245 // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be |
| 246 // returned from ContextIdHandelAssign() |
| 247 result = ContextIdSessionCreate(sessionHandle, slotIndex); |
| 248 if(result != TPM_RC_SUCCESS) |
| 249 return result; |
| 250 |
| 251 //*** Only return from this point on is TPM_RC_SUCCESS |
| 252 |
| 253 // Can now indicate that the session array entry is occupied. |
| 254 s_freeSessionSlots--; |
| 255 s_sessions[slotIndex].occupied = TRUE; |
| 256 |
| 257 // Initialize the session data |
| 258 MemorySet(session, 0, sizeof(SESSION)); |
| 259 |
| 260 // Initialize internal session data |
| 261 session->authHashAlg = authHash; |
| 262 // Initialize session type |
| 263 if(sessionType == TPM_SE_HMAC) |
| 264 { |
| 265 *sessionHandle += HMAC_SESSION_FIRST; |
| 266 |
| 267 } |
| 268 else |
| 269 { |
| 270 *sessionHandle += POLICY_SESSION_FIRST; |
| 271 |
| 272 // For TPM_SE_POLICY or TPM_SE_TRIAL |
| 273 session->attributes.isPolicy = SET; |
| 274 if(sessionType == TPM_SE_TRIAL) |
| 275 session->attributes.isTrialPolicy = SET; |
| 276 |
| 277 // Initialize policy session data |
| 278 SessionInitPolicyData(session); |
| 279 } |
| 280 // Create initial session nonce |
| 281 session->nonceTPM.t.size = nonceCaller->t.size; |
| 282 CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer); |
| 283 |
| 284 // Set up session parameter encryption algorithm |
| 285 session->symmetric = *symmetric; |
| 286 |
| 287 // If there is a bind object or a session secret, then need to compute |
| 288 // a sessionKey. |
| 289 if(bind != TPM_RH_NULL || seed->t.size != 0) |
| 290 { |
| 291 // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM, |
| 292 // nonceCaller, bits) |
| 293 // The HMAC key for generating the sessionSecret can be the concatenation |
| 294 // of an authorization value and a seed value |
| 295 TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer))); |
| 296 TPM2B_KEY key; |
| 297 |
| 298 UINT16 hashSize; // The size of the hash used by the |
| 299 // session crated by this command |
| 300 TPM2B_AUTH entityAuth; // The authValue of the entity |
| |
| Page 200 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 301 // associated with HMAC session |
| 302 |
| 303 // Get hash size, which is also the length of sessionKey |
| 304 hashSize = CryptGetHashDigestSize(session->authHashAlg); |
| 305 |
| 306 // Get authValue of associated entity |
| 307 entityAuth.t.size = EntityGetAuthValue(bind, &entityAuth.t.buffer); |
| 308 |
| 309 // Concatenate authValue and seed |
| 310 pAssert(entityAuth.t.size + seed->t.size <= sizeof(key.t.buffer)); |
| 311 MemoryCopy2B(&key.b, &entityAuth.b, sizeof(key.t.buffer)); |
| 312 MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer)); |
| 313 |
| 314 session->sessionKey.t.size = hashSize; |
| 315 |
| 316 // Compute the session key |
| 317 KDFa(session->authHashAlg, &key.b, "ATH", &session->nonceTPM.b, |
| 318 &nonceCaller->b, hashSize * 8, session->sessionKey.t.buffer, NULL); |
| 319 } |
| 320 |
| 321 // Copy the name of the entity that the HMAC session is bound to |
| 322 // Policy session is not bound to an entity |
| 323 if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC) |
| 324 { |
| 325 session->attributes.isBound = SET; |
| 326 SessionComputeBoundEntity(bind, &session->u1.boundEntity); |
| 327 } |
| 328 // If there is a bind object and it is subject to DA, then use of this session |
| 329 // is subject to DA regardless of how it is used. |
| 330 session->attributes.isDaBound = (bind != TPM_RH_NULL) |
| 331 && (IsDAExempted(bind) == FALSE); |
| 332 |
| 333 // If the session is bound, then check to see if it is bound to lockoutAuth |
| 334 session->attributes.isLockoutBound = (session->attributes.isDaBound == SET) |
| 335 && (bind == TPM_RH_LOCKOUT); |
| 336 return TPM_RC_SUCCESS; |
| 337 |
| 338 } |
| |
| |
| 8.8.6.3 SessionContextSave() |
| |
| This function is called when a session context is to be saved. The contextID of the saved session is |
| returned. If no contextID can be assigned, then the routine returns TPM_RC_CONTEXT_GAP. If the |
| function completes normally, the session slot will be freed. |
| This function requires that handle references a loaded session. Otherwise, it should not be called at the |
| first place. |
| |
| Error Returns Meaning |
| |
| TPM_RC_CONTEXT_GAP a contextID could not be assigned. |
| TPM_RC_TOO_MANY_CONTEXTS the counter maxed out |
| |
| 339 TPM_RC |
| 340 SessionContextSave ( |
| 341 TPM_HANDLE handle, // IN: session handle |
| 342 CONTEXT_COUNTER *contextID // OUT: assigned contextID |
| 343 ) |
| 344 { |
| 345 UINT32 contextIndex; |
| 346 CONTEXT_SLOT slotIndex; |
| 347 |
| 348 pAssert(SessionIsLoaded(handle)); |
| |
| Family "2.0" TCG Published Page 201 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 349 |
| 350 // check to see if the gap is already maxed out |
| 351 // Need to have a saved session |
| 352 if( s_oldestSavedSession < MAX_ACTIVE_SESSIONS |
| 353 // if the oldest saved session has the same value as the low bits |
| 354 // of the contextCounter, then the GAP is maxed out. |
| 355 && gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter) |
| 356 return TPM_RC_CONTEXT_GAP; |
| 357 |
| 358 // if the caller wants the context counter, set it |
| 359 if(contextID != NULL) |
| 360 *contextID = gr.contextCounter; |
| 361 |
| 362 pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS); |
| 363 |
| 364 contextIndex = handle & HR_HANDLE_MASK; |
| 365 |
| 366 // Extract the session slot number referenced by the contextArray |
| 367 // because we are going to overwrite this with the low order |
| 368 // contextID value. |
| 369 slotIndex = gr.contextArray[contextIndex] - 1; |
| 370 |
| 371 // Set the contextID for the contextArray |
| 372 gr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter; |
| 373 |
| 374 // Increment the counter |
| 375 gr.contextCounter++; |
| 376 |
| 377 // In the unlikely event that the 64-bit context counter rolls over... |
| 378 if(gr.contextCounter == 0) |
| 379 { |
| 380 // back it up |
| 381 gr.contextCounter--; |
| 382 // return an error |
| 383 return TPM_RC_TOO_MANY_CONTEXTS; |
| 384 } |
| 385 // if the low-order bits wrapped, need to advance the value to skip over |
| 386 // the values used to indicate that a session is loaded |
| 387 if(((CONTEXT_SLOT)gr.contextCounter) == 0) |
| 388 gr.contextCounter += MAX_LOADED_SESSIONS + 1; |
| 389 |
| 390 // If no other sessions are saved, this is now the oldest. |
| 391 if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS) |
| 392 s_oldestSavedSession = contextIndex; |
| 393 |
| 394 // Mark the session slot as unoccupied |
| 395 s_sessions[slotIndex].occupied = FALSE; |
| 396 |
| 397 // and indicate that there is an additional open slot |
| 398 s_freeSessionSlots++; |
| 399 |
| 400 return TPM_RC_SUCCESS; |
| 401 } |
| |
| |
| 8.8.6.4 SessionContextLoad() |
| |
| This function is used to load a session from saved context. The session handle must be for a saved |
| context. |
| If the gap is at a maximum, then the only session that can be loaded is the oldest session, otherwise |
| TPM_RC_CONTEXT_GAP is returned. |
| This function requires that handle references a valid saved session. |
| |
| |
| |
| Page 202 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_SESSION_MEMORY no free session slots |
| TPM_RC_CONTEXT_GAP the gap count is maximum and this is not the oldest saved context |
| |
| 402 TPM_RC |
| 403 SessionContextLoad( |
| 404 SESSION *session, // IN: session structure from saved context |
| 405 TPM_HANDLE *handle // IN/OUT: session handle |
| 406 ) |
| 407 { |
| 408 UINT32 contextIndex; |
| 409 CONTEXT_SLOT slotIndex; |
| 410 |
| 411 pAssert( HandleGetType(*handle) == TPM_HT_POLICY_SESSION |
| 412 || HandleGetType(*handle) == TPM_HT_HMAC_SESSION); |
| 413 |
| 414 // Don't bother looking if no openings |
| 415 if(s_freeSessionSlots == 0) |
| 416 return TPM_RC_SESSION_MEMORY; |
| 417 |
| 418 // Find a free session slot to load the session |
| 419 for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) |
| 420 if(s_sessions[slotIndex].occupied == FALSE) break; |
| 421 |
| 422 // if no spot found, then this is an internal error |
| 423 pAssert (slotIndex < MAX_LOADED_SESSIONS); |
| 424 |
| 425 contextIndex = *handle & HR_HANDLE_MASK; // extract the index |
| 426 |
| 427 // If there is only one slot left, and the gap is at maximum, the only session |
| 428 // context that we can safely load is the oldest one. |
| 429 if( s_oldestSavedSession < MAX_ACTIVE_SESSIONS |
| 430 && s_freeSessionSlots == 1 |
| 431 && (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession] |
| 432 && contextIndex != s_oldestSavedSession |
| 433 ) |
| 434 return TPM_RC_CONTEXT_GAP; |
| 435 |
| 436 pAssert(contextIndex < MAX_ACTIVE_SESSIONS); |
| 437 |
| 438 // set the contextArray value to point to the session slot where |
| 439 // the context is loaded |
| 440 gr.contextArray[contextIndex] = slotIndex + 1; |
| 441 |
| 442 // if this was the oldest context, find the new oldest |
| 443 if(contextIndex == s_oldestSavedSession) |
| 444 ContextIdSetOldest(); |
| 445 |
| 446 // Copy session data to session slot |
| 447 s_sessions[slotIndex].session = *session; |
| 448 |
| 449 // Set session slot as occupied |
| 450 s_sessions[slotIndex].occupied = TRUE; |
| 451 |
| 452 // Reduce the number of open spots |
| 453 s_freeSessionSlots--; |
| 454 |
| 455 return TPM_RC_SUCCESS; |
| 456 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 203 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.8.6.5 SessionFlush() |
| |
| This function is used to flush a session referenced by its handle. If the session associated with handle is |
| loaded, the session array entry is marked as available. |
| This function requires that handle be a valid active session. |
| |
| 457 void |
| 458 SessionFlush( |
| 459 TPM_HANDLE handle // IN: loaded or saved session handle |
| 460 ) |
| 461 { |
| 462 CONTEXT_SLOT slotIndex; |
| 463 UINT32 contextIndex; // Index into contextArray |
| 464 |
| 465 pAssert( ( HandleGetType(handle) == TPM_HT_POLICY_SESSION |
| 466 || HandleGetType(handle) == TPM_HT_HMAC_SESSION |
| 467 ) |
| 468 && (SessionIsLoaded(handle) || SessionIsSaved(handle)) |
| 469 ); |
| 470 |
| 471 // Flush context ID of this session |
| 472 // Convert handle to an index into the contextArray |
| 473 contextIndex = handle & HR_HANDLE_MASK; |
| 474 |
| 475 pAssert(contextIndex < sizeof(gr.contextArray)/sizeof(gr.contextArray[0])); |
| 476 |
| 477 // Get the current contents of the array |
| 478 slotIndex = gr.contextArray[contextIndex]; |
| 479 |
| 480 // Mark context array entry as available |
| 481 gr.contextArray[contextIndex] = 0; |
| 482 |
| 483 // Is this a saved session being flushed |
| 484 if(slotIndex > MAX_LOADED_SESSIONS) |
| 485 { |
| 486 // Flushing the oldest session? |
| 487 if(contextIndex == s_oldestSavedSession) |
| 488 // If so, find a new value for oldest. |
| 489 ContextIdSetOldest(); |
| 490 } |
| 491 else |
| 492 { |
| 493 // Adjust slot index to point to session array index |
| 494 slotIndex -= 1; |
| 495 |
| 496 // Free session array index |
| 497 s_sessions[slotIndex].occupied = FALSE; |
| 498 s_freeSessionSlots++; |
| 499 } |
| 500 |
| 501 return; |
| 502 } |
| |
| |
| 8.8.6.6 SessionComputeBoundEntity() |
| |
| This function computes the binding value for a session. The binding value for a reserved handle is the |
| handle itself. For all the other entities, the authValue at the time of binding is included to prevent |
| squatting. For those values, the Name and the authValue are concatenated into the bind buffer. If they |
| will not both fit, the will be overlapped by XORing() bytes. If XOR is required, the bind value will be full. |
| |
| 503 void |
| 504 SessionComputeBoundEntity( |
| |
| Page 204 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 505 TPMI_DH_ENTITY entityHandle, // IN: handle of entity |
| 506 TPM2B_NAME *bind // OUT: binding value |
| 507 ) |
| 508 { |
| 509 TPM2B_AUTH auth; |
| 510 INT16 overlap; |
| 511 |
| 512 // Get name |
| 513 bind->t.size = EntityGetName(entityHandle, &bind->t.name); |
| 514 |
| 515 // // The bound value of a reserved handle is the handle itself |
| 516 // if(bind->t.size == sizeof(TPM_HANDLE)) return; |
| 517 |
| 518 // For all the other entities, concatenate the auth value to the name. |
| 519 // Get a local copy of the auth value because some overlapping |
| 520 // may be necessary. |
| 521 auth.t.size = EntityGetAuthValue(entityHandle, &auth.t.buffer); |
| 522 pAssert(auth.t.size <= sizeof(TPMU_HA)); |
| 523 |
| 524 // Figure out if there will be any overlap |
| 525 overlap = bind->t.size + auth.t.size - sizeof(bind->t.name); |
| 526 |
| 527 // There is overlap if the combined sizes are greater than will fit |
| 528 if(overlap > 0) |
| 529 { |
| 530 // The overlap area is at the end of the Name |
| 531 BYTE *result = &bind->t.name[bind->t.size - overlap]; |
| 532 int i; |
| 533 |
| 534 // XOR the auth value into the Name for the overlap area |
| 535 for(i = 0; i < overlap; i++) |
| 536 result[i] ^= auth.t.buffer[i]; |
| 537 } |
| 538 else |
| 539 { |
| 540 // There is no overlap |
| 541 overlap = 0; |
| 542 } |
| 543 //copy the remainder of the authData to the end of the name |
| 544 MemoryCopy(&bind->t.name[bind->t.size], &auth.t.buffer[overlap], |
| 545 auth.t.size - overlap, sizeof(bind->t.name) - bind->t.size); |
| 546 |
| 547 // Increase the size of the bind data by the size of the auth - the overlap |
| 548 bind->t.size += auth.t.size-overlap; |
| 549 |
| 550 return; |
| 551 } |
| |
| |
| 8.8.6.7 SessionInitPolicyData() |
| |
| This function initializes the portions of the session policy data that are not set by the allocation of a |
| session. |
| |
| 552 void |
| 553 SessionInitPolicyData( |
| 554 SESSION *session // IN: session handle |
| 555 ) |
| 556 { |
| 557 // Initialize start time |
| 558 session->startTime = go.clock; |
| 559 |
| 560 // Initialize policyDigest. policyDigest is initialized with a string of 0 of |
| 561 // session algorithm digest size. Since the policy already contains all zeros |
| 562 // it is only necessary to set the size |
| |
| Family "2.0" TCG Published Page 205 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 563 session->u2.policyDigest.t.size = CryptGetHashDigestSize(session->authHashAlg); |
| 564 return; |
| 565 } |
| |
| |
| 8.8.6.8 SessionResetPolicyData() |
| |
| This function is used to reset the policy data without changing the nonce or the start time of the session. |
| |
| 566 void |
| 567 SessionResetPolicyData( |
| 568 SESSION *session // IN: the session to reset |
| 569 ) |
| 570 { |
| 571 session->commandCode = 0; // No command |
| 572 |
| 573 // No locality selected |
| 574 MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality)); |
| 575 |
| 576 // The cpHash size to zero |
| 577 session->u1.cpHash.b.size = 0; |
| 578 |
| 579 // No timeout |
| 580 session->timeOut = 0; |
| 581 |
| 582 // Reset the pcrCounter |
| 583 session->pcrCounter = 0; |
| 584 |
| 585 // Reset the policy hash |
| 586 MemorySet(&session->u2.policyDigest.t.buffer, 0, |
| 587 session->u2.policyDigest.t.size); |
| 588 |
| 589 // Reset the session attributes |
| 590 MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES)); |
| 591 |
| 592 // set the policy attribute |
| 593 session->attributes.isPolicy = SET; |
| 594 } |
| |
| |
| 8.8.6.9 SessionCapGetLoaded() |
| |
| This function returns a list of handles of loaded session, started from input handle |
| Handle must be in valid loaded session handle range, but does not have to point to a loaded session. |
| |
| Return Value Meaning |
| |
| YES if there are more handles available |
| NO all the available handles has been returned |
| |
| 595 TPMI_YES_NO |
| 596 SessionCapGetLoaded( |
| 597 TPMI_SH_POLICY handle, // IN: start handle |
| 598 UINT32 count, // IN: count of returned handle |
| 599 TPML_HANDLE *handleList // OUT: list of handle |
| 600 ) |
| 601 { |
| 602 TPMI_YES_NO more = NO; |
| 603 UINT32 i; |
| 604 |
| 605 pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION); |
| 606 |
| 607 // Initialize output handle list |
| |
| Page 206 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 608 handleList->count = 0; |
| 609 |
| 610 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 611 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 612 |
| 613 // Iterate session context ID slots to get loaded session handles |
| 614 for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) |
| 615 { |
| 616 // If session is active |
| 617 if(gr.contextArray[i] != 0) |
| 618 { |
| 619 // If session is loaded |
| 620 if (gr.contextArray[i] <= MAX_LOADED_SESSIONS) |
| 621 { |
| 622 if(handleList->count < count) |
| 623 { |
| 624 SESSION *session; |
| 625 |
| 626 // If we have not filled up the return list, add this |
| 627 // session handle to it |
| 628 // assume that this is going to be an HMAC session |
| 629 handle = i + HMAC_SESSION_FIRST; |
| 630 session = SessionGet(handle); |
| 631 if(session->attributes.isPolicy) |
| 632 handle = i + POLICY_SESSION_FIRST; |
| 633 handleList->handle[handleList->count] = handle; |
| 634 handleList->count++; |
| 635 } |
| 636 else |
| 637 { |
| 638 // If the return list is full but we still have loaded object |
| 639 // available, report this and stop iterating |
| 640 more = YES; |
| 641 break; |
| 642 } |
| 643 } |
| 644 } |
| 645 } |
| 646 |
| 647 return more; |
| 648 |
| 649 } |
| |
| |
| 8.8.6.10 SessionCapGetSaved() |
| |
| This function returns a list of handles for saved session, starting at handle. |
| Handle must be in a valid handle range, but does not have to point to a saved session |
| |
| Return Value Meaning |
| |
| YES if there are more handles available |
| NO all the available handles has been returned |
| |
| 650 TPMI_YES_NO |
| 651 SessionCapGetSaved( |
| 652 TPMI_SH_HMAC handle, // IN: start handle |
| 653 UINT32 count, // IN: count of returned handle |
| 654 TPML_HANDLE *handleList // OUT: list of handle |
| 655 ) |
| 656 { |
| 657 TPMI_YES_NO more = NO; |
| 658 UINT32 i; |
| 659 |
| |
| Family "2.0" TCG Published Page 207 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 660 pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION); |
| 661 |
| 662 // Initialize output handle list |
| 663 handleList->count = 0; |
| 664 |
| 665 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 666 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 667 |
| 668 // Iterate session context ID slots to get loaded session handles |
| 669 for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) |
| 670 { |
| 671 // If session is active |
| 672 if(gr.contextArray[i] != 0) |
| 673 { |
| 674 // If session is saved |
| 675 if (gr.contextArray[i] > MAX_LOADED_SESSIONS) |
| 676 { |
| 677 if(handleList->count < count) |
| 678 { |
| 679 // If we have not filled up the return list, add this |
| 680 // session handle to it |
| 681 handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST; |
| 682 handleList->count++; |
| 683 } |
| 684 else |
| 685 { |
| 686 // If the return list is full but we still have loaded object |
| 687 // available, report this and stop iterating |
| 688 more = YES; |
| 689 break; |
| 690 } |
| 691 } |
| 692 } |
| 693 } |
| 694 |
| 695 return more; |
| 696 |
| 697 } |
| |
| |
| 8.8.6.11 SessionCapGetLoadedNumber() |
| |
| This function return the number of authorization sessions currently loaded into TPM RAM. |
| |
| 698 UINT32 |
| 699 SessionCapGetLoadedNumber( |
| 700 void |
| 701 ) |
| 702 { |
| 703 return MAX_LOADED_SESSIONS - s_freeSessionSlots; |
| 704 } |
| |
| |
| 8.8.6.12 SessionCapGetLoadedAvail() |
| |
| This function returns the number of additional authorization sessions, of any type, that could be loaded |
| into TPM RAM. |
| |
| NOTE: In other implementations, this number may just be an estimate. The only requirement for the estimate is, if it is |
| one or more, then at least one session must be loadable. |
| |
| 705 UINT32 |
| 706 SessionCapGetLoadedAvail( |
| 707 void |
| 708 ) |
| |
| Page 208 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 709 { |
| 710 return s_freeSessionSlots; |
| 711 } |
| |
| |
| 8.8.6.13 SessionCapGetActiveNumber() |
| |
| This function returns the number of active authorization sessions currently being tracked by the TPM. |
| |
| 712 UINT32 |
| 713 SessionCapGetActiveNumber( |
| 714 void |
| 715 ) |
| 716 { |
| 717 UINT32 i; |
| 718 UINT32 num = 0; |
| 719 |
| 720 // Iterate the context array to find the number of non-zero slots |
| 721 for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) |
| 722 { |
| 723 if(gr.contextArray[i] != 0) num++; |
| 724 } |
| 725 |
| 726 return num; |
| 727 } |
| |
| |
| 8.8.6.14 SessionCapGetActiveAvail() |
| |
| This function returns the number of additional authorization sessions, of any type, that could be created. |
| This not the number of slots for sessions, but the number of additional sessions that the TPM is capable |
| of tracking. |
| |
| 728 UINT32 |
| 729 SessionCapGetActiveAvail( |
| 730 void |
| 731 ) |
| 732 { |
| 733 UINT32 i; |
| 734 UINT32 num = 0; |
| 735 |
| 736 // Iterate the context array to find the number of zero slots |
| 737 for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) |
| 738 { |
| 739 if(gr.contextArray[i] == 0) num++; |
| 740 } |
| 741 |
| 742 return num; |
| 743 } |
| |
| |
| 8.9 Time.c |
| |
| 8.9.1 Introduction |
| |
| This file contains the functions relating to the TPM's time functions including the interface to the |
| implementation-specific time functions. |
| |
| 8.9.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| 2 #include "Platform.h" |
| |
| Family "2.0" TCG Published Page 209 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 8.9.3 Functions |
| |
| 8.9.3.1 TimePowerOn() |
| |
| This function initialize time info at _TPM_Init(). |
| |
| 3 void |
| 4 TimePowerOn( |
| 5 void |
| 6 ) |
| 7 { |
| 8 TPM_SU orderlyShutDown; |
| 9 |
| 10 // Read orderly data info from NV memory |
| 11 NvReadReserved(NV_ORDERLY_DATA, &go); |
| 12 |
| 13 // Read orderly shut down state flag |
| 14 NvReadReserved(NV_ORDERLY, &orderlyShutDown); |
| 15 |
| 16 // If the previous cycle is orderly shut down, the value of the safe bit |
| 17 // the same as previously saved. Otherwise, it is not safe. |
| 18 if(orderlyShutDown == SHUTDOWN_NONE) |
| 19 go.clockSafe= NO; |
| 20 else |
| 21 go.clockSafe = YES; |
| 22 |
| 23 // Set the initial state of the DRBG |
| 24 CryptDrbgGetPutState(PUT_STATE); |
| 25 |
| 26 // Clear time since TPM power on |
| 27 g_time = 0; |
| 28 |
| 29 return; |
| 30 } |
| |
| |
| 8.9.3.2 TimeStartup() |
| |
| This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at |
| TPM2_Startup(). |
| |
| 31 void |
| 32 TimeStartup( |
| 33 STARTUP_TYPE type // IN: start up type |
| 34 ) |
| 35 { |
| 36 if(type == SU_RESUME) |
| 37 { |
| 38 // Resume sequence |
| 39 gr.restartCount++; |
| 40 } |
| 41 else |
| 42 { |
| 43 if(type == SU_RESTART) |
| 44 { |
| 45 // Hibernate sequence |
| 46 gr.clearCount++; |
| 47 gr.restartCount++; |
| 48 } |
| 49 else |
| 50 { |
| 51 // Reset sequence |
| 52 // Increase resetCount |
| 53 gp.resetCount++; |
| |
| Page 210 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 54 |
| 55 // Write resetCount to NV |
| 56 NvWriteReserved(NV_RESET_COUNT, &gp.resetCount); |
| 57 gp.totalResetCount++; |
| 58 |
| 59 // We do not expect the total reset counter overflow during the life |
| 60 // time of TPM. if it ever happens, TPM will be put to failure mode |
| 61 // and there is no way to recover it. |
| 62 // The reason that there is no recovery is that we don't increment |
| 63 // the NV totalResetCount when incrementing would make it 0. When the |
| 64 // TPM starts up again, the old value of totalResetCount will be read |
| 65 // and we will get right back to here with the increment failing. |
| 66 if(gp.totalResetCount == 0) |
| 67 FAIL(FATAL_ERROR_INTERNAL); |
| 68 |
| 69 // Write total reset counter to NV |
| 70 NvWriteReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount); |
| 71 |
| 72 // Reset restartCount |
| 73 gr.restartCount = 0; |
| 74 } |
| 75 } |
| 76 |
| 77 return; |
| 78 } |
| |
| |
| 8.9.3.3 TimeUpdateToCurrent() |
| |
| This function updates the Time and Clock in the global TPMS_TIME_INFO structure. |
| In this implementation, Time and Clock are updated at the beginning of each command and the values |
| are unchanged for the duration of the command. |
| Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance if |
| NV is not available. When clock is not advancing, any function that uses Clock will fail and return |
| TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE. |
| This implementations does not do rate limiting. If the implementation does do rate limiting, then the Clock |
| update should not be inhibited even when doing rather limiting. |
| |
| 79 void |
| 80 TimeUpdateToCurrent( |
| 81 void |
| 82 ) |
| 83 { |
| 84 UINT64 oldClock; |
| 85 UINT64 elapsed; |
| 86 #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1) |
| 87 |
| 88 // Can't update time during the dark interval or when rate limiting. |
| 89 if(NvIsAvailable() != TPM_RC_SUCCESS) |
| 90 return; |
| 91 |
| 92 // Save the old clock value |
| 93 oldClock = go.clock; |
| 94 |
| 95 // Update the time info to current |
| 96 elapsed = _plat__ClockTimeElapsed(); |
| 97 go.clock += elapsed; |
| 98 g_time += elapsed; |
| 99 |
| 100 // Check to see if the update has caused a need for an nvClock update |
| 101 // CLOCK_UPDATE_MASK is measured by second, while the value in go.clock is |
| 102 // recorded by millisecond. Align the clock value to second before the bit |
| |
| |
| Family "2.0" TCG Published Page 211 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 103 // operations |
| 104 if( ((go.clock/1000) | CLOCK_UPDATE_MASK) |
| 105 > ((oldClock/1000) | CLOCK_UPDATE_MASK)) |
| 106 { |
| 107 // Going to update the time state so the safe flag |
| 108 // should be set |
| 109 go.clockSafe = YES; |
| 110 |
| 111 // Get the DRBG state before updating orderly data |
| 112 CryptDrbgGetPutState(GET_STATE); |
| 113 |
| 114 NvWriteReserved(NV_ORDERLY_DATA, &go); |
| 115 } |
| 116 |
| 117 // Call self healing logic for dictionary attack parameters |
| 118 DASelfHeal(); |
| 119 |
| 120 return; |
| 121 } |
| |
| |
| 8.9.3.4 TimeSetAdjustRate() |
| |
| This function is used to perform rate adjustment on Time and Clock. |
| |
| 122 void |
| 123 TimeSetAdjustRate( |
| 124 TPM_CLOCK_ADJUST adjust // IN: adjust constant |
| 125 ) |
| 126 { |
| 127 switch(adjust) |
| 128 { |
| 129 case TPM_CLOCK_COARSE_SLOWER: |
| 130 _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE); |
| 131 break; |
| 132 case TPM_CLOCK_COARSE_FASTER: |
| 133 _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE); |
| 134 break; |
| 135 case TPM_CLOCK_MEDIUM_SLOWER: |
| 136 _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM); |
| 137 break; |
| 138 case TPM_CLOCK_MEDIUM_FASTER: |
| 139 _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM); |
| 140 break; |
| 141 case TPM_CLOCK_FINE_SLOWER: |
| 142 _plat__ClockAdjustRate(CLOCK_ADJUST_FINE); |
| 143 break; |
| 144 case TPM_CLOCK_FINE_FASTER: |
| 145 _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE); |
| 146 break; |
| 147 case TPM_CLOCK_NO_CHANGE: |
| 148 break; |
| 149 default: |
| 150 pAssert(FALSE); |
| 151 break; |
| 152 } |
| 153 |
| 154 return; |
| 155 } |
| |
| |
| 8.9.3.5 TimeGetRange() |
| |
| This function is used to access TPMS_TIME_INFO. The TPMS_TIME_INFO structure is treaded as an |
| array of bytes, and a byte offset and length determine what bytes are returned. |
| |
| Page 212 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_RANGE invalid data range |
| |
| 156 TPM_RC |
| 157 TimeGetRange( |
| 158 UINT16 offset, // IN: offset in TPMS_TIME_INFO |
| 159 UINT16 size, // IN: size of data |
| 160 TIME_INFO *dataBuffer // OUT: result buffer |
| 161 ) |
| 162 { |
| 163 TPMS_TIME_INFO timeInfo; |
| 164 UINT16 infoSize; |
| 165 BYTE infoData[sizeof(TPMS_TIME_INFO)]; |
| 166 BYTE *buffer; |
| 167 |
| 168 // Fill TPMS_TIME_INFO structure |
| 169 timeInfo.time = g_time; |
| 170 TimeFillInfo(&timeInfo.clockInfo); |
| 171 |
| 172 // Marshal TPMS_TIME_INFO to canonical form |
| 173 buffer = infoData; |
| 174 infoSize = TPMS_TIME_INFO_Marshal(&timeInfo, &buffer, NULL); |
| 175 |
| 176 // Check if the input range is valid |
| 177 if(offset + size > infoSize) return TPM_RC_RANGE; |
| 178 |
| 179 // Copy info data to output buffer |
| 180 MemoryCopy(dataBuffer, infoData + offset, size, sizeof(TIME_INFO)); |
| 181 |
| 182 return TPM_RC_SUCCESS; |
| 183 } |
| |
| |
| 8.9.3.6 TimeFillInfo |
| |
| This function gathers information to fill in a TPMS_CLOCK_INFO structure. |
| |
| 184 void |
| 185 TimeFillInfo( |
| 186 TPMS_CLOCK_INFO *clockInfo |
| 187 ) |
| 188 { |
| 189 clockInfo->clock = go.clock; |
| 190 clockInfo->resetCount = gp.resetCount; |
| 191 clockInfo->restartCount = gr.restartCount; |
| 192 |
| 193 // If NV is not available, clock stopped advancing and the value reported is |
| 194 // not "safe". |
| 195 if(NvIsAvailable() == TPM_RC_SUCCESS) |
| 196 clockInfo->safe = go.clockSafe; |
| 197 else |
| 198 clockInfo->safe = NO; |
| 199 |
| 200 return; |
| 201 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 213 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| 9 Support |
| |
| 9.1 AlgorithmCap.c |
| |
| 9.1.1 Description |
| |
| This file contains the algorithm property definitions for the algorithms and the code for the |
| TPM2_GetCapability() to return the algorithm properties. |
| |
| 9.1.2 Includes and Defines |
| |
| 1 #include "InternalRoutines.h" |
| 2 typedef struct |
| 3 { |
| 4 TPM_ALG_ID algID; |
| 5 TPMA_ALGORITHM attributes; |
| 6 } ALGORITHM; |
| 7 static const ALGORITHM s_algorithms[] = |
| 8 { |
| 9 #ifdef TPM_ALG_RSA |
| 10 {TPM_ALG_RSA, {1, 0, 0, 1, 0, 0, 0, 0, 0}}, |
| 11 #endif |
| 12 #ifdef TPM_ALG_DES |
| 13 {TPM_ALG_DES, {0, 1, 0, 0, 0, 0, 0, 0, 0}}, |
| 14 #endif |
| 15 #ifdef TPM_ALG_3DES |
| 16 {TPM_ALG__3DES, {0, 1, 0, 0, 0, 0, 0, 0, 0}}, |
| 17 #endif |
| 18 #ifdef TPM_ALG_SHA1 |
| 19 {TPM_ALG_SHA1, {0, 0, 1, 0, 0, 0, 0, 0, 0}}, |
| 20 #endif |
| 21 #ifdef TPM_ALG_HMAC |
| 22 {TPM_ALG_HMAC, {0, 0, 1, 0, 0, 1, 0, 0, 0}}, |
| 23 #endif |
| 24 #ifdef TPM_ALG_AES |
| 25 {TPM_ALG_AES, {0, 1, 0, 0, 0, 0, 0, 0, 0}}, |
| 26 #endif |
| 27 #ifdef TPM_ALG_MGF1 |
| 28 {TPM_ALG_MGF1, {0, 0, 1, 0, 0, 0, 0, 1, 0}}, |
| 29 #endif |
| 30 |
| 31 {TPM_ALG_KEYEDHASH, {0, 0, 1, 1, 0, 1, 1, 0, 0}}, |
| 32 |
| 33 #ifdef TPM_ALG_XOR |
| 34 {TPM_ALG_XOR, {0, 1, 1, 0, 0, 0, 0, 0, 0}}, |
| 35 #endif |
| 36 |
| 37 #ifdef TPM_ALG_SHA256 |
| 38 {TPM_ALG_SHA256, {0, 0, 1, 0, 0, 0, 0, 0, 0}}, |
| 39 #endif |
| 40 #ifdef TPM_ALG_SHA384 |
| 41 {TPM_ALG_SHA384, {0, 0, 1, 0, 0, 0, 0, 0, 0}}, |
| 42 #endif |
| 43 #ifdef TPM_ALG_SHA512 |
| 44 {TPM_ALG_SHA512, {0, 0, 1, 0, 0, 0, 0, 0, 0}}, |
| 45 #endif |
| 46 #ifdef TPM_ALG_WHIRLPOOL512 |
| 47 {TPM_ALG_WHIRLPOOL512, {0, 0, 1, 0, 0, 0, 0, 0, 0}}, |
| 48 #endif |
| 49 #ifdef TPM_ALG_SM3_256 |
| 50 {TPM_ALG_SM3_256, {0, 0, 1, 0, 0, 0, 0, 0, 0}}, |
| 51 #endif |
| |
| Page 214 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 52 #ifdef TPM_ALG_SM4 |
| 53 {TPM_ALG_SM4, {0, 1, 0, 0, 0, 0, 0, 0, 0}}, |
| 54 #endif |
| 55 #ifdef TPM_ALG_RSASSA |
| 56 {TPM_ALG_RSASSA, {1, 0, 0, 0, 0, 1, 0, 0, 0}}, |
| 57 #endif |
| 58 #ifdef TPM_ALG_RSAES |
| 59 {TPM_ALG_RSAES, {1, 0, 0, 0, 0, 0, 1, 0, 0}}, |
| 60 #endif |
| 61 #ifdef TPM_ALG_RSAPSS |
| 62 {TPM_ALG_RSAPSS, {1, 0, 0, 0, 0, 1, 0, 0, 0}}, |
| 63 #endif |
| 64 #ifdef TPM_ALG_OAEP |
| 65 {TPM_ALG_OAEP, {1, 0, 0, 0, 0, 0, 1, 0, 0}}, |
| 66 #endif |
| 67 #ifdef TPM_ALG_ECDSA |
| 68 {TPM_ALG_ECDSA, {1, 0, 0, 0, 0, 1, 0, 1, 0}}, |
| 69 #endif |
| 70 #ifdef TPM_ALG_ECDH |
| 71 {TPM_ALG_ECDH, {1, 0, 0, 0, 0, 0, 0, 1, 0}}, |
| 72 #endif |
| 73 #ifdef TPM_ALG_ECDAA |
| 74 {TPM_ALG_ECDAA, {1, 0, 0, 0, 0, 1, 0, 0, 0}}, |
| 75 #endif |
| 76 #ifdef TPM_ALG_ECSCHNORR |
| 77 {TPM_ALG_ECSCHNORR, {1, 0, 0, 0, 0, 1, 0, 0, 0}}, |
| 78 #endif |
| 79 #ifdef TPM_ALG_KDF1_SP800_56a |
| 80 {TPM_ALG_KDF1_SP800_56a,{0, 0, 1, 0, 0, 0, 0, 1, 0}}, |
| 81 #endif |
| 82 #ifdef TPM_ALG_KDF2 |
| 83 {TPM_ALG_KDF2, {0, 0, 1, 0, 0, 0, 0, 1, 0}}, |
| 84 #endif |
| 85 #ifdef TPM_ALG_KDF1_SP800_108 |
| 86 {TPM_ALG_KDF1_SP800_108,{0, 0, 1, 0, 0, 0, 0, 1, 0}}, |
| 87 #endif |
| 88 #ifdef TPM_ALG_ECC |
| 89 {TPM_ALG_ECC, {1, 0, 0, 1, 0, 0, 0, 0, 0}}, |
| 90 #endif |
| 91 |
| 92 {TPM_ALG_SYMCIPHER, {0, 0, 0, 1, 0, 0, 0, 0, 0}}, |
| 93 |
| 94 #ifdef TPM_ALG_CTR |
| 95 {TPM_ALG_CTR, {0, 1, 0, 0, 0, 0, 1, 0, 0}}, |
| 96 #endif |
| 97 #ifdef TPM_ALG_OFB |
| 98 {TPM_ALG_OFB, {0, 1, 0, 0, 0, 0, 1, 0, 0}}, |
| 99 #endif |
| 100 #ifdef TPM_ALG_CBC |
| 101 {TPM_ALG_CBC, {0, 1, 0, 0, 0, 0, 1, 0, 0}}, |
| 102 #endif |
| 103 #ifdef TPM_ALG_CFB |
| 104 {TPM_ALG_CFB, {0, 1, 0, 0, 0, 0, 1, 0, 0}}, |
| 105 #endif |
| 106 #ifdef TPM_ALG_ECB |
| 107 {TPM_ALG_ECB, {0, 1, 0, 0, 0, 0, 1, 0, 0}}, |
| 108 #endif |
| 109 }; |
| |
| |
| 9.1.3 AlgorithmCapGetImplemented() |
| |
| This function is used by TPM2_GetCapability() to return a list of the implemented algorithms. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 215 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| YES more algorithms to report |
| NO no more algorithms to report |
| |
| 110 TPMI_YES_NO |
| 111 AlgorithmCapGetImplemented( |
| 112 TPM_ALG_ID algID, // IN: the starting algorithm ID |
| 113 UINT32 count, // IN: count of returned algorithms |
| 114 TPML_ALG_PROPERTY *algList // OUT: algorithm list |
| 115 ) |
| 116 { |
| 117 TPMI_YES_NO more = NO; |
| 118 UINT32 i; |
| 119 UINT32 algNum; |
| 120 |
| 121 // initialize output algorithm list |
| 122 algList->count = 0; |
| 123 |
| 124 // The maximum count of algorithms we may return is MAX_CAP_ALGS. |
| 125 if(count > MAX_CAP_ALGS) |
| 126 count = MAX_CAP_ALGS; |
| 127 |
| 128 // Compute how many algorithms are defined in s_algorithms array. |
| 129 algNum = sizeof(s_algorithms) / sizeof(s_algorithms[0]); |
| 130 |
| 131 // Scan the implemented algorithm list to see if there is a match to 'algID'. |
| 132 for(i = 0; i < algNum; i++) |
| 133 { |
| 134 // If algID is less than the starting algorithm ID, skip it |
| 135 if(s_algorithms[i].algID < algID) |
| 136 continue; |
| 137 if(algList->count < count) |
| 138 { |
| 139 // If we have not filled up the return list, add more algorithms |
| 140 // to it |
| 141 algList->algProperties[algList->count].alg = s_algorithms[i].algID; |
| 142 algList->algProperties[algList->count].algProperties = |
| 143 s_algorithms[i].attributes; |
| 144 algList->count++; |
| 145 } |
| 146 else |
| 147 { |
| 148 // If the return list is full but we still have algorithms |
| 149 // available, report this and stop scanning. |
| 150 more = YES; |
| 151 break; |
| 152 } |
| 153 |
| 154 } |
| 155 |
| 156 return more; |
| 157 |
| 158 } |
| 159 LIB_EXPORT |
| 160 void |
| 161 AlgorithmGetImplementedVector( |
| 162 ALGORITHM_VECTOR *implemented // OUT: the implemented bits are SET |
| 163 ) |
| 164 { |
| 165 int index; |
| 166 |
| 167 // Nothing implemented until we say it is |
| 168 MemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR)); |
| |
| Page 216 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 169 |
| 170 for(index = (sizeof(s_algorithms) / sizeof(s_algorithms[0])) - 1; |
| 171 index >= 0; |
| 172 index--) |
| 173 SET_BIT(s_algorithms[index].algID, *implemented); |
| 174 return; |
| 175 } |
| |
| |
| 9.2 Bits.c |
| |
| 9.2.1 Introduction |
| |
| This file contains bit manipulation routines. They operate on bit arrays. |
| The 0th bit in the array is the right-most bit in the 0th octet in the array. |
| |
| NOTE: If pAssert() is defined, the functions will assert if the indicated bit number is outside of the range of bArray. How |
| the assert is handled is implementation dependent. |
| |
| |
| 9.2.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| 9.2.3 Functions |
| |
| 9.2.3.1 BitIsSet() |
| |
| This function is used to check the setting of a bit in an array of bits. |
| |
| Return Value Meaning |
| |
| TRUE bit is set |
| FALSE bit is not set |
| |
| 2 BOOL |
| 3 BitIsSet( |
| 4 unsigned int bitNum, // IN: number of the bit in 'bArray' |
| 5 BYTE *bArray, // IN: array containing the bit |
| 6 unsigned int arraySize // IN: size in bytes of 'bArray' |
| 7 ) |
| 8 { |
| 9 pAssert(arraySize > (bitNum >> 3)); |
| 10 return((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0); |
| 11 } |
| |
| |
| 9.2.3.2 BitSet() |
| |
| This function will set the indicated bit in bArray. |
| |
| 12 void |
| 13 BitSet( |
| 14 unsigned int bitNum, // IN: number of the bit in 'bArray' |
| 15 BYTE *bArray, // IN: array containing the bit |
| 16 unsigned int arraySize // IN: size in bytes of 'bArray' |
| 17 ) |
| 18 { |
| 19 pAssert(arraySize > bitNum/8); |
| 20 bArray[bitNum >> 3] |= (1 << (bitNum & 7)); |
| |
| Family "2.0" TCG Published Page 217 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 21 } |
| |
| |
| 9.2.3.3 BitClear() |
| |
| This function will clear the indicated bit in bArray. |
| |
| 22 void |
| 23 BitClear( |
| 24 unsigned int bitNum, // IN: number of the bit in 'bArray'. |
| 25 BYTE *bArray, // IN: array containing the bit |
| 26 unsigned int arraySize // IN: size in bytes of 'bArray' |
| 27 ) |
| 28 { |
| 29 pAssert(arraySize > bitNum/8); |
| 30 bArray[bitNum >> 3] &= ~(1 << (bitNum & 7)); |
| 31 } |
| |
| |
| 9.3 CommandAttributeData.c |
| |
| This is the command code attribute array for GetCapability(). Both this array and s_commandAttributes |
| provides command code attributes, but tuned for different purpose |
| |
| 1 static const TPMA_CC s_ccAttr [] = { |
| 2 {0x011f, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_UndefineSpaceSpecial |
| 3 {0x0120, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_EvictControl |
| 4 {0x0121, 0, 1, 1, 0, 1, 0, 0, 0}, // TPM_CC_HierarchyControl |
| 5 {0x0122, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_UndefineSpace |
| 6 {0x0123, 0, 0, 0, 0, 0, 0, 0, 0}, // No command |
| 7 {0x0124, 0, 1, 1, 0, 1, 0, 0, 0}, // TPM_CC_ChangeEPS |
| 8 {0x0125, 0, 1, 1, 0, 1, 0, 0, 0}, // TPM_CC_ChangePPS |
| 9 {0x0126, 0, 1, 1, 0, 1, 0, 0, 0}, // TPM_CC_Clear |
| 10 {0x0127, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_ClearControl |
| 11 {0x0128, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_ClockSet |
| 12 {0x0129, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_HierarchyChangeAuth |
| 13 {0x012a, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_NV_DefineSpace |
| 14 {0x012b, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_PCR_Allocate |
| 15 {0x012c, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_PCR_SetAuthPolicy |
| 16 {0x012d, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_PP_Commands |
| 17 {0x012e, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_SetPrimaryPolicy |
| 18 {0x012f, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_FieldUpgradeStart |
| 19 {0x0130, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_ClockRateAdjust |
| 20 {0x0131, 0, 0, 0, 0, 1, 1, 0, 0}, // TPM_CC_CreatePrimary |
| 21 {0x0132, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_NV_GlobalWriteLock |
| 22 {0x0133, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_GetCommandAuditDigest |
| 23 {0x0134, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_Increment |
| 24 {0x0135, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_SetBits |
| 25 {0x0136, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_Extend |
| 26 {0x0137, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_Write |
| 27 {0x0138, 0, 1, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_WriteLock |
| 28 {0x0139, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_DictionaryAttackLockReset |
| 29 {0x013a, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_DictionaryAttackParameters |
| 30 {0x013b, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_NV_ChangeAuth |
| 31 {0x013c, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_PCR_Event |
| 32 {0x013d, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_PCR_Reset |
| 33 {0x013e, 0, 0, 0, 1, 1, 0, 0, 0}, // TPM_CC_SequenceComplete |
| 34 {0x013f, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_SetAlgorithmSet |
| 35 {0x0140, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_SetCommandCodeAuditStatus |
| 36 {0x0141, 0, 1, 0, 0, 0, 0, 0, 0}, // TPM_CC_FieldUpgradeData |
| 37 {0x0142, 0, 1, 0, 0, 0, 0, 0, 0}, // TPM_CC_IncrementalSelfTest |
| 38 {0x0143, 0, 1, 0, 0, 0, 0, 0, 0}, // TPM_CC_SelfTest |
| 39 {0x0144, 0, 1, 0, 0, 0, 0, 0, 0}, // TPM_CC_Startup |
| 40 {0x0145, 0, 1, 0, 0, 0, 0, 0, 0}, // TPM_CC_Shutdown |
| 41 {0x0146, 0, 1, 0, 0, 0, 0, 0, 0}, // TPM_CC_StirRandom |
| |
| Page 218 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 42 {0x0147, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_ActivateCredential |
| 43 {0x0148, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_Certify |
| 44 {0x0149, 0, 0, 0, 0, 3, 0, 0, 0}, // TPM_CC_PolicyNV |
| 45 {0x014a, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_CertifyCreation |
| 46 {0x014b, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_Duplicate |
| 47 {0x014c, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_GetTime |
| 48 {0x014d, 0, 0, 0, 0, 3, 0, 0, 0}, // TPM_CC_GetSessionAuditDigest |
| 49 {0x014e, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_Read |
| 50 {0x014f, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_NV_ReadLock |
| 51 {0x0150, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_ObjectChangeAuth |
| 52 {0x0151, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_PolicySecret |
| 53 {0x0152, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_Rewrap |
| 54 {0x0153, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_Create |
| 55 {0x0154, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_ECDH_ZGen |
| 56 {0x0155, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_HMAC |
| 57 {0x0156, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_Import |
| 58 {0x0157, 0, 0, 0, 0, 1, 1, 0, 0}, // TPM_CC_Load |
| 59 {0x0158, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_Quote |
| 60 {0x0159, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_RSA_Decrypt |
| 61 {0x015a, 0, 0, 0, 0, 0, 0, 0, 0}, // No command |
| 62 {0x015b, 0, 0, 0, 0, 1, 1, 0, 0}, // TPM_CC_HMAC_Start |
| 63 {0x015c, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_SequenceUpdate |
| 64 {0x015d, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_Sign |
| 65 {0x015e, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_Unseal |
| 66 {0x015f, 0, 0, 0, 0, 0, 0, 0, 0}, // No command |
| 67 {0x0160, 0, 0, 0, 0, 2, 0, 0, 0}, // TPM_CC_PolicySigned |
| 68 {0x0161, 0, 0, 0, 0, 0, 1, 0, 0}, // TPM_CC_ContextLoad |
| 69 {0x0162, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_ContextSave |
| 70 {0x0163, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_ECDH_KeyGen |
| 71 {0x0164, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_EncryptDecrypt |
| 72 {0x0165, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_FlushContext |
| 73 {0x0166, 0, 0, 0, 0, 0, 0, 0, 0}, // No command |
| 74 {0x0167, 0, 0, 0, 0, 0, 1, 0, 0}, // TPM_CC_LoadExternal |
| 75 {0x0168, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_MakeCredential |
| 76 {0x0169, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_NV_ReadPublic |
| 77 {0x016a, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyAuthorize |
| 78 {0x016b, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyAuthValue |
| 79 {0x016c, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyCommandCode |
| 80 {0x016d, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyCounterTimer |
| 81 {0x016e, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyCpHash |
| 82 {0x016f, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyLocality |
| 83 {0x0170, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyNameHash |
| 84 {0x0171, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyOR |
| 85 {0x0172, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyTicket |
| 86 {0x0173, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_ReadPublic |
| 87 {0x0174, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_RSA_Encrypt |
| 88 {0x0175, 0, 0, 0, 0, 0, 0, 0, 0}, // No command |
| 89 {0x0176, 0, 0, 0, 0, 2, 1, 0, 0}, // TPM_CC_StartAuthSession |
| 90 {0x0177, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_VerifySignature |
| 91 {0x0178, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_ECC_Parameters |
| 92 {0x0179, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_FirmwareRead |
| 93 {0x017a, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_GetCapability |
| 94 {0x017b, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_GetRandom |
| 95 {0x017c, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_GetTestResult |
| 96 {0x017d, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_Hash |
| 97 {0x017e, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_PCR_Read |
| 98 {0x017f, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyPCR |
| 99 {0x0180, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyRestart |
| 100 {0x0181, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_ReadClock |
| 101 {0x0182, 0, 1, 0, 0, 1, 0, 0, 0}, // TPM_CC_PCR_Extend |
| 102 {0x0183, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PCR_SetAuthValue |
| 103 {0x0184, 0, 0, 0, 0, 3, 0, 0, 0}, // TPM_CC_NV_Certify |
| 104 {0x0185, 0, 1, 0, 1, 2, 0, 0, 0}, // TPM_CC_EventSequenceComplete |
| 105 {0x0186, 0, 0, 0, 0, 0, 1, 0, 0}, // TPM_CC_HashSequenceStart |
| 106 {0x0187, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyPhysicalPresence |
| 107 {0x0188, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyDuplicationSelect |
| |
| Family "2.0" TCG Published Page 219 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 108 {0x0189, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyGetDigest |
| 109 {0x018a, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_TestParms |
| 110 {0x018b, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_Commit |
| 111 {0x018c, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_PolicyPassword |
| 112 {0x018d, 0, 0, 0, 0, 1, 0, 0, 0}, // TPM_CC_ZGen_2Phase |
| 113 {0x018e, 0, 0, 0, 0, 0, 0, 0, 0}, // TPM_CC_EC_Ephemeral |
| 114 {0x018f, 0, 0, 0, 0, 1, 0, 0, 0} // TPM_CC_PolicyNvWritten |
| 115 }; |
| 116 typedef UINT16 _ATTR_; |
| 117 #define NOT_IMPLEMENTED (_ATTR_)(0) |
| 118 #define ENCRYPT_2 (_ATTR_)(1 << 0) |
| 119 #define ENCRYPT_4 (_ATTR_)(1 << 1) |
| 120 #define DECRYPT_2 (_ATTR_)(1 << 2) |
| 121 #define DECRYPT_4 (_ATTR_)(1 << 3) |
| 122 #define HANDLE_1_USER (_ATTR_)(1 << 4) |
| 123 #define HANDLE_1_ADMIN (_ATTR_)(1 << 5) |
| 124 #define HANDLE_1_DUP (_ATTR_)(1 << 6) |
| 125 #define HANDLE_2_USER (_ATTR_)(1 << 7) |
| 126 #define PP_COMMAND (_ATTR_)(1 << 8) |
| 127 #define IS_IMPLEMENTED (_ATTR_)(1 << 9) |
| 128 #define NO_SESSIONS (_ATTR_)(1 << 10) |
| 129 #define NV_COMMAND (_ATTR_)(1 << 11) |
| 130 #define PP_REQUIRED (_ATTR_)(1 << 12) |
| 131 #define R_HANDLE (_ATTR_)(1 << 13) |
| |
| This is the command code attribute structure. |
| |
| 132 typedef UINT16 COMMAND_ATTRIBUTES; |
| 133 static const COMMAND_ATTRIBUTES s_commandAttributes [] = { |
| 134 (_ATTR_)(CC_NV_UndefineSpaceSpecial * |
| (IS_IMPLEMENTED+HANDLE_1_ADMIN+HANDLE_2_USER+PP_COMMAND)), // 0x011f |
| 135 (_ATTR_)(CC_EvictControl * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0120 |
| 136 (_ATTR_)(CC_HierarchyControl * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0121 |
| 137 (_ATTR_)(CC_NV_UndefineSpace * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0122 |
| 138 (_ATTR_) (NOT_IMPLEMENTED), |
| // 0x0123 - Not assigned |
| 139 (_ATTR_)(CC_ChangeEPS * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0124 |
| 140 (_ATTR_)(CC_ChangePPS * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0125 |
| 141 (_ATTR_)(CC_Clear * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0126 |
| 142 (_ATTR_)(CC_ClearControl * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0127 |
| 143 (_ATTR_)(CC_ClockSet * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0128 |
| 144 (_ATTR_)(CC_HierarchyChangeAuth * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), // 0x0129 |
| 145 (_ATTR_)(CC_NV_DefineSpace * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), // 0x012a |
| 146 (_ATTR_)(CC_PCR_Allocate * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x012b |
| 147 (_ATTR_)(CC_PCR_SetAuthPolicy * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), // 0x012c |
| 148 (_ATTR_)(CC_PP_Commands * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_REQUIRED)), // 0x012d |
| 149 (_ATTR_)(CC_SetPrimaryPolicy * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), // 0x012e |
| 150 (_ATTR_)(CC_FieldUpgradeStart * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+PP_COMMAND)), // 0x012f |
| 151 (_ATTR_)(CC_ClockRateAdjust * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0130 |
| |
| |
| Page 220 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 152 (_ATTR_)(CC_CreatePrimary * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)), // 0x0131 |
| 153 (_ATTR_)(CC_NV_GlobalWriteLock * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0132 |
| 154 (_ATTR_)(CC_GetCommandAuditDigest * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), // 0x0133 |
| 155 (_ATTR_)(CC_NV_Increment * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x0134 |
| 156 (_ATTR_)(CC_NV_SetBits * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x0135 |
| 157 (_ATTR_)(CC_NV_Extend * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x0136 |
| 158 (_ATTR_)(CC_NV_Write * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x0137 |
| 159 (_ATTR_)(CC_NV_WriteLock * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x0138 |
| 160 (_ATTR_)(CC_DictionaryAttackLockReset * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x0139 |
| 161 (_ATTR_)(CC_DictionaryAttackParameters * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x013a |
| 162 (_ATTR_)(CC_NV_ChangeAuth * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN)), // 0x013b |
| 163 (_ATTR_)(CC_PCR_Event * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x013c |
| 164 (_ATTR_)(CC_PCR_Reset * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x013d |
| 165 (_ATTR_)(CC_SequenceComplete * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x013e |
| 166 (_ATTR_)(CC_SetAlgorithmSet * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x013f |
| 167 (_ATTR_)(CC_SetCommandCodeAuditStatus * |
| (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), // 0x0140 |
| 168 (_ATTR_)(CC_FieldUpgradeData * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x0141 |
| 169 (_ATTR_)(CC_IncrementalSelfTest * (IS_IMPLEMENTED)), |
| // 0x0142 |
| 170 (_ATTR_)(CC_SelfTest * (IS_IMPLEMENTED)), |
| // 0x0143 |
| 171 (_ATTR_)(CC_Startup * (IS_IMPLEMENTED+NO_SESSIONS)), |
| // 0x0144 |
| 172 (_ATTR_)(CC_Shutdown * (IS_IMPLEMENTED)), |
| // 0x0145 |
| 173 (_ATTR_)(CC_StirRandom * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x0146 |
| 174 (_ATTR_)(CC_ActivateCredential * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), // 0x0147 |
| 175 (_ATTR_)(CC_Certify * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), // 0x0148 |
| 176 (_ATTR_)(CC_PolicyNV * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x0149 |
| 177 (_ATTR_)(CC_CertifyCreation * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x014a |
| 178 (_ATTR_)(CC_Duplicate * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+ENCRYPT_2)), // 0x014b |
| 179 (_ATTR_)(CC_GetTime * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), // 0x014c |
| 180 (_ATTR_)(CC_GetSessionAuditDigest * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), // 0x014d |
| 181 (_ATTR_)(CC_NV_Read * |
| (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), // 0x014e |
| 182 (_ATTR_)(CC_NV_ReadLock * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x014f |
| 183 (_ATTR_)(CC_ObjectChangeAuth * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+ENCRYPT_2)), // 0x0150 |
| 184 (_ATTR_)(CC_PolicySecret * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0151 |
| |
| Family "2.0" TCG Published Page 221 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 185 (_ATTR_)(CC_Rewrap * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0152 |
| 186 (_ATTR_)(CC_Create * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0153 |
| 187 (_ATTR_)(CC_ECDH_ZGen * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0154 |
| 188 (_ATTR_)(CC_HMAC * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0155 |
| 189 (_ATTR_)(CC_Import * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0156 |
| 190 (_ATTR_)(CC_Load * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2+R_HANDLE)), // 0x0157 |
| 191 (_ATTR_)(CC_Quote * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0158 |
| 192 (_ATTR_)(CC_RSA_Decrypt * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x0159 |
| 193 (_ATTR_) (NOT_IMPLEMENTED), |
| // 0x015a - Not assigned |
| 194 (_ATTR_)(CC_HMAC_Start * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+R_HANDLE)), // 0x015b |
| 195 (_ATTR_)(CC_SequenceUpdate * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x015c |
| 196 (_ATTR_)(CC_Sign * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x015d |
| 197 (_ATTR_)(CC_Unseal * |
| (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), // 0x015e |
| 198 (_ATTR_) (NOT_IMPLEMENTED), |
| // 0x015f - Not assigned |
| 199 (_ATTR_)(CC_PolicySigned * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), |
| // 0x0160 |
| 200 (_ATTR_)(CC_ContextLoad * (IS_IMPLEMENTED+NO_SESSIONS+R_HANDLE)), |
| // 0x0161 |
| 201 (_ATTR_)(CC_ContextSave * (IS_IMPLEMENTED+NO_SESSIONS)), |
| // 0x0162 |
| 202 (_ATTR_)(CC_ECDH_KeyGen * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x0163 |
| 203 (_ATTR_)(CC_EncryptDecrypt * |
| (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), // 0x0164 |
| 204 (_ATTR_)(CC_FlushContext * (IS_IMPLEMENTED+NO_SESSIONS)), |
| // 0x0165 |
| 205 (_ATTR_) (NOT_IMPLEMENTED), |
| // 0x0166 - Not assigned |
| 206 (_ATTR_)(CC_LoadExternal * |
| (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)), // 0x0167 |
| 207 (_ATTR_)(CC_MakeCredential * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), |
| // 0x0168 |
| 208 (_ATTR_)(CC_NV_ReadPublic * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x0169 |
| 209 (_ATTR_)(CC_PolicyAuthorize * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x016a |
| 210 (_ATTR_)(CC_PolicyAuthValue * (IS_IMPLEMENTED)), |
| // 0x016b |
| 211 (_ATTR_)(CC_PolicyCommandCode * (IS_IMPLEMENTED)), |
| // 0x016c |
| 212 (_ATTR_)(CC_PolicyCounterTimer * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x016d |
| 213 (_ATTR_)(CC_PolicyCpHash * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x016e |
| 214 (_ATTR_)(CC_PolicyLocality * (IS_IMPLEMENTED)), |
| // 0x016f |
| 215 (_ATTR_)(CC_PolicyNameHash * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x0170 |
| 216 (_ATTR_)(CC_PolicyOR * (IS_IMPLEMENTED)), |
| // 0x0171 |
| 217 (_ATTR_)(CC_PolicyTicket * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x0172 |
| |
| Page 222 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 218 (_ATTR_)(CC_ReadPublic * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x0173 |
| 219 (_ATTR_)(CC_RSA_Encrypt * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), |
| // 0x0174 |
| 220 (_ATTR_) (NOT_IMPLEMENTED), |
| // 0x0175 - Not assigned |
| 221 (_ATTR_)(CC_StartAuthSession * |
| (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)), // 0x0176 |
| 222 (_ATTR_)(CC_VerifySignature * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x0177 |
| 223 (_ATTR_)(CC_ECC_Parameters * (IS_IMPLEMENTED)), |
| // 0x0178 |
| 224 (_ATTR_)(CC_FirmwareRead * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x0179 |
| 225 (_ATTR_)(CC_GetCapability * (IS_IMPLEMENTED)), |
| // 0x017a |
| 226 (_ATTR_)(CC_GetRandom * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x017b |
| 227 (_ATTR_)(CC_GetTestResult * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x017c |
| 228 (_ATTR_)(CC_Hash * (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), |
| // 0x017d |
| 229 (_ATTR_)(CC_PCR_Read * (IS_IMPLEMENTED)), |
| // 0x017e |
| 230 (_ATTR_)(CC_PolicyPCR * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x017f |
| 231 (_ATTR_)(CC_PolicyRestart * (IS_IMPLEMENTED)), |
| // 0x0180 |
| 232 (_ATTR_)(CC_ReadClock * (IS_IMPLEMENTED+NO_SESSIONS)), |
| // 0x0181 |
| 233 (_ATTR_)(CC_PCR_Extend * (IS_IMPLEMENTED+HANDLE_1_USER)), |
| // 0x0182 |
| 234 (_ATTR_)(CC_PCR_SetAuthValue * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), // 0x0183 |
| 235 (_ATTR_)(CC_NV_Certify * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), // 0x0184 |
| 236 (_ATTR_)(CC_EventSequenceComplete * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER)), // 0x0185 |
| 237 (_ATTR_)(CC_HashSequenceStart * (IS_IMPLEMENTED+DECRYPT_2+R_HANDLE)), |
| // 0x0186 |
| 238 (_ATTR_)(CC_PolicyPhysicalPresence * (IS_IMPLEMENTED)), |
| // 0x0187 |
| 239 (_ATTR_)(CC_PolicyDuplicationSelect * (IS_IMPLEMENTED+DECRYPT_2)), |
| // 0x0188 |
| 240 (_ATTR_)(CC_PolicyGetDigest * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x0189 |
| 241 (_ATTR_)(CC_TestParms * (IS_IMPLEMENTED)), |
| // 0x018a |
| 242 (_ATTR_)(CC_Commit * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x018b |
| 243 (_ATTR_)(CC_PolicyPassword * (IS_IMPLEMENTED)), |
| // 0x018c |
| 244 (_ATTR_)(CC_ZGen_2Phase * |
| (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), // 0x018d |
| 245 (_ATTR_)(CC_EC_Ephemeral * (IS_IMPLEMENTED+ENCRYPT_2)), |
| // 0x018e |
| 246 (_ATTR_)(CC_PolicyNvWritten * (IS_IMPLEMENTED)) |
| // 0x018f |
| 247 }; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 223 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.4 CommandCodeAttributes.c |
| |
| 9.4.1 Introduction |
| |
| This file contains the functions for testing various command properties. |
| |
| 9.4.2 Includes and Defines |
| |
| 1 #include "Tpm.h" |
| 2 #include "InternalRoutines.h" |
| 3 typedef UINT16 ATTRIBUTE_TYPE; |
| |
| The following file is produced from the command tables in part 3 of the specification. It defines the |
| attributes for each of the commands. |
| |
| NOTE: This file is currently produced by an automated process. Files produced from Part 2 or Part 3 tables through |
| automated processes are not included in the specification so that their is no ambiguity about the table |
| containing the information being the normative definition. |
| |
| 4 #include "CommandAttributeData.c" |
| |
| |
| 9.4.3 Command Attribute Functions |
| |
| 9.4.3.1 CommandAuthRole() |
| |
| This function returns the authorization role required of a handle. |
| |
| Return Value Meaning |
| |
| AUTH_NONE no authorization is required |
| AUTH_USER user role authorization is required |
| AUTH_ADMIN admin role authorization is required |
| AUTH_DUP duplication role authorization is required |
| |
| 5 AUTH_ROLE |
| 6 CommandAuthRole( |
| 7 TPM_CC commandCode, // IN: command code |
| 8 UINT32 handleIndex // IN: handle index (zero based) |
| 9 ) |
| 10 { |
| 11 if(handleIndex > 1) |
| 12 return AUTH_NONE; |
| 13 if(handleIndex == 0) { |
| 14 ATTRIBUTE_TYPE properties = s_commandAttributes[commandCode - TPM_CC_FIRST]; |
| 15 if(properties & HANDLE_1_USER) return AUTH_USER; |
| 16 if(properties & HANDLE_1_ADMIN) return AUTH_ADMIN; |
| 17 if(properties & HANDLE_1_DUP) return AUTH_DUP; |
| 18 return AUTH_NONE; |
| 19 } |
| 20 if(s_commandAttributes[commandCode - TPM_CC_FIRST] & HANDLE_2_USER) return |
| AUTH_USER; |
| 21 return AUTH_NONE; |
| 22 } |
| |
| |
| 9.4.3.2 CommandIsImplemented() |
| |
| This function indicates if a command is implemented. |
| |
| Page 224 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| TRUE if the command is implemented |
| FALSE if the command is not implemented |
| |
| 23 BOOL |
| 24 CommandIsImplemented( |
| 25 TPM_CC commandCode // IN: command code |
| 26 ) |
| 27 { |
| 28 if(commandCode < TPM_CC_FIRST || commandCode > TPM_CC_LAST) |
| 29 return FALSE; |
| 30 if((s_commandAttributes[commandCode - TPM_CC_FIRST] & IS_IMPLEMENTED)) |
| 31 return TRUE; |
| 32 else |
| 33 return FALSE; |
| 34 } |
| |
| |
| 9.4.3.3 CommandGetAttribute() |
| |
| return a TPMA_CC structure for the given command code |
| |
| 35 TPMA_CC |
| 36 CommandGetAttribute( |
| 37 TPM_CC commandCode // IN: command code |
| 38 ) |
| 39 { |
| 40 UINT32 size = sizeof(s_ccAttr) / sizeof(s_ccAttr[0]); |
| 41 UINT32 i; |
| 42 for(i = 0; i < size; i++) { |
| 43 if(s_ccAttr[i].commandIndex == (UINT16) commandCode) |
| 44 return s_ccAttr[i]; |
| 45 } |
| 46 |
| 47 // This function should be called in the way that the command code |
| 48 // attribute is available. |
| 49 FAIL(FATAL_ERROR_INTERNAL); |
| 50 } |
| |
| |
| 9.4.3.4 EncryptSize() |
| |
| This function returns the size of the decrypt size field. This function returns 0 if encryption is not allowed |
| |
| Return Value Meaning |
| |
| 0 encryption not allowed |
| 2 size field is two bytes |
| 4 size field is four bytes |
| |
| 51 int |
| 52 EncryptSize( |
| 53 TPM_CC commandCode // IN: commandCode |
| 54 ) |
| 55 { |
| 56 COMMAND_ATTRIBUTES ca = s_commandAttributes[commandCode - TPM_CC_FIRST]; |
| 57 if(ca & ENCRYPT_2) |
| 58 return 2; |
| 59 if(ca & ENCRYPT_4) |
| 60 return 4; |
| 61 return 0; |
| |
| Family "2.0" TCG Published Page 225 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 62 } |
| |
| |
| 9.4.3.5 DecryptSize() |
| |
| This function returns the size of the decrypt size field. This function returns 0 if decryption is not allowed |
| |
| Return Value Meaning |
| |
| 0 encryption not allowed |
| 2 size field is two bytes |
| 4 size field is four bytes |
| |
| 63 int |
| 64 DecryptSize( |
| 65 TPM_CC commandCode // IN: commandCode |
| 66 ) |
| 67 { |
| 68 COMMAND_ATTRIBUTES ca = s_commandAttributes[commandCode - TPM_CC_FIRST]; |
| 69 |
| 70 if(ca & DECRYPT_2) |
| 71 return 2; |
| 72 if(ca & DECRYPT_4) |
| 73 return 4; |
| 74 return 0; |
| 75 } |
| |
| |
| 9.4.3.6 IsSessionAllowed() |
| |
| This function indicates if the command is allowed to have sessions. |
| This function must not be called if the command is not known to be implemented. |
| |
| Return Value Meaning |
| |
| TRUE session is allowed with this command |
| FALSE session is not allowed with this command |
| |
| 76 BOOL |
| 77 IsSessionAllowed( |
| 78 TPM_CC commandCode // IN: the command to be checked |
| 79 ) |
| 80 { |
| 81 if(s_commandAttributes[commandCode - TPM_CC_FIRST] & NO_SESSIONS) |
| 82 return FALSE; |
| 83 else |
| 84 return TRUE; |
| 85 } |
| |
| |
| 9.4.3.7 IsHandleInResponse() |
| |
| 86 BOOL |
| 87 IsHandleInResponse( |
| 88 TPM_CC commandCode |
| 89 ) |
| 90 { |
| 91 if(s_commandAttributes[commandCode - TPM_CC_FIRST] & R_HANDLE) |
| 92 return TRUE; |
| 93 else |
| 94 return FALSE; |
| |
| |
| Page 226 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 95 } |
| |
| |
| 9.4.3.8 IsWriteOperation() |
| |
| Checks to see if an operation will write to NV memory |
| |
| 96 BOOL |
| 97 IsWriteOperation( |
| 98 TPM_CC command // IN: Command to check |
| 99 ) |
| 100 { |
| 101 switch (command) |
| 102 { |
| 103 case TPM_CC_NV_Write: |
| 104 case TPM_CC_NV_Increment: |
| 105 case TPM_CC_NV_SetBits: |
| 106 case TPM_CC_NV_Extend: |
| 107 // Nv write lock counts as a write operation for authorization purposes. |
| 108 // We check to see if the NV is write locked before we do the authorization |
| 109 // If it is locked, we fail the command early. |
| 110 case TPM_CC_NV_WriteLock: |
| 111 return TRUE; |
| 112 default: |
| 113 break; |
| 114 } |
| 115 return FALSE; |
| 116 } |
| |
| |
| 9.4.3.9 IsReadOperation() |
| |
| Checks to see if an operation will write to NV memory |
| |
| 117 BOOL |
| 118 IsReadOperation( |
| 119 TPM_CC command // IN: Command to check |
| 120 ) |
| 121 { |
| 122 switch (command) |
| 123 { |
| 124 case TPM_CC_NV_Read: |
| 125 case TPM_CC_PolicyNV: |
| 126 case TPM_CC_NV_Certify: |
| 127 // Nv read lock counts as a read operation for authorization purposes. |
| 128 // We check to see if the NV is read locked before we do the authorization |
| 129 // If it is locked, we fail the command early. |
| 130 case TPM_CC_NV_ReadLock: |
| 131 return TRUE; |
| 132 default: |
| 133 break; |
| 134 } |
| 135 return FALSE; |
| 136 } |
| |
| |
| 9.4.3.10 CommandCapGetCCList() |
| |
| This function returns a list of implemented commands and command attributes starting from the |
| command in commandCode. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 227 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| YES more command attributes are available |
| NO no more command attributes are available |
| |
| 137 TPMI_YES_NO |
| 138 CommandCapGetCCList( |
| 139 TPM_CC commandCode, // IN: start command code |
| 140 UINT32 count, // IN: maximum count for number of entries in |
| 141 // 'commandList' |
| 142 TPML_CCA *commandList // OUT: list of TPMA_CC |
| 143 ) |
| 144 { |
| 145 TPMI_YES_NO more = NO; |
| 146 UINT32 i; |
| 147 |
| 148 // initialize output handle list count |
| 149 commandList->count = 0; |
| 150 |
| 151 // The maximum count of commands that may be return is MAX_CAP_CC. |
| 152 if(count > MAX_CAP_CC) count = MAX_CAP_CC; |
| 153 |
| 154 // If the command code is smaller than TPM_CC_FIRST, start from TPM_CC_FIRST |
| 155 if(commandCode < TPM_CC_FIRST) commandCode = TPM_CC_FIRST; |
| 156 |
| 157 // Collect command attributes |
| 158 for(i = commandCode; i <= TPM_CC_LAST; i++) |
| 159 { |
| 160 if(CommandIsImplemented(i)) |
| 161 { |
| 162 if(commandList->count < count) |
| 163 { |
| 164 // If the list is not full, add the attributes for this command. |
| 165 commandList->commandAttributes[commandList->count] |
| 166 = CommandGetAttribute(i); |
| 167 commandList->count++; |
| 168 } |
| 169 else |
| 170 { |
| 171 // If the list is full but there are more commands to report, |
| 172 // indicate this and return. |
| 173 more = YES; |
| 174 break; |
| 175 } |
| 176 } |
| 177 } |
| 178 return more; |
| 179 } |
| |
| |
| 9.5 DRTM.c |
| |
| 9.5.1 Description |
| |
| This file contains functions that simulate the DRTM events. Its primary purpose is to isolate the name |
| space of the simulator from the name space of the TPM. This is only an issue with the parameters to |
| _TPM_Hash_Data(). |
| |
| 9.5.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| Page 228 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.5.3 Functions |
| |
| 9.5.3.1 Signal_Hash_Start() |
| |
| This function interfaces between the platform code and _TPM_Hash_Start(). |
| |
| 2 LIB_EXPORT void |
| 3 Signal_Hash_Start( |
| 4 void |
| 5 ) |
| 6 { |
| 7 _TPM_Hash_Start(); |
| 8 return; |
| 9 } |
| |
| |
| 9.5.3.2 Signal_Hash_Data() |
| |
| This function interfaces between the platform code and _TPM_Hash_Data(). |
| |
| 10 LIB_EXPORT void |
| 11 Signal_Hash_Data( |
| 12 unsigned int size, |
| 13 unsigned char *buffer |
| 14 ) |
| 15 { |
| 16 _TPM_Hash_Data(size, buffer); |
| 17 return; |
| 18 } |
| |
| |
| 9.5.3.3 Signal_Hash_End() |
| |
| This function interfaces between the platform code and _TPM_Hash_End(). |
| |
| 19 LIB_EXPORT void |
| 20 Signal_Hash_End( |
| 21 void |
| 22 ) |
| 23 { |
| 24 _TPM_Hash_End(); |
| 25 return; |
| 26 } |
| |
| |
| 9.6 Entity.c |
| |
| 9.6.1 Description |
| |
| The functions in this file are used for accessing properties for handles of various types. Functions in other |
| files require handles of a specific type but the functions in this file allow use of any handle type. |
| |
| 9.6.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 229 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.6.3 Functions |
| |
| 9.6.3.1 EntityGetLoadStatus() |
| |
| This function will indicate if the entity associated with a handle is present in TPM memory. If the handle is |
| a persistent object handle, and the object exists, the persistent object is moved from NV memory into a |
| RAM object slot and the persistent handle is replaced with the transient object handle for the slot. |
| |
| Error Returns Meaning |
| |
| TPM_RC_HANDLE handle type does not match |
| TPM_RC_REFERENCE_H0 entity is not present |
| TPM_RC_HIERARCHY entity belongs to a disabled hierarchy |
| TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM |
| |
| 2 TPM_RC |
| 3 EntityGetLoadStatus( |
| 4 TPM_HANDLE *handle, // IN/OUT: handle of the entity |
| 5 TPM_CC commandCode // IN: the commmandCode |
| 6 ) |
| 7 { |
| 8 TPM_RC result = TPM_RC_SUCCESS; |
| 9 |
| 10 switch(HandleGetType(*handle)) |
| 11 { |
| 12 // For handles associated with hierarchies, the entity is present |
| 13 // only if the associated enable is SET. |
| 14 case TPM_HT_PERMANENT: |
| 15 switch(*handle) |
| 16 { |
| 17 case TPM_RH_OWNER: |
| 18 if(!gc.shEnable) |
| 19 result = TPM_RC_HIERARCHY; |
| 20 break; |
| 21 |
| 22 #ifdef VENDOR_PERMANENT |
| 23 case VENDOR_PERMANENT: |
| 24 #endif |
| 25 case TPM_RH_ENDORSEMENT: |
| 26 if(!gc.ehEnable) |
| 27 result = TPM_RC_HIERARCHY; |
| 28 break; |
| 29 case TPM_RH_PLATFORM: |
| 30 if(!g_phEnable) |
| 31 result = TPM_RC_HIERARCHY; |
| 32 break; |
| 33 // null handle, PW session handle and lockout |
| 34 // handle are always available |
| 35 case TPM_RH_NULL: |
| 36 case TPM_RS_PW: |
| 37 case TPM_RH_LOCKOUT: |
| 38 break; |
| 39 default: |
| 40 // handling of the manufacture_specific handles |
| 41 if( ((TPM_RH)*handle >= TPM_RH_AUTH_00) |
| 42 && ((TPM_RH)*handle <= TPM_RH_AUTH_FF)) |
| 43 // use the value that would have been returned from |
| 44 // unmarshaling if it did the handle filtering |
| 45 result = TPM_RC_VALUE; |
| 46 else |
| 47 pAssert(FALSE); |
| 48 break; |
| |
| Page 230 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 49 } |
| 50 break; |
| 51 case TPM_HT_TRANSIENT: |
| 52 // For a transient object, check if the handle is associated |
| 53 // with a loaded object. |
| 54 if(!ObjectIsPresent(*handle)) |
| 55 result = TPM_RC_REFERENCE_H0; |
| 56 break; |
| 57 case TPM_HT_PERSISTENT: |
| 58 // Persistent object |
| 59 // Copy the persistent object to RAM and replace the handle with the |
| 60 // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY, |
| 61 // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by |
| 62 // ObjectLoadEvict() |
| 63 result = ObjectLoadEvict(handle, commandCode); |
| 64 break; |
| 65 case TPM_HT_HMAC_SESSION: |
| 66 // For an HMAC session, see if the session is loaded |
| 67 // and if the session in the session slot is actually |
| 68 // an HMAC session. |
| 69 if(SessionIsLoaded(*handle)) |
| 70 { |
| 71 SESSION *session; |
| 72 session = SessionGet(*handle); |
| 73 // Check if the session is a HMAC session |
| 74 if(session->attributes.isPolicy == SET) |
| 75 result = TPM_RC_HANDLE; |
| 76 } |
| 77 else |
| 78 result = TPM_RC_REFERENCE_H0; |
| 79 break; |
| 80 case TPM_HT_POLICY_SESSION: |
| 81 // For a policy session, see if the session is loaded |
| 82 // and if the session in the session slot is actually |
| 83 // a policy session. |
| 84 if(SessionIsLoaded(*handle)) |
| 85 { |
| 86 SESSION *session; |
| 87 session = SessionGet(*handle); |
| 88 // Check if the session is a policy session |
| 89 if(session->attributes.isPolicy == CLEAR) |
| 90 result = TPM_RC_HANDLE; |
| 91 } |
| 92 else |
| 93 result = TPM_RC_REFERENCE_H0; |
| 94 break; |
| 95 case TPM_HT_NV_INDEX: |
| 96 // For an NV Index, use the platform-specific routine |
| 97 // to search the IN Index space. |
| 98 result = NvIndexIsAccessible(*handle, commandCode); |
| 99 break; |
| 100 case TPM_HT_PCR: |
| 101 // Any PCR handle that is unmarshaled successfully referenced |
| 102 // a PCR that is defined. |
| 103 break; |
| 104 default: |
| 105 // Any other handle type is a defect in the unmarshaling code. |
| 106 pAssert(FALSE); |
| 107 break; |
| 108 } |
| 109 return result; |
| 110 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 231 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.6.3.2 EntityGetAuthValue() |
| |
| This function is used to access the authValue associated with a handle. This function assumes that the |
| handle references an entity that is accessible and the handle is not for a persistent objects. That is |
| EntityGetLoadStatus() should have been called. Also, the accessibility of the authValue should have been |
| verified by IsAuthValueAvailable(). |
| This function copies the authorization value of the entity to auth. |
| Return value is the number of octets copied to auth. |
| |
| 111 UINT16 |
| 112 EntityGetAuthValue( |
| 113 TPMI_DH_ENTITY handle, // IN: handle of entity |
| 114 AUTH_VALUE *auth // OUT: authValue of the entity |
| 115 ) |
| 116 { |
| 117 TPM2B_AUTH authValue = {0}; |
| 118 |
| 119 switch(HandleGetType(handle)) |
| 120 { |
| 121 case TPM_HT_PERMANENT: |
| 122 switch(handle) |
| 123 { |
| 124 case TPM_RH_OWNER: |
| 125 // ownerAuth for TPM_RH_OWNER |
| 126 authValue = gp.ownerAuth; |
| 127 break; |
| 128 case TPM_RH_ENDORSEMENT: |
| 129 // endorsementAuth for TPM_RH_ENDORSEMENT |
| 130 authValue = gp.endorsementAuth; |
| 131 break; |
| 132 case TPM_RH_PLATFORM: |
| 133 // platformAuth for TPM_RH_PLATFORM |
| 134 authValue = gc.platformAuth; |
| 135 break; |
| 136 case TPM_RH_LOCKOUT: |
| 137 // lockoutAuth for TPM_RH_LOCKOUT |
| 138 authValue = gp.lockoutAuth; |
| 139 break; |
| 140 case TPM_RH_NULL: |
| 141 // nullAuth for TPM_RH_NULL. Return 0 directly here |
| 142 return 0; |
| 143 break; |
| 144 #ifdef VENDOR_PERMANENT |
| 145 case VENDOR_PERMANENT: |
| 146 // vendor auth value |
| 147 authValue = g_platformUniqueDetails; |
| 148 #endif |
| 149 default: |
| 150 // If any other permanent handle is present it is |
| 151 // a code defect. |
| 152 pAssert(FALSE); |
| 153 break; |
| 154 } |
| 155 break; |
| 156 case TPM_HT_TRANSIENT: |
| 157 // authValue for an object |
| 158 // A persistent object would have been copied into RAM |
| 159 // and would have an transient object handle here. |
| 160 { |
| 161 OBJECT *object; |
| 162 object = ObjectGet(handle); |
| 163 // special handling if this is a sequence object |
| 164 if(ObjectIsSequence(object)) |
| |
| Page 232 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 165 { |
| 166 authValue = ((HASH_OBJECT *)object)->auth; |
| 167 } |
| 168 else |
| 169 { |
| 170 // Auth value is available only when the private portion of |
| 171 // the object is loaded. The check should be made before |
| 172 // this function is called |
| 173 pAssert(object->attributes.publicOnly == CLEAR); |
| 174 authValue = object->sensitive.authValue; |
| 175 } |
| 176 } |
| 177 break; |
| 178 case TPM_HT_NV_INDEX: |
| 179 // authValue for an NV index |
| 180 { |
| 181 NV_INDEX nvIndex; |
| 182 NvGetIndexInfo(handle, &nvIndex); |
| 183 authValue = nvIndex.authValue; |
| 184 } |
| 185 break; |
| 186 case TPM_HT_PCR: |
| 187 // authValue for PCR |
| 188 PCRGetAuthValue(handle, &authValue); |
| 189 break; |
| 190 default: |
| 191 // If any other handle type is present here, then there is a defect |
| 192 // in the unmarshaling code. |
| 193 pAssert(FALSE); |
| 194 break; |
| 195 } |
| 196 |
| 197 // Copy the authValue |
| 198 pAssert(authValue.t.size <= sizeof(authValue.t.buffer)); |
| 199 MemoryCopy(auth, authValue.t.buffer, authValue.t.size, sizeof(TPMU_HA)); |
| 200 |
| 201 return authValue.t.size; |
| 202 } |
| |
| |
| 9.6.3.3 EntityGetAuthPolicy() |
| |
| This function is used to access the authPolicy associated with a handle. This function assumes that the |
| handle references an entity that is accessible and the handle is not for a persistent objects. That is |
| EntityGetLoadStatus() should have been called. Also, the accessibility of the authPolicy should have |
| been verified by IsAuthPolicyAvailable(). |
| This function copies the authorization policy of the entity to authPolicy. |
| The return value is the hash algorithm for the policy. |
| |
| 203 TPMI_ALG_HASH |
| 204 EntityGetAuthPolicy( |
| 205 TPMI_DH_ENTITY handle, // IN: handle of entity |
| 206 TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity |
| 207 ) |
| 208 { |
| 209 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; |
| 210 |
| 211 switch(HandleGetType(handle)) |
| 212 { |
| 213 case TPM_HT_PERMANENT: |
| 214 switch(handle) |
| 215 { |
| 216 case TPM_RH_OWNER: |
| |
| |
| Family "2.0" TCG Published Page 233 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 217 // ownerPolicy for TPM_RH_OWNER |
| 218 *authPolicy = gp.ownerPolicy; |
| 219 hashAlg = gp.ownerAlg; |
| 220 break; |
| 221 case TPM_RH_ENDORSEMENT: |
| 222 // endorsementPolicy for TPM_RH_ENDORSEMENT |
| 223 *authPolicy = gp.endorsementPolicy; |
| 224 hashAlg = gp.endorsementAlg; |
| 225 break; |
| 226 case TPM_RH_PLATFORM: |
| 227 // platformPolicy for TPM_RH_PLATFORM |
| 228 *authPolicy = gc.platformPolicy; |
| 229 hashAlg = gc.platformAlg; |
| 230 break; |
| 231 case TPM_RH_LOCKOUT: |
| 232 // lockoutPolicy for TPM_RH_LOCKOUT |
| 233 *authPolicy = gp.lockoutPolicy; |
| 234 hashAlg = gp.lockoutAlg; |
| 235 break; |
| 236 default: |
| 237 // If any other permanent handle is present it is |
| 238 // a code defect. |
| 239 pAssert(FALSE); |
| 240 break; |
| 241 } |
| 242 break; |
| 243 case TPM_HT_TRANSIENT: |
| 244 // authPolicy for an object |
| 245 { |
| 246 OBJECT *object = ObjectGet(handle); |
| 247 *authPolicy = object->publicArea.authPolicy; |
| 248 hashAlg = object->publicArea.nameAlg; |
| 249 } |
| 250 break; |
| 251 case TPM_HT_NV_INDEX: |
| 252 // authPolicy for a NV index |
| 253 { |
| 254 NV_INDEX nvIndex; |
| 255 NvGetIndexInfo(handle, &nvIndex); |
| 256 *authPolicy = nvIndex.publicArea.authPolicy; |
| 257 hashAlg = nvIndex.publicArea.nameAlg; |
| 258 } |
| 259 break; |
| 260 case TPM_HT_PCR: |
| 261 // authPolicy for a PCR |
| 262 hashAlg = PCRGetAuthPolicy(handle, authPolicy); |
| 263 break; |
| 264 default: |
| 265 // If any other handle type is present it is a code defect. |
| 266 pAssert(FALSE); |
| 267 break; |
| 268 } |
| 269 return hashAlg; |
| 270 } |
| |
| |
| 9.6.3.4 EntityGetName() |
| |
| This function returns the Name associated with a handle. It will set name to the Name and return the size |
| of the Name string. |
| |
| 271 UINT16 |
| 272 EntityGetName( |
| 273 TPMI_DH_ENTITY handle, // IN: handle of entity |
| 274 NAME *name // OUT: name of entity |
| |
| Page 234 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 275 ) |
| 276 { |
| 277 UINT16 nameSize; |
| 278 |
| 279 switch(HandleGetType(handle)) |
| 280 { |
| 281 case TPM_HT_TRANSIENT: |
| 282 // Name for an object |
| 283 nameSize = ObjectGetName(handle, name); |
| 284 break; |
| 285 case TPM_HT_NV_INDEX: |
| 286 // Name for a NV index |
| 287 nameSize = NvGetName(handle, name); |
| 288 break; |
| 289 default: |
| 290 // For all other types, the handle is the Name |
| 291 nameSize = TPM_HANDLE_Marshal(&handle, (BYTE **)&name, NULL); |
| 292 break; |
| 293 } |
| 294 return nameSize; |
| 295 } |
| |
| |
| 9.6.3.5 EntityGetHierarchy() |
| |
| This function returns the hierarchy handle associated with an entity. |
| a) A handle that is a hierarchy handle is associated with itself. |
| b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET, |
| otherwise it belongs to TPM_RH_OWNER |
| c) An object handle belongs to its hierarchy. All other handles belong to the platform hierarchy. or an NV |
| Index. |
| |
| 296 TPMI_RH_HIERARCHY |
| 297 EntityGetHierarchy( |
| 298 TPMI_DH_ENTITY handle // IN :handle of entity |
| 299 ) |
| 300 { |
| 301 TPMI_RH_HIERARCHY hierarcy = TPM_RH_NULL; |
| 302 |
| 303 switch(HandleGetType(handle)) |
| 304 { |
| 305 case TPM_HT_PERMANENT: |
| 306 // hierarchy for a permanent handle |
| 307 switch(handle) |
| 308 { |
| 309 case TPM_RH_PLATFORM: |
| 310 case TPM_RH_ENDORSEMENT: |
| 311 case TPM_RH_NULL: |
| 312 hierarcy = handle; |
| 313 break; |
| 314 // all other permanent handles are associated with the owner |
| 315 // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) |
| 316 default: |
| 317 hierarcy = TPM_RH_OWNER; |
| 318 break; |
| 319 } |
| 320 break; |
| 321 case TPM_HT_NV_INDEX: |
| 322 // hierarchy for NV index |
| 323 { |
| 324 NV_INDEX nvIndex; |
| 325 NvGetIndexInfo(handle, &nvIndex); |
| 326 // If only the platform can delete the index, then it is |
| |
| Family "2.0" TCG Published Page 235 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 327 // considered to be in the platform hierarchy, otherwise it |
| 328 // is in the owner hierarchy. |
| 329 if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET) |
| 330 hierarcy = TPM_RH_PLATFORM; |
| 331 else |
| 332 hierarcy = TPM_RH_OWNER; |
| 333 } |
| 334 break; |
| 335 case TPM_HT_TRANSIENT: |
| 336 // hierarchy for an object |
| 337 { |
| 338 OBJECT *object; |
| 339 object = ObjectGet(handle); |
| 340 if(object->attributes.ppsHierarchy) |
| 341 { |
| 342 hierarcy = TPM_RH_PLATFORM; |
| 343 } |
| 344 else if(object->attributes.epsHierarchy) |
| 345 { |
| 346 hierarcy = TPM_RH_ENDORSEMENT; |
| 347 } |
| 348 else if(object->attributes.spsHierarchy) |
| 349 { |
| 350 hierarcy = TPM_RH_OWNER; |
| 351 } |
| 352 |
| 353 } |
| 354 break; |
| 355 case TPM_HT_PCR: |
| 356 hierarcy = TPM_RH_OWNER; |
| 357 break; |
| 358 default: |
| 359 pAssert(0); |
| 360 break; |
| 361 } |
| 362 // this is unreachable but it provides a return value for the default |
| 363 // case which makes the complier happy |
| 364 return hierarcy; |
| 365 } |
| |
| |
| 9.7 Global.c |
| |
| 9.7.1 Description |
| |
| This file will instance the TPM variables that are not stack allocated. The descriptions for these variables |
| is in Global.h. |
| |
| 9.7.2 Includes and Defines |
| |
| 1 #define GLOBAL_C |
| 2 #include "InternalRoutines.h" |
| |
| |
| 9.7.3 Global Data Values |
| |
| These values are visible across multiple modules. |
| |
| 3 BOOL g_phEnable; |
| 4 const UINT16 g_rcIndex[15] = {TPM_RC_1, TPM_RC_2, TPM_RC_3, TPM_RC_4, |
| 5 TPM_RC_5, TPM_RC_6, TPM_RC_7, TPM_RC_8, |
| 6 TPM_RC_9, TPM_RC_A, TPM_RC_B, TPM_RC_C, |
| 7 TPM_RC_D, TPM_RC_E, TPM_RC_F |
| |
| Page 236 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 8 }; |
| 9 TPM_HANDLE g_exclusiveAuditSession; |
| 10 UINT64 g_time; |
| 11 BOOL g_pcrReConfig; |
| 12 TPMI_DH_OBJECT g_DRTMHandle; |
| 13 BOOL g_DrtmPreStartup; |
| 14 BOOL g_StartupLocality3; |
| 15 BOOL g_clearOrderly; |
| 16 TPM_SU g_prevOrderlyState; |
| 17 BOOL g_updateNV; |
| 18 BOOL g_nvOk; |
| 19 TPM2B_AUTH g_platformUniqueDetails; |
| 20 STATE_CLEAR_DATA gc; |
| 21 STATE_RESET_DATA gr; |
| 22 PERSISTENT_DATA gp; |
| 23 ORDERLY_DATA go; |
| |
| |
| 9.7.4 Private Values |
| |
| 9.7.4.1 SessionProcess.c |
| |
| 24 #ifndef __IGNORE_STATE__ // DO NOT DEFINE THIS VALUE |
| |
| These values do not need to be retained between commands. |
| |
| 25 TPM_HANDLE s_sessionHandles[MAX_SESSION_NUM]; |
| 26 TPMA_SESSION s_attributes[MAX_SESSION_NUM]; |
| 27 TPM_HANDLE s_associatedHandles[MAX_SESSION_NUM]; |
| 28 TPM2B_NONCE s_nonceCaller[MAX_SESSION_NUM]; |
| 29 TPM2B_AUTH s_inputAuthValues[MAX_SESSION_NUM]; |
| 30 UINT32 s_encryptSessionIndex; |
| 31 UINT32 s_decryptSessionIndex; |
| 32 UINT32 s_auditSessionIndex; |
| 33 TPM2B_DIGEST s_cpHashForAudit; |
| 34 UINT32 s_sessionNum; |
| 35 #endif // __IGNORE_STATE__ |
| 36 BOOL s_DAPendingOnNV; |
| 37 #ifdef TPM_CC_GetCommandAuditDigest |
| 38 TPM2B_DIGEST s_cpHashForCommandAudit; |
| 39 #endif |
| |
| |
| 9.7.4.2 DA.c |
| |
| 40 UINT64 s_selfHealTimer; |
| 41 UINT64 s_lockoutTimer; |
| |
| |
| 9.7.4.3 NV.c |
| |
| 42 UINT32 s_reservedAddr[NV_RESERVE_LAST]; |
| 43 UINT32 s_reservedSize[NV_RESERVE_LAST]; |
| 44 UINT32 s_ramIndexSize; |
| 45 BYTE s_ramIndex[RAM_INDEX_SPACE]; |
| 46 UINT32 s_ramIndexSizeAddr; |
| 47 UINT32 s_ramIndexAddr; |
| 48 UINT32 s_maxCountAddr; |
| 49 UINT32 s_evictNvStart; |
| 50 UINT32 s_evictNvEnd; |
| 51 TPM_RC s_NvStatus; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 237 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.7.4.4 Object.c |
| |
| 52 OBJECT_SLOT s_objects[MAX_LOADED_OBJECTS]; |
| |
| |
| 9.7.4.5 PCR.c |
| |
| 53 PCR s_pcrs[IMPLEMENTATION_PCR]; |
| |
| |
| 9.7.4.6 Session.c |
| |
| 54 SESSION_SLOT s_sessions[MAX_LOADED_SESSIONS]; |
| 55 UINT32 s_oldestSavedSession; |
| 56 int s_freeSessionSlots; |
| |
| |
| 9.7.4.7 Manufacture.c |
| |
| 57 BOOL g_manufactured = FALSE; |
| |
| |
| 9.7.4.8 Power.c |
| |
| 58 BOOL s_initialized = FALSE; |
| |
| |
| 9.7.4.9 MemoryLib.c |
| |
| The s_actionOutputBuffer should not be modifiable by the host system until the TPM has returned a |
| response code. The s_actionOutputBuffer should not be accessible until response parameter encryption, |
| if any, is complete. This memory is not used between commands |
| |
| 59 #ifndef __IGNORE_STATE__ // DO NOT DEFINE THIS VALUE |
| 60 UINT32 s_actionInputBuffer[1024]; // action input buffer |
| 61 UINT32 s_actionOutputBuffer[1024]; // action output buffer |
| 62 BYTE s_responseBuffer[MAX_RESPONSE_SIZE];// response buffer |
| 63 #endif |
| |
| |
| 9.7.4.10 SelfTest.c |
| |
| Define these values here if the AlgorithmTests() project is not used |
| |
| 64 #ifndef SELF_TEST |
| 65 ALGORITHM_VECTOR g_implementedAlgorithms; |
| 66 ALGORITHM_VECTOR g_toTest; |
| 67 #endif |
| |
| |
| 9.7.4.11 TpmFail.c |
| |
| 68 jmp_buf g_jumpBuffer; |
| 69 BOOL g_forceFailureMode; |
| 70 BOOL g_inFailureMode; |
| 71 UINT32 s_failFunction; |
| 72 UINT32 s_failLine; |
| 73 UINT32 s_failCode; |
| |
| |
| |
| |
| Page 238 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.8 Handle.c |
| |
| 9.8.1 Description |
| |
| This file contains the functions that return the type of a handle. |
| |
| 9.8.2 Includes |
| |
| 1 #include "Tpm.h" |
| 2 #include "InternalRoutines.h" |
| |
| |
| 9.8.3 Functions |
| |
| 9.8.3.1 HandleGetType() |
| |
| This function returns the type of a handle which is the MSO of the handle. |
| |
| 3 TPM_HT |
| 4 HandleGetType( |
| 5 TPM_HANDLE handle // IN: a handle to be checked |
| 6 ) |
| 7 { |
| 8 // return the upper bytes of input data |
| 9 return (TPM_HT) ((handle & HR_RANGE_MASK) >> HR_SHIFT); |
| 10 } |
| |
| |
| 9.8.3.2 NextPermanentHandle() |
| |
| This function returns the permanent handle that is equal to the input value or is the next higher value. If |
| there is no handle with the input value and there is no next higher value, it returns 0: |
| |
| Return Value Meaning |
| |
| 11 TPM_HANDLE |
| 12 NextPermanentHandle( |
| 13 TPM_HANDLE inHandle // IN: the handle to check |
| 14 ) |
| 15 { |
| 16 // If inHandle is below the start of the range of permanent handles |
| 17 // set it to the start and scan from there |
| 18 if(inHandle < TPM_RH_FIRST) |
| 19 inHandle = TPM_RH_FIRST; |
| 20 // scan from input value untill we find an implemented permanent handle |
| 21 // or go out of range |
| 22 for(; inHandle <= TPM_RH_LAST; inHandle++) |
| 23 { |
| 24 switch (inHandle) |
| 25 { |
| 26 case TPM_RH_OWNER: |
| 27 case TPM_RH_NULL: |
| 28 case TPM_RS_PW: |
| 29 case TPM_RH_LOCKOUT: |
| 30 case TPM_RH_ENDORSEMENT: |
| 31 case TPM_RH_PLATFORM: |
| 32 case TPM_RH_PLATFORM_NV: |
| 33 #ifdef VENDOR_PERMANENT |
| 34 case VENDOR_PERMANENT: |
| 35 #endif |
| 36 return inHandle; |
| |
| Family "2.0" TCG Published Page 239 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 37 break; |
| 38 default: |
| 39 break; |
| 40 } |
| 41 } |
| 42 // Out of range on the top |
| 43 return 0; |
| 44 } |
| |
| |
| 9.8.3.3 PermanentCapGetHandles() |
| |
| This function returns a list of the permanent handles of PCR, started from handle. If handle is larger than |
| the largest permanent handle, an empty list will be returned with more set to NO. |
| |
| Return Value Meaning |
| |
| YES if there are more handles available |
| NO all the available handles has been returned |
| |
| 45 TPMI_YES_NO |
| 46 PermanentCapGetHandles( |
| 47 TPM_HANDLE handle, // IN: start handle |
| 48 UINT32 count, // IN: count of returned handle |
| 49 TPML_HANDLE *handleList // OUT: list of handle |
| 50 ) |
| 51 { |
| 52 TPMI_YES_NO more = NO; |
| 53 UINT32 i; |
| 54 |
| 55 pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); |
| 56 |
| 57 // Initialize output handle list |
| 58 handleList->count = 0; |
| 59 |
| 60 // The maximum count of handles we may return is MAX_CAP_HANDLES |
| 61 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
| 62 |
| 63 // Iterate permanent handle range |
| 64 for(i = NextPermanentHandle(handle); |
| 65 i != 0; i = NextPermanentHandle(i+1)) |
| 66 { |
| 67 if(handleList->count < count) |
| 68 { |
| 69 // If we have not filled up the return list, add this permanent |
| 70 // handle to it |
| 71 handleList->handle[handleList->count] = i; |
| 72 handleList->count++; |
| 73 } |
| 74 else |
| 75 { |
| 76 // If the return list is full but we still have permanent handle |
| 77 // available, report this and stop iterating |
| 78 more = YES; |
| 79 break; |
| 80 } |
| 81 } |
| 82 return more; |
| 83 } |
| |
| |
| |
| |
| Page 240 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.9 Locality.c |
| |
| 9.9.1 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| 9.9.2 LocalityGetAttributes() |
| |
| This function will convert a locality expressed as an integer into TPMA_LOCALITY form. |
| The function returns the locality attribute. |
| |
| 2 TPMA_LOCALITY |
| 3 LocalityGetAttributes( |
| 4 UINT8 locality // IN: locality value |
| 5 ) |
| 6 { |
| 7 TPMA_LOCALITY locality_attributes; |
| 8 BYTE *localityAsByte = (BYTE *)&locality_attributes; |
| 9 |
| 10 MemorySet(&locality_attributes, 0, sizeof(TPMA_LOCALITY)); |
| 11 switch(locality) |
| 12 { |
| 13 case 0: |
| 14 locality_attributes.TPM_LOC_ZERO = SET; |
| 15 break; |
| 16 case 1: |
| 17 locality_attributes.TPM_LOC_ONE = SET; |
| 18 break; |
| 19 case 2: |
| 20 locality_attributes.TPM_LOC_TWO = SET; |
| 21 break; |
| 22 case 3: |
| 23 locality_attributes.TPM_LOC_THREE = SET; |
| 24 break; |
| 25 case 4: |
| 26 locality_attributes.TPM_LOC_FOUR = SET; |
| 27 break; |
| 28 default: |
| 29 pAssert(locality < 256 && locality > 31); |
| 30 *localityAsByte = locality; |
| 31 break; |
| 32 } |
| 33 return locality_attributes; |
| 34 } |
| |
| |
| 9.10 Manufacture.c |
| |
| 9.10.1 Description |
| |
| This file contains the function that performs the manufacturing of the TPM in a simulated environment. |
| These functions should not be used outside of a manufacturing or simulation environment. |
| |
| 9.10.2 Includes and Data Definitions |
| |
| 1 #define MANUFACTURE_C |
| 2 #include "InternalRoutines.h" |
| 3 #include "Global.h" |
| |
| |
| |
| Family "2.0" TCG Published Page 241 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.10.3 Functions |
| |
| 9.10.3.1 TPM_Manufacture() |
| |
| This function initializes the TPM values in preparation for the TPM's first use. This function will fail if |
| previously called. The TPM can be re-manufactured by calling TPM_Teardown() first and then calling this |
| function again. |
| |
| Return Value Meaning |
| |
| 0 success |
| 1 manufacturing process previously performed |
| |
| 4 LIB_EXPORT int |
| 5 TPM_Manufacture( |
| 6 BOOL firstTime // IN: indicates if this is the first call from |
| 7 // main() |
| 8 ) |
| 9 { |
| 10 TPM_SU orderlyShutdown; |
| 11 UINT64 totalResetCount = 0; |
| 12 |
| 13 // If TPM has been manufactured, return indication. |
| 14 if(!firstTime && g_manufactured) |
| 15 return 1; |
| 16 |
| 17 // initialize crypto units |
| 18 //CryptInitUnits(); |
| 19 |
| 20 // |
| 21 s_selfHealTimer = 0; |
| 22 s_lockoutTimer = 0; |
| 23 s_DAPendingOnNV = FALSE; |
| 24 |
| 25 // initialize NV |
| 26 NvInit(); |
| 27 |
| 28 #ifdef _DRBG_STATE_SAVE |
| 29 // Initialize the drbg. This needs to come before the install |
| 30 // of the hierarchies |
| 31 if(!_cpri__Startup()) // Have to start the crypto units first |
| 32 FAIL(FATAL_ERROR_INTERNAL); |
| 33 _cpri__DrbgGetPutState(PUT_STATE, 0, NULL); |
| 34 #endif |
| 35 |
| 36 // default configuration for PCR |
| 37 PCRSimStart(); |
| 38 |
| 39 // initialize pre-installed hierarchy data |
| 40 // This should happen after NV is initialized because hierarchy data is |
| 41 // stored in NV. |
| 42 HierarchyPreInstall_Init(); |
| 43 |
| 44 // initialize dictionary attack parameters |
| 45 DAPreInstall_Init(); |
| 46 |
| 47 // initialize PP list |
| 48 PhysicalPresencePreInstall_Init(); |
| 49 |
| 50 // initialize command audit list |
| 51 CommandAuditPreInstall_Init(); |
| 52 |
| 53 // first start up is required to be Startup(CLEAR) |
| |
| Page 242 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 54 orderlyShutdown = TPM_SU_CLEAR; |
| 55 NvWriteReserved(NV_ORDERLY, &orderlyShutdown); |
| 56 |
| 57 // initialize the firmware version |
| 58 gp.firmwareV1 = FIRMWARE_V1; |
| 59 #ifdef FIRMWARE_V2 |
| 60 gp.firmwareV2 = FIRMWARE_V2; |
| 61 #else |
| 62 gp.firmwareV2 = 0; |
| 63 #endif |
| 64 NvWriteReserved(NV_FIRMWARE_V1, &gp.firmwareV1); |
| 65 NvWriteReserved(NV_FIRMWARE_V2, &gp.firmwareV2); |
| 66 |
| 67 // initialize the total reset counter to 0 |
| 68 NvWriteReserved(NV_TOTAL_RESET_COUNT, &totalResetCount); |
| 69 |
| 70 // initialize the clock stuff |
| 71 go.clock = 0; |
| 72 go.clockSafe = YES; |
| 73 |
| 74 #ifdef _DRBG_STATE_SAVE |
| 75 // initialize the current DRBG state in NV |
| 76 |
| 77 _cpri__DrbgGetPutState(GET_STATE, sizeof(go.drbgState), (BYTE *)&go.drbgState); |
| 78 #endif |
| 79 |
| 80 NvWriteReserved(NV_ORDERLY_DATA, &go); |
| 81 |
| 82 // Commit NV writes. Manufacture process is an artificial process existing |
| 83 // only in simulator environment and it is not defined in the specification |
| 84 // that what should be the expected behavior if the NV write fails at this |
| 85 // point. Therefore, it is assumed the NV write here is always success and |
| 86 // no return code of this function is checked. |
| 87 NvCommit(); |
| 88 |
| 89 g_manufactured = TRUE; |
| 90 |
| 91 return 0; |
| 92 } |
| |
| |
| 9.10.3.2 TPM_TearDown() |
| |
| This function prepares the TPM for re-manufacture. It should not be implemented in anything other than a |
| simulated TPM. |
| In this implementation, all that is needs is to stop the cryptographic units and set a flag to indicate that the |
| TPM can be re-manufactured. This should be all that is necessary to start the manufacturing process |
| again. |
| |
| Return Value Meaning |
| |
| 0 success |
| 1 TPM not previously manufactured |
| |
| 93 LIB_EXPORT int |
| 94 TPM_TearDown( |
| 95 void |
| 96 ) |
| 97 { |
| 98 // stop crypt units |
| 99 CryptStopUnits(); |
| 100 |
| 101 g_manufactured = FALSE; |
| |
| Family "2.0" TCG Published Page 243 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 102 return 0; |
| 103 } |
| |
| |
| 9.11 Marshal.c |
| |
| 9.11.1 Introduction |
| |
| This file contains the marshaling and unmarshaling code. |
| The marshaling and unmarshaling code and function prototypes are not listed, as the code is repetitive, |
| long, and not very useful to read. Examples of a few unmarshaling routines are provided. Most of the |
| others are similar. |
| Depending on the table header flags, a type will have an unmarshaling routine and a marshaling routine |
| The table header flags that control the generation of the unmarshaling and marshaling code are delimited |
| by angle brackets ("<>") in the table header. If no brackets are present, then both unmarshaling and |
| marshaling code is generated (i.e., generation of both marshaling and unmarshaling code is the default). |
| |
| 9.11.2 Unmarshal and Marshal a Value |
| |
| In TPM 2.0 Part 2, a TPMI_DI_OBJECT is defined by this table: |
| |
| Table xxx — Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type |
| Values Comments |
| |
| {TRANSIENT_FIRST:TRANSIENT_LAST} allowed range for transient objects |
| {PERSISTENT_FIRST:PERSISTENT_LAST} allowed range for persistent objects |
| +TPM_RH_NULL the null handle |
| #TPM_RC_VALUE |
| |
| This generates the following unmarshaling code: |
| |
| 1 TPM_RC |
| 2 TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, |
| 3 bool flag) |
| 4 { |
| 5 TPM_RC result; |
| 6 result = TPM_HANDLE_Unmarshal((TPM_HANDLE *)target, buffer, size); |
| 7 if(result != TPM_RC_SUCCESS) |
| 8 return result; |
| 9 if (*target == TPM_RH_NULL) { |
| 10 if(flag) |
| 11 return TPM_RC_SUCCESS; |
| 12 else |
| 13 return TPM_RC_VALUE; |
| 14 } |
| 15 if((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST)) |
| 16 if((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST)) |
| 17 return TPM_RC_VALUE; |
| 18 return TPM_RC_SUCCESS; |
| 19 } |
| |
| |
| |
| |
| Page 244 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| and the following marshaling code: |
| |
| NOTE The marshaling code does not do parameter checking, as the TPM is the source of the marshaling data. |
| |
| 1 UINT16 |
| 2 TPMI_DH_OBJECT_Marshal(TPMI_DH_OBJECT *source, BYTE **buffer, INT32 *size) |
| 3 { |
| 4 return UINT32_Marshal((UINT32 *)source, buffer, size); |
| 5 } |
| |
| |
| 9.11.3 Unmarshal and Marshal a Union |
| |
| In TPM 2.0 Part 2, a TPMU_PUBLIC_PARMS union is defined by: |
| |
| Table xxx — Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S> |
| Parameter Type Selector Description |
| |
| keyedHash TPMS_KEYEDHASH_PARMS TPM_ALG_KEYEDHASH sign | encrypt | neither |
| symDetail TPMT_SYM_DEF_OBJECT TPM_ALG_SYMCIPHER a symmetric block cipher |
| rsaDetail TPMS_RSA_PARMS TPM_ALG_RSA decrypt + sign |
| eccDetail TPMS_ECC_PARMS TPM_ALG_ECC decrypt + sign |
| asymDetail TPMS_ASYM_PARMS common scheme structure |
| for RSA and ECC keys |
| NOTE The Description column indicates which of TPMA_OBJECT.decrypt or TPMA_OBJECT.sign may be set. |
| “+” indicates that both may be set but one shall be set. “|” indicates the optional settings. |
| |
| From this table, the following unmarshaling code is generated. |
| |
| 1 TPM_RC |
| 2 TPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size, |
| 3 UINT32 selector) |
| 4 { |
| 5 switch(selector) { |
| 6 #ifdef TPM_ALG_KEYEDHASH |
| 7 case TPM_ALG_KEYEDHASH: |
| 8 return TPMS_KEYEDHASH_PARMS_Unmarshal( |
| 9 (TPMS_KEYEDHASH_PARMS *)&(target->keyedHash), buffer, size); |
| 10 #endif |
| 11 #ifdef TPM_ALG_SYMCIPHER |
| 12 case TPM_ALG_SYMCIPHER: |
| 13 return TPMT_SYM_DEF_OBJECT_Unmarshal( |
| 14 (TPMT_SYM_DEF_OBJECT *)&(target->symDetail), buffer, size, FALSE); |
| 15 #endif |
| 16 #ifdef TPM_ALG_RSA |
| 17 case TPM_ALG_RSA: |
| 18 return TPMS_RSA_PARMS_Unmarshal( |
| 19 (TPMS_RSA_PARMS *)&(target->rsaDetail), buffer, size); |
| 20 #endif |
| 21 #ifdef TPM_ALG_ECC |
| 22 case TPM_ALG_ECC: |
| 23 return TPMS_ECC_PARMS_Unmarshal( |
| 24 (TPMS_ECC_PARMS *)&(target->eccDetail), buffer, size); |
| 25 #endif |
| 26 } |
| 27 return TPM_RC_SELECTOR; |
| 28 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 245 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| NOTE The #ifdef/#endif directives are added whenever a value is dependent on an algorithm ID so that |
| removing the algorithm definition will remove the related code. |
| |
| The marshaling code for the union is: |
| |
| 1 UINT16 |
| 2 TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size, |
| 3 UINT32 selector) |
| 4 { |
| 5 switch(selector) { |
| 6 #ifdef TPM_ALG_KEYEDHASH |
| 7 case TPM_ALG_KEYEDHASH: |
| 8 return TPMS_KEYEDHASH_PARMS_Marshal( |
| 9 (TPMS_KEYEDHASH_PARMS *)&(source->keyedHash), buffer, size); |
| 10 #endif |
| 11 #ifdef TPM_ALG_SYMCIPHER |
| 12 case TPM_ALG_SYMCIPHER: |
| 13 return TPMT_SYM_DEF_OBJECT_Marshal( |
| 14 (TPMT_SYM_DEF_OBJECT *)&(source->symDetail), buffer, size); |
| 15 #endif |
| 16 #ifdef TPM_ALG_RSA |
| 17 case TPM_ALG_RSA: |
| 18 return TPMS_RSA_PARMS_Marshal( |
| 19 (TPMS_RSA_PARMS *)&(source->rsaDetail), buffer, size); |
| 20 #endif |
| 21 #ifdef TPM_ALG_ECC |
| 22 case TPM_ALG_ECC: |
| 23 return TPMS_ECC_PARMS_Marshal( |
| 24 (TPMS_ECC_PARMS *)&(source->eccDetail), buffer, size); |
| 25 #endif |
| 26 } |
| 27 assert(1); |
| 28 return 0; |
| 29 } |
| |
| For the marshaling and unmarshaling code, a value in the structure containing the union provides the |
| value used for selector. The example in the next section illustrates this. |
| |
| |
| |
| |
| Page 246 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.11.4 Unmarshal and Marshal a Structure |
| |
| In TPM 2.0 Part 2, the TPMT_PUBLiC structure is defined by: |
| |
| Table xxx — Definition of TPMT_PUBLIC Structure |
| Parameter Type Description |
| |
| type TPMI_ALG_PUBLIC “algorithm” associated with this object |
| nameAlg +TPMI_ALG_HASH algorithm used for computing the Name of the object |
| NOTE The "+" indicates that the instance of a TPMT_PUBLIC may have |
| a "+" to indicate that the nameAlg may be TPM_ALG_NULL. |
| |
| objectAttributes TPMA_OBJECT attributes that, along with type, determine the manipulations of this |
| object |
| authPolicy TPM2B_DIGEST optional policy for using this key |
| The policy is computed using the nameAlg of the object. |
| NOTE shall be the Empty Buffer if no authorization policy is present |
| |
| [type]parameters TPMU_PUBLIC_PARMS the algorithm or structure details |
| [type]unique TPMU_PUBLIC_ID the unique identifier of the structure |
| For an asymmetric key, this would be the public key. |
| |
| This structure is tagged (the first value indicates the structure type), and that tag is used to determine how |
| the parameters and unique fields are unmarshaled and marshaled. The use of the type for specifying the |
| union selector is emphasized below. |
| The unmarshaling code for the structure in the table above is: |
| |
| 1 TPM_RC |
| 2 TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, bool flag) |
| 3 { |
| 4 TPM_RC result; |
| 5 result = TPMI_ALG_PUBLIC_Unmarshal((TPMI_ALG_PUBLIC *)&(target->type), |
| 6 buffer, size); |
| 7 if(result != TPM_RC_SUCCESS) |
| 8 return result; |
| 9 result = TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH *)&(target->nameAlg), |
| 10 buffer, size, flag); |
| 11 if(result != TPM_RC_SUCCESS) |
| 12 return result; |
| 13 result = TPMA_OBJECT_Unmarshal((TPMA_OBJECT *)&(target->objectAttributes), |
| 14 buffer, size); |
| 15 if(result != TPM_RC_SUCCESS) |
| 16 return result; |
| 17 result = TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST *)&(target->authPolicy), |
| 18 buffer, size); |
| 19 if(result != TPM_RC_SUCCESS) |
| 20 return result; |
| 21 |
| 22 result = TPMU_PUBLIC_PARMS_Unmarshal((TPMU_PUBLIC_PARMS *)&(target->parameters), |
| 23 buffer, size, ); |
| 24 if(result != TPM_RC_SUCCESS) |
| 25 return result; |
| 26 |
| 27 result = TPMU_PUBLIC_ID_Unmarshal((TPMU_PUBLIC_ID *)&(target->unique), |
| 28 buffer, size, ) |
| 29 if(result != TPM_RC_SUCCESS) |
| 30 return result; |
| 31 |
| 32 return TPM_RC_SUCCESS; |
| 33 } |
| |
| Family "2.0" TCG Published Page 247 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| The marshaling code for the TPMT_PUBLIC structure is: |
| |
| 1 UINT16 |
| 2 TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size) |
| 3 { |
| 4 UINT16 result = 0; |
| 5 result = (UINT16)(result + TPMI_ALG_PUBLIC_Marshal( |
| 6 (TPMI_ALG_PUBLIC *)&(source->type), buffer, size)); |
| 7 result = (UINT16)(result + TPMI_ALG_HASH_Marshal( |
| 8 (TPMI_ALG_HASH *)&(source->nameAlg), buffer, size)) |
| 9 ; |
| 10 result = (UINT16)(result + TPMA_OBJECT_Marshal( |
| 11 (TPMA_OBJECT *)&(source->objectAttributes), buffer, size)); |
| 12 |
| 13 result = (UINT16)(result + TPM2B_DIGEST_Marshal( |
| 14 (TPM2B_DIGEST *)&(source->authPolicy), buffer, size)); |
| 15 |
| 16 result = (UINT16)(result + TPMU_PUBLIC_PARMS_Marshal( |
| 17 (TPMU_PUBLIC_PARMS *)&(source->parameters), buffer, size, |
| 18 )); |
| 19 |
| 20 result = (UINT16)(result + TPMU_PUBLIC_ID_Marshal( |
| 21 (TPMU_PUBLIC_ID *)&(source->unique), buffer, size, |
| 22 )); |
| 23 |
| 24 return result; |
| 25 } |
| |
| |
| |
| |
| Page 248 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.11.5 Unmarshal and Marshal an Array |
| |
| In TPM 2.0 Part 2, the TPML_DIGEST is defined by: |
| |
| Table xxx — Definition of TPML_DIGEST Structure |
| Parameter Type Description |
| |
| count {2:} UINT32 number of digests in the list, minimum is two |
| digests[count]{:8} TPM2B_DIGEST a list of digests |
| For TPM2_PolicyOR(), all digests will have been |
| computed using the digest of the policy session. For |
| TPM2_PCR_Read(), each digest will be the size of the |
| digest for the bank containing the PCR. |
| #TPM_RC_SIZE response code when count is not at least two or is |
| greater than 8 |
| The digests parameter is an array of up to count structures (TPM2B_DIGESTS). The auto-generated code |
| to Unmarshal this structure is: |
| |
| 1 TPM_RC |
| 2 TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size) |
| 3 { |
| 4 TPM_RC result; |
| 5 result = UINT32_Unmarshal((UINT32 *)&(target->count), buffer, size); |
| 6 if(result != TPM_RC_SUCCESS) |
| 7 return result; |
| 8 |
| 9 if( (target->count < 2)) // This check is triggered by the {2:} notation |
| 10 // on ‘count’ |
| 11 return TPM_RC_SIZE; |
| 12 |
| 13 if((target->count) > 8) // This check is triggered by the {:8} notation |
| 14 // on ‘digests’. |
| 15 return TPM_RC_SIZE; |
| 16 |
| 17 result = TPM2B_DIGEST_Array_Unmarshal((TPM2B_DIGEST *)(target->digests), |
| 18 buffer, size, ); |
| 19 if(result != TPM_RC_SUCCESS) |
| 20 return result; |
| 21 |
| 22 return TPM_RC_SUCCESS; |
| 23 } |
| |
| The routine unmarshals a count value and passes that value to a routine that unmarshals an array of |
| TPM2B_DIGEST values. The unmarshaling code for the array is: |
| |
| 1 TPM_RC |
| 2 TPM2B_DIGEST_Array_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size, |
| 3 INT32 count) |
| 4 { |
| 5 TPM_RC result; |
| 6 INT32 i; |
| 7 for(i = 0; i < count; i++) { |
| 8 result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size); |
| 9 if(result != TPM_RC_SUCCESS) |
| 10 return result; |
| 11 } |
| 12 return TPM_RC_SUCCESS; |
| 13 } |
| 14 |
| |
| |
| Family "2.0" TCG Published Page 249 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Marshaling of the TPML_DIGEST uses a similar scheme with a structure specifying the number of |
| elements in an array and a subsequent call to a routine to marshal an array of that type. |
| |
| 1 UINT16 |
| 2 TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size) |
| 3 { |
| 4 UINT16 result = 0; |
| 5 result = (UINT16)(result + UINT32_Marshal((UINT32 *)&(source->count), buffer, |
| 6 size)); |
| 7 result = (UINT16)(result + TPM2B_DIGEST_Array_Marshal( |
| 8 (TPM2B_DIGEST *)(source->digests), buffer, size, |
| 9 (INT32)(source->count))); |
| 10 |
| 11 return result; |
| 12 } |
| |
| The marshaling code for the array is: |
| |
| 1 TPM_RC |
| 2 TPM2B_DIGEST_Array_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size, |
| 3 INT32 count) |
| 4 { |
| 5 TPM_RC result; |
| 6 INT32 i; |
| 7 for(i = 0; i < count; i++) { |
| 8 result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size); |
| 9 if(result != TPM_RC_SUCCESS) |
| 10 return result; |
| 11 } |
| 12 return TPM_RC_SUCCESS; |
| 13 } |
| |
| |
| |
| |
| Page 250 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.11.6 TPM2B Handling |
| |
| A TPM2B structure is handled as a special case. The unmarshaling code is similar to what is shown in |
| 10.11.5 but the unmarshaling/marshaling is to a union element. Each TPM2B is a union of two sized |
| buffers, one of which is type specific (the ‘t’ element) and the other is a generic value (the ‘b’ element). |
| This allows each of the TPM2B structures to have some inheritance property with all other TPM2B. The |
| purpose is to allow functions that have parameters that can be any TPM2B structure while allowing other |
| functions to be specific about the type of the TPM2B that is used. When the generic structure is allowed, |
| the input parameter would use the ‘b’ element and when the type-specific structure is required, the ‘t’ |
| element is used. |
| |
| Table xxx — Definition of TPM2B_EVENT Structure |
| Parameter Type Description |
| |
| size UINT16 Size of the operand |
| buffer [size] {:1024} BYTE The operand |
| |
| 1 TPM_RC |
| 2 TPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size) |
| 3 { |
| 4 TPM_RC result; |
| 5 result = UINT16_Unmarshal((UINT16 *)&(target->t.size), buffer, size); |
| 6 if(result != TPM_RC_SUCCESS) |
| 7 return result; |
| 8 |
| 9 // if size equal to 0, the rest of the structure is a zero buffer. Stop |
| processing |
| 10 if(target->t.size == 0) |
| 11 return TPM_RC_SUCCESS; |
| 12 |
| 13 if((target->t.size) > 1024) // This check is triggered by the {:1024} notation |
| 14 // on ‘buffer’ |
| 15 return TPM_RC_SIZE; |
| 16 |
| 17 result = BYTE_Array_Unmarshal((BYTE *)(target->t.buffer), buffer, size, |
| 18 (INT32)(target->t.size)); |
| 19 if(result != TPM_RC_SUCCESS) |
| 20 return result; |
| 21 |
| 22 return TPM_RC_SUCCESS; |
| 23 } |
| |
| Which use these structure definitions: |
| |
| 1 typedef struct { |
| 2 UINT16 size; |
| 3 BYTE buffer[1]; |
| 4 } TPM2B; |
| 5 |
| 6 typedef struct { |
| 7 UINT16 size; |
| 8 BYTE buffer[1024]; |
| 9 } EVENT_2B; |
| 10 |
| 11 typedef union { |
| 12 EVENT_2B t; // The type-specific union member |
| 13 TPM2B b; // The generic union member |
| 14 } TPM2B_EVENT; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 251 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.12 MemoryLib.c |
| |
| 9.12.1 Description |
| |
| This file contains a set of miscellaneous memory manipulation routines. Many of the functions have the |
| same semantics as functions defined in string.h. Those functions are not used in the TPM in order to |
| avoid namespace contamination. |
| |
| 9.12.2 Includes and Data Definitions |
| |
| 1 #define MEMORY_LIB_C |
| 2 #include "InternalRoutines.h" |
| |
| These buffers are set aside to hold command and response values. In this implementation, it is not |
| guaranteed that the code will stop accessing the s_actionInputBuffer before starting to put values in the |
| s_actionOutputBuffer so different buffers are required. However, the s_actionInputBuffer and |
| s_responseBuffer are not needed at the same time and they could be the same buffer. |
| |
| 9.12.3 Functions on BYTE Arrays |
| |
| 9.12.3.1 MemoryMove() |
| |
| This function moves data from one place in memory to another. No safety checks of any type are |
| performed. If source and data buffer overlap, then the move is done as if an intermediate buffer were |
| used. |
| |
| NOTE: This function is used by MemoryCopy(), MemoryCopy2B(), and MemoryConcat2b() and requires that the caller |
| know the maximum size of the destination buffer so that there is no possibility of buffer overrun. |
| |
| 3 LIB_EXPORT void |
| 4 MemoryMove( |
| 5 void *destination, // OUT: move destination |
| 6 const void *source, // IN: move source |
| 7 UINT32 size, // IN: number of octets to moved |
| 8 UINT32 dSize // IN: size of the receive buffer |
| 9 ) |
| 10 { |
| 11 const BYTE *p = (BYTE *)source; |
| 12 BYTE *q = (BYTE *)destination; |
| 13 |
| 14 if(destination == NULL || source == NULL) |
| 15 return; |
| 16 |
| 17 pAssert(size <= dSize); |
| 18 // if the destination buffer has a lower address than the |
| 19 // source, then moving bytes in ascending order is safe. |
| 20 dSize -= size; |
| 21 |
| 22 if (p>q || (p+size <= q)) |
| 23 { |
| 24 while(size--) |
| 25 *q++ = *p++; |
| 26 } |
| 27 // If the destination buffer has a higher address than the |
| 28 // source, then move bytes from the end to the beginning. |
| 29 else if (p < q) |
| 30 { |
| 31 p += size; |
| 32 q += size; |
| |
| |
| Page 252 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 33 while (size--) |
| 34 *--q = *--p; |
| 35 } |
| 36 |
| 37 // If the source and destination address are the same, nothing to move. |
| 38 return; |
| 39 } |
| |
| |
| 9.12.3.2 MemoryCopy() |
| |
| This function moves data from one place in memory to another. No safety checks of any type are |
| performed. If the destination and source overlap, then the results are unpredictable. void MemoryCopy( |
| |
| void *destination, // OUT: copy destination |
| |
| void *source, // IN: copy source |
| UINT32 size, // IN: number of octets being copied |
| UINT32 dSize // IN: size of the receive buffer |
| |
| MemoryMove(destination, source, size, dSize); |
| |
| 40 //%#define MemoryCopy(destination, source, size, destSize) \ |
| 41 //% MemoryMove((destination), (source), (size), (destSize)) |
| |
| |
| 9.12.3.3 MemoryEqual() |
| |
| This function indicates if two buffers have the same values in the indicated number of bytes. |
| |
| Return Value Meaning |
| |
| TRUE all octets are the same |
| FALSE all octets are not the same |
| |
| 42 LIB_EXPORT BOOL |
| 43 MemoryEqual( |
| 44 const void *buffer1, // IN: compare buffer1 |
| 45 const void *buffer2, // IN: compare buffer2 |
| 46 UINT32 size // IN: size of bytes being compared |
| 47 ) |
| 48 { |
| 49 BOOL equal = TRUE; |
| 50 const BYTE *b1, *b2; |
| 51 |
| 52 b1 = (BYTE *)buffer1; |
| 53 b2 = (BYTE *)buffer2; |
| 54 |
| 55 // Compare all bytes so that there is no leakage of information |
| 56 // due to timing differences. |
| 57 for(; size > 0; size--) |
| 58 equal = (*b1++ == *b2++) && equal; |
| 59 |
| 60 return equal; |
| 61 } |
| |
| |
| 9.12.3.4 MemoryCopy2B() |
| |
| This function copies a TPM2B. This can be used when the TPM2B types are the same or different. No |
| size checking is done on the destination so the caller should make sure that the destination is large |
| enough. |
| |
| Family "2.0" TCG Published Page 253 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| This function returns the number of octets in the data buffer of the TPM2B. |
| |
| 62 LIB_EXPORT INT16 |
| 63 MemoryCopy2B( |
| 64 TPM2B *dest, // OUT: receiving TPM2B |
| 65 const TPM2B *source, // IN: source TPM2B |
| 66 UINT16 dSize // IN: size of the receiving buffer |
| 67 ) |
| 68 { |
| 69 |
| 70 if(dest == NULL) |
| 71 return 0; |
| 72 if(source == NULL) |
| 73 dest->size = 0; |
| 74 else |
| 75 { |
| 76 dest->size = source->size; |
| 77 MemoryMove(dest->buffer, source->buffer, dest->size, dSize); |
| 78 } |
| 79 return dest->size; |
| 80 } |
| |
| |
| 9.12.3.5 MemoryConcat2B() |
| |
| This function will concatenate the buffer contents of a TPM2B to an the buffer contents of another TPM2B |
| and adjust the size accordingly (a := (a | b)). |
| |
| 81 LIB_EXPORT void |
| 82 MemoryConcat2B( |
| 83 TPM2B *aInOut, // IN/OUT: destination 2B |
| 84 TPM2B *bIn, // IN: second 2B |
| 85 UINT16 aSize // IN: The size of aInOut.buffer (max values for |
| 86 // aInOut.size) |
| 87 ) |
| 88 { |
| 89 MemoryMove(&aInOut->buffer[aInOut->size], |
| 90 bIn->buffer, |
| 91 bIn->size, |
| 92 aSize - aInOut->size); |
| 93 aInOut->size = aInOut->size + bIn->size; |
| 94 return; |
| 95 } |
| |
| |
| 9.12.3.6 Memory2BEqual() |
| |
| This function will compare two TPM2B structures. To be equal, they need to be the same size and the |
| buffer contexts need to be the same in all octets. |
| |
| Return Value Meaning |
| |
| TRUE size and buffer contents are the same |
| FALSE size or buffer contents are not the same |
| |
| 96 LIB_EXPORT BOOL |
| 97 Memory2BEqual( |
| 98 const TPM2B *aIn, // IN: compare value |
| 99 const TPM2B *bIn // IN: compare value |
| 100 ) |
| 101 { |
| 102 if(aIn->size != bIn->size) |
| 103 return FALSE; |
| |
| Page 254 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 104 |
| 105 return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size); |
| 106 } |
| |
| |
| 9.12.3.7 MemorySet() |
| |
| This function will set all the octets in the specified memory range to the specified octet value. |
| |
| NOTE: the dSize parameter forces the caller to know how big the receiving buffer is to make sure that there is no |
| possibility that the caller will inadvertently run over the end of the buffer. |
| |
| 107 LIB_EXPORT void |
| 108 MemorySet( |
| 109 void *destination, // OUT: memory destination |
| 110 char value, // IN: fill value |
| 111 UINT32 size // IN: number of octets to fill |
| 112 ) |
| 113 { |
| 114 char *p = (char *)destination; |
| 115 while (size--) |
| 116 *p++ = value; |
| 117 return; |
| 118 } |
| |
| |
| 9.12.3.8 MemoryGetActionInputBuffer() |
| |
| This function returns the address of the buffer into which the command parameters will be unmarshaled in |
| preparation for calling the command actions. |
| |
| 119 BYTE * |
| 120 MemoryGetActionInputBuffer( |
| 121 UINT32 size // Size, in bytes, required for the input |
| 122 // unmarshaling |
| 123 ) |
| 124 { |
| 125 BYTE *buf = NULL; |
| 126 |
| 127 if(size > 0) |
| 128 { |
| 129 // In this implementation, a static buffer is set aside for action output. |
| 130 // Other implementations may apply additional optimization based on command |
| 131 // code or other factors. |
| 132 UINT32 *p = s_actionInputBuffer; |
| 133 buf = (BYTE *)p; |
| 134 pAssert(size < sizeof(s_actionInputBuffer)); |
| 135 |
| 136 // size of an element in the buffer |
| 137 #define SZ sizeof(s_actionInputBuffer[0]) |
| 138 |
| 139 for(size = (size + SZ - 1) / SZ; size > 0; size--) |
| 140 *p++ = 0; |
| 141 #undef SZ |
| 142 } |
| 143 return buf; |
| 144 } |
| |
| |
| 9.12.3.9 MemoryGetActionOutputBuffer() |
| |
| This function returns the address of the buffer into which the command action code places its output |
| values. |
| |
| |
| Family "2.0" TCG Published Page 255 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 145 void * |
| 146 MemoryGetActionOutputBuffer( |
| 147 TPM_CC command // Command that requires the buffer |
| 148 ) |
| 149 { |
| 150 // In this implementation, a static buffer is set aside for action output. |
| 151 // Other implementations may apply additional optimization based on the command |
| 152 // code or other factors. |
| 153 command = 0; // Unreferenced parameter |
| 154 return s_actionOutputBuffer; |
| 155 } |
| |
| |
| 9.12.3.10 MemoryGetResponseBuffer() |
| |
| This function returns the address into which the command response is marshaled from values in the |
| action output buffer. |
| |
| 156 BYTE * |
| 157 MemoryGetResponseBuffer( |
| 158 TPM_CC command // Command that requires the buffer |
| 159 ) |
| 160 { |
| 161 // In this implementation, a static buffer is set aside for responses. |
| 162 // Other implementation may apply additional optimization based on the command |
| 163 // code or other factors. |
| 164 command = 0; // Unreferenced parameter |
| 165 return s_responseBuffer; |
| 166 } |
| |
| |
| 9.12.3.11 MemoryRemoveTrailingZeros() |
| |
| This function is used to adjust the length of an authorization value. It adjusts the size of the TPM2B so |
| that it does not include octets at the end of the buffer that contain zero. The function returns the number |
| of non-zero octets in the buffer. |
| |
| 167 UINT16 |
| 168 MemoryRemoveTrailingZeros ( |
| 169 TPM2B_AUTH *auth // IN/OUT: value to adjust |
| 170 ) |
| 171 { |
| 172 BYTE *a = &auth->t.buffer[auth->t.size-1]; |
| 173 for(; auth->t.size > 0; auth->t.size--) |
| 174 { |
| 175 if(*a--) |
| 176 break; |
| 177 } |
| 178 return auth->t.size; |
| 179 } |
| |
| |
| 9.13 Power.c |
| |
| 9.13.1 Description |
| |
| This file contains functions that receive the simulated power state transitions of the TPM. |
| |
| 9.13.2 Includes and Data Definitions |
| |
| 1 #define POWER_C |
| 2 #include "InternalRoutines.h" |
| |
| Page 256 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 9.13.3 Functions |
| |
| 9.13.3.1 TPMInit() |
| |
| This function is used to process a power on event. |
| |
| 3 void |
| 4 TPMInit( |
| 5 void |
| 6 ) |
| 7 { |
| 8 // Set state as not initialized. This means that Startup is required |
| 9 s_initialized = FALSE; |
| 10 |
| 11 return; |
| 12 } |
| |
| |
| 9.13.3.2 TPMRegisterStartup() |
| |
| This function registers the fact that the TPM has been initialized (a TPM2_Startup() has completed |
| successfully). |
| |
| 13 void |
| 14 TPMRegisterStartup( |
| 15 void |
| 16 ) |
| 17 { |
| 18 s_initialized = TRUE; |
| 19 |
| 20 return; |
| 21 } |
| |
| |
| 9.13.3.3 TPMIsStarted() |
| |
| Indicates if the TPM has been initialized (a TPM2_Startup() has completed successfully after a |
| _TPM_Init()). |
| |
| Return Value Meaning |
| |
| TRUE TPM has been initialized |
| FALSE TPM has not been initialized |
| |
| 22 BOOL |
| 23 TPMIsStarted( |
| 24 void |
| 25 ) |
| 26 { |
| 27 return s_initialized; |
| 28 } |
| |
| |
| 9.14 PropertyCap.c |
| |
| 9.14.1 Description |
| |
| This file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 257 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 9.14.2 Includes |
| |
| 1 #include "InternalRoutines.h" |
| |
| |
| 9.14.3 Functions |
| |
| 9.14.3.1 PCRGetProperty() |
| |
| This function accepts a property selection and, if so, sets value to the value of the property. |
| All the fixed values are vendor dependent or determined by a platform-specific specification. The values |
| in the table below are examples and should be changed by the vendor. |
| |
| Return Value Meaning |
| |
| TRUE referenced property exists and value set |
| FALSE referenced property does not exist |
| |
| 2 static BOOL |
| 3 TPMPropertyIsDefined( |
| 4 TPM_PT property, // IN: property |
| 5 UINT32 *value // OUT: property value |
| 6 ) |
| 7 { |
| 8 switch(property) |
| 9 { |
| 10 case TPM_PT_FAMILY_INDICATOR: |
| 11 // from the title page of the specification |
| 12 // For this specification, the value is "2.0". |
| 13 *value = TPM_SPEC_FAMILY; |
| 14 break; |
| 15 case TPM_PT_LEVEL: |
| 16 // from the title page of the specification |
| 17 *value = TPM_SPEC_LEVEL; |
| 18 break; |
| 19 case TPM_PT_REVISION: |
| 20 // from the title page of the specification |
| 21 *value = TPM_SPEC_VERSION; |
| 22 break; |
| 23 case TPM_PT_DAY_OF_YEAR: |
| 24 // computed from the date value on the title page of the specification |
| 25 *value = TPM_SPEC_DAY_OF_YEAR; |
| 26 break; |
| 27 case TPM_PT_YEAR: |
| 28 // from the title page of the specification |
| 29 *value = TPM_SPEC_YEAR; |
| 30 break; |
| 31 case TPM_PT_MANUFACTURER: |
| 32 // vendor ID unique to each TPM manufacturer |
| 33 *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER); |
| 34 break; |
| 35 case TPM_PT_VENDOR_STRING_1: |
| 36 // first four characters of the vendor ID string |
| 37 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1); |
| 38 break; |
| 39 case TPM_PT_VENDOR_STRING_2: |
| 40 // second four characters of the vendor ID string |
| 41 #ifdef VENDOR_STRING_2 |
| 42 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2); |
| 43 #else |
| 44 *value = 0; |
| 45 #endif |
| |
| Page 258 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 46 break; |
| 47 case TPM_PT_VENDOR_STRING_3: |
| 48 // third four characters of the vendor ID string |
| 49 #ifdef VENDOR_STRING_3 |
| 50 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3); |
| 51 #else |
| 52 *value = 0; |
| 53 #endif |
| 54 break; |
| 55 case TPM_PT_VENDOR_STRING_4: |
| 56 // fourth four characters of the vendor ID string |
| 57 #ifdef VENDOR_STRING_4 |
| 58 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4); |
| 59 #else |
| 60 *value = 0; |
| 61 #endif |
| 62 break; |
| 63 case TPM_PT_VENDOR_TPM_TYPE: |
| 64 // vendor-defined value indicating the TPM model |
| 65 *value = 1; |
| 66 break; |
| 67 case TPM_PT_FIRMWARE_VERSION_1: |
| 68 // more significant 32-bits of a vendor-specific value |
| 69 *value = gp.firmwareV1; |
| 70 break; |
| 71 case TPM_PT_FIRMWARE_VERSION_2: |
| 72 // less significant 32-bits of a vendor-specific value |
| 73 *value = gp.firmwareV2; |
| 74 break; |
| 75 case TPM_PT_INPUT_BUFFER: |
| 76 // maximum size of TPM2B_MAX_BUFFER |
| 77 *value = MAX_DIGEST_BUFFER; |
| 78 break; |
| 79 case TPM_PT_HR_TRANSIENT_MIN: |
| 80 // minimum number of transient objects that can be held in TPM |
| 81 // RAM |
| 82 *value = MAX_LOADED_OBJECTS; |
| 83 break; |
| 84 case TPM_PT_HR_PERSISTENT_MIN: |
| 85 // minimum number of persistent objects that can be held in |
| 86 // TPM NV memory |
| 87 // In this implementation, there is no minimum number of |
| 88 // persistent objects. |
| 89 *value = MIN_EVICT_OBJECTS; |
| 90 break; |
| 91 case TPM_PT_HR_LOADED_MIN: |
| 92 // minimum number of authorization sessions that can be held in |
| 93 // TPM RAM |
| 94 *value = MAX_LOADED_SESSIONS; |
| 95 break; |
| 96 case TPM_PT_ACTIVE_SESSIONS_MAX: |
| 97 // number of authorization sessions that may be active at a time |
| 98 *value = MAX_ACTIVE_SESSIONS; |
| 99 break; |
| 100 case TPM_PT_PCR_COUNT: |
| 101 // number of PCR implemented |
| 102 *value = IMPLEMENTATION_PCR; |
| 103 break; |
| 104 case TPM_PT_PCR_SELECT_MIN: |
| 105 // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect |
| 106 *value = PCR_SELECT_MIN; |
| 107 break; |
| 108 case TPM_PT_CONTEXT_GAP_MAX: |
| 109 // maximum allowed difference (unsigned) between the contextID |
| 110 // values of two saved session contexts |
| 111 *value = (1 << (sizeof(CONTEXT_SLOT) * 8)) - 1; |
| |
| Family "2.0" TCG Published Page 259 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 112 break; |
| 113 case TPM_PT_NV_COUNTERS_MAX: |
| 114 // maximum number of NV indexes that are allowed to have the |
| 115 // TPMA_NV_COUNTER attribute SET |
| 116 // In this implementation, there is no limitation on the number |
| 117 // of counters, except for the size of the NV Index memory. |
| 118 *value = 0; |
| 119 break; |
| 120 case TPM_PT_NV_INDEX_MAX: |
| 121 // maximum size of an NV index data area |
| 122 *value = MAX_NV_INDEX_SIZE; |
| 123 break; |
| 124 case TPM_PT_MEMORY: |
| 125 // a TPMA_MEMORY indicating the memory management method for the TPM |
| 126 { |
| 127 TPMA_MEMORY attributes = {0}; |
| 128 attributes.sharedNV = SET; |
| 129 attributes.objectCopiedToRam = SET; |
| 130 |
| 131 // Note: Different compilers may require a different method to cast |
| 132 // a bit field structure to a UINT32. |
| 133 *value = * (UINT32 *) &attributes; |
| 134 break; |
| 135 } |
| 136 case TPM_PT_CLOCK_UPDATE: |
| 137 // interval, in seconds, between updates to the copy of |
| 138 // TPMS_TIME_INFO .clock in NV |
| 139 *value = (1 << NV_CLOCK_UPDATE_INTERVAL); |
| 140 break; |
| 141 case TPM_PT_CONTEXT_HASH: |
| 142 // algorithm used for the integrity hash on saved contexts and |
| 143 // for digesting the fuData of TPM2_FirmwareRead() |
| 144 *value = CONTEXT_INTEGRITY_HASH_ALG; |
| 145 break; |
| 146 case TPM_PT_CONTEXT_SYM: |
| 147 // algorithm used for encryption of saved contexts |
| 148 *value = CONTEXT_ENCRYPT_ALG; |
| 149 break; |
| 150 case TPM_PT_CONTEXT_SYM_SIZE: |
| 151 // size of the key used for encryption of saved contexts |
| 152 *value = CONTEXT_ENCRYPT_KEY_BITS; |
| 153 break; |
| 154 case TPM_PT_ORDERLY_COUNT: |
| 155 // maximum difference between the volatile and non-volatile |
| 156 // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET |
| 157 *value = MAX_ORDERLY_COUNT; |
| 158 break; |
| 159 case TPM_PT_MAX_COMMAND_SIZE: |
| 160 // maximum value for 'commandSize' |
| 161 *value = MAX_COMMAND_SIZE; |
| 162 break; |
| 163 case TPM_PT_MAX_RESPONSE_SIZE: |
| 164 // maximum value for 'responseSize' |
| 165 *value = MAX_RESPONSE_SIZE; |
| 166 break; |
| 167 case TPM_PT_MAX_DIGEST: |
| 168 // maximum size of a digest that can be produced by the TPM |
| 169 *value = sizeof(TPMU_HA); |
| 170 break; |
| 171 case TPM_PT_MAX_OBJECT_CONTEXT: |
| 172 // maximum size of a TPMS_CONTEXT that will be returned by |
| 173 // TPM2_ContextSave for object context |
| 174 *value = 0; |
| 175 |
| 176 // adding sequence, saved handle and hierarchy |
| 177 *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + |
| |
| Page 260 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 178 sizeof(TPMI_RH_HIERARCHY); |
| 179 // add size field in TPM2B_CONTEXT |
| 180 *value += sizeof(UINT16); |
| 181 |
| 182 // add integrity hash size |
| 183 *value += sizeof(UINT16) + |
| 184 CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG); |
| 185 |
| 186 // Add fingerprint size, which is the same as sequence size |
| 187 *value += sizeof(UINT64); |
| 188 |
| 189 // Add OBJECT structure size |
| 190 *value += sizeof(OBJECT); |
| 191 break; |
| 192 case TPM_PT_MAX_SESSION_CONTEXT: |
| 193 // the maximum size of a TPMS_CONTEXT that will be returned by |
| 194 // TPM2_ContextSave for object context |
| 195 *value = 0; |
| 196 |
| 197 // adding sequence, saved handle and hierarchy |
| 198 *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + |
| 199 sizeof(TPMI_RH_HIERARCHY); |
| 200 // Add size field in TPM2B_CONTEXT |
| 201 *value += sizeof(UINT16); |
| 202 |
| 203 // Add integrity hash size |
| 204 *value += sizeof(UINT16) + |
| 205 CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG); |
| 206 // Add fingerprint size, which is the same as sequence size |
| 207 *value += sizeof(UINT64); |
| 208 |
| 209 // Add SESSION structure size |
| 210 *value += sizeof(SESSION); |
| 211 break; |
| 212 case TPM_PT_PS_FAMILY_INDICATOR: |
| 213 // platform specific values for the TPM_PT_PS parameters from |
| 214 // the relevant platform-specific specification |
| 215 // In this reference implementation, all of these values are 0. |
| 216 *value = 0; |
| 217 break; |
| 218 case TPM_PT_PS_LEVEL: |
| 219 // level of the platform-specific specification |
| 220 *value = 0; |
| 221 break; |
| 222 case TPM_PT_PS_REVISION: |
| 223 // specification Revision times 100 for the platform-specific |
| 224 // specification |
| 225 *value = 0; |
| 226 break; |
| 227 case TPM_PT_PS_DAY_OF_YEAR: |
| 228 // platform-specific specification day of year using TCG calendar |
| 229 *value = 0; |
| 230 break; |
| 231 case TPM_PT_PS_YEAR: |
| 232 // platform-specific specification year using the CE |
| 233 *value = 0; |
| 234 break; |
| 235 case TPM_PT_SPLIT_MAX: |
| 236 // number of split signing operations supported by the TPM |
| 237 *value = 0; |
| 238 #ifdef TPM_ALG_ECC |
| 239 *value = sizeof(gr.commitArray) * 8; |
| 240 #endif |
| 241 break; |
| 242 case TPM_PT_TOTAL_COMMANDS: |
| 243 // total number of commands implemented in the TPM |
| |
| Family "2.0" TCG Published Page 261 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 244 // Since the reference implementation does not have any |
| 245 // vendor-defined commands, this will be the same as the |
| 246 // number of library commands. |
| 247 { |
| 248 UINT32 i; |
| 249 *value = 0; |
| 250 |
| 251 // calculate implemented command numbers |
| 252 for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++) |
| 253 { |
| 254 if(CommandIsImplemented(i)) (*value)++; |
| 255 } |
| 256 break; |
| 257 } |
| 258 case TPM_PT_LIBRARY_COMMANDS: |
| 259 // number of commands from the TPM library that are implemented |
| 260 { |
| 261 UINT32 i; |
| 262 *value = 0; |
| 263 |
| 264 // calculate implemented command numbers |
| 265 for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++) |
| 266 { |
| 267 if(CommandIsImplemented(i)) (*value)++; |
| 268 } |
| 269 break; |
| 270 } |
| 271 case TPM_PT_VENDOR_COMMANDS: |
| 272 // number of vendor commands that are implemented |
| 273 *value = 0; |
| 274 break; |
| 275 case TPM_PT_PERMANENT: |
| 276 // TPMA_PERMANENT |
| 277 { |
| 278 TPMA_PERMANENT flags = {0}; |
| 279 if(gp.ownerAuth.t.size != 0) |
| 280 flags.ownerAuthSet = SET; |
| 281 if(gp.endorsementAuth.t.size != 0) |
| 282 flags.endorsementAuthSet = SET; |
| 283 if(gp.lockoutAuth.t.size != 0) |
| 284 flags.lockoutAuthSet = SET; |
| 285 if(gp.disableClear) |
| 286 flags.disableClear = SET; |
| 287 if(gp.failedTries >= gp.maxTries) |
| 288 flags.inLockout = SET; |
| 289 // In this implementation, EPS is always generated by TPM |
| 290 flags.tpmGeneratedEPS = SET; |
| 291 |
| 292 // Note: Different compilers may require a different method to cast |
| 293 // a bit field structure to a UINT32. |
| 294 *value = * (UINT32 *) &flags; |
| 295 break; |
| 296 } |
| 297 case TPM_PT_STARTUP_CLEAR: |
| 298 // TPMA_STARTUP_CLEAR |
| 299 { |
| 300 TPMA_STARTUP_CLEAR flags = {0}; |
| 301 if(g_phEnable) |
| 302 flags.phEnable = SET; |
| 303 if(gc.shEnable) |
| 304 flags.shEnable = SET; |
| 305 if(gc.ehEnable) |
| 306 flags.ehEnable = SET; |
| 307 if(gc.phEnableNV) |
| 308 flags.phEnableNV = SET; |
| 309 if(g_prevOrderlyState != SHUTDOWN_NONE) |
| |
| Page 262 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 310 flags.orderly = SET; |
| 311 |
| 312 // Note: Different compilers may require a different method to cast |
| 313 // a bit field structure to a UINT32. |
| 314 *value = * (UINT32 *) &flags; |
| 315 break; |
| 316 } |
| 317 case TPM_PT_HR_NV_INDEX: |
| 318 // number of NV indexes currently defined |
| 319 *value = NvCapGetIndexNumber(); |
| 320 break; |
| 321 case TPM_PT_HR_LOADED: |
| 322 // number of authorization sessions currently loaded into TPM |
| 323 // RAM |
| 324 *value = SessionCapGetLoadedNumber(); |
| 325 break; |
| 326 case TPM_PT_HR_LOADED_AVAIL: |
| 327 // number of additional authorization sessions, of any type, |
| 328 // that could be loaded into TPM RAM |
| 329 *value = SessionCapGetLoadedAvail(); |
| 330 break; |
| 331 case TPM_PT_HR_ACTIVE: |
| 332 // number of active authorization sessions currently being |
| 333 // tracked by the TPM |
| 334 *value = SessionCapGetActiveNumber(); |
| 335 break; |
| 336 case TPM_PT_HR_ACTIVE_AVAIL: |
| 337 // number of additional authorization sessions, of any type, |
| 338 // that could be created |
| 339 *value = SessionCapGetActiveAvail(); |
| 340 break; |
| 341 case TPM_PT_HR_TRANSIENT_AVAIL: |
| 342 // estimate of the number of additional transient objects that |
| 343 // could be loaded into TPM RAM |
| 344 *value = ObjectCapGetTransientAvail(); |
| 345 break; |
| 346 case TPM_PT_HR_PERSISTENT: |
| 347 // number of persistent objects currently loaded into TPM |
| 348 // NV memory |
| 349 *value = NvCapGetPersistentNumber(); |
| 350 break; |
| 351 case TPM_PT_HR_PERSISTENT_AVAIL: |
| 352 // number of additional persistent objects that could be loaded |
| 353 // into NV memory |
| 354 *value = NvCapGetPersistentAvail(); |
| 355 break; |
| 356 case TPM_PT_NV_COUNTERS: |
| 357 // number of defined NV indexes that have NV TPMA_NV_COUNTER |
| 358 // attribute SET |
| 359 *value = NvCapGetCounterNumber(); |
| 360 break; |
| 361 case TPM_PT_NV_COUNTERS_AVAIL: |
| 362 // number of additional NV indexes that can be defined with their |
| 363 // TPMA_NV_COUNTER attribute SET |
| 364 *value = NvCapGetCounterAvail(); |
| 365 break; |
| 366 case TPM_PT_ALGORITHM_SET: |
| 367 // region code for the TPM |
| 368 *value = gp.algorithmSet; |
| 369 break; |
| 370 |
| 371 case TPM_PT_LOADED_CURVES: |
| 372 #ifdef TPM_ALG_ECC |
| 373 // number of loaded ECC curves |
| 374 *value = CryptCapGetEccCurveNumber(); |
| 375 #else // TPM_ALG_ECC |
| |
| Family "2.0" TCG Published Page 263 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 376 *value = 0; |
| 377 #endif // TPM_ALG_ECC |
| 378 break; |
| 379 |
| 380 case TPM_PT_LOCKOUT_COUNTER: |
| 381 // current value of the lockout counter |
| 382 *value = gp.failedTries; |
| 383 break; |
| 384 case TPM_PT_MAX_AUTH_FAIL: |
| 385 // number of authorization failures before DA lockout is invoked |
| 386 *value = gp.maxTries; |
| 387 break; |
| 388 case TPM_PT_LOCKOUT_INTERVAL: |
| 389 // number of seconds before the value reported by |
| 390 // TPM_PT_LOCKOUT_COUNTER is decremented |
| 391 *value = gp.recoveryTime; |
| 392 break; |
| 393 case TPM_PT_LOCKOUT_RECOVERY: |
| 394 // number of seconds after a lockoutAuth failure before use of |
| 395 // lockoutAuth may be attempted again |
| 396 *value = gp.lockoutRecovery; |
| 397 break; |
| 398 case TPM_PT_AUDIT_COUNTER_0: |
| 399 // high-order 32 bits of the command audit counter |
| 400 *value = (UINT32) (gp.auditCounter >> 32); |
| 401 break; |
| 402 case TPM_PT_AUDIT_COUNTER_1: |
| 403 // low-order 32 bits of the command audit counter |
| 404 *value = (UINT32) (gp.auditCounter); |
| 405 break; |
| 406 default: |
| 407 // property is not defined |
| 408 return FALSE; |
| 409 break; |
| 410 } |
| 411 |
| 412 return TRUE; |
| 413 } |
| |
| |
| 9.14.3.2 TPMCapGetProperties() |
| |
| This function is used to get the TPM_PT values. The search of properties will start at property and |
| continue until propertyList has as many values as will fit, or the last property has been reported, or the list |
| has as many values as requested in count. |
| |
| Return Value Meaning |
| |
| YES more properties are available |
| NO no more properties to be reported |
| |
| 414 TPMI_YES_NO |
| 415 TPMCapGetProperties( |
| 416 TPM_PT property, // IN: the starting TPM property |
| 417 UINT32 count, // IN: maximum number of returned |
| 418 // propertie |
| 419 TPML_TAGGED_TPM_PROPERTY *propertyList // OUT: property list |
| 420 ) |
| 421 { |
| 422 TPMI_YES_NO more = NO; |
| 423 UINT32 i; |
| 424 |
| 425 // initialize output property list |
| 426 propertyList->count = 0; |
| |
| Page 264 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 427 |
| 428 // maximum count of properties we may return is MAX_PCR_PROPERTIES |
| 429 if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES; |
| 430 |
| 431 // If property is less than PT_FIXED, start from PT_FIXED. |
| 432 if(property < PT_FIXED) property = PT_FIXED; |
| 433 |
| 434 // Scan through the TPM properties of the requested group. |
| 435 // The size of TPM property group is PT_GROUP * 2 for fix and |
| 436 // variable groups. |
| 437 for(i = property; i <= PT_FIXED + PT_GROUP * 2; i++) |
| 438 { |
| 439 UINT32 value; |
| 440 if(TPMPropertyIsDefined((TPM_PT) i, &value)) |
| 441 { |
| 442 if(propertyList->count < count) |
| 443 { |
| 444 |
| 445 // If the list is not full, add this property |
| 446 propertyList->tpmProperty[propertyList->count].property = |
| 447 (TPM_PT) i; |
| 448 propertyList->tpmProperty[propertyList->count].value = value; |
| 449 propertyList->count++; |
| 450 } |
| 451 else |
| 452 { |
| 453 // If the return list is full but there are more properties |
| 454 // available, set the indication and exit the loop. |
| 455 more = YES; |
| 456 break; |
| 457 } |
| 458 } |
| 459 } |
| 460 return more; |
| 461 } |
| |
| |
| 9.15 TpmFail.c |
| |
| 9.15.1 Includes, Defines, and Types |
| |
| 1 #define TPM_FAIL_C |
| 2 #include "InternalRoutines.h" |
| 3 #include <assert.h> |
| |
| On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of the |
| TPM_Types.h include. This will avoid a lot of alignment warnings from the compiler for the unaligned |
| structures. The alignment of the structures is not important as this function does not use any of the |
| structures in TPM_Types.h and only include it for the #defines of the capabilities, properties, and |
| command code values. |
| |
| 4 #pragma pack(push, 1) |
| 5 #include "TPM_Types.h" |
| 6 #pragma pack (pop) |
| 7 #include "swap.h" |
| |
| |
| 9.15.2 Typedefs |
| |
| These defines are used primarily for sizing of the local response buffer. |
| |
| 8 #pragma pack(push,1) |
| 9 typedef struct { |
| |
| Family "2.0" TCG Published Page 265 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 10 TPM_ST tag; |
| 11 UINT32 size; |
| 12 TPM_RC code; |
| 13 } HEADER; |
| 14 typedef struct { |
| 15 UINT16 size; |
| 16 struct { |
| 17 UINT32 function; |
| 18 UINT32 line; |
| 19 UINT32 code; |
| 20 } values; |
| 21 TPM_RC returnCode; |
| 22 } GET_TEST_RESULT_PARAMETERS; |
| 23 typedef struct { |
| 24 TPMI_YES_NO moreData; |
| 25 TPM_CAP capability; // Always TPM_CAP_TPM_PROPERTIES |
| 26 TPML_TAGGED_TPM_PROPERTY tpmProperty; // a single tagged property |
| 27 } GET_CAPABILITY_PARAMETERS; |
| 28 typedef struct { |
| 29 HEADER header; |
| 30 GET_TEST_RESULT_PARAMETERS getTestResult; |
| 31 } TEST_RESPONSE; |
| 32 typedef struct { |
| 33 HEADER header; |
| 34 GET_CAPABILITY_PARAMETERS getCap; |
| 35 } CAPABILITY_RESPONSE; |
| 36 typedef union { |
| 37 TEST_RESPONSE test; |
| 38 CAPABILITY_RESPONSE cap; |
| 39 } RESPONSES; |
| 40 #pragma pack(pop) |
| |
| Buffer to hold the responses. This may be a little larger than required due to padding that a compiler |
| might add. |
| |
| NOTE: This is not in Global.c because of the specialized data definitions above. Since the data contained in this |
| structure is not relevant outside of the execution of a single command (when the TPM is in failure mode. There |
| is no compelling reason to move all the typedefs to Global.h and this structure to Global.c. |
| |
| 41 #ifndef __IGNORE_STATE__ // Don't define this value |
| 42 static BYTE response[sizeof(RESPONSES)]; |
| 43 #endif |
| |
| |
| 9.15.3 Local Functions |
| |
| 9.15.3.1 MarshalUint16() |
| |
| Function to marshal a 16 bit value to the output buffer. |
| |
| 44 static INT32 |
| 45 MarshalUint16( |
| 46 UINT16 integer, |
| 47 BYTE **buffer |
| 48 ) |
| 49 { |
| 50 return UINT16_Marshal(&integer, buffer, NULL); |
| 51 } |
| |
| |
| 9.15.3.2 MarshalUint32() |
| |
| Function to marshal a 32 bit value to the output buffer. |
| |
| Page 266 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 52 static INT32 |
| 53 MarshalUint32( |
| 54 UINT32 integer, |
| 55 BYTE **buffer |
| 56 ) |
| 57 { |
| 58 return UINT32_Marshal(&integer, buffer, NULL); |
| 59 } |
| |
| |
| 9.15.3.3 UnmarshalHeader() |
| |
| Funtion to unmarshal the 10-byte command header. |
| |
| 60 static BOOL |
| 61 UnmarshalHeader( |
| 62 HEADER *header, |
| 63 BYTE **buffer, |
| 64 INT32 *size |
| 65 ) |
| 66 { |
| 67 UINT32 usize; |
| 68 TPM_RC ucode; |
| 69 if( UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS |
| 70 || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS |
| 71 || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS |
| 72 ) |
| 73 return FALSE; |
| 74 header->size = usize; |
| 75 header->code = ucode; |
| 76 return TRUE; |
| 77 } |
| |
| |
| 9.15.4 Public Functions |
| |
| 9.15.4.1 SetForceFailureMode() |
| |
| This function is called by the simulator to enable failure mode testing. |
| |
| 78 LIB_EXPORT void |
| 79 SetForceFailureMode( |
| 80 void |
| 81 ) |
| 82 { |
| 83 g_forceFailureMode = TRUE; |
| 84 return; |
| 85 } |
| |
| |
| 9.15.4.2 TpmFail() |
| |
| This function is called by TPM.lib when a failure occurs. It will set up the failure values to be returned on |
| TPM2_GetTestResult(). |
| |
| 86 void |
| 87 TpmFail( |
| 88 const char *function, |
| 89 int line, int code |
| 90 ) |
| 91 { |
| 92 // Save the values that indicate where the error occurred. |
| 93 // On a 64-bit machine, this may truncate the address of the string |
| |
| Family "2.0" TCG Published Page 267 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 94 // of the function name where the error occurred. |
| 95 s_failFunction = *(UINT32*)&function; |
| 96 s_failLine = line; |
| 97 s_failCode = code; |
| 98 |
| 99 // if asserts are enabled, then do an assert unless the failure mode code |
| 100 // is being tested |
| 101 assert(g_forceFailureMode); |
| 102 |
| 103 // Clear this flag |
| 104 g_forceFailureMode = FALSE; |
| 105 |
| 106 // Jump to the failure mode code. |
| 107 // Note: only get here if asserts are off or if we are testing failure mode |
| 108 longjmp(&g_jumpBuffer[0], 1); |
| 109 } |
| |
| |
| 9.15.5 TpmFailureMode |
| |
| This function is called by the interface code when the platform is in failure mode. |
| |
| 110 void |
| 111 TpmFailureMode ( |
| 112 unsigned int inRequestSize, // IN: command buffer size |
| 113 unsigned char *inRequest, // IN: command buffer |
| 114 unsigned int *outResponseSize, // OUT: response buffer size |
| 115 unsigned char **outResponse // OUT: response buffer |
| 116 ) |
| 117 { |
| 118 BYTE *buffer; |
| 119 UINT32 marshalSize; |
| 120 UINT32 capability; |
| 121 HEADER header; // unmarshaled command header |
| 122 UINT32 pt; // unmarshaled property type |
| 123 UINT32 count; // unmarshaled property count |
| 124 |
| 125 // If there is no command buffer, then just return TPM_RC_FAILURE |
| 126 if(inRequestSize == 0 || inRequest == NULL) |
| 127 goto FailureModeReturn; |
| 128 |
| 129 // If the header is not correct for TPM2_GetCapability() or |
| 130 // TPM2_GetTestResult() then just return the in failure mode response; |
| 131 buffer = inRequest; |
| 132 if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize)) |
| 133 goto FailureModeReturn; |
| 134 if( header.tag != TPM_ST_NO_SESSIONS |
| 135 || header.size < 10) |
| 136 goto FailureModeReturn; |
| 137 |
| 138 switch (header.code) { |
| 139 case TPM_CC_GetTestResult: |
| 140 |
| 141 // make sure that the command size is correct |
| 142 if(header.size != 10) |
| 143 goto FailureModeReturn; |
| 144 buffer = &response[10]; |
| 145 marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer); |
| 146 marshalSize += MarshalUint32(s_failFunction, &buffer); |
| 147 marshalSize += MarshalUint32(s_failLine, &buffer); |
| 148 marshalSize += MarshalUint32(s_failCode, &buffer); |
| 149 if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) |
| 150 marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer); |
| 151 else |
| 152 marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); |
| |
| |
| Page 268 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 153 break; |
| 154 |
| 155 case TPM_CC_GetCapability: |
| 156 // make sure that the size of the command is exactly the size |
| 157 // returned for the capability, property, and count |
| 158 if( header.size!= (10 + (3 * sizeof(UINT32))) |
| 159 // also verify that this is requesting TPM properties |
| 160 || (UINT32_Unmarshal(&capability, &inRequest, |
| 161 (INT32 *)&inRequestSize) |
| 162 != TPM_RC_SUCCESS) |
| 163 || (capability != TPM_CAP_TPM_PROPERTIES) |
| 164 || (UINT32_Unmarshal(&pt, &inRequest, (INT32 *)&inRequestSize) |
| 165 != TPM_RC_SUCCESS) |
| 166 || (UINT32_Unmarshal(&count, &inRequest, (INT32 *)&inRequestSize) |
| 167 != TPM_RC_SUCCESS) |
| 168 ) |
| 169 |
| 170 goto FailureModeReturn; |
| 171 |
| 172 // If in failure mode because of an unrecoverable read error, and the |
| 173 // property is 0 and the count is 0, then this is an indication to |
| 174 // re-manufacture the TPM. Do the re-manufacture but stay in failure |
| 175 // mode until the TPM is reset. |
| 176 // Note: this behavior is not required by the specification and it is |
| 177 // OK to leave the TPM permanently bricked due to an unrecoverable NV |
| 178 // error. |
| 179 if( count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) |
| 180 { |
| 181 g_manufactured = FALSE; |
| 182 TPM_Manufacture(0); |
| 183 } |
| 184 |
| 185 if(count > 0) |
| 186 count = 1; |
| 187 else if(pt > TPM_PT_FIRMWARE_VERSION_2) |
| 188 count = 0; |
| 189 if(pt < TPM_PT_MANUFACTURER) |
| 190 pt = TPM_PT_MANUFACTURER; |
| 191 |
| 192 // set up for return |
| 193 buffer = &response[10]; |
| 194 // if the request was for a PT less than the last one |
| 195 // then we indicate more, otherwise, not. |
| 196 if(pt < TPM_PT_FIRMWARE_VERSION_2) |
| 197 *buffer++ = YES; |
| 198 else |
| 199 *buffer++ = NO; |
| 200 |
| 201 marshalSize = 1; |
| 202 |
| 203 // indicate the capability type |
| 204 marshalSize += MarshalUint32(capability, &buffer); |
| 205 // indicate the number of values that are being returned (0 or 1) |
| 206 marshalSize += MarshalUint32(count, &buffer); |
| 207 // indicate the property |
| 208 marshalSize += MarshalUint32(pt, &buffer); |
| 209 |
| 210 if(count > 0) |
| 211 switch (pt) { |
| 212 case TPM_PT_MANUFACTURER: |
| 213 // the vendor ID unique to each TPM manufacturer |
| 214 #ifdef MANUFACTURER |
| 215 pt = *(UINT32*)MANUFACTURER; |
| 216 #else |
| 217 pt = 0; |
| 218 #endif |
| |
| Family "2.0" TCG Published Page 269 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 219 break; |
| 220 case TPM_PT_VENDOR_STRING_1: |
| 221 // the first four characters of the vendor ID string |
| 222 #ifdef VENDOR_STRING_1 |
| 223 pt = *(UINT32*)VENDOR_STRING_1; |
| 224 #else |
| 225 pt = 0; |
| 226 #endif |
| 227 break; |
| 228 case TPM_PT_VENDOR_STRING_2: |
| 229 // the second four characters of the vendor ID string |
| 230 #ifdef VENDOR_STRING_2 |
| 231 pt = *(UINT32*)VENDOR_STRING_2; |
| 232 #else |
| 233 pt = 0; |
| 234 #endif |
| 235 break; |
| 236 case TPM_PT_VENDOR_STRING_3: |
| 237 // the third four characters of the vendor ID string |
| 238 #ifdef VENDOR_STRING_3 |
| 239 pt = *(UINT32*)VENDOR_STRING_3; |
| 240 #else |
| 241 pt = 0; |
| 242 #endif |
| 243 break; |
| 244 case TPM_PT_VENDOR_STRING_4: |
| 245 // the fourth four characters of the vendor ID string |
| 246 #ifdef VENDOR_STRING_4 |
| 247 pt = *(UINT32*)VENDOR_STRING_4; |
| 248 #else |
| 249 pt = 0; |
| 250 #endif |
| 251 |
| 252 break; |
| 253 case TPM_PT_VENDOR_TPM_TYPE: |
| 254 // vendor-defined value indicating the TPM model |
| 255 // We just make up a number here |
| 256 pt = 1; |
| 257 break; |
| 258 case TPM_PT_FIRMWARE_VERSION_1: |
| 259 // the more significant 32-bits of a vendor-specific value |
| 260 // indicating the version of the firmware |
| 261 #ifdef FIRMWARE_V1 |
| 262 pt = FIRMWARE_V1; |
| 263 #else |
| 264 pt = 0; |
| 265 #endif |
| 266 break; |
| 267 default: // TPM_PT_FIRMWARE_VERSION_2: |
| 268 // the less significant 32-bits of a vendor-specific value |
| 269 // indicating the version of the firmware |
| 270 #ifdef FIRMWARE_V2 |
| 271 pt = FIRMWARE_V2; |
| 272 #else |
| 273 pt = 0; |
| 274 #endif |
| 275 break; |
| 276 } |
| 277 marshalSize += MarshalUint32(pt, &buffer); |
| 278 break; |
| 279 default: // default for switch (cc) |
| 280 goto FailureModeReturn; |
| 281 } |
| 282 // Now do the header |
| 283 buffer = response; |
| 284 marshalSize = marshalSize + 10; // Add the header size to the |
| |
| Page 270 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 285 // stuff already marshaled |
| 286 MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag |
| 287 MarshalUint32(marshalSize, &buffer); // responseSize |
| 288 MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code |
| 289 |
| 290 *outResponseSize = marshalSize; |
| 291 *outResponse = (unsigned char *)&response; |
| 292 return; |
| 293 |
| 294 FailureModeReturn: |
| 295 |
| 296 buffer = response; |
| 297 |
| 298 marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); |
| 299 marshalSize += MarshalUint32(10, &buffer); |
| 300 marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); |
| 301 |
| 302 *outResponseSize = marshalSize; |
| 303 *outResponse = (unsigned char *)response; |
| 304 return; |
| 305 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 271 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| 10 Cryptographic Functions |
| |
| 10.1 Introduction |
| |
| The files in this section provide cryptographic support for the other functions in the TPM and the interface |
| to the Crypto Engine. |
| |
| 10.2 CryptUtil.c |
| |
| 10.2.1 Includes |
| |
| 1 #include "TPM_Types.h" |
| 2 #include "CryptoEngine.h" // types shared by CryptUtil and CryptoEngine. |
| 3 // Includes the function prototypes for the |
| 4 // CryptoEngine functions. |
| 5 #include "Global.h" |
| 6 #include "InternalRoutines.h" |
| 7 #include "MemoryLib_fp.h" |
| 8 //#include "CryptSelfTest_fp.h" |
| |
| |
| 10.2.2 TranslateCryptErrors() |
| |
| This function converts errors from the cryptographic library into TPM_RC_VALUES. |
| |
| Error Returns Meaning |
| |
| TPM_RC_VALUE CRYPT_FAIL |
| TPM_RC_NO_RESULT CRYPT_NO_RESULT |
| TPM_RC_SCHEME CRYPT_SCHEME |
| TPM_RC_VALUE CRYPT_PARAMETER |
| TPM_RC_SIZE CRYPT_UNDERFLOW |
| TPM_RC_ECC_POINT CRYPT_POINT |
| TPM_RC_CANCELLED CRYPT_CANCEL |
| |
| 9 static TPM_RC |
| 10 TranslateCryptErrors ( |
| 11 CRYPT_RESULT retVal // IN: crypt error to evaluate |
| 12 ) |
| 13 { |
| 14 switch (retVal) |
| 15 { |
| 16 case CRYPT_SUCCESS: |
| 17 return TPM_RC_SUCCESS; |
| 18 case CRYPT_FAIL: |
| 19 return TPM_RC_VALUE; |
| 20 case CRYPT_NO_RESULT: |
| 21 return TPM_RC_NO_RESULT; |
| 22 case CRYPT_SCHEME: |
| 23 return TPM_RC_SCHEME; |
| 24 case CRYPT_PARAMETER: |
| 25 return TPM_RC_VALUE; |
| 26 case CRYPT_UNDERFLOW: |
| 27 return TPM_RC_SIZE; |
| 28 case CRYPT_POINT: |
| 29 return TPM_RC_ECC_POINT; |
| 30 case CRYPT_CANCEL: |
| |
| Page 272 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 31 return TPM_RC_CANCELED; |
| 32 default: // Other unknown warnings |
| 33 return TPM_RC_FAILURE; |
| 34 } |
| 35 } |
| |
| |
| 10.2.3 Random Number Generation Functions |
| |
| 36 #ifdef TPM_ALG_NULL //% |
| 37 #ifdef _DRBG_STATE_SAVE //% |
| |
| |
| 10.2.3.1 CryptDrbgGetPutState() |
| |
| Read or write the current state from the DRBG in the cryptoEngine. |
| |
| 38 void |
| 39 CryptDrbgGetPutState( |
| 40 GET_PUT direction // IN: Get from or put to DRBG |
| 41 ) |
| 42 { |
| 43 _cpri__DrbgGetPutState(direction, |
| 44 sizeof(go.drbgState), |
| 45 (BYTE *)&go.drbgState); |
| 46 } |
| 47 #else //% 00 |
| 48 //%#define CryptDrbgGetPutState(ignored) // If not doing state save, turn this |
| 49 //% // into a null macro |
| 50 #endif //% |
| |
| |
| 10.2.3.2 CryptStirRandom() |
| |
| Stir random entropy |
| |
| 51 void |
| 52 CryptStirRandom( |
| 53 UINT32 entropySize, // IN: size of entropy buffer |
| 54 BYTE *buffer // IN: entropy buffer |
| 55 ) |
| 56 { |
| 57 // RNG self testing code may be inserted here |
| 58 |
| 59 // Call crypto engine random number stirring function |
| 60 _cpri__StirRandom(entropySize, buffer); |
| 61 |
| 62 return; |
| 63 } |
| |
| |
| 10.2.3.3 CryptGenerateRandom() |
| |
| This is the interface to _cpri__GenerateRandom(). |
| |
| 64 UINT16 |
| 65 CryptGenerateRandom( |
| 66 UINT16 randomSize, // IN: size of random number |
| 67 BYTE *buffer // OUT: buffer of random number |
| 68 ) |
| 69 { |
| 70 UINT16 result; |
| 71 pAssert(randomSize <= MAX_RSA_KEY_BYTES || randomSize <= PRIMARY_SEED_SIZE); |
| 72 if(randomSize == 0) |
| |
| Family "2.0" TCG Published Page 273 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 73 return 0; |
| 74 |
| 75 // Call crypto engine random number generation |
| 76 result = _cpri__GenerateRandom(randomSize, buffer); |
| 77 if(result != randomSize) |
| 78 FAIL(FATAL_ERROR_INTERNAL); |
| 79 |
| 80 return result; |
| 81 } |
| 82 #endif //TPM_ALG_NULL //% |
| |
| |
| 10.2.4 Hash/HMAC Functions |
| |
| 10.2.4.1 CryptGetContextAlg() |
| |
| This function returns the hash algorithm associated with a hash context. |
| |
| 83 #ifdef TPM_ALG_KEYEDHASH //% 1 |
| 84 TPM_ALG_ID |
| 85 CryptGetContextAlg( |
| 86 void *state // IN: the context to check |
| 87 ) |
| 88 { |
| 89 HASH_STATE *context = (HASH_STATE *)state; |
| 90 return _cpri__GetContextAlg(&context->state); |
| 91 } |
| |
| |
| 10.2.4.2 CryptStartHash() |
| |
| This function starts a hash and return the size, in bytes, of the digest. |
| |
| Return Value Meaning |
| |
| >0 the digest size of the algorithm |
| =0 the hashAlg was TPM_ALG_NULL |
| |
| 92 UINT16 |
| 93 CryptStartHash( |
| 94 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 95 HASH_STATE *hashState // OUT: the state of hash stack. It will be used |
| 96 // in hash update and completion |
| 97 ) |
| 98 { |
| 99 CRYPT_RESULT retVal = 0; |
| 100 |
| 101 pAssert(hashState != NULL); |
| 102 |
| 103 TEST_HASH(hashAlg); |
| 104 |
| 105 hashState->type = HASH_STATE_EMPTY; |
| 106 |
| 107 // Call crypto engine start hash function |
| 108 if((retVal = _cpri__StartHash(hashAlg, FALSE, &hashState->state)) > 0) |
| 109 hashState->type = HASH_STATE_HASH; |
| 110 |
| 111 return retVal; |
| 112 } |
| |
| |
| |
| |
| Page 274 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 10.2.4.3 CryptStartHashSequence() |
| |
| Start a hash stack for a sequence object and return the size, in bytes, of the digest. This call uses the |
| form of the hash state that requires context save and restored. |
| |
| Return Value Meaning |
| |
| >0 the digest size of the algorithm |
| =0 the hashAlg was TPM_ALG_NULL |
| |
| 113 UINT16 |
| 114 CryptStartHashSequence( |
| 115 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 116 HASH_STATE *hashState // OUT: the state of hash stack. It will be used |
| 117 // in hash update and completion |
| 118 ) |
| 119 { |
| 120 CRYPT_RESULT retVal = 0; |
| 121 |
| 122 pAssert(hashState != NULL); |
| 123 |
| 124 TEST_HASH(hashAlg); |
| 125 |
| 126 hashState->type = HASH_STATE_EMPTY; |
| 127 |
| 128 // Call crypto engine start hash function |
| 129 if((retVal = _cpri__StartHash(hashAlg, TRUE, &hashState->state)) > 0) |
| 130 hashState->type = HASH_STATE_HASH; |
| 131 |
| 132 return retVal; |
| 133 |
| 134 } |
| |
| |
| 10.2.4.4 CryptStartHMAC() |
| |
| This function starts an HMAC sequence and returns the size of the digest that will be produced. |
| The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
| not alter the contents of this buffer until the hash sequence is completed or abandoned. |
| |
| Return Value Meaning |
| |
| >0 the digest size of the algorithm |
| =0 the hashAlg was TPM_ALG_NULL |
| |
| 135 UINT16 |
| 136 CryptStartHMAC( |
| 137 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 138 UINT16 keySize, // IN: the size of HMAC key in byte |
| 139 BYTE *key, // IN: HMAC key |
| 140 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
| 141 // in HMAC update and completion |
| 142 ) |
| 143 { |
| 144 HASH_STATE *hashState = (HASH_STATE *)hmacState; |
| 145 CRYPT_RESULT retVal; |
| 146 |
| 147 // This has to come before the pAssert in case we all calling this function |
| 148 // during testing. If so, the first instance will have no arguments but the |
| 149 // hash algorithm. The call from the test routine will have arguments. When |
| 150 // the second call is done, then we return to the test dispatcher. |
| 151 TEST_HASH(hashAlg); |
| |
| Family "2.0" TCG Published Page 275 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 152 |
| 153 pAssert(hashState != NULL); |
| 154 |
| 155 hashState->type = HASH_STATE_EMPTY; |
| 156 |
| 157 if((retVal = _cpri__StartHMAC(hashAlg, FALSE, &hashState->state, keySize, key, |
| 158 &hmacState->hmacKey.b)) > 0) |
| 159 hashState->type = HASH_STATE_HMAC; |
| 160 |
| 161 return retVal; |
| 162 } |
| |
| |
| 10.2.4.5 CryptStartHMACSequence() |
| |
| This function starts an HMAC sequence and returns the size of the digest that will be produced. |
| The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
| not alter the contents of this buffer until the hash sequence is completed or abandoned. |
| This call is used to start a sequence HMAC that spans multiple TPM commands. |
| |
| Return Value Meaning |
| |
| >0 the digest size of the algorithm |
| =0 the hashAlg was TPM_ALG_NULL |
| |
| 163 UINT16 |
| 164 CryptStartHMACSequence( |
| 165 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 166 UINT16 keySize, // IN: the size of HMAC key in byte |
| 167 BYTE *key, // IN: HMAC key |
| 168 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
| 169 // in HMAC update and completion |
| 170 ) |
| 171 { |
| 172 HASH_STATE *hashState = (HASH_STATE *)hmacState; |
| 173 CRYPT_RESULT retVal; |
| 174 |
| 175 TEST_HASH(hashAlg); |
| 176 |
| 177 hashState->type = HASH_STATE_EMPTY; |
| 178 |
| 179 if((retVal = _cpri__StartHMAC(hashAlg, TRUE, &hashState->state, |
| 180 keySize, key, &hmacState->hmacKey.b)) > 0) |
| 181 hashState->type = HASH_STATE_HMAC; |
| 182 |
| 183 return retVal; |
| 184 } |
| |
| |
| 10.2.4.6 CryptStartHMAC2B() |
| |
| This function starts an HMAC and returns the size of the digest that will be produced. |
| This function is provided to support the most common use of starting an HMAC with a TPM2B key. |
| The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
| not alter the contents of this buffer until the hash sequence is completed or abandoned. |
| |
| |
| |
| |
| Page 276 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| >0 the digest size of the algorithm |
| =0 the hashAlg was TPM_ALG_NULL |
| |
| 185 LIB_EXPORT UINT16 |
| 186 CryptStartHMAC2B( |
| 187 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 188 TPM2B *key, // IN: HMAC key |
| 189 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
| 190 // in HMAC update and completion |
| 191 ) |
| 192 { |
| 193 return CryptStartHMAC(hashAlg, key->size, key->buffer, hmacState); |
| 194 } |
| |
| |
| 10.2.4.7 CryptStartHMACSequence2B() |
| |
| This function starts an HMAC sequence and returns the size of the digest that will be produced. |
| This function is provided to support the most common use of starting an HMAC with a TPM2B key. |
| The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
| not alter the contents of this buffer until the hash sequence is completed or abandoned. |
| |
| Return Value Meaning |
| |
| >0 the digest size of the algorithm |
| =0 the hashAlg was TPM_ALG_NULL |
| |
| 195 UINT16 |
| 196 CryptStartHMACSequence2B( |
| 197 TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
| 198 TPM2B *key, // IN: HMAC key |
| 199 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
| 200 // in HMAC update and completion |
| 201 ) |
| 202 { |
| 203 return CryptStartHMACSequence(hashAlg, key->size, key->buffer, hmacState); |
| 204 } |
| |
| |
| 10.2.4.8 CryptUpdateDigest() |
| |
| This function updates a digest (hash or HMAC) with an array of octets. |
| This function can be used for both HMAC and hash functions so the digestState is void so that either |
| state type can be passed. |
| |
| 205 LIB_EXPORT void |
| 206 CryptUpdateDigest( |
| 207 void *digestState, // IN: the state of hash stack |
| 208 UINT32 dataSize, // IN: the size of data |
| 209 BYTE *data // IN: data to be hashed |
| 210 ) |
| 211 { |
| 212 HASH_STATE *hashState = (HASH_STATE *)digestState; |
| 213 |
| 214 pAssert(digestState != NULL); |
| 215 |
| 216 if(hashState->type != HASH_STATE_EMPTY && data != NULL && dataSize != 0) |
| 217 { |
| |
| Family "2.0" TCG Published Page 277 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 218 // Call crypto engine update hash function |
| 219 _cpri__UpdateHash(&hashState->state, dataSize, data); |
| 220 } |
| 221 return; |
| 222 } |
| |
| |
| 10.2.4.9 CryptUpdateDigest2B() |
| |
| This function updates a digest (hash or HMAC) with a TPM2B. |
| This function can be used for both HMAC and hash functions so the digestState is void so that either |
| state type can be passed. |
| |
| 223 LIB_EXPORT void |
| 224 CryptUpdateDigest2B( |
| 225 void *digestState, // IN: the digest state |
| 226 TPM2B *bIn // IN: 2B containing the data |
| 227 ) |
| 228 { |
| 229 // Only compute the digest if a pointer to the 2B is provided. |
| 230 // In CryptUpdateDigest(), if size is zero or buffer is NULL, then no change |
| 231 // to the digest occurs. This function should not provide a buffer if bIn is |
| 232 // not provided. |
| 233 if(bIn != NULL) |
| 234 CryptUpdateDigest(digestState, bIn->size, bIn->buffer); |
| 235 return; |
| 236 } |
| |
| |
| 10.2.4.10 CryptUpdateDigestInt() |
| |
| This function is used to include an integer value to a hash stack. The function marshals the integer into its |
| canonical form before calling CryptUpdateHash(). |
| |
| 237 LIB_EXPORT void |
| 238 CryptUpdateDigestInt( |
| 239 void *state, // IN: the state of hash stack |
| 240 UINT32 intSize, // IN: the size of 'intValue' in byte |
| 241 void *intValue // IN: integer value to be hashed |
| 242 ) |
| 243 { |
| 244 |
| 245 #if BIG_ENDIAN_TPM == YES |
| 246 pAssert( intValue != NULL && (intSize == 1 || intSize == 2 |
| 247 || intSize == 4 || intSize == 8)); |
| 248 CryptUpdateHash(state, inSize, (BYTE *)intValue); |
| 249 #else |
| 250 |
| 251 BYTE marshalBuffer[8]; |
| 252 // Point to the big end of an little-endian value |
| 253 BYTE *p = &((BYTE *)intValue)[intSize - 1]; |
| 254 // Point to the big end of an big-endian value |
| 255 BYTE *q = marshalBuffer; |
| 256 |
| 257 pAssert(intValue != NULL); |
| 258 switch (intSize) |
| 259 { |
| 260 case 8: |
| 261 *q++ = *p--; |
| 262 *q++ = *p--; |
| 263 *q++ = *p--; |
| 264 *q++ = *p--; |
| 265 case 4: |
| 266 *q++ = *p--; |
| |
| Page 278 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 267 *q++ = *p--; |
| 268 case 2: |
| 269 *q++ = *p--; |
| 270 case 1: |
| 271 *q = *p; |
| 272 // Call update the hash |
| 273 CryptUpdateDigest(state, intSize, marshalBuffer); |
| 274 break; |
| 275 default: |
| 276 FAIL(0); |
| 277 } |
| 278 |
| 279 #endif |
| 280 return; |
| 281 } |
| |
| |
| 10.2.4.11 CryptCompleteHash() |
| |
| This function completes a hash sequence and returns the digest. |
| This function can be called to complete either an HMAC or hash sequence. The state type determines if |
| the context type is a hash or HMAC. If an HMAC, then the call is forwarded to CryptCompleteHash(). |
| If digestSize is smaller than the digest size of hash/HMAC algorithm, the most significant bytes of |
| required size will be returned |
| |
| Return Value Meaning |
| |
| >=0 the number of bytes placed in digest |
| |
| 282 LIB_EXPORT UINT16 |
| 283 CryptCompleteHash( |
| 284 void *state, // IN: the state of hash stack |
| 285 UINT16 digestSize, // IN: size of digest buffer |
| 286 BYTE *digest // OUT: hash digest |
| 287 ) |
| 288 { |
| 289 HASH_STATE *hashState = (HASH_STATE *)state; // local value |
| 290 |
| 291 // If the session type is HMAC, then could forward this to |
| 292 // the HMAC processing and not cause an error. However, if no |
| 293 // function calls this routine to forward it, then we can't get |
| 294 // test coverage. The decision is to assert if this is called with |
| 295 // the type == HMAC and fix anything that makes the wrong call. |
| 296 pAssert(hashState->type == HASH_STATE_HASH); |
| 297 |
| 298 // Set the state to empty so that it doesn't get used again |
| 299 hashState->type = HASH_STATE_EMPTY; |
| 300 |
| 301 // Call crypto engine complete hash function |
| 302 return _cpri__CompleteHash(&hashState->state, digestSize, digest); |
| 303 } |
| |
| |
| 10.2.4.12 CryptCompleteHash2B() |
| |
| This function is the same as CypteCompleteHash() but the digest is placed in a TPM2B. This is the most |
| common use and this is provided for specification clarity. 'digest.size' should be set to indicate the number |
| of bytes to place in the buffer |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 279 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| >=0 the number of bytes placed in 'digest.buffer' |
| |
| 304 LIB_EXPORT UINT16 |
| 305 CryptCompleteHash2B( |
| 306 void *state, // IN: the state of hash stack |
| 307 TPM2B *digest // IN: the size of the buffer Out: requested |
| 308 // number of byte |
| 309 ) |
| 310 { |
| 311 UINT16 retVal = 0; |
| 312 |
| 313 if(digest != NULL) |
| 314 retVal = CryptCompleteHash(state, digest->size, digest->buffer); |
| 315 |
| 316 return retVal; |
| 317 } |
| |
| |
| 10.2.4.13 CryptHashBlock() |
| |
| Hash a block of data and return the results. If the digest is larger than retSize, it is truncated and with the |
| least significant octets dropped. |
| |
| Return Value Meaning |
| |
| >=0 the number of bytes placed in ret |
| |
| 318 LIB_EXPORT UINT16 |
| 319 CryptHashBlock( |
| 320 TPM_ALG_ID algId, // IN: the hash algorithm to use |
| 321 UINT16 blockSize, // IN: size of the data block |
| 322 BYTE *block, // IN: address of the block to hash |
| 323 UINT16 retSize, // IN: size of the return buffer |
| 324 BYTE *ret // OUT: address of the buffer |
| 325 ) |
| 326 { |
| 327 TEST_HASH(algId); |
| 328 |
| 329 return _cpri__HashBlock(algId, blockSize, block, retSize, ret); |
| 330 } |
| |
| |
| 10.2.4.14 CryptCompleteHMAC() |
| |
| This function completes a HMAC sequence and returns the digest. If digestSize is smaller than the digest |
| size of the HMAC algorithm, the most significant bytes of required size will be returned. |
| |
| Return Value Meaning |
| |
| >=0 the number of bytes placed in digest |
| |
| 331 LIB_EXPORT UINT16 |
| 332 CryptCompleteHMAC( |
| 333 HMAC_STATE *hmacState, // IN: the state of HMAC stack |
| 334 UINT32 digestSize, // IN: size of digest buffer |
| 335 BYTE *digest // OUT: HMAC digest |
| 336 ) |
| 337 { |
| 338 HASH_STATE *hashState; |
| 339 |
| 340 pAssert(hmacState != NULL); |
| |
| Page 280 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 341 hashState = &hmacState->hashState; |
| 342 |
| 343 pAssert(hashState->type == HASH_STATE_HMAC); |
| 344 |
| 345 hashState->type = HASH_STATE_EMPTY; |
| 346 |
| 347 return _cpri__CompleteHMAC(&hashState->state, &hmacState->hmacKey.b, |
| 348 digestSize, digest); |
| 349 |
| 350 } |
| |
| |
| 10.2.4.15 CryptCompleteHMAC2B() |
| |
| This function is the same as CryptCompleteHMAC() but the HMAC result is returned in a TPM2B which is |
| the most common use. |
| |
| Return Value Meaning |
| |
| >=0 the number of bytes placed in digest |
| |
| 351 LIB_EXPORT UINT16 |
| 352 CryptCompleteHMAC2B( |
| 353 HMAC_STATE *hmacState, // IN: the state of HMAC stack |
| 354 TPM2B *digest // OUT: HMAC |
| 355 ) |
| 356 { |
| 357 UINT16 retVal = 0; |
| 358 if(digest != NULL) |
| 359 retVal = CryptCompleteHMAC(hmacState, digest->size, digest->buffer); |
| 360 return retVal; |
| 361 } |
| |
| |
| 10.2.4.16 CryptHashStateImportExport() |
| |
| This function is used to prepare a hash state context for LIB_EXPORT or to import it into the internal |
| format. It is used by TPM2_ContextSave() and TPM2_ContextLoad() via SequenceDataImportExport(). |
| This is just a pass-through function to the crypto library. |
| |
| 362 void |
| 363 CryptHashStateImportExport( |
| 364 HASH_STATE *internalFmt, // IN: state to LIB_EXPORT |
| 365 HASH_STATE *externalFmt, // OUT: exported state |
| 366 IMPORT_EXPORT direction |
| 367 ) |
| 368 { |
| 369 _cpri__ImportExportHashState(&internalFmt->state, |
| 370 (EXPORT_HASH_STATE *)&externalFmt->state, |
| 371 direction); |
| 372 } |
| |
| |
| 10.2.4.17 CryptGetHashDigestSize() |
| |
| This function returns the digest size in bytes for a hash algorithm. |
| |
| Return Value Meaning |
| |
| 0 digest size for TPM_ALG_NULL |
| >0 digest size |
| |
| 373 LIB_EXPORT UINT16 |
| |
| Family "2.0" TCG Published Page 281 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 374 CryptGetHashDigestSize( |
| 375 TPM_ALG_ID hashAlg // IN: hash algorithm |
| 376 ) |
| 377 { |
| 378 return _cpri__GetDigestSize(hashAlg); |
| 379 } |
| |
| |
| 10.2.4.18 CryptGetHashBlockSize() |
| |
| Get the digest size in byte of a hash algorithm. |
| |
| Return Value Meaning |
| |
| 0 block size for TPM_ALG_NULL |
| >0 block size |
| |
| 380 LIB_EXPORT UINT16 |
| 381 CryptGetHashBlockSize( |
| 382 TPM_ALG_ID hash // IN: hash algorithm to look up |
| 383 ) |
| 384 { |
| 385 return _cpri__GetHashBlockSize(hash); |
| 386 } |
| |
| |
| 10.2.4.19 CryptGetHashAlgByIndex() |
| |
| This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are |
| not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first |
| implemented hash and an index value of 2 will return the last implemented hash. All other index values |
| will return TPM_ALG_NULL. |
| |
| Return Value Meaning |
| |
| TPM_ALG_xxx() a hash algorithm |
| TPM_ALG_NULL this can be used as a stop value |
| |
| 387 LIB_EXPORT TPM_ALG_ID |
| 388 CryptGetHashAlgByIndex( |
| 389 UINT32 index // IN: the index |
| 390 ) |
| 391 { |
| 392 return _cpri__GetHashAlgByIndex(index); |
| 393 } |
| |
| |
| 10.2.4.20 CryptSignHMAC() |
| |
| Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message. |
| |
| Error Returns Meaning |
| |
| 394 static TPM_RC |
| 395 CryptSignHMAC( |
| 396 OBJECT *signKey, // IN: HMAC key sign the hash |
| 397 TPMT_SIG_SCHEME *scheme, // IN: signing scheme |
| 398 TPM2B_DIGEST *hashData, // IN: hash to be signed |
| 399 TPMT_SIGNATURE *signature // OUT: signature |
| 400 ) |
| 401 { |
| |
| |
| Page 282 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 402 HMAC_STATE hmacState; |
| 403 UINT32 digestSize; |
| 404 |
| 405 // HMAC algorithm self testing code may be inserted here |
| 406 |
| 407 digestSize = CryptStartHMAC2B(scheme->details.hmac.hashAlg, |
| 408 &signKey->sensitive.sensitive.bits.b, |
| 409 &hmacState); |
| 410 |
| 411 // The hash algorithm must be a valid one. |
| 412 pAssert(digestSize > 0); |
| 413 |
| 414 CryptUpdateDigest2B(&hmacState, &hashData->b); |
| 415 |
| 416 CryptCompleteHMAC(&hmacState, digestSize, |
| 417 (BYTE *) &signature->signature.hmac.digest); |
| 418 |
| 419 // Set HMAC algorithm |
| 420 signature->signature.hmac.hashAlg = scheme->details.hmac.hashAlg; |
| 421 |
| 422 return TPM_RC_SUCCESS; |
| 423 } |
| |
| |
| 10.2.4.21 CryptHMACVerifySignature() |
| |
| This function will verify a signature signed by a HMAC key. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SIGNATURE if invalid input or signature is not genuine |
| |
| 424 static TPM_RC |
| 425 CryptHMACVerifySignature( |
| 426 OBJECT *signKey, // IN: HMAC key signed the hash |
| 427 TPM2B_DIGEST *hashData, // IN: digest being verified |
| 428 TPMT_SIGNATURE *signature // IN: signature to be verified |
| 429 ) |
| 430 { |
| 431 HMAC_STATE hmacState; |
| 432 TPM2B_DIGEST digestToCompare; |
| 433 |
| 434 digestToCompare.t.size = CryptStartHMAC2B(signature->signature.hmac.hashAlg, |
| 435 &signKey->sensitive.sensitive.bits.b, &hmacState); |
| 436 |
| 437 CryptUpdateDigest2B(&hmacState, &hashData->b); |
| 438 |
| 439 CryptCompleteHMAC2B(&hmacState, &digestToCompare.b); |
| 440 |
| 441 // Compare digest |
| 442 if(MemoryEqual(digestToCompare.t.buffer, |
| 443 (BYTE *) &signature->signature.hmac.digest, |
| 444 digestToCompare.t.size)) |
| 445 return TPM_RC_SUCCESS; |
| 446 else |
| 447 return TPM_RC_SIGNATURE; |
| 448 |
| 449 } |
| |
| |
| 10.2.4.22 CryptGenerateKeyedHash() |
| |
| This function creates a keyedHash object. |
| |
| |
| |
| Family "2.0" TCG Published Page 283 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_SIZE sensitive data size is larger than allowed for the scheme |
| |
| 450 static TPM_RC |
| 451 CryptGenerateKeyedHash( |
| 452 TPMT_PUBLIC *publicArea, // IN/OUT: the public area template |
| 453 // for the new key. |
| 454 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data |
| 455 TPMT_SENSITIVE *sensitive, // OUT: sensitive area |
| 456 TPM_ALG_ID kdfHashAlg, // IN: algorithm for the KDF |
| 457 TPM2B_SEED *seed, // IN: the seed |
| 458 TPM2B_NAME *name // IN: name of the object |
| 459 ) |
| 460 { |
| 461 TPMT_KEYEDHASH_SCHEME *scheme; |
| 462 TPM_ALG_ID hashAlg; |
| 463 UINT16 hashBlockSize; |
| 464 |
| 465 scheme = &publicArea->parameters.keyedHashDetail.scheme; |
| 466 |
| 467 pAssert(publicArea->type == TPM_ALG_KEYEDHASH); |
| 468 |
| 469 // Pick the limiting hash algorithm |
| 470 if(scheme->scheme == TPM_ALG_NULL) |
| 471 hashAlg = publicArea->nameAlg; |
| 472 else if(scheme->scheme == TPM_ALG_XOR) |
| 473 hashAlg = scheme->details.xor.hashAlg; |
| 474 else |
| 475 hashAlg = scheme->details.hmac.hashAlg; |
| 476 hashBlockSize = CryptGetHashBlockSize(hashAlg); |
| 477 |
| 478 // if this is a signing or a decryption key, then then the limit |
| 479 // for the data size is the block size of the hash. This limit |
| 480 // is set because larger values have lower entropy because of the |
| 481 // HMAC function. |
| 482 if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR) |
| 483 { |
| 484 if( ( publicArea->objectAttributes.decrypt |
| 485 || publicArea->objectAttributes.sign) |
| 486 && sensitiveCreate->data.t.size > hashBlockSize) |
| 487 |
| 488 return TPM_RC_SIZE; |
| 489 } |
| 490 else |
| 491 { |
| 492 // If the TPM is going to generate the data, then set the size to be the |
| 493 // size of the digest of the algorithm |
| 494 sensitive->sensitive.sym.t.size = CryptGetHashDigestSize(hashAlg); |
| 495 sensitiveCreate->data.t.size = 0; |
| 496 } |
| 497 |
| 498 // Fill in the sensitive area |
| 499 CryptGenerateNewSymmetric(sensitiveCreate, sensitive, kdfHashAlg, |
| 500 seed, name); |
| 501 |
| 502 // Create unique area in public |
| 503 CryptComputeSymmetricUnique(publicArea->nameAlg, |
| 504 sensitive, &publicArea->unique.sym); |
| 505 |
| 506 return TPM_RC_SUCCESS; |
| 507 } |
| |
| |
| |
| |
| Page 284 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 10.2.4.23 CryptKDFa() |
| |
| This function generates a key using the KDFa() formulation in Part 1 of the TPM specification. In this |
| implementation, this is a macro invocation of _cpri__KDFa() in the hash module of the CryptoEngine(). |
| This macro sets once to FALSE so that KDFa() will iterate as many times as necessary to generate |
| sizeInBits number of bits. |
| |
| 508 //%#define CryptKDFa(hashAlg, key, label, contextU, contextV, \ |
| 509 //% sizeInBits, keyStream, counterInOut) \ |
| 510 //% TEST_HASH(hashAlg); \ |
| 511 //% _cpri__KDFa( \ |
| 512 //% ((TPM_ALG_ID)hashAlg), \ |
| 513 //% ((TPM2B *)key), \ |
| 514 //% ((const char *)label), \ |
| 515 //% ((TPM2B *)contextU), \ |
| 516 //% ((TPM2B *)contextV), \ |
| 517 //% ((UINT32)sizeInBits), \ |
| 518 //% ((BYTE *)keyStream), \ |
| 519 //% ((UINT32 *)counterInOut), \ |
| 520 //% ((BOOL) FALSE) \ |
| 521 //% ) |
| 522 //% |
| |
| |
| 10.2.4.24 CryptKDFaOnce() |
| |
| This function generates a key using the KDFa() formulation in Part 1 of the TPM specification. In this |
| implementation, this is a macro invocation of _cpri__KDFa() in the hash module of the CryptoEngine(). |
| This macro will call _cpri__KDFa() with once TRUE so that only one iteration is performed, regardless of |
| sizeInBits. |
| |
| 523 //%#define CryptKDFaOnce(hashAlg, key, label, contextU, contextV, \ |
| 524 //% sizeInBits, keyStream, counterInOut) \ |
| 525 //% TEST_HASH(hashAlg); \ |
| 526 //% _cpri__KDFa( \ |
| 527 //% ((TPM_ALG_ID)hashAlg), \ |
| 528 //% ((TPM2B *)key), \ |
| 529 //% ((const char *)label), \ |
| 530 //% ((TPM2B *)contextU), \ |
| 531 //% ((TPM2B *)contextV), \ |
| 532 //% ((UINT32)sizeInBits), \ |
| 533 //% ((BYTE *)keyStream), \ |
| 534 //% ((UINT32 *)counterInOut), \ |
| 535 //% ((BOOL) TRUE) \ |
| 536 //% ) |
| 537 //% |
| |
| |
| 10.2.4.25 KDFa() |
| |
| This function is used by functions outside of CryptUtil() to access _cpri_KDFa(). |
| |
| 538 void |
| 539 KDFa( |
| 540 TPM_ALG_ID hash, // IN: hash algorithm used in HMAC |
| 541 TPM2B *key, // IN: HMAC key |
| 542 const char *label, // IN: a null-terminated label for KDF |
| 543 TPM2B *contextU, // IN: context U |
| 544 TPM2B *contextV, // IN: context V |
| 545 UINT32 sizeInBits, // IN: size of generated key in bit |
| 546 BYTE *keyStream, // OUT: key buffer |
| 547 UINT32 *counterInOut // IN/OUT: caller may provide the iteration |
| 548 // counter for incremental operations to |
| |
| Family "2.0" TCG Published Page 285 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 549 // avoid large intermediate buffers. |
| 550 ) |
| 551 { |
| 552 CryptKDFa(hash, key, label, contextU, contextV, sizeInBits, |
| 553 keyStream, counterInOut); |
| 554 } |
| |
| |
| 10.2.4.26 CryptKDFe() |
| |
| This function generates a key using the KDFa() formulation in Part 1 of the TPM specification. In this |
| implementation, this is a macro invocation of _cpri__KDFe() in the hash module of the CryptoEngine(). |
| |
| 555 //%#define CryptKDFe(hashAlg, Z, label, partyUInfo, partyVInfo, \ |
| 556 //% sizeInBits, keyStream) \ |
| 557 //% TEST_HASH(hashAlg); \ |
| 558 //% _cpri__KDFe( \ |
| 559 //% ((TPM_ALG_ID)hashAlg), \ |
| 560 //% ((TPM2B *)Z), \ |
| 561 //% ((const char *)label), \ |
| 562 //% ((TPM2B *)partyUInfo), \ |
| 563 //% ((TPM2B *)partyVInfo), \ |
| 564 //% ((UINT32)sizeInBits), \ |
| 565 //% ((BYTE *)keyStream) \ |
| 566 //% ) |
| 567 //% |
| 568 #endif //TPM_ALG_KEYEDHASH //% 1 |
| |
| |
| 10.2.5 RSA Functions |
| |
| 10.2.5.1 BuildRSA() |
| |
| Function to set the cryptographic elements of an RSA key into a structure to simplify the interface to |
| _cpri__ RSA function. This can/should be eliminated by building this structure into the object structure. |
| |
| 569 #ifdef TPM_ALG_RSA //% 2 |
| 570 static void |
| 571 BuildRSA( |
| 572 OBJECT *rsaKey, |
| 573 RSA_KEY *key |
| 574 ) |
| 575 { |
| 576 key->exponent = rsaKey->publicArea.parameters.rsaDetail.exponent; |
| 577 if(key->exponent == 0) |
| 578 key->exponent = RSA_DEFAULT_PUBLIC_EXPONENT; |
| 579 key->publicKey = &rsaKey->publicArea.unique.rsa.b; |
| 580 |
| 581 if(rsaKey->attributes.publicOnly || rsaKey->privateExponent.t.size == 0) |
| 582 key->privateKey = NULL; |
| 583 else |
| 584 key->privateKey = &(rsaKey->privateExponent.b); |
| 585 } |
| |
| |
| 10.2.5.2 CryptTestKeyRSA() |
| |
| This function provides the interface to _cpri__TestKeyRSA(). If both p and q are provided, n will be set to |
| p*q. |
| If only p is provided, q is computed by q = n/p. If n mod p != 0, TPM_RC_BINDING is returned. |
| The key is validated by checking that a d can be found such that e d mod ((p-1)*(q-1)) = 1. If d is found |
| that satisfies this requirement, it will be placed in d. |
| Page 286 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_BINDING the public and private portions of the key are not matched |
| |
| 586 TPM_RC |
| 587 CryptTestKeyRSA( |
| 588 TPM2B *d, // OUT: receives the private exponent |
| 589 UINT32 e, // IN: public exponent |
| 590 TPM2B *n, // IN/OUT: public modulu |
| 591 TPM2B *p, // IN: a first prime |
| 592 TPM2B *q // IN: an optional second prime |
| 593 ) |
| 594 { |
| 595 CRYPT_RESULT retVal; |
| 596 |
| 597 TEST(ALG_NULL_VALUE); |
| 598 |
| 599 pAssert(d != NULL && n != NULL && p != NULL); |
| 600 // Set the exponent |
| 601 if(e == 0) |
| 602 e = RSA_DEFAULT_PUBLIC_EXPONENT; |
| 603 // CRYPT_PARAMETER |
| 604 retVal =_cpri__TestKeyRSA(d, e, n, p, q); |
| 605 if(retVal == CRYPT_SUCCESS) |
| 606 return TPM_RC_SUCCESS; |
| 607 else |
| 608 return TPM_RC_BINDING; // convert CRYPT_PARAMETER |
| 609 } |
| |
| |
| 10.2.5.3 CryptGenerateKeyRSA() |
| |
| This function is called to generate an RSA key from a provided seed. It calls _cpri__GenerateKeyRSA() |
| to perform the computations. The implementation is vendor specific. |
| |
| Error Returns Meaning |
| |
| TPM_RC_RANGE the exponent value is not supported |
| TPM_RC_CANCELLED key generation has been canceled |
| TPM_RC_VALUE exponent is not prime or is less than 3; or could not find a prime using |
| the provided parameters |
| |
| 610 static TPM_RC |
| 611 CryptGenerateKeyRSA( |
| 612 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for |
| 613 // the new key. The public key |
| 614 // area will be replaced by the |
| 615 // product of two primes found by |
| 616 // this function |
| 617 TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be |
| 618 // updated to contain the first |
| 619 // prime and the symmetric |
| 620 // encryption key |
| 621 TPM_ALG_ID hashAlg, // IN: the hash algorithm for the KDF |
| 622 TPM2B_SEED *seed, // IN: Seed for the creation |
| 623 TPM2B_NAME *name, // IN: Object name |
| 624 UINT32 *counter // OUT: last iteration of the counter |
| 625 ) |
| 626 { |
| 627 CRYPT_RESULT retVal; |
| 628 UINT32 exponent = publicArea->parameters.rsaDetail.exponent; |
| 629 |
| 630 TEST_HASH(hashAlg); |
| |
| Family "2.0" TCG Published Page 287 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 631 TEST(ALG_NULL_VALUE); |
| 632 |
| 633 // In this implementation, only the default exponent is allowed |
| 634 if(exponent != 0 && exponent != RSA_DEFAULT_PUBLIC_EXPONENT) |
| 635 return TPM_RC_RANGE; |
| 636 exponent = RSA_DEFAULT_PUBLIC_EXPONENT; |
| 637 |
| 638 *counter = 0; |
| 639 |
| 640 // _cpri_GenerateKeyRSA can return CRYPT_CANCEL or CRYPT_FAIL |
| 641 retVal = _cpri__GenerateKeyRSA(&publicArea->unique.rsa.b, |
| 642 &sensitive->sensitive.rsa.b, |
| 643 publicArea->parameters.rsaDetail.keyBits, |
| 644 exponent, |
| 645 hashAlg, |
| 646 &seed->b, |
| 647 "RSA key by vendor", |
| 648 &name->b, |
| 649 counter); |
| 650 |
| 651 // CRYPT_CANCEL -> TPM_RC_CANCELLED; CRYPT_FAIL -> TPM_RC_VALUE |
| 652 return TranslateCryptErrors(retVal); |
| 653 |
| 654 } |
| |
| |
| 10.2.5.4 CryptLoadPrivateRSA() |
| |
| This function is called to generate the private exponent of an RSA key. It uses CryptTestKeyRSA(). |
| |
| Error Returns Meaning |
| |
| TPM_RC_BINDING public and private parts of rsaKey are not matched |
| |
| 655 TPM_RC |
| 656 CryptLoadPrivateRSA( |
| 657 OBJECT *rsaKey // IN: the RSA key object |
| 658 ) |
| 659 { |
| 660 TPM_RC result; |
| 661 TPMT_PUBLIC *publicArea = &rsaKey->publicArea; |
| 662 TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; |
| 663 |
| 664 // Load key by computing the private exponent |
| 665 // TPM_RC_BINDING |
| 666 result = CryptTestKeyRSA(&(rsaKey->privateExponent.b), |
| 667 publicArea->parameters.rsaDetail.exponent, |
| 668 &(publicArea->unique.rsa.b), |
| 669 &(sensitive->sensitive.rsa.b), |
| 670 NULL); |
| 671 if(result == TPM_RC_SUCCESS) |
| 672 rsaKey->attributes.privateExp = SET; |
| 673 |
| 674 return result; |
| 675 } |
| |
| |
| 10.2.5.5 CryptSelectRSAScheme() |
| |
| This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select a |
| scheme between input and object default. This function assume the RSA object is loaded. If a default |
| scheme is defined in object, the default scheme should be chosen, otherwise, the input scheme should |
| be chosen. In the case that both the object and scheme are not TPM_ALG_NULL, then if the schemes |
| |
| |
| Page 288 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| are the same, the input scheme will be chosen. if the scheme are not compatible, a NULL pointer will be |
| returned. |
| The return pointer may point to a TPM_ALG_NULL scheme. |
| |
| 676 TPMT_RSA_DECRYPT* |
| 677 CryptSelectRSAScheme( |
| 678 TPMI_DH_OBJECT rsaHandle, // IN: handle of sign key |
| 679 TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme |
| 680 ) |
| 681 { |
| 682 OBJECT *rsaObject; |
| 683 TPMT_ASYM_SCHEME *keyScheme; |
| 684 TPMT_RSA_DECRYPT *retVal = NULL; |
| 685 |
| 686 // Get sign object pointer |
| 687 rsaObject = ObjectGet(rsaHandle); |
| 688 keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme; |
| 689 |
| 690 // if the default scheme of the object is TPM_ALG_NULL, then select the |
| 691 // input scheme |
| 692 if(keyScheme->scheme == TPM_ALG_NULL) |
| 693 { |
| 694 retVal = scheme; |
| 695 } |
| 696 // if the object scheme is not TPM_ALG_NULL and the input scheme is |
| 697 // TPM_ALG_NULL, then select the default scheme of the object. |
| 698 else if(scheme->scheme == TPM_ALG_NULL) |
| 699 { |
| 700 // if input scheme is NULL |
| 701 retVal = (TPMT_RSA_DECRYPT *)keyScheme; |
| 702 } |
| 703 // get here if both the object scheme and the input scheme are |
| 704 // not TPM_ALG_NULL. Need to insure that they are the same. |
| 705 // IMPLEMENTATION NOTE: This could cause problems if future versions have |
| 706 // schemes that have more values than just a hash algorithm. A new function |
| 707 // (IsSchemeSame()) might be needed then. |
| 708 else if( keyScheme->scheme == scheme->scheme |
| 709 && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg) |
| 710 { |
| 711 retVal = scheme; |
| 712 } |
| 713 // two different, incompatible schemes specified will return NULL |
| 714 return retVal; |
| 715 } |
| |
| |
| 10.2.5.6 CryptDecryptRSA() |
| |
| This function is the interface to _cpri__DecryptRSA(). It handles the return codes from that function and |
| converts them from CRYPT_RESULT to TPM_RC values. The rsaKey parameter must reference an RSA |
| decryption key |
| |
| Error Returns Meaning |
| |
| TPM_RC_BINDING Public and private parts of the key are not cryptographically bound. |
| TPM_RC_SIZE Size of data to decrypt is not the same as the key size. |
| TPM_RC_VALUE Numeric value of the encrypted data is greater than the public |
| exponent, or output buffer is too small for the decrypted message. |
| |
| 716 TPM_RC |
| 717 CryptDecryptRSA( |
| 718 UINT16 *dataOutSize, // OUT: size of plain text in byte |
| |
| Family "2.0" TCG Published Page 289 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 719 BYTE *dataOut, // OUT: plain text |
| 720 OBJECT *rsaKey, // IN: internal RSA key |
| 721 TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme |
| 722 UINT16 cipherInSize, // IN: size of cipher text in byte |
| 723 BYTE *cipherIn, // IN: cipher text |
| 724 const char *label // IN: a label, when needed |
| 725 ) |
| 726 { |
| 727 RSA_KEY key; |
| 728 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 729 UINT32 dSize; // Place to put temporary value for the |
| 730 // returned data size |
| 731 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in the selected |
| 732 // padding scheme |
| 733 TPM_RC result = TPM_RC_SUCCESS; |
| 734 |
| 735 // pointer checks |
| 736 pAssert( (dataOutSize != NULL) && (dataOut != NULL) |
| 737 && (rsaKey != NULL) && (cipherIn != NULL)); |
| 738 |
| 739 // The public type is a RSA decrypt key |
| 740 pAssert( (rsaKey->publicArea.type == TPM_ALG_RSA |
| 741 && rsaKey->publicArea.objectAttributes.decrypt == SET)); |
| 742 |
| 743 // Must have the private portion loaded. This check is made before this |
| 744 // function is called. |
| 745 pAssert(rsaKey->attributes.publicOnly == CLEAR); |
| 746 |
| 747 // decryption requires that the private modulus be present |
| 748 if(rsaKey->attributes.privateExp == CLEAR) |
| 749 { |
| 750 |
| 751 // Load key by computing the private exponent |
| 752 // CryptLoadPrivateRSA may return TPM_RC_BINDING |
| 753 result = CryptLoadPrivateRSA(rsaKey); |
| 754 } |
| 755 |
| 756 // the input buffer must be the size of the key |
| 757 if(result == TPM_RC_SUCCESS) |
| 758 { |
| 759 if(cipherInSize != rsaKey->publicArea.unique.rsa.t.size) |
| 760 result = TPM_RC_SIZE; |
| 761 else |
| 762 { |
| 763 BuildRSA(rsaKey, &key); |
| 764 |
| 765 // Initialize the dOutSize parameter |
| 766 dSize = *dataOutSize; |
| 767 |
| 768 // For OAEP scheme, initialize the hash algorithm for padding |
| 769 if(scheme->scheme == TPM_ALG_OAEP) |
| 770 { |
| 771 hashAlg = scheme->details.oaep.hashAlg; |
| 772 TEST_HASH(hashAlg); |
| 773 } |
| 774 // See if the padding mode needs to be tested |
| 775 TEST(scheme->scheme); |
| 776 |
| 777 // _cpri__DecryptRSA may return CRYPT_PARAMETER CRYPT_FAIL CRYPT_SCHEME |
| 778 retVal = _cpri__DecryptRSA(&dSize, dataOut, &key, scheme->scheme, |
| 779 cipherInSize, cipherIn, hashAlg, label); |
| 780 |
| 781 // Scheme must have been validated when the key was loaded/imported |
| 782 pAssert(retVal != CRYPT_SCHEME); |
| 783 |
| 784 // Set the return size |
| |
| Page 290 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 785 pAssert(dSize <= UINT16_MAX); |
| 786 *dataOutSize = (UINT16)dSize; |
| 787 |
| 788 // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_FAIL -> TPM_RC_VALUE |
| 789 result = TranslateCryptErrors(retVal); |
| 790 } |
| 791 } |
| 792 return result; |
| 793 } |
| |
| |
| 10.2.5.7 CryptEncryptRSA() |
| |
| This function provides the interface to _cpri__EncryptRSA(). The object referenced by rsaKey is required |
| to be an RSA decryption key. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SCHEME scheme is not supported |
| TPM_RC_VALUE numeric value of dataIn is greater than the key modulus |
| |
| 794 TPM_RC |
| 795 CryptEncryptRSA( |
| 796 UINT16 *cipherOutSize, // OUT: size of cipher text in byte |
| 797 BYTE *cipherOut, // OUT: cipher text |
| 798 OBJECT *rsaKey, // IN: internal RSA key |
| 799 TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme |
| 800 UINT16 dataInSize, // IN: size of plain text in byte |
| 801 BYTE *dataIn, // IN: plain text |
| 802 const char *label // IN: an optional label |
| 803 ) |
| 804 { |
| 805 RSA_KEY key; |
| 806 CRYPT_RESULT retVal; |
| 807 UINT32 cOutSize; // Conversion variable |
| 808 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in selected |
| 809 // padding scheme |
| 810 |
| 811 // must have a pointer to a key and some data to encrypt |
| 812 pAssert(rsaKey != NULL && dataIn != NULL); |
| 813 |
| 814 // The public type is a RSA decryption key |
| 815 pAssert( rsaKey->publicArea.type == TPM_ALG_RSA |
| 816 && rsaKey->publicArea.objectAttributes.decrypt == SET); |
| 817 |
| 818 // If the cipher buffer must be provided and it must be large enough |
| 819 // for the result |
| 820 pAssert( cipherOut != NULL |
| 821 && cipherOutSize != NULL |
| 822 && *cipherOutSize >= rsaKey->publicArea.unique.rsa.t.size); |
| 823 |
| 824 // Only need the public key and exponent for encryption |
| 825 BuildRSA(rsaKey, &key); |
| 826 |
| 827 // Copy the size to the conversion buffer |
| 828 cOutSize = *cipherOutSize; |
| 829 |
| 830 // For OAEP scheme, initialize the hash algorithm for padding |
| 831 if(scheme->scheme == TPM_ALG_OAEP) |
| 832 { |
| 833 hashAlg = scheme->details.oaep.hashAlg; |
| 834 TEST_HASH(hashAlg); |
| 835 } |
| 836 |
| |
| Family "2.0" TCG Published Page 291 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 837 // This is a public key operation and does not require that the private key |
| 838 // be loaded. To verify this, need to do the full algorithm |
| 839 TEST(scheme->scheme); |
| 840 |
| 841 // Encrypt the data with the public exponent |
| 842 // _cpri__EncryptRSA may return CRYPT_PARAMETER or CRYPT_SCHEME |
| 843 retVal = _cpri__EncryptRSA(&cOutSize,cipherOut, &key, scheme->scheme, |
| 844 dataInSize, dataIn, hashAlg, label); |
| 845 |
| 846 pAssert (cOutSize <= UINT16_MAX); |
| 847 *cipherOutSize = (UINT16)cOutSize; |
| 848 // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_SCHEME -> TPM_RC_SCHEME |
| 849 return TranslateCryptErrors(retVal); |
| 850 } |
| |
| |
| 10.2.5.8 CryptSignRSA() |
| |
| This function is used to sign a digest with an RSA signing key. |
| |
| Error Returns Meaning |
| |
| TPM_RC_BINDING public and private part of signKey are not properly bound |
| TPM_RC_SCHEME scheme is not supported |
| TPM_RC_VALUE hashData is larger than the modulus of signKey, or the size of |
| hashData does not match hash algorithm in scheme |
| |
| 851 static TPM_RC |
| 852 CryptSignRSA( |
| 853 OBJECT *signKey, // IN: RSA key signs the hash |
| 854 TPMT_SIG_SCHEME *scheme, // IN: sign scheme |
| 855 TPM2B_DIGEST *hashData, // IN: hash to be signed |
| 856 TPMT_SIGNATURE *sig // OUT: signature |
| 857 ) |
| 858 { |
| 859 UINT32 signSize; |
| 860 RSA_KEY key; |
| 861 CRYPT_RESULT retVal; |
| 862 TPM_RC result = TPM_RC_SUCCESS; |
| 863 |
| 864 pAssert( (signKey != NULL) && (scheme != NULL) |
| 865 && (hashData != NULL) && (sig != NULL)); |
| 866 |
| 867 // assume that the key has private part loaded and that it is a signing key. |
| 868 pAssert( (signKey->attributes.publicOnly == CLEAR) |
| 869 && (signKey->publicArea.objectAttributes.sign == SET)); |
| 870 |
| 871 // check if the private exponent has been computed |
| 872 if(signKey->attributes.privateExp == CLEAR) |
| 873 // May return TPM_RC_BINDING |
| 874 result = CryptLoadPrivateRSA(signKey); |
| 875 |
| 876 if(result == TPM_RC_SUCCESS) |
| 877 { |
| 878 BuildRSA(signKey, &key); |
| 879 |
| 880 // Make sure that the hash is tested |
| 881 TEST_HASH(sig->signature.any.hashAlg); |
| 882 |
| 883 // Run a test of the RSA sign |
| 884 TEST(scheme->scheme); |
| 885 |
| 886 // _crypi__SignRSA can return CRYPT_SCHEME and CRYPT_PARAMETER |
| 887 retVal = _cpri__SignRSA(&signSize, |
| |
| Page 292 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 888 sig->signature.rsassa.sig.t.buffer, |
| 889 &key, |
| 890 sig->sigAlg, |
| 891 sig->signature.any.hashAlg, |
| 892 hashData->t.size, hashData->t.buffer); |
| 893 pAssert(signSize <= UINT16_MAX); |
| 894 sig->signature.rsassa.sig.t.size = (UINT16)signSize; |
| 895 |
| 896 // CRYPT_SCHEME -> TPM_RC_SCHEME; CRYPT_PARAMTER -> TPM_RC_VALUE |
| 897 result = TranslateCryptErrors(retVal); |
| 898 } |
| 899 return result; |
| 900 } |
| |
| |
| 10.2.5.9 CryptRSAVerifySignature() |
| |
| This function is used to verify signature signed by a RSA key. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SIGNATURE if signature is not genuine |
| TPM_RC_SCHEME signature scheme not supported |
| |
| 901 static TPM_RC |
| 902 CryptRSAVerifySignature( |
| 903 OBJECT *signKey, // IN: RSA key signed the hash |
| 904 TPM2B_DIGEST *digestData, // IN: digest being signed |
| 905 TPMT_SIGNATURE *sig // IN: signature to be verified |
| 906 ) |
| 907 { |
| 908 RSA_KEY key; |
| 909 CRYPT_RESULT retVal; |
| 910 TPM_RC result; |
| 911 |
| 912 // Validate parameter assumptions |
| 913 pAssert((signKey != NULL) && (digestData != NULL) && (sig != NULL)); |
| 914 |
| 915 TEST_HASH(sig->signature.any.hashAlg); |
| 916 TEST(sig->sigAlg); |
| 917 |
| 918 // This is a public-key-only operation |
| 919 BuildRSA(signKey, &key); |
| 920 |
| 921 // Call crypto engine to verify signature |
| 922 // _cpri_ValidateSignaturRSA may return CRYPT_FAIL or CRYPT_SCHEME |
| 923 retVal = _cpri__ValidateSignatureRSA(&key, |
| 924 sig->sigAlg, |
| 925 sig->signature.any.hashAlg, |
| 926 digestData->t.size, |
| 927 digestData->t.buffer, |
| 928 sig->signature.rsassa.sig.t.size, |
| 929 sig->signature.rsassa.sig.t.buffer, |
| 930 0); |
| 931 // _cpri__ValidateSignatureRSA can return CRYPT_SUCCESS, CRYPT_FAIL, or |
| 932 // CRYPT_SCHEME. Translate CRYPT_FAIL to TPM_RC_SIGNATURE |
| 933 if(retVal == CRYPT_FAIL) |
| 934 result = TPM_RC_SIGNATURE; |
| 935 else |
| 936 // CRYPT_SCHEME -> TPM_RC_SCHEME |
| 937 result = TranslateCryptErrors(retVal); |
| 938 |
| 939 return result; |
| 940 } |
| |
| |
| Family "2.0" TCG Published Page 293 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 941 #endif //TPM_ALG_RSA //% 2 |
| |
| |
| 10.2.6 ECC Functions |
| |
| 10.2.6.1 CryptEccGetCurveDataPointer() |
| |
| This function returns a pointer to an ECC_CURVE_VALUES structure that contains the parameters for |
| the key size and schemes for a given curve. |
| |
| 942 #ifdef TPM_ALG_ECC //% 3 |
| 943 static const ECC_CURVE * |
| 944 CryptEccGetCurveDataPointer( |
| 945 TPM_ECC_CURVE curveID // IN: id of the curve |
| 946 ) |
| 947 { |
| 948 return _cpri__EccGetParametersByCurveId(curveID); |
| 949 } |
| |
| |
| 10.2.6.2 CryptEccGetKeySizeInBits() |
| |
| This function returns the size in bits of the key associated with a curve. |
| |
| 950 UINT16 |
| 951 CryptEccGetKeySizeInBits( |
| 952 TPM_ECC_CURVE curveID // IN: id of the curve |
| 953 ) |
| 954 { |
| 955 const ECC_CURVE *curve = CryptEccGetCurveDataPointer(curveID); |
| 956 UINT16 keySizeInBits = 0; |
| 957 |
| 958 if(curve != NULL) |
| 959 keySizeInBits = curve->keySizeBits; |
| 960 |
| 961 return keySizeInBits; |
| 962 } |
| |
| |
| 10.2.6.3 CryptEccGetKeySizeBytes() |
| |
| This macro returns the size of the ECC key in bytes. It uses CryptEccGetKeySizeInBits(). |
| |
| 963 // The next lines will be placed in CyrptUtil_fp.h with the //% removed |
| 964 //% #define CryptEccGetKeySizeInBytes(curve) \ |
| 965 //% ((CryptEccGetKeySizeInBits(curve)+7)/8) |
| |
| |
| 10.2.6.4 CryptEccGetParameter() |
| |
| This function returns a pointer to an ECC curve parameter. The parameter is selected by a single |
| character designator from the set of {pnabxyh}. |
| |
| 966 LIB_EXPORT const TPM2B * |
| 967 CryptEccGetParameter( |
| 968 char p, // IN: the parameter selector |
| 969 TPM_ECC_CURVE curveId // IN: the curve id |
| 970 ) |
| 971 { |
| 972 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
| 973 const TPM2B *parameter = NULL; |
| 974 |
| 975 if(curve != NULL) |
| |
| Page 294 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 976 { |
| 977 switch (p) |
| 978 { |
| 979 case 'p': |
| 980 parameter = curve->curveData->p; |
| 981 break; |
| 982 case 'n': |
| 983 parameter = curve->curveData->n; |
| 984 break; |
| 985 case 'a': |
| 986 parameter = curve->curveData->a; |
| 987 break; |
| 988 case 'b': |
| 989 parameter = curve->curveData->b; |
| 990 break; |
| 991 case 'x': |
| 992 parameter = curve->curveData->x; |
| 993 break; |
| 994 case 'y': |
| 995 parameter = curve->curveData->y; |
| 996 break; |
| 997 case 'h': |
| 998 parameter = curve->curveData->h; |
| 999 break; |
| 1000 default: |
| 1001 break; |
| 1002 } |
| 1003 } |
| 1004 return parameter; |
| 1005 } |
| |
| |
| 10.2.6.5 CryptGetCurveSignScheme() |
| |
| This function will return a pointer to the scheme of the curve. |
| |
| 1006 const TPMT_ECC_SCHEME * |
| 1007 CryptGetCurveSignScheme( |
| 1008 TPM_ECC_CURVE curveId // IN: The curve selector |
| 1009 ) |
| 1010 { |
| 1011 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
| 1012 const TPMT_ECC_SCHEME *scheme = NULL; |
| 1013 |
| 1014 if(curve != NULL) |
| 1015 scheme = &(curve->sign); |
| 1016 return scheme; |
| 1017 } |
| |
| |
| 10.2.6.6 CryptEccIsPointOnCurve() |
| |
| This function will validate that an ECC point is on the curve of given curveID. |
| |
| Return Value Meaning |
| |
| TRUE if the point is on curve |
| FALSE if the point is not on curve |
| |
| 1018 BOOL |
| 1019 CryptEccIsPointOnCurve( |
| 1020 TPM_ECC_CURVE curveID, // IN: ECC curve ID |
| 1021 TPMS_ECC_POINT *Q // IN: ECC point |
| 1022 ) |
| |
| Family "2.0" TCG Published Page 295 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1023 { |
| 1024 // Make sure that point multiply is working |
| 1025 TEST(TPM_ALG_ECC); |
| 1026 // Check point on curve logic by seeing if the test key is on the curve |
| 1027 |
| 1028 // Call crypto engine function to check if a ECC public point is on the |
| 1029 // given curve |
| 1030 if(_cpri__EccIsPointOnCurve(curveID, Q)) |
| 1031 return TRUE; |
| 1032 else |
| 1033 return FALSE; |
| 1034 } |
| |
| |
| 10.2.6.7 CryptNewEccKey() |
| |
| This function creates a random ECC key that is not derived from other parameters as is a Primary Key. |
| |
| 1035 TPM_RC |
| 1036 CryptNewEccKey( |
| 1037 TPM_ECC_CURVE curveID, // IN: ECC curve |
| 1038 TPMS_ECC_POINT *publicPoint, // OUT: public point |
| 1039 TPM2B_ECC_PARAMETER *sensitive // OUT: private area |
| 1040 ) |
| 1041 { |
| 1042 TPM_RC result = TPM_RC_SUCCESS; |
| 1043 // _cpri__GetEphemeralECC may return CRYPT_PARAMETER |
| 1044 if(_cpri__GetEphemeralEcc(publicPoint, sensitive, curveID) != CRYPT_SUCCESS) |
| 1045 // Something is wrong with the key. |
| 1046 result = TPM_RC_KEY; |
| 1047 |
| 1048 return result; |
| 1049 } |
| |
| |
| 10.2.6.8 CryptEccPointMultiply() |
| |
| This function is used to perform a point multiply R = [d]Q. If Q is not provided, the multiplication is |
| performed using the generator point of the curve. |
| |
| Error Returns Meaning |
| |
| TPM_RC_ECC_POINT invalid optional ECC point pIn |
| TPM_RC_NO_RESULT multiplication resulted in a point at infinity |
| TPM_RC_CANCELED if a self-test was done, it might have been aborted |
| |
| 1050 TPM_RC |
| 1051 CryptEccPointMultiply( |
| 1052 TPMS_ECC_POINT *pOut, // OUT: output point |
| 1053 TPM_ECC_CURVE curveId, // IN: curve selector |
| 1054 TPM2B_ECC_PARAMETER *dIn, // IN: public scalar |
| 1055 TPMS_ECC_POINT *pIn // IN: optional point |
| 1056 ) |
| 1057 { |
| 1058 TPM2B_ECC_PARAMETER *n = NULL; |
| 1059 CRYPT_RESULT retVal; |
| 1060 |
| 1061 pAssert(pOut != NULL && dIn != NULL); |
| 1062 |
| 1063 if(pIn != NULL) |
| 1064 { |
| 1065 n = dIn; |
| 1066 dIn = NULL; |
| |
| Page 296 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1067 } |
| 1068 // Do a test of point multiply |
| 1069 TEST(TPM_ALG_ECC); |
| 1070 |
| 1071 // _cpri__EccPointMultiply may return CRYPT_POINT or CRYPT_NO_RESULT |
| 1072 retVal = _cpri__EccPointMultiply(pOut, curveId, dIn, pIn, n); |
| 1073 |
| 1074 // CRYPT_POINT->TPM_RC_ECC_POINT and CRYPT_NO_RESULT->TPM_RC_NO_RESULT |
| 1075 return TranslateCryptErrors(retVal); |
| 1076 } |
| |
| |
| 10.2.6.9 CryptGenerateKeyECC() |
| |
| This function generates an ECC key from a seed value. |
| The method here may not work for objects that have an order (G) that with a different size than a private |
| key. |
| |
| Error Returns Meaning |
| |
| TPM_RC_VALUE hash algorithm is not supported |
| |
| 1077 static TPM_RC |
| 1078 CryptGenerateKeyECC( |
| 1079 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for the new |
| 1080 // key. |
| 1081 TPMT_SENSITIVE *sensitive, // IN/OUT: the sensitive area |
| 1082 TPM_ALG_ID hashAlg, // IN: algorithm for the KDF |
| 1083 TPM2B_SEED *seed, // IN: the seed value |
| 1084 TPM2B_NAME *name, // IN: the name of the object |
| 1085 UINT32 *counter // OUT: the iteration counter |
| 1086 ) |
| 1087 { |
| 1088 CRYPT_RESULT retVal; |
| 1089 |
| 1090 TEST_HASH(hashAlg); |
| 1091 TEST(ALG_ECDSA_VALUE); // ECDSA is used to verify each key |
| 1092 |
| 1093 // The iteration counter has no meaning for ECC key generation. The parameter |
| 1094 // will be overloaded for those implementations that have a requirement for |
| 1095 // doing pair-wise consistency checks on signing keys. If the counter parameter |
| 1096 // is 0 or NULL, then no consistency check is done. If it is other than 0, then |
| 1097 // a consistency check is run. This modification allow this code to work with |
| 1098 // the existing versions of the CrytpoEngine and with FIPS-compliant versions |
| 1099 // as well. |
| 1100 *counter = (UINT32)(publicArea->objectAttributes.sign == SET); |
| 1101 |
| 1102 // _cpri__GenerateKeyEcc only has one error return (CRYPT_PARAMETER) which means |
| 1103 // that the hash algorithm is not supported. This should not be possible |
| 1104 retVal = _cpri__GenerateKeyEcc(&publicArea->unique.ecc, |
| 1105 &sensitive->sensitive.ecc, |
| 1106 publicArea->parameters.eccDetail.curveID, |
| 1107 hashAlg, &seed->b, "ECC key by vendor", |
| 1108 &name->b, counter); |
| 1109 // This will only be useful if _cpri__GenerateKeyEcc return CRYPT_CANCEL |
| 1110 return TranslateCryptErrors(retVal); |
| 1111 } |
| |
| |
| 10.2.6.10 CryptSignECC() |
| |
| This function is used for ECC signing operations. If the signing scheme is a split scheme, and the signing |
| operation is successful, the commit value is retired. |
| |
| |
| Family "2.0" TCG Published Page 297 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Error Returns Meaning |
| |
| TPM_RC_SCHEME unsupported scheme |
| TPM_RC_VALUE invalid commit status (in case of a split scheme) or failed to generate |
| r value. |
| |
| 1112 static TPM_RC |
| 1113 CryptSignECC( |
| 1114 OBJECT *signKey, // IN: ECC key to sign the hash |
| 1115 TPMT_SIG_SCHEME *scheme, // IN: sign scheme |
| 1116 TPM2B_DIGEST *hashData, // IN: hash to be signed |
| 1117 TPMT_SIGNATURE *signature // OUT: signature |
| 1118 ) |
| 1119 { |
| 1120 TPM2B_ECC_PARAMETER r; |
| 1121 TPM2B_ECC_PARAMETER *pr = NULL; |
| 1122 CRYPT_RESULT retVal; |
| 1123 |
| 1124 // Run a test of the ECC sign and verify if it has not already been run |
| 1125 TEST_HASH(scheme->details.any.hashAlg); |
| 1126 TEST(scheme->scheme); |
| 1127 |
| 1128 if(CryptIsSplitSign(scheme->scheme)) |
| 1129 { |
| 1130 // When this code was written, the only split scheme was ECDAA |
| 1131 // (which can also be used for U-Prove). |
| 1132 if(!CryptGenerateR(&r, |
| 1133 &scheme->details.ecdaa.count, |
| 1134 signKey->publicArea.parameters.eccDetail.curveID, |
| 1135 &signKey->name)) |
| 1136 return TPM_RC_VALUE; |
| 1137 pr = &r; |
| 1138 } |
| 1139 // Call crypto engine function to sign |
| 1140 // _cpri__SignEcc may return CRYPT_SCHEME |
| 1141 retVal = _cpri__SignEcc(&signature->signature.ecdsa.signatureR, |
| 1142 &signature->signature.ecdsa.signatureS, |
| 1143 scheme->scheme, |
| 1144 scheme->details.any.hashAlg, |
| 1145 signKey->publicArea.parameters.eccDetail.curveID, |
| 1146 &signKey->sensitive.sensitive.ecc, |
| 1147 &hashData->b, |
| 1148 pr |
| 1149 ); |
| 1150 if(CryptIsSplitSign(scheme->scheme) && retVal == CRYPT_SUCCESS) |
| 1151 CryptEndCommit(scheme->details.ecdaa.count); |
| 1152 // CRYPT_SCHEME->TPM_RC_SCHEME |
| 1153 return TranslateCryptErrors(retVal); |
| 1154 } |
| |
| |
| 10.2.6.11 CryptECCVerifySignature() |
| |
| This function is used to verify a signature created with an ECC key. |
| |
| Error Returns Meaning |
| |
| TPM_RC_SIGNATURE if signature is not valid |
| TPM_RC_SCHEME the signing scheme or hashAlg is not supported |
| |
| 1155 static TPM_RC |
| 1156 CryptECCVerifySignature( |
| 1157 OBJECT *signKey, // IN: ECC key signed the hash |
| |
| Page 298 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1158 TPM2B_DIGEST *digestData, // IN: digest being signed |
| 1159 TPMT_SIGNATURE *signature // IN: signature to be verified |
| 1160 ) |
| 1161 { |
| 1162 CRYPT_RESULT retVal; |
| 1163 |
| 1164 TEST_HASH(signature->signature.any.hashAlg); |
| 1165 TEST(signature->sigAlg); |
| 1166 |
| 1167 // This implementation uses the fact that all the defined ECC signing |
| 1168 // schemes have the hash as the first parameter. |
| 1169 // _cpriValidateSignatureEcc may return CRYPT_FAIL or CRYP_SCHEME |
| 1170 retVal = _cpri__ValidateSignatureEcc(&signature->signature.ecdsa.signatureR, |
| 1171 &signature->signature.ecdsa.signatureS, |
| 1172 signature->sigAlg, |
| 1173 signature->signature.any.hashAlg, |
| 1174 signKey->publicArea.parameters.eccDetail.curveID, |
| 1175 &signKey->publicArea.unique.ecc, |
| 1176 &digestData->b); |
| 1177 if(retVal == CRYPT_FAIL) |
| 1178 return TPM_RC_SIGNATURE; |
| 1179 // CRYPT_SCHEME->TPM_RC_SCHEME |
| 1180 return TranslateCryptErrors(retVal); |
| 1181 } |
| |
| |
| 10.2.6.12 CryptGenerateR() |
| |
| This function computes the commit random value for a split signing scheme. |
| If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM will |
| validate that the gr.commitArray bit associated with the input value of c is SET. If not, the TPM returns |
| FALSE and no r value is generated. |
| |
| Return Value Meaning |
| |
| TRUE r value computed |
| FALSE no r value computed |
| |
| 1182 BOOL |
| 1183 CryptGenerateR( |
| 1184 TPM2B_ECC_PARAMETER *r, // OUT: the generated random value |
| 1185 UINT16 *c, // IN/OUT: count value. |
| 1186 TPMI_ECC_CURVE curveID, // IN: the curve for the value |
| 1187 TPM2B_NAME *name // IN: optional name of a key to |
| 1188 // associate with 'r' |
| 1189 ) |
| 1190 { |
| 1191 // This holds the marshaled g_commitCounter. |
| 1192 TPM2B_TYPE(8B, 8); |
| 1193 TPM2B_8B cntr = {8,{0}}; |
| 1194 |
| 1195 UINT32 iterations; |
| 1196 const TPM2B *n; |
| 1197 UINT64 currentCount = gr.commitCounter; |
| 1198 // This is just to suppress a compiler warning about a conditional expression |
| 1199 // being a constant. This is because of the macro expansion of ryptKDFa |
| 1200 TPMI_ALG_HASH hashAlg = CONTEXT_INTEGRITY_HASH_ALG; |
| 1201 |
| 1202 n = CryptEccGetParameter('n', curveID); |
| 1203 pAssert(r != NULL && n != NULL); |
| 1204 |
| 1205 // If this is the commit phase, use the current value of the commit counter |
| 1206 if(c != NULL) |
| |
| |
| Family "2.0" TCG Published Page 299 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1207 { |
| 1208 |
| 1209 UINT16 t1; |
| 1210 // if the array bit is not set, can't use the value. |
| 1211 if(!BitIsSet((*c & COMMIT_INDEX_MASK), gr.commitArray, |
| 1212 sizeof(gr.commitArray))) |
| 1213 return FALSE; |
| 1214 |
| 1215 // If it is the sign phase, figure out what the counter value was |
| 1216 // when the commitment was made. |
| 1217 // |
| 1218 // When gr.commitArray has less than 64K bits, the extra |
| 1219 // bits of 'c' are used as a check to make sure that the |
| 1220 // signing operation is not using an out of range count value |
| 1221 t1 = (UINT16)currentCount; |
| 1222 |
| 1223 // If the lower bits of c are greater or equal to the lower bits of t1 |
| 1224 // then the upper bits of t1 must be one more than the upper bits |
| 1225 // of c |
| 1226 if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK)) |
| 1227 // Since the counter is behind, reduce the current count |
| 1228 currentCount = currentCount - (COMMIT_INDEX_MASK + 1); |
| 1229 |
| 1230 t1 = (UINT16)currentCount; |
| 1231 if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK)) |
| 1232 return FALSE; |
| 1233 // set the counter to the value that was |
| 1234 // present when the commitment was made |
| 1235 currentCount = (currentCount & 0xffffffffffff0000) | *c; |
| 1236 |
| 1237 } |
| 1238 // Marshal the count value to a TPM2B buffer for the KDF |
| 1239 cntr.t.size = sizeof(currentCount); |
| 1240 UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer); |
| 1241 |
| 1242 // Now can do the KDF to create the random value for the signing operation |
| 1243 // During the creation process, we may generate an r that does not meet the |
| 1244 // requirements of the random value. |
| 1245 // want to generate a new r. |
| 1246 |
| 1247 r->t.size = n->size; |
| 1248 |
| 1249 // Arbitrary upper limit on the number of times that we can look for |
| 1250 // a suitable random value. The normally number of tries will be 1. |
| 1251 for(iterations = 1; iterations < 1000000;) |
| 1252 { |
| 1253 BYTE *pr = &r->b.buffer[0]; |
| 1254 int i; |
| 1255 CryptKDFa(hashAlg, &gr.commitNonce.b, "ECDAA Commit", |
| 1256 name, &cntr.b, n->size * 8, r->t.buffer, &iterations); |
| 1257 |
| 1258 // random value must be less than the prime |
| 1259 if(CryptCompare(r->b.size, r->b.buffer, n->size, n->buffer) >= 0) |
| 1260 continue; |
| 1261 |
| 1262 // in this implementation it is required that at least bit |
| 1263 // in the upper half of the number be set |
| 1264 for(i = n->size/2; i > 0; i--) |
| 1265 if(*pr++ != 0) |
| 1266 return TRUE; |
| 1267 } |
| 1268 return FALSE; |
| 1269 } |
| |
| |
| |
| |
| Page 300 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 10.2.6.13 CryptCommit() |
| |
| This function is called when the count value is committed. The gr.commitArray value associated with the |
| current count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of the |
| counter is returned. |
| |
| 1270 UINT16 |
| 1271 CryptCommit( |
| 1272 void |
| 1273 ) |
| 1274 { |
| 1275 UINT16 oldCount = (UINT16)gr.commitCounter; |
| 1276 gr.commitCounter++; |
| 1277 BitSet(oldCount & COMMIT_INDEX_MASK, gr.commitArray, sizeof(gr.commitArray)); |
| 1278 return oldCount; |
| 1279 } |
| |
| |
| 10.2.6.14 CryptEndCommit() |
| |
| This function is called when the signing operation using the committed value is completed. It clears the |
| gr.commitArray bit associated with the count value so that it can't be used again. |
| |
| 1280 void |
| 1281 CryptEndCommit( |
| 1282 UINT16 c // IN: the counter value of the commitment |
| 1283 ) |
| 1284 { |
| 1285 BitClear((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray)); |
| 1286 } |
| |
| |
| 10.2.6.15 CryptCommitCompute() |
| |
| This function performs the computations for the TPM2_Commit() command. This could be a macro. |
| |
| Error Returns Meaning |
| |
| TPM_RC_NO_RESULT K, L, or E is the point at infinity |
| TPM_RC_CANCELLED command was canceled |
| |
| 1287 TPM_RC |
| 1288 CryptCommitCompute( |
| 1289 TPMS_ECC_POINT *K, // OUT: [d]B |
| 1290 TPMS_ECC_POINT *L, // OUT: [r]B |
| 1291 TPMS_ECC_POINT *E, // OUT: [r]M |
| 1292 TPM_ECC_CURVE curveID, // IN: The curve for the computation |
| 1293 TPMS_ECC_POINT *M, // IN: M (P1) |
| 1294 TPMS_ECC_POINT *B, // IN: B (x2, y2) |
| 1295 TPM2B_ECC_PARAMETER *d, // IN: the private scalar |
| 1296 TPM2B_ECC_PARAMETER *r // IN: the computed r value |
| 1297 ) |
| 1298 { |
| 1299 TEST(ALG_ECDH_VALUE); |
| 1300 // CRYPT_NO_RESULT->TPM_RC_NO_RESULT CRYPT_CANCEL->TPM_RC_CANCELLED |
| 1301 return TranslateCryptErrors( |
| 1302 _cpri__EccCommitCompute(K, L , E, curveID, M, B, d, r)); |
| 1303 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 301 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 10.2.6.16 CryptEccGetParameters() |
| |
| This function returns the ECC parameter details of the given curve |
| |
| Return Value Meaning |
| |
| TRUE Get parameters success |
| FALSE Unsupported ECC curve ID |
| |
| 1304 BOOL |
| 1305 CryptEccGetParameters( |
| 1306 TPM_ECC_CURVE curveId, // IN: ECC curve ID |
| 1307 TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameter |
| 1308 ) |
| 1309 { |
| 1310 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
| 1311 const ECC_CURVE_DATA *data; |
| 1312 BOOL found = curve != NULL; |
| 1313 |
| 1314 if(found) |
| 1315 { |
| 1316 |
| 1317 data = curve->curveData; |
| 1318 |
| 1319 parameters->curveID = curve->curveId; |
| 1320 |
| 1321 // Key size in bit |
| 1322 parameters->keySize = curve->keySizeBits; |
| 1323 |
| 1324 // KDF |
| 1325 parameters->kdf = curve->kdf; |
| 1326 |
| 1327 // Sign |
| 1328 parameters->sign = curve->sign; |
| 1329 |
| 1330 // Copy p value |
| 1331 MemoryCopy2B(¶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<<ORDERLY_BITS)-1) |
| 237 #define ALG_ID_FIRST TPM_ALG_FIRST |
| 238 #define ALG_ID_LAST TPM_ALG_LAST |
| 239 #define MAX_SYM_DATA 128 |
| 240 #define MAX_RNG_ENTROPY_SIZE 64 |
| 241 #define RAM_INDEX_SPACE 512 |
| 242 #define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 |
| 243 #define ENABLE_PCR_NO_INCREMENT YES |
| 244 #define CRT_FORMAT_RSA YES |
| 245 #define PRIVATE_VENDOR_SPECIFIC_BYTES \ |
| 246 ((MAX_RSA_KEY_BYTES/2)*(3+CRT_FORMAT_RSA*2)) |
| |
| From TCG Algorithm Registry: Table 2 - Definition of TPM_ALG_ID Constants |
| |
| 247 typedef UINT16 TPM_ALG_ID; |
| 248 #define TPM_ALG_ERROR (TPM_ALG_ID)(0x0000) |
| 249 #define ALG_ERROR_VALUE 0x0000 |
| 250 #if defined ALG_RSA && ALG_RSA == YES |
| 251 #define TPM_ALG_RSA (TPM_ALG_ID)(0x0001) |
| 252 #endif |
| 253 #define ALG_RSA_VALUE 0x0001 |
| 254 #if defined ALG_SHA && ALG_SHA == YES |
| 255 #define TPM_ALG_SHA (TPM_ALG_ID)(0x0004) |
| 256 #endif |
| 257 #define ALG_SHA_VALUE 0x0004 |
| 258 #if defined ALG_SHA1 && ALG_SHA1 == YES |
| 259 #define TPM_ALG_SHA1 (TPM_ALG_ID)(0x0004) |
| 260 #endif |
| 261 #define ALG_SHA1_VALUE 0x0004 |
| 262 #if defined ALG_HMAC && ALG_HMAC == YES |
| 263 #define TPM_ALG_HMAC (TPM_ALG_ID)(0x0005) |
| 264 #endif |
| 265 #define ALG_HMAC_VALUE 0x0005 |
| 266 #if defined ALG_AES && ALG_AES == YES |
| 267 #define TPM_ALG_AES (TPM_ALG_ID)(0x0006) |
| 268 #endif |
| 269 #define ALG_AES_VALUE 0x0006 |
| 270 #if defined ALG_MGF1 && ALG_MGF1 == YES |
| 271 #define TPM_ALG_MGF1 (TPM_ALG_ID)(0x0007) |
| 272 #endif |
| 273 #define ALG_MGF1_VALUE 0x0007 |
| 274 #if defined ALG_KEYEDHASH && ALG_KEYEDHASH == YES |
| 275 #define TPM_ALG_KEYEDHASH (TPM_ALG_ID)(0x0008) |
| 276 #endif |
| 277 #define ALG_KEYEDHASH_VALUE 0x0008 |
| 278 #if defined ALG_XOR && ALG_XOR == YES |
| 279 #define TPM_ALG_XOR (TPM_ALG_ID)(0x000A) |
| |
| |
| Page 348 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 280 #endif |
| 281 #define ALG_XOR_VALUE 0x000A |
| 282 #if defined ALG_SHA256 && ALG_SHA256 == YES |
| 283 #define TPM_ALG_SHA256 (TPM_ALG_ID)(0x000B) |
| 284 #endif |
| 285 #define ALG_SHA256_VALUE 0x000B |
| 286 #if defined ALG_SHA384 && ALG_SHA384 == YES |
| 287 #define TPM_ALG_SHA384 (TPM_ALG_ID)(0x000C) |
| 288 #endif |
| 289 #define ALG_SHA384_VALUE 0x000C |
| 290 #if defined ALG_SHA512 && ALG_SHA512 == YES |
| 291 #define TPM_ALG_SHA512 (TPM_ALG_ID)(0x000D) |
| 292 #endif |
| 293 #define ALG_SHA512_VALUE 0x000D |
| 294 #define TPM_ALG_NULL (TPM_ALG_ID)(0x0010) |
| 295 #define ALG_NULL_VALUE 0x0010 |
| 296 #if defined ALG_SM3_256 && ALG_SM3_256 == YES |
| 297 #define TPM_ALG_SM3_256 (TPM_ALG_ID)(0x0012) |
| 298 #endif |
| 299 #define ALG_SM3_256_VALUE 0x0012 |
| 300 #if defined ALG_SM4 && ALG_SM4 == YES |
| 301 #define TPM_ALG_SM4 (TPM_ALG_ID)(0x0013) |
| 302 #endif |
| 303 #define ALG_SM4_VALUE 0x0013 |
| 304 #if defined ALG_RSASSA && ALG_RSASSA == YES |
| 305 #define TPM_ALG_RSASSA (TPM_ALG_ID)(0x0014) |
| 306 #endif |
| 307 #define ALG_RSASSA_VALUE 0x0014 |
| 308 #if defined ALG_RSAES && ALG_RSAES == YES |
| 309 #define TPM_ALG_RSAES (TPM_ALG_ID)(0x0015) |
| 310 #endif |
| 311 #define ALG_RSAES_VALUE 0x0015 |
| 312 #if defined ALG_RSAPSS && ALG_RSAPSS == YES |
| 313 #define TPM_ALG_RSAPSS (TPM_ALG_ID)(0x0016) |
| 314 #endif |
| 315 #define ALG_RSAPSS_VALUE 0x0016 |
| 316 #if defined ALG_OAEP && ALG_OAEP == YES |
| 317 #define TPM_ALG_OAEP (TPM_ALG_ID)(0x0017) |
| 318 #endif |
| 319 #define ALG_OAEP_VALUE 0x0017 |
| 320 #if defined ALG_ECDSA && ALG_ECDSA == YES |
| 321 #define TPM_ALG_ECDSA (TPM_ALG_ID)(0x0018) |
| 322 #endif |
| 323 #define ALG_ECDSA_VALUE 0x0018 |
| 324 #if defined ALG_ECDH && ALG_ECDH == YES |
| 325 #define TPM_ALG_ECDH (TPM_ALG_ID)(0x0019) |
| 326 #endif |
| 327 #define ALG_ECDH_VALUE 0x0019 |
| 328 #if defined ALG_ECDAA && ALG_ECDAA == YES |
| 329 #define TPM_ALG_ECDAA (TPM_ALG_ID)(0x001A) |
| 330 #endif |
| 331 #define ALG_ECDAA_VALUE 0x001A |
| 332 #if defined ALG_SM2 && ALG_SM2 == YES |
| 333 #define TPM_ALG_SM2 (TPM_ALG_ID)(0x001B) |
| 334 #endif |
| 335 #define ALG_SM2_VALUE 0x001B |
| 336 #if defined ALG_ECSCHNORR && ALG_ECSCHNORR == YES |
| 337 #define TPM_ALG_ECSCHNORR (TPM_ALG_ID)(0x001C) |
| 338 #endif |
| 339 #define ALG_ECSCHNORR_VALUE 0x001C |
| 340 #if defined ALG_ECMQV && ALG_ECMQV == YES |
| 341 #define TPM_ALG_ECMQV (TPM_ALG_ID)(0x001D) |
| 342 #endif |
| 343 #define ALG_ECMQV_VALUE 0x001D |
| 344 #if defined ALG_KDF1_SP800_56A && ALG_KDF1_SP800_56A == YES |
| 345 #define TPM_ALG_KDF1_SP800_56A (TPM_ALG_ID)(0x0020) |
| |
| Family "2.0" TCG Published Page 349 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 346 #endif |
| 347 #define ALG_KDF1_SP800_56A_VALUE 0x0020 |
| 348 #if defined ALG_KDF2 && ALG_KDF2 == YES |
| 349 #define TPM_ALG_KDF2 (TPM_ALG_ID)(0x0021) |
| 350 #endif |
| 351 #define ALG_KDF2_VALUE 0x0021 |
| 352 #if defined ALG_KDF1_SP800_108 && ALG_KDF1_SP800_108 == YES |
| 353 #define TPM_ALG_KDF1_SP800_108 (TPM_ALG_ID)(0x0022) |
| 354 #endif |
| 355 #define ALG_KDF1_SP800_108_VALUE 0x0022 |
| 356 #if defined ALG_ECC && ALG_ECC == YES |
| 357 #define TPM_ALG_ECC (TPM_ALG_ID)(0x0023) |
| 358 #endif |
| 359 #define ALG_ECC_VALUE 0x0023 |
| 360 #if defined ALG_SYMCIPHER && ALG_SYMCIPHER == YES |
| 361 #define TPM_ALG_SYMCIPHER (TPM_ALG_ID)(0x0025) |
| 362 #endif |
| 363 #define ALG_SYMCIPHER_VALUE 0x0025 |
| 364 #if defined ALG_CAMELLIA && ALG_CAMELLIA == YES |
| 365 #define TPM_ALG_CAMELLIA (TPM_ALG_ID)(0x0026) |
| 366 #endif |
| 367 #define ALG_CAMELLIA_VALUE 0x0026 |
| 368 #if defined ALG_CTR && ALG_CTR == YES |
| 369 #define TPM_ALG_CTR (TPM_ALG_ID)(0x0040) |
| 370 #endif |
| 371 #define ALG_CTR_VALUE 0x0040 |
| 372 #if defined ALG_OFB && ALG_OFB == YES |
| 373 #define TPM_ALG_OFB (TPM_ALG_ID)(0x0041) |
| 374 #endif |
| 375 #define ALG_OFB_VALUE 0x0041 |
| 376 #if defined ALG_CBC && ALG_CBC == YES |
| 377 #define TPM_ALG_CBC (TPM_ALG_ID)(0x0042) |
| 378 #endif |
| 379 #define ALG_CBC_VALUE 0x0042 |
| 380 #if defined ALG_CFB && ALG_CFB == YES |
| 381 #define TPM_ALG_CFB (TPM_ALG_ID)(0x0043) |
| 382 #endif |
| 383 #define ALG_CFB_VALUE 0x0043 |
| 384 #if defined ALG_ECB && ALG_ECB == YES |
| 385 #define TPM_ALG_ECB (TPM_ALG_ID)(0x0044) |
| 386 #endif |
| 387 #define ALG_ECB_VALUE 0x0044 |
| 388 #define TPM_ALG_FIRST (TPM_ALG_ID)(0x0001) |
| 389 #define ALG_FIRST_VALUE 0x0001 |
| 390 #define TPM_ALG_LAST (TPM_ALG_ID)(0x0044) |
| 391 #define ALG_LAST_VALUE 0x0044 |
| |
| From TCG Algorithm Registry: Table 3 - Definition of TPM_ECC_CURVE Constants |
| |
| 392 typedef UINT16 TPM_ECC_CURVE; |
| 393 #define TPM_ECC_NONE (TPM_ECC_CURVE)(0x0000) |
| 394 #define TPM_ECC_NIST_P192 (TPM_ECC_CURVE)(0x0001) |
| 395 #define TPM_ECC_NIST_P224 (TPM_ECC_CURVE)(0x0002) |
| 396 #define TPM_ECC_NIST_P256 (TPM_ECC_CURVE)(0x0003) |
| 397 #define TPM_ECC_NIST_P384 (TPM_ECC_CURVE)(0x0004) |
| 398 #define TPM_ECC_NIST_P521 (TPM_ECC_CURVE)(0x0005) |
| 399 #define TPM_ECC_BN_P256 (TPM_ECC_CURVE)(0x0010) |
| 400 #define TPM_ECC_BN_P638 (TPM_ECC_CURVE)(0x0011) |
| 401 #define TPM_ECC_SM2_P256 (TPM_ECC_CURVE)(0x0020) |
| |
| From TCG Algorithm Registry: Table 4 - Defines for NIST_P192 ECC Values Data in CrpiEccData.c From |
| TCG Algorithm Registry: Table 5 - Defines for NIST_P224 ECC Values Data in CrpiEccData.c From TCG |
| Algorithm Registry: Table 6 - Defines for NIST_P256 ECC Values Data in CrpiEccData.c From TCG |
| Algorithm Registry: Table 7 - Defines for NIST_P384 ECC Values Data in CrpiEccData.c From TCG |
| |
| Page 350 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Algorithm Registry: Table 8 - Defines for NIST_P521 ECC Values Data in CrpiEccData.c From TCG |
| Algorithm Registry: Table 9 - Defines for BN_P256 ECC Values Data in CrpiEccData.c From TCG |
| Algorithm Registry: Table 10 - Defines for BN_P638 ECC Values Data in CrpiEccData.c From TCG |
| Algorithm Registry: Table 11 - Defines for SM2_P256 ECC Values Data in CrpiEccData.c From TCG |
| Algorithm Registry: Table 12 - Defines for SHA1 Hash Values |
| |
| 402 #define SHA1_DIGEST_SIZE 20 |
| 403 #define SHA1_BLOCK_SIZE 64 |
| 404 #define SHA1_DER_SIZE 15 |
| 405 #define SHA1_DER \ |
| 406 0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14 |
| |
| From TCG Algorithm Registry: Table 13 - Defines for SHA256 Hash Values |
| |
| 407 #define SHA256_DIGEST_SIZE 32 |
| 408 #define SHA256_BLOCK_SIZE 64 |
| 409 #define SHA256_DER_SIZE 19 |
| 410 #define SHA256_DER \ |
| 411 |
| 0x30,0x31,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0 |
| x04,0x20 |
| |
| From TCG Algorithm Registry: Table 14 - Defines for SHA384 Hash Values |
| |
| 412 #define SHA384_DIGEST_SIZE 48 |
| 413 #define SHA384_BLOCK_SIZE 128 |
| 414 #define SHA384_DER_SIZE 19 |
| 415 #define SHA384_DER \ |
| 416 |
| 0x30,0x41,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0 |
| x04,0x30 |
| |
| From TCG Algorithm Registry: Table 15 - Defines for SHA512 Hash Values |
| |
| 417 #define SHA512_DIGEST_SIZE 64 |
| 418 #define SHA512_BLOCK_SIZE 128 |
| 419 #define SHA512_DER_SIZE 19 |
| 420 #define SHA512_DER \ |
| 421 |
| 0x30,0x51,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0 |
| x04,0x40 |
| |
| From TCG Algorithm Registry: Table 16 - Defines for SM3_256 Hash Values |
| |
| 422 #define SM3_256_DIGEST_SIZE 32 |
| 423 #define SM3_256_BLOCK_SIZE 64 |
| 424 #define SM3_256_DER_SIZE 18 |
| 425 #define SM3_256_DER \ |
| 426 |
| 0x30,0x30,0x30,0x0C,0x06,0x08,0x2A,0x81,0x1C,0x81,0x45,0x01,0x83,0x11,0x05,0x00,0x04,0 |
| x20 |
| |
| From TCG Algorithm Registry: Table 17 - Defines for AES Symmetric Cipher Algorithm Constants |
| |
| 427 #define AES_ALLOWED_KEY_SIZE_128 YES |
| 428 #define AES_ALLOWED_KEY_SIZE_192 YES |
| 429 #define AES_ALLOWED_KEY_SIZE_256 YES |
| 430 #define AES_128_BLOCK_SIZE_BYTES 16 |
| 431 #define AES_192_BLOCK_SIZE_BYTES 16 |
| 432 #define AES_256_BLOCK_SIZE_BYTES 16 |
| |
| From TCG Algorithm Registry: Table 18 - Defines for SM4 Symmetric Cipher Algorithm Constants |
| |
| Family "2.0" TCG Published Page 351 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 433 #define SM4_ALLOWED_KEY_SIZE_128 YES |
| 434 #define SM4_128_BLOCK_SIZE_BYTES 16 |
| |
| From TCG Algorithm Registry: Table 19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants |
| |
| 435 #define CAMELLIA_ALLOWED_KEY_SIZE_128 YES |
| 436 #define CAMELLIA_ALLOWED_KEY_SIZE_192 YES |
| 437 #define CAMELLIA_ALLOWED_KEY_SIZE_256 YES |
| 438 #define CAMELLIA_128_BLOCK_SIZE_BYTES 16 |
| 439 #define CAMELLIA_192_BLOCK_SIZE_BYTES 16 |
| 440 #define CAMELLIA_256_BLOCK_SIZE_BYTES 16 |
| |
| From TPM 2.0 Part 2: Table 13 - Definition of TPM_CC Constants |
| |
| 441 typedef UINT32 TPM_CC; |
| 442 #define TPM_CC_FIRST (TPM_CC)(0x0000011F) |
| 443 #define TPM_CC_PP_FIRST (TPM_CC)(0x0000011F) |
| 444 #if defined CC_NV_UndefineSpaceSpecial && CC_NV_UndefineSpaceSpecial == YES |
| 445 #define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F) |
| 446 #endif |
| 447 #if defined CC_EvictControl && CC_EvictControl == YES |
| 448 #define TPM_CC_EvictControl (TPM_CC)(0x00000120) |
| 449 #endif |
| 450 #if defined CC_HierarchyControl && CC_HierarchyControl == YES |
| 451 #define TPM_CC_HierarchyControl (TPM_CC)(0x00000121) |
| 452 #endif |
| 453 #if defined CC_NV_UndefineSpace && CC_NV_UndefineSpace == YES |
| 454 #define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122) |
| 455 #endif |
| 456 #if defined CC_ChangeEPS && CC_ChangeEPS == YES |
| 457 #define TPM_CC_ChangeEPS (TPM_CC)(0x00000124) |
| 458 #endif |
| 459 #if defined CC_ChangePPS && CC_ChangePPS == YES |
| 460 #define TPM_CC_ChangePPS (TPM_CC)(0x00000125) |
| 461 #endif |
| 462 #if defined CC_Clear && CC_Clear == YES |
| 463 #define TPM_CC_Clear (TPM_CC)(0x00000126) |
| 464 #endif |
| 465 #if defined CC_ClearControl && CC_ClearControl == YES |
| 466 #define TPM_CC_ClearControl (TPM_CC)(0x00000127) |
| 467 #endif |
| 468 #if defined CC_ClockSet && CC_ClockSet == YES |
| 469 #define TPM_CC_ClockSet (TPM_CC)(0x00000128) |
| 470 #endif |
| 471 #if defined CC_HierarchyChangeAuth && CC_HierarchyChangeAuth == YES |
| 472 #define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129) |
| 473 #endif |
| 474 #if defined CC_NV_DefineSpace && CC_NV_DefineSpace == YES |
| 475 #define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A) |
| 476 #endif |
| 477 #if defined CC_PCR_Allocate && CC_PCR_Allocate == YES |
| 478 #define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B) |
| 479 #endif |
| 480 #if defined CC_PCR_SetAuthPolicy && CC_PCR_SetAuthPolicy == YES |
| 481 #define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C) |
| 482 #endif |
| 483 #if defined CC_PP_Commands && CC_PP_Commands == YES |
| 484 #define TPM_CC_PP_Commands (TPM_CC)(0x0000012D) |
| 485 #endif |
| 486 #if defined CC_SetPrimaryPolicy && CC_SetPrimaryPolicy == YES |
| 487 #define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E) |
| 488 #endif |
| 489 #if defined CC_FieldUpgradeStart && CC_FieldUpgradeStart == YES |
| 490 #define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F) |
| 491 #endif |
| |
| Page 352 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 492 #if defined CC_ClockRateAdjust && CC_ClockRateAdjust == YES |
| 493 #define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130) |
| 494 #endif |
| 495 #if defined CC_CreatePrimary && CC_CreatePrimary == YES |
| 496 #define TPM_CC_CreatePrimary (TPM_CC)(0x00000131) |
| 497 #endif |
| 498 #if defined CC_NV_GlobalWriteLock && CC_NV_GlobalWriteLock == YES |
| 499 #define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132) |
| 500 #endif |
| 501 #define TPM_CC_PP_LAST (TPM_CC)(0x00000132) |
| 502 #if defined CC_GetCommandAuditDigest && CC_GetCommandAuditDigest == YES |
| 503 #define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133) |
| 504 #endif |
| 505 #if defined CC_NV_Increment && CC_NV_Increment == YES |
| 506 #define TPM_CC_NV_Increment (TPM_CC)(0x00000134) |
| 507 #endif |
| 508 #if defined CC_NV_SetBits && CC_NV_SetBits == YES |
| 509 #define TPM_CC_NV_SetBits (TPM_CC)(0x00000135) |
| 510 #endif |
| 511 #if defined CC_NV_Extend && CC_NV_Extend == YES |
| 512 #define TPM_CC_NV_Extend (TPM_CC)(0x00000136) |
| 513 #endif |
| 514 #if defined CC_NV_Write && CC_NV_Write == YES |
| 515 #define TPM_CC_NV_Write (TPM_CC)(0x00000137) |
| 516 #endif |
| 517 #if defined CC_NV_WriteLock && CC_NV_WriteLock == YES |
| 518 #define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138) |
| 519 #endif |
| 520 #if defined CC_DictionaryAttackLockReset && CC_DictionaryAttackLockReset == YES |
| 521 #define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139) |
| 522 #endif |
| 523 #if defined CC_DictionaryAttackParameters && CC_DictionaryAttackParameters == YES |
| 524 #define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A) |
| 525 #endif |
| 526 #if defined CC_NV_ChangeAuth && CC_NV_ChangeAuth == YES |
| 527 #define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B) |
| 528 #endif |
| 529 #if defined CC_PCR_Event && CC_PCR_Event == YES |
| 530 #define TPM_CC_PCR_Event (TPM_CC)(0x0000013C) |
| 531 #endif |
| 532 #if defined CC_PCR_Reset && CC_PCR_Reset == YES |
| 533 #define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D) |
| 534 #endif |
| 535 #if defined CC_SequenceComplete && CC_SequenceComplete == YES |
| 536 #define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E) |
| 537 #endif |
| 538 #if defined CC_SetAlgorithmSet && CC_SetAlgorithmSet == YES |
| 539 #define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F) |
| 540 #endif |
| 541 #if defined CC_SetCommandCodeAuditStatus && CC_SetCommandCodeAuditStatus == YES |
| 542 #define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140) |
| 543 #endif |
| 544 #if defined CC_FieldUpgradeData && CC_FieldUpgradeData == YES |
| 545 #define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141) |
| 546 #endif |
| 547 #if defined CC_IncrementalSelfTest && CC_IncrementalSelfTest == YES |
| 548 #define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142) |
| 549 #endif |
| 550 #if defined CC_SelfTest && CC_SelfTest == YES |
| 551 #define TPM_CC_SelfTest (TPM_CC)(0x00000143) |
| 552 #endif |
| 553 #if defined CC_Startup && CC_Startup == YES |
| 554 #define TPM_CC_Startup (TPM_CC)(0x00000144) |
| 555 #endif |
| 556 #if defined CC_Shutdown && CC_Shutdown == YES |
| 557 #define TPM_CC_Shutdown (TPM_CC)(0x00000145) |
| |
| Family "2.0" TCG Published Page 353 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 558 #endif |
| 559 #if defined CC_StirRandom && CC_StirRandom == YES |
| 560 #define TPM_CC_StirRandom (TPM_CC)(0x00000146) |
| 561 #endif |
| 562 #if defined CC_ActivateCredential && CC_ActivateCredential == YES |
| 563 #define TPM_CC_ActivateCredential (TPM_CC)(0x00000147) |
| 564 #endif |
| 565 #if defined CC_Certify && CC_Certify == YES |
| 566 #define TPM_CC_Certify (TPM_CC)(0x00000148) |
| 567 #endif |
| 568 #if defined CC_PolicyNV && CC_PolicyNV == YES |
| 569 #define TPM_CC_PolicyNV (TPM_CC)(0x00000149) |
| 570 #endif |
| 571 #if defined CC_CertifyCreation && CC_CertifyCreation == YES |
| 572 #define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A) |
| 573 #endif |
| 574 #if defined CC_Duplicate && CC_Duplicate == YES |
| 575 #define TPM_CC_Duplicate (TPM_CC)(0x0000014B) |
| 576 #endif |
| 577 #if defined CC_GetTime && CC_GetTime == YES |
| 578 #define TPM_CC_GetTime (TPM_CC)(0x0000014C) |
| 579 #endif |
| 580 #if defined CC_GetSessionAuditDigest && CC_GetSessionAuditDigest == YES |
| 581 #define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D) |
| 582 #endif |
| 583 #if defined CC_NV_Read && CC_NV_Read == YES |
| 584 #define TPM_CC_NV_Read (TPM_CC)(0x0000014E) |
| 585 #endif |
| 586 #if defined CC_NV_ReadLock && CC_NV_ReadLock == YES |
| 587 #define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F) |
| 588 #endif |
| 589 #if defined CC_ObjectChangeAuth && CC_ObjectChangeAuth == YES |
| 590 #define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150) |
| 591 #endif |
| 592 #if defined CC_PolicySecret && CC_PolicySecret == YES |
| 593 #define TPM_CC_PolicySecret (TPM_CC)(0x00000151) |
| 594 #endif |
| 595 #if defined CC_Rewrap && CC_Rewrap == YES |
| 596 #define TPM_CC_Rewrap (TPM_CC)(0x00000152) |
| 597 #endif |
| 598 #if defined CC_Create && CC_Create == YES |
| 599 #define TPM_CC_Create (TPM_CC)(0x00000153) |
| 600 #endif |
| 601 #if defined CC_ECDH_ZGen && CC_ECDH_ZGen == YES |
| 602 #define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154) |
| 603 #endif |
| 604 #if defined CC_HMAC && CC_HMAC == YES |
| 605 #define TPM_CC_HMAC (TPM_CC)(0x00000155) |
| 606 #endif |
| 607 #if defined CC_Import && CC_Import == YES |
| 608 #define TPM_CC_Import (TPM_CC)(0x00000156) |
| 609 #endif |
| 610 #if defined CC_Load && CC_Load == YES |
| 611 #define TPM_CC_Load (TPM_CC)(0x00000157) |
| 612 #endif |
| 613 #if defined CC_Quote && CC_Quote == YES |
| 614 #define TPM_CC_Quote (TPM_CC)(0x00000158) |
| 615 #endif |
| 616 #if defined CC_RSA_Decrypt && CC_RSA_Decrypt == YES |
| 617 #define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159) |
| 618 #endif |
| 619 #if defined CC_HMAC_Start && CC_HMAC_Start == YES |
| 620 #define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B) |
| 621 #endif |
| 622 #if defined CC_SequenceUpdate && CC_SequenceUpdate == YES |
| 623 #define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C) |
| |
| Page 354 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 624 #endif |
| 625 #if defined CC_Sign && CC_Sign == YES |
| 626 #define TPM_CC_Sign (TPM_CC)(0x0000015D) |
| 627 #endif |
| 628 #if defined CC_Unseal && CC_Unseal == YES |
| 629 #define TPM_CC_Unseal (TPM_CC)(0x0000015E) |
| 630 #endif |
| 631 #if defined CC_PolicySigned && CC_PolicySigned == YES |
| 632 #define TPM_CC_PolicySigned (TPM_CC)(0x00000160) |
| 633 #endif |
| 634 #if defined CC_ContextLoad && CC_ContextLoad == YES |
| 635 #define TPM_CC_ContextLoad (TPM_CC)(0x00000161) |
| 636 #endif |
| 637 #if defined CC_ContextSave && CC_ContextSave == YES |
| 638 #define TPM_CC_ContextSave (TPM_CC)(0x00000162) |
| 639 #endif |
| 640 #if defined CC_ECDH_KeyGen && CC_ECDH_KeyGen == YES |
| 641 #define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163) |
| 642 #endif |
| 643 #if defined CC_EncryptDecrypt && CC_EncryptDecrypt == YES |
| 644 #define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164) |
| 645 #endif |
| 646 #if defined CC_FlushContext && CC_FlushContext == YES |
| 647 #define TPM_CC_FlushContext (TPM_CC)(0x00000165) |
| 648 #endif |
| 649 #if defined CC_LoadExternal && CC_LoadExternal == YES |
| 650 #define TPM_CC_LoadExternal (TPM_CC)(0x00000167) |
| 651 #endif |
| 652 #if defined CC_MakeCredential && CC_MakeCredential == YES |
| 653 #define TPM_CC_MakeCredential (TPM_CC)(0x00000168) |
| 654 #endif |
| 655 #if defined CC_NV_ReadPublic && CC_NV_ReadPublic == YES |
| 656 #define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169) |
| 657 #endif |
| 658 #if defined CC_PolicyAuthorize && CC_PolicyAuthorize == YES |
| 659 #define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A) |
| 660 #endif |
| 661 #if defined CC_PolicyAuthValue && CC_PolicyAuthValue == YES |
| 662 #define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B) |
| 663 #endif |
| 664 #if defined CC_PolicyCommandCode && CC_PolicyCommandCode == YES |
| 665 #define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C) |
| 666 #endif |
| 667 #if defined CC_PolicyCounterTimer && CC_PolicyCounterTimer == YES |
| 668 #define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D) |
| 669 #endif |
| 670 #if defined CC_PolicyCpHash && CC_PolicyCpHash == YES |
| 671 #define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E) |
| 672 #endif |
| 673 #if defined CC_PolicyLocality && CC_PolicyLocality == YES |
| 674 #define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F) |
| 675 #endif |
| 676 #if defined CC_PolicyNameHash && CC_PolicyNameHash == YES |
| 677 #define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170) |
| 678 #endif |
| 679 #if defined CC_PolicyOR && CC_PolicyOR == YES |
| 680 #define TPM_CC_PolicyOR (TPM_CC)(0x00000171) |
| 681 #endif |
| 682 #if defined CC_PolicyTicket && CC_PolicyTicket == YES |
| 683 #define TPM_CC_PolicyTicket (TPM_CC)(0x00000172) |
| 684 #endif |
| 685 #if defined CC_ReadPublic && CC_ReadPublic == YES |
| 686 #define TPM_CC_ReadPublic (TPM_CC)(0x00000173) |
| 687 #endif |
| 688 #if defined CC_RSA_Encrypt && CC_RSA_Encrypt == YES |
| 689 #define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174) |
| |
| Family "2.0" TCG Published Page 355 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 690 #endif |
| 691 #if defined CC_StartAuthSession && CC_StartAuthSession == YES |
| 692 #define TPM_CC_StartAuthSession (TPM_CC)(0x00000176) |
| 693 #endif |
| 694 #if defined CC_VerifySignature && CC_VerifySignature == YES |
| 695 #define TPM_CC_VerifySignature (TPM_CC)(0x00000177) |
| 696 #endif |
| 697 #if defined CC_ECC_Parameters && CC_ECC_Parameters == YES |
| 698 #define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178) |
| 699 #endif |
| 700 #if defined CC_FirmwareRead && CC_FirmwareRead == YES |
| 701 #define TPM_CC_FirmwareRead (TPM_CC)(0x00000179) |
| 702 #endif |
| 703 #if defined CC_GetCapability && CC_GetCapability == YES |
| 704 #define TPM_CC_GetCapability (TPM_CC)(0x0000017A) |
| 705 #endif |
| 706 #if defined CC_GetRandom && CC_GetRandom == YES |
| 707 #define TPM_CC_GetRandom (TPM_CC)(0x0000017B) |
| 708 #endif |
| 709 #if defined CC_GetTestResult && CC_GetTestResult == YES |
| 710 #define TPM_CC_GetTestResult (TPM_CC)(0x0000017C) |
| 711 #endif |
| 712 #if defined CC_Hash && CC_Hash == YES |
| 713 #define TPM_CC_Hash (TPM_CC)(0x0000017D) |
| 714 #endif |
| 715 #if defined CC_PCR_Read && CC_PCR_Read == YES |
| 716 #define TPM_CC_PCR_Read (TPM_CC)(0x0000017E) |
| 717 #endif |
| 718 #if defined CC_PolicyPCR && CC_PolicyPCR == YES |
| 719 #define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F) |
| 720 #endif |
| 721 #if defined CC_PolicyRestart && CC_PolicyRestart == YES |
| 722 #define TPM_CC_PolicyRestart (TPM_CC)(0x00000180) |
| 723 #endif |
| 724 #if defined CC_ReadClock && CC_ReadClock == YES |
| 725 #define TPM_CC_ReadClock (TPM_CC)(0x00000181) |
| 726 #endif |
| 727 #if defined CC_PCR_Extend && CC_PCR_Extend == YES |
| 728 #define TPM_CC_PCR_Extend (TPM_CC)(0x00000182) |
| 729 #endif |
| 730 #if defined CC_PCR_SetAuthValue && CC_PCR_SetAuthValue == YES |
| 731 #define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183) |
| 732 #endif |
| 733 #if defined CC_NV_Certify && CC_NV_Certify == YES |
| 734 #define TPM_CC_NV_Certify (TPM_CC)(0x00000184) |
| 735 #endif |
| 736 #if defined CC_EventSequenceComplete && CC_EventSequenceComplete == YES |
| 737 #define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185) |
| 738 #endif |
| 739 #if defined CC_HashSequenceStart && CC_HashSequenceStart == YES |
| 740 #define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186) |
| 741 #endif |
| 742 #if defined CC_PolicyPhysicalPresence && CC_PolicyPhysicalPresence == YES |
| 743 #define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187) |
| 744 #endif |
| 745 #if defined CC_PolicyDuplicationSelect && CC_PolicyDuplicationSelect == YES |
| 746 #define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188) |
| 747 #endif |
| 748 #if defined CC_PolicyGetDigest && CC_PolicyGetDigest == YES |
| 749 #define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189) |
| 750 #endif |
| 751 #if defined CC_TestParms && CC_TestParms == YES |
| 752 #define TPM_CC_TestParms (TPM_CC)(0x0000018A) |
| 753 #endif |
| 754 #if defined CC_Commit && CC_Commit == YES |
| 755 #define TPM_CC_Commit (TPM_CC)(0x0000018B) |
| |
| Page 356 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 756 #endif |
| 757 #if defined CC_PolicyPassword && CC_PolicyPassword == YES |
| 758 #define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C) |
| 759 #endif |
| 760 #if defined CC_ZGen_2Phase && CC_ZGen_2Phase == YES |
| 761 #define TPM_CC_ZGen_2Phase (TPM_CC)(0x0000018D) |
| 762 #endif |
| 763 #if defined CC_EC_Ephemeral && CC_EC_Ephemeral == YES |
| 764 #define TPM_CC_EC_Ephemeral (TPM_CC)(0x0000018E) |
| 765 #endif |
| 766 #if defined CC_PolicyNvWritten && CC_PolicyNvWritten == YES |
| 767 #define TPM_CC_PolicyNvWritten (TPM_CC)(0x0000018F) |
| 768 #endif |
| 769 #define TPM_CC_LAST (TPM_CC)(0x0000018F) |
| 770 #ifndef MAX |
| 771 #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| 772 #endif |
| 773 #define MAX_HASH_BLOCK_SIZE ( \ |
| 774 MAX(ALG_SHA1 * SHA1_BLOCK_SIZE, \ |
| 775 MAX(ALG_SHA256 * SHA256_BLOCK_SIZE, \ |
| 776 MAX(ALG_SHA384 * SHA384_BLOCK_SIZE, \ |
| 777 MAX(ALG_SM3_256 * SM3_256_BLOCK_SIZE, \ |
| 778 MAX(ALG_SHA512 * SHA512_BLOCK_SIZE, \ |
| 779 0 )))))) |
| 780 #define MAX_DIGEST_SIZE ( \ |
| 781 MAX(ALG_SHA1 * SHA1_DIGEST_SIZE, \ |
| 782 MAX(ALG_SHA256 * SHA256_DIGEST_SIZE, \ |
| 783 MAX(ALG_SHA384 * SHA384_DIGEST_SIZE, \ |
| 784 MAX(ALG_SM3_256 * SM3_256_DIGEST_SIZE, \ |
| 785 MAX(ALG_SHA512 * SHA512_DIGEST_SIZE, \ |
| 786 0 )))))) |
| 787 #if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0 |
| 788 #error "Hash data not valid" |
| 789 #endif |
| 790 #define HASH_COUNT (ALG_SHA1+ALG_SHA256+ALG_SHA384+ALG_SM3_256+ALG_SHA512) |
| |
| Define the 2B structure that would hold any hash block |
| |
| 791 TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE); |
| |
| Folloing typedef is for some old code |
| |
| 792 typedef TPM2B_MAX_HASH_BLOCK TPM2B_HASH_BLOCK; |
| 793 #ifndef MAX |
| 794 #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| 795 #endif |
| 796 #ifndef ALG_CAMELLIA |
| 797 # define ALG_CAMELLIA NO |
| 798 #endif |
| 799 #ifndef MAX_CAMELLIA_KEY_BITS |
| 800 # define MAX_CAMELLIA_KEY_BITS 0 |
| 801 # define MAX_CAMELLIA_BLOCK_SIZE_BYTES 0 |
| 802 #endif |
| 803 #ifndef ALG_SM4 |
| 804 # define ALG_SM4 NO |
| 805 #endif |
| 806 #ifndef MAX_SM4_KEY_BITS |
| 807 # define MAX_SM4_KEY_BITS 0 |
| 808 # define MAX_SM4_BLOCK_SIZE_BYTES 0 |
| 809 #endif |
| 810 #ifndef ALG_AES |
| 811 # define ALG_AES NO |
| 812 #endif |
| 813 #ifndef MAX_AES_KEY_BITS |
| 814 # define MAX_AES_KEY_BITS 0 |
| |
| Family "2.0" TCG Published Page 357 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 815 # define MAX_AES_BLOCK_SIZE_BYTES 0 |
| 816 #endif |
| 817 #define MAX_SYM_KEY_BITS ( \ |
| 818 MAX(MAX_CAMELLIA_KEY_BITS * ALG_CAMELLIA, \ |
| 819 MAX(MAX_SM4_KEY_BITS * ALG_SM4, \ |
| 820 MAX(MAX_AES_KEY_BITS * ALG_AES, \ |
| 821 0)))) |
| 822 #define MAX_SYM_KEY_BYTES ((MAX_SYM_KEY_BITS + 7) / 8) |
| 823 #define MAX_SYM_BLOCK_SIZE ( \ |
| 824 MAX(MAX_CAMELLIA_BLOCK_SIZE_BYTES * ALG_CAMELLIA, \ |
| 825 MAX(MAX_SM4_BLOCK_SIZE_BYTES * ALG_SM4, \ |
| 826 MAX(MAX_AES_BLOCK_SIZE_BYTES * ALG_AES, \ |
| 827 0)))) |
| 828 #if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0 |
| 829 # error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK_SIZE |
| 830 #endif |
| |
| Define the 2B structure for a seed |
| |
| 831 TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE); |
| 832 #endif // _IMPLEMENTATION_H_ |
| |
| |
| |
| |
| Page 358 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Annex B |
| (informative) |
| Cryptographic Library Interface |
| |
| B.1 Introduction |
| |
| The files in this annex provide cryptographic support functions for the TPM. |
| When possible, the functions in these files make calls to functions that are provided by a cryptographic |
| library (for this annex, it is OpenSSL). In many cases, there is a mismatch between the function |
| performed by the cryptographic library and the function needed by the TPM. In those cases, a function is |
| provided in the code in this clause. |
| There are cases where the cryptographic library could have been used for a specific function but not all |
| functions of the same group. An example is that the OpenSSL version of CFB was not suitable for the |
| requirements of the TPM. Rather than have one symmetric mode be provided in this code with the |
| remaining modes provided by OpenSSL, all the symmetric modes are provided in this code. |
| The provided cryptographic code is believed to be functionally correct but it might not be conformant with |
| all applicable standards. For example, the RSA key generation schemes produces serviceable RSA keys |
| but the method is not compliant with FIPS 186-3. Still, the implementation meets the major objective of |
| the implementation, which is to demonstrate proper TPM behavior. It is not an objective of this |
| implementation to be submitted for certification. |
| |
| B.2 Integer Format |
| |
| The big integers passed to/from the function interfaces in the crypto engine are in BYTE buffers that have |
| the same format used in the TPM 2.0 specification that states: |
| "Integer values are considered to be an array of one or more bytes. The byte at offset zero within the |
| array is the most significant byte of the integer." |
| |
| |
| |
| |
| B.3 CryptoEngine.h |
| |
| B.3.1. Introduction |
| |
| This file contains constant definition shared by CryptUtil() and the parts of the Crypto Engine. |
| |
| 1 #ifndef _CRYPT_PRI_H |
| 2 #define _CRYPT_PRI_H |
| 3 #include <stddef.h> |
| 4 #include "TpmBuildSwitches.h" |
| 5 #include "BaseTypes.h" |
| 6 #include "TpmError.h" |
| 7 #include "swap.h" |
| 8 #include "Implementation.h" |
| 9 #include "TPM_types.h" |
| 10 //#include "TPMB.h" |
| 11 #include "bool.h" |
| 12 #include "Platform.h" |
| 13 #ifndef NULL |
| 14 #define NULL 0 |
| 15 #endif |
| 16 typedef UINT16 NUMBYTES; // When a size is a number of bytes |
| 17 typedef UINT32 NUMDIGITS; // When a size is a number of "digits" |
| |
| Family "2.0" TCG Published Page 359 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.3.2. General Purpose Macros |
| |
| 18 #ifndef MAX |
| 19 # define MAX(a, b) ((a) > (b) ? (a) : b) |
| 20 #endif |
| |
| This is the definition of a bit array with one bit per algorithm |
| |
| 21 typedef BYTE ALGORITHM_VECTOR[(ALG_LAST_VALUE + 7) / 8]; |
| |
| |
| B.3.3. Self-test |
| |
| This structure is used to contain self-test tracking information for the crypto engine. Each of the major |
| modules is given a 32-bit value in which it may maintain its own self test information. The convention for |
| this state is that when all of the bits in this structure are 0, all functions need to be tested. |
| |
| 22 typedef struct { |
| 23 UINT32 rng; |
| 24 UINT32 hash; |
| 25 UINT32 sym; |
| 26 #ifdef TPM_ALG_RSA |
| 27 UINT32 rsa; |
| 28 #endif |
| 29 #ifdef TPM_ALG_ECC |
| 30 UINT32 ecc; |
| 31 #endif |
| 32 } CRYPTO_SELF_TEST_STATE; |
| |
| |
| B.3.4. Hash-related Structures |
| |
| 33 typedef struct { |
| 34 const TPM_ALG_ID alg; |
| 35 const NUMBYTES digestSize; |
| 36 const NUMBYTES blockSize; |
| 37 const NUMBYTES derSize; |
| 38 const BYTE der[20]; |
| 39 } HASH_INFO; |
| |
| This value will change with each implementation. The value of 16 is used to account for any slop in the |
| context values. The overall size needs to be as large as any of the hash contexts. The structure needs to |
| start on an alignment boundary and be an even multiple of the alignment |
| |
| 40 #define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b)) |
| 41 #define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16) |
| 42 #define MAX_HASH_STATE_SIZE_ALIGNED \ |
| 43 ALIGNED_SIZE(MAX_HASH_STATE_SIZE, CRYPTO_ALIGNMENT) |
| |
| This is an byte array that will hold any of the hash contexts. |
| |
| 44 typedef CRYPTO_ALIGNED BYTE ALIGNED_HASH_STATE[MAX_HASH_STATE_SIZE_ALIGNED]; |
| |
| Macro to align an address to the next higher size |
| |
| 45 #define AlignPointer(address, align) \ |
| 46 ((((intptr_t)&(address)) + (align - 1)) & ~(align - 1)) |
| |
| Macro to test alignment |
| |
| 47 #define IsAddressAligned(address, align) \ |
| 48 (((intptr_t)(address) & (align - 1)) == 0) |
| |
| Page 360 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| This is the structure that is used for passing a context into the hashing functions. It should be the same |
| size as the function context used within the hashing functions. This is checked when the hash function is |
| initialized. This version uses a new layout for the contexts and a different definition. The state buffer is an |
| array of HASH_UNIT values so that a decent compiler will put the structure on a HASH_UNIT boundary. |
| If the structure is not properly aligned, the code that manipulates the structure will copy to a properly |
| aligned structure before it is used and copy the result back. This just makes things slower. |
| |
| 49 typedef struct _HASH_STATE |
| 50 { |
| 51 ALIGNED_HASH_STATE state; |
| 52 TPM_ALG_ID hashAlg; |
| 53 } CPRI_HASH_STATE, *PCPRI_HASH_STATE; |
| 54 extern const HASH_INFO g_hashData[HASH_COUNT + 1]; |
| |
| This is for the external hash state. This implementation assumes that the size of the exported hash state |
| is no larger than the internal hash state. There is a compile-time check to make sure that this is true. |
| |
| 55 typedef struct { |
| 56 ALIGNED_HASH_STATE buffer; |
| 57 TPM_ALG_ID hashAlg; |
| 58 } EXPORT_HASH_STATE; |
| 59 typedef enum { |
| 60 IMPORT_STATE, // Converts externally formatted state to internal |
| 61 EXPORT_STATE // Converts internal formatted state to external |
| 62 } IMPORT_EXPORT; |
| |
| Values and structures for the random number generator. These values are defined in this header file so |
| that the size of the RNG state can be known to TPM.lib. This allows the allocation of some space in NV |
| memory for the state to be stored on an orderly shutdown. The GET_PUT enum is used by |
| _cpri__DrbgGetPutState() to indicate the direction of data flow. |
| |
| 63 typedef enum { |
| 64 GET_STATE, // Get the state to save to NV |
| 65 PUT_STATE // Restore the state from NV |
| 66 } GET_PUT; |
| |
| The DRBG based on a symmetric block cipher is defined by three values, |
| a) the key size |
| b) the block size (the IV size) |
| c) the symmetric algorithm |
| |
| 67 #define DRBG_KEY_SIZE_BITS MAX_AES_KEY_BITS |
| 68 #define DRBG_IV_SIZE_BITS (MAX_AES_BLOCK_SIZE_BYTES * 8) |
| 69 #define DRBG_ALGORITHM TPM_ALG_AES |
| 70 #if ((DRBG_KEY_SIZE_BITS % 8) != 0) || ((DRBG_IV_SIZE_BITS % 8) != 0) |
| 71 #error "Key size and IV for DRBG must be even multiples of 8" |
| 72 #endif |
| 73 #if (DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0 |
| 74 #error "Key size for DRBG must be even multiple of the cypher block size" |
| 75 #endif |
| 76 typedef UINT32 DRBG_SEED[(DRBG_KEY_SIZE_BITS + DRBG_IV_SIZE_BITS) / 32]; |
| 77 typedef struct { |
| 78 UINT64 reseedCounter; |
| 79 UINT32 magic; |
| 80 DRBG_SEED seed; // contains the key and IV for the counter mode DRBG |
| 81 UINT32 lastValue[4]; // used when the TPM does continuous self-test |
| 82 // for FIPS compliance of DRBG |
| 83 } DRBG_STATE, *pDRBG_STATE; |
| |
| |
| |
| Family "2.0" TCG Published Page 361 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.3.5. Asymmetric Structures and Values |
| |
| 84 #ifdef TPM_ALG_ECC |
| |
| |
| B.3.5.1. ECC-related Structures |
| |
| This structure replicates the structure definition in TPM_Types.h. It is duplicated to avoid inclusion of all of |
| TPM_Types.h This structure is similar to the RSA_KEY structure below. The purpose of these structures |
| is to reduce the overhead of a function call and to make the code less dependent on key types as much |
| as possible. |
| |
| 85 typedef struct { |
| 86 UINT32 curveID; // The curve identifier |
| 87 TPMS_ECC_POINT *publicPoint; // Pointer to the public point |
| 88 TPM2B_ECC_PARAMETER *privateKey; // Pointer to the private key |
| 89 } ECC_KEY; |
| 90 #endif // TPM_ALG_ECC |
| 91 #ifdef TPM_ALG_RSA |
| |
| |
| B.3.5.2. RSA-related Structures |
| |
| This structure is a succinct representation of the cryptographic components of an RSA key. |
| |
| 92 typedef struct { |
| 93 UINT32 exponent; // The public exponent pointer |
| 94 TPM2B *publicKey; // Pointer to the public modulus |
| 95 TPM2B *privateKey; // The private exponent (not a prime) |
| 96 } RSA_KEY; |
| 97 #endif // TPM_ALG_RSA |
| |
| |
| B.3.6. Miscelaneous |
| |
| 98 #ifdef TPM_ALG_RSA |
| 99 # ifdef TPM_ALG_ECC |
| 100 # if MAX_RSA_KEY_BYTES > MAX_ECC_KEY_BYTES |
| 101 # define MAX_NUMBER_SIZE MAX_RSA_KEY_BYTES |
| 102 # else |
| 103 # define MAX_NUMBER_SIZE MAX_ECC_KEY_BYTES |
| 104 # endif |
| 105 # else // RSA but no ECC |
| 106 # define MAX_NUMBER_SIZE MAX_RSA_KEY_BYTES |
| 107 # endif |
| 108 #elif defined TPM_ALG_ECC |
| 109 # define MAX_NUMBER_SIZE MAX_ECC_KEY_BYTES |
| 110 #else |
| 111 # error No assymmetric algorithm implemented. |
| 112 #endif |
| 113 typedef INT16 CRYPT_RESULT; |
| 114 #define CRYPT_RESULT_MIN INT16_MIN |
| 115 #define CRYPT_RESULT_MAX INT16_MAX |
| |
| |
| <0 recoverable error |
| |
| 0 success |
| >0 command specific return value (generally a digest size) |
| |
| 116 #define CRYPT_FAIL ((CRYPT_RESULT) 1) |
| 117 #define CRYPT_SUCCESS ((CRYPT_RESULT) 0) |
| 118 #define CRYPT_NO_RESULT ((CRYPT_RESULT) -1) |
| |
| |
| Page 362 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 119 #define CRYPT_SCHEME ((CRYPT_RESULT) -2) |
| 120 #define CRYPT_PARAMETER ((CRYPT_RESULT) -3) |
| 121 #define CRYPT_UNDERFLOW ((CRYPT_RESULT) -4) |
| 122 #define CRYPT_POINT ((CRYPT_RESULT) -5) |
| 123 #define CRYPT_CANCEL ((CRYPT_RESULT) -6) |
| 124 typedef UINT64 HASH_CONTEXT[MAX_HASH_STATE_SIZE/sizeof(UINT64)]; |
| 125 #include "CpriCryptPri_fp.h" |
| 126 #ifdef TPM_ALG_ECC |
| 127 # include "CpriDataEcc.h" |
| 128 # include "CpriECC_fp.h" |
| 129 #endif |
| 130 #include "MathFunctions_fp.h" |
| 131 #include "CpriRNG_fp.h" |
| 132 #include "CpriHash_fp.h" |
| 133 #include "CpriSym_fp.h" |
| 134 #ifdef TPM_ALG_RSA |
| 135 # include "CpriRSA_fp.h" |
| 136 #endif |
| 137 #endif // !_CRYPT_PRI_H |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 363 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| |
| B.4 OsslCryptoEngine.h |
| |
| B.4.1. Introduction |
| |
| This is the header file used by the components of the CryptoEngine(). This file should not be included in |
| any file other than the files in the crypto engine. |
| Vendors may replace the implementation in this file by a local crypto engine. The implementation in this |
| file is based on OpenSSL() library. Integer format: the big integers passed in/out the function interfaces in |
| this library by a byte buffer (BYTE *) adopt the same format used in TPM 2.0 specification: Integer values |
| are considered to be an array of one or more bytes. The byte at offset zero within the array is the most |
| significant byte of the integer. |
| |
| B.4.2. Defines |
| |
| 1 #ifndef _OSSL_CRYPTO_ENGINE_H |
| 2 #define _OSSL_CRYPTO_ENGINE_H |
| 3 #include <openssl/aes.h> |
| 4 #include <openssl/evp.h> |
| 5 #include <openssl/sha.h> |
| 6 #include <openssl/ec.h> |
| 7 #include <openssl/rand.h> |
| 8 #include <openssl/bn.h> |
| 9 #include <openSSL/ec_lcl.h> |
| 10 #define CRYPTO_ENGINE |
| 11 #include "CryptoEngine.h" |
| 12 #include "CpriMisc_fp.h" |
| 13 #define MAX_ECC_PARAMETER_BYTES 32 |
| 14 #define MAX_2B_BYTES MAX((MAX_RSA_KEY_BYTES * ALG_RSA), \ |
| 15 MAX((MAX_ECC_PARAMETER_BYTES * ALG_ECC), \ |
| 16 MAX_DIGEST_SIZE)) |
| 17 #define assert2Bsize(a) pAssert((a).size <= sizeof((a).buffer)) |
| 18 #ifdef TPM_ALG_RSA |
| 19 # ifdef RSA_KEY_SIEVE |
| 20 # include "RsaKeySieve.h" |
| 21 # include "RsaKeySieve_fp.h" |
| 22 # endif |
| 23 # include "CpriRSA_fp.h" |
| 24 #endif |
| |
| This is a structure to hold the parameters for the version of KDFa() used by the CryptoEngine(). This |
| structure allows the state to be passed between multiple functions that use the same pseudo-random |
| sequence. |
| |
| 25 typedef struct { |
| 26 CPRI_HASH_STATE iPadCtx; |
| 27 CPRI_HASH_STATE oPadCtx; |
| 28 TPM2B *extra; |
| 29 UINT32 *outer; |
| 30 TPM_ALG_ID hashAlg; |
| 31 UINT16 keySizeInBits; |
| 32 } KDFa_CONTEXT; |
| 33 #endif // _OSSL_CRYPTO_ENGINE_H |
| |
| |
| |
| |
| Page 364 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.5 MathFunctions.c |
| |
| B.5.1. Introduction |
| |
| This file contains implementation of some of the big number primitives. This is used in order to reduce the |
| overhead in dealing with data conversions to standard big number format. |
| The simulator code uses the canonical form whenever possible in order to make the code in Part 3 more |
| accessible. The canonical data formats are simple and not well suited for complex big number |
| computations. This library provides functions that are found in typical big number libraries but they are |
| written to handle the canonical data format of the reference TPM. |
| In some cases, data is converted to a big number format used by a standard library, such as OpenSSL(). |
| This is done when the computations are complex enough warrant conversion. Vendors may replace the |
| implementation in this file with a library that provides equivalent functions. A vendor may also rewrite the |
| TPM code so that it uses a standard big number format instead of the canonical form and use the |
| standard libraries instead of the code in this file. |
| The implementation in this file makes use of the OpenSSL() library. |
| Integer format: integers passed through the function interfaces in this library adopt the same format used |
| in TPM 2.0 specification. It defines an integer as "an array of one or more octets with the most significant |
| octet at the lowest index of the array." An additional value is needed to indicate the number of significant |
| bytes. |
| |
| 1 #include "OsslCryptoEngine.h" |
| |
| |
| B.5.2. Externally Accessible Functions |
| |
| B.5.2.1. _math__Normalize2B() |
| |
| This function will normalize the value in a TPM2B. If there are leading bytes of zero, the first non-zero |
| byte is shifted up. |
| |
| Return Value Meaning |
| |
| 0 no significant bytes, value is zero |
| >0 number of significant bytes |
| |
| 2 LIB_EXPORT UINT16 |
| 3 _math__Normalize2B( |
| 4 TPM2B *b // IN/OUT: number to normalize |
| 5 ) |
| 6 { |
| 7 UINT16 from; |
| 8 UINT16 to; |
| 9 UINT16 size = b->size; |
| 10 |
| 11 for(from = 0; b->buffer[from] == 0 && from < size; from++); |
| 12 b->size -= from; |
| 13 for(to = 0; from < size; to++, from++ ) |
| 14 b->buffer[to] = b->buffer[from]; |
| 15 return b->size; |
| 16 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 365 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.5.2.2. _math__Denormalize2B() |
| |
| This function is used to adjust a TPM2B so that the number has the desired number of bytes. This is |
| accomplished by adding bytes of zero at the start of the number. |
| |
| Return Value Meaning |
| |
| TRUE number de-normalized |
| FALSE number already larger than the desired size |
| |
| 17 LIB_EXPORT BOOL |
| 18 _math__Denormalize2B( |
| 19 TPM2B *in, // IN:OUT TPM2B number to de-normalize |
| 20 UINT32 size // IN: the desired size |
| 21 ) |
| 22 { |
| 23 UINT32 to; |
| 24 UINT32 from; |
| 25 // If the current size is greater than the requested size, see if this can be |
| 26 // normalized to a value smaller than the requested size and then de-normalize |
| 27 if(in->size > size) |
| 28 { |
| 29 _math__Normalize2B(in); |
| 30 if(in->size > size) |
| 31 return FALSE; |
| 32 } |
| 33 // If the size is already what is requested, leave |
| 34 if(in->size == size) |
| 35 return TRUE; |
| 36 |
| 37 // move the bytes to the 'right' |
| 38 for(from = in->size, to = size; from > 0;) |
| 39 in->buffer[--to] = in->buffer[--from]; |
| 40 |
| 41 // 'to' will always be greater than 0 because we checked for equal above. |
| 42 for(; to > 0;) |
| 43 in->buffer[--to] = 0; |
| 44 |
| 45 in->size = (UINT16)size; |
| 46 return TRUE; |
| 47 } |
| |
| |
| B.5.2.3. _math__sub() |
| |
| This function to subtract one unsigned value from another c = a - b. c may be the same as a or b. |
| |
| Return Value Meaning |
| |
| 1 if (a > b) so no borrow |
| 0 if (a = b) so no borrow and b == a |
| -1 if (a < b) so there was a borrow |
| |
| 48 LIB_EXPORT int |
| 49 _math__sub( |
| 50 const UINT32 aSize, // IN: size of a |
| 51 const BYTE *a, // IN: a |
| 52 const UINT32 bSize, // IN: size of b |
| 53 const BYTE *b, // IN: b |
| 54 UINT16 *cSize, // OUT: set to MAX(aSize, bSize) |
| 55 BYTE *c // OUT: the difference |
| 56 ) |
| |
| Page 366 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 57 { |
| 58 int borrow = 0; |
| 59 int notZero = 0; |
| 60 int i; |
| 61 int i2; |
| 62 |
| 63 // set c to the longer of a or b |
| 64 *cSize = (UINT16)((aSize > bSize) ? aSize : bSize); |
| 65 // pick the shorter of a and b |
| 66 i = (aSize > bSize) ? bSize : aSize; |
| 67 i2 = *cSize - i; |
| 68 a = &a[aSize - 1]; |
| 69 b = &b[bSize - 1]; |
| 70 c = &c[*cSize - 1]; |
| 71 for(; i > 0; i--) |
| 72 { |
| 73 borrow = *a-- - *b-- + borrow; |
| 74 *c-- = (BYTE)borrow; |
| 75 notZero = notZero || borrow; |
| 76 borrow >>= 8; |
| 77 } |
| 78 if(aSize > bSize) |
| 79 { |
| 80 for(;i2 > 0; i2--) |
| 81 { |
| 82 borrow = *a-- + borrow; |
| 83 *c-- = (BYTE)borrow; |
| 84 notZero = notZero || borrow; |
| 85 borrow >>= 8; |
| 86 } |
| 87 } |
| 88 else if(aSize < bSize) |
| 89 { |
| 90 for(;i2 > 0; i2--) |
| 91 { |
| 92 borrow = 0 - *b-- + borrow; |
| 93 *c-- = (BYTE)borrow; |
| 94 notZero = notZero || borrow; |
| 95 borrow >>= 8; |
| 96 } |
| 97 } |
| 98 // if there is a borrow, then b > a |
| 99 if(borrow) |
| 100 return -1; |
| 101 // either a > b or they are the same |
| 102 return notZero; |
| 103 } |
| |
| |
| B.5.2.4. _math__Inc() |
| |
| This function increments a large, big-endian number value by one. |
| |
| Return Value Meaning |
| |
| 0 result is zero |
| !0 result is not zero |
| |
| 104 LIB_EXPORT int |
| 105 _math__Inc( |
| 106 UINT32 aSize, // IN: size of a |
| 107 BYTE *a // IN: a |
| 108 ) |
| 109 { |
| |
| |
| Family "2.0" TCG Published Page 367 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 110 |
| 111 for(a = &a[aSize-1];aSize > 0; aSize--) |
| 112 { |
| 113 if((*a-- += 1) != 0) |
| 114 return 1; |
| 115 } |
| 116 return 0; |
| 117 } |
| |
| |
| B.5.2.5. _math__Dec() |
| |
| This function decrements a large, ENDIAN value by one. |
| |
| 118 LIB_EXPORT void |
| 119 _math__Dec( |
| 120 UINT32 aSize, // IN: size of a |
| 121 BYTE *a // IN: a |
| 122 ) |
| 123 { |
| 124 for(a = &a[aSize-1]; aSize > 0; aSize--) |
| 125 { |
| 126 if((*a-- -= 1) != 0xff) |
| 127 return; |
| 128 } |
| 129 return; |
| 130 } |
| |
| |
| B.5.2.6. _math__Mul() |
| |
| This function is used to multiply two large integers: p = a* b. If the size of p is not specified (pSize == |
| NULL), the size of the results p is assumed to be aSize + bSize and the results are de-normalized so that |
| the resulting size is exactly aSize + bSize. If pSize is provided, then the actual size of the result is |
| returned. The initial value for pSize must be at least aSize + pSize. |
| |
| Return Value Meaning |
| |
| <0 indicates an error |
| >= 0 the size of the product |
| |
| 131 LIB_EXPORT int |
| 132 _math__Mul( |
| 133 const UINT32 aSize, // IN: size of a |
| 134 const BYTE *a, // IN: a |
| 135 const UINT32 bSize, // IN: size of b |
| 136 const BYTE *b, // IN: b |
| 137 UINT32 *pSize, // IN/OUT: size of the product |
| 138 BYTE *p // OUT: product. length of product = aSize + |
| 139 // bSize |
| 140 ) |
| 141 { |
| 142 BIGNUM *bnA; |
| 143 BIGNUM *bnB; |
| 144 BIGNUM *bnP; |
| 145 BN_CTX *context; |
| 146 int retVal = 0; |
| 147 |
| 148 // First check that pSize is large enough if present |
| 149 if((pSize != NULL) && (*pSize < (aSize + bSize))) |
| 150 return CRYPT_PARAMETER; |
| 151 pAssert(pSize == NULL || *pSize <= MAX_2B_BYTES); |
| 152 // |
| |
| |
| Page 368 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 153 // Allocate space for BIGNUM context |
| 154 // |
| 155 context = BN_CTX_new(); |
| 156 if(context == NULL) |
| 157 FAIL(FATAL_ERROR_ALLOCATION); |
| 158 bnA = BN_CTX_get(context); |
| 159 bnB = BN_CTX_get(context); |
| 160 bnP = BN_CTX_get(context); |
| 161 if (bnP == NULL) |
| 162 FAIL(FATAL_ERROR_ALLOCATION); |
| 163 |
| 164 // Convert the inputs to BIGNUMs |
| 165 // |
| 166 if (BN_bin2bn(a, aSize, bnA) == NULL || BN_bin2bn(b, bSize, bnB) == NULL) |
| 167 FAIL(FATAL_ERROR_INTERNAL); |
| 168 |
| 169 // Perform the multiplication |
| 170 // |
| 171 if (BN_mul(bnP, bnA, bnB, context) != 1) |
| 172 FAIL(FATAL_ERROR_INTERNAL); |
| 173 |
| 174 // If the size of the results is allowed to float, then set the return |
| 175 // size. Otherwise, it might be necessary to de-normalize the results |
| 176 retVal = BN_num_bytes(bnP); |
| 177 if(pSize == NULL) |
| 178 { |
| 179 BN_bn2bin(bnP, &p[aSize + bSize - retVal]); |
| 180 memset(p, 0, aSize + bSize - retVal); |
| 181 retVal = aSize + bSize; |
| 182 } |
| 183 else |
| 184 { |
| 185 BN_bn2bin(bnP, p); |
| 186 *pSize = retVal; |
| 187 } |
| 188 |
| 189 BN_CTX_end(context); |
| 190 BN_CTX_free(context); |
| 191 return retVal; |
| 192 } |
| |
| |
| B.5.2.7. _math__Div() |
| |
| Divide an integer (n) by an integer (d) producing a quotient (q) and a remainder (r). If q or r is not needed, |
| then the pointer to them may be set to NULL. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS operation complete |
| CRYPT_UNDERFLOW q or r is too small to receive the result |
| |
| 193 LIB_EXPORT CRYPT_RESULT |
| 194 _math__Div( |
| 195 const TPM2B *n, // IN: numerator |
| 196 const TPM2B *d, // IN: denominator |
| 197 TPM2B *q, // OUT: quotient |
| 198 TPM2B *r // OUT: remainder |
| 199 ) |
| 200 { |
| 201 BIGNUM *bnN; |
| 202 BIGNUM *bnD; |
| 203 BIGNUM *bnQ; |
| 204 BIGNUM *bnR; |
| |
| Family "2.0" TCG Published Page 369 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 205 BN_CTX *context; |
| 206 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 207 |
| 208 // Get structures for the big number representations |
| 209 context = BN_CTX_new(); |
| 210 if(context == NULL) |
| 211 FAIL(FATAL_ERROR_ALLOCATION); |
| 212 BN_CTX_start(context); |
| 213 bnN = BN_CTX_get(context); |
| 214 bnD = BN_CTX_get(context); |
| 215 bnQ = BN_CTX_get(context); |
| 216 bnR = BN_CTX_get(context); |
| 217 |
| 218 // Errors in BN_CTX_get() are sticky so only need to check the last allocation |
| 219 if ( bnR == NULL |
| 220 || BN_bin2bn(n->buffer, n->size, bnN) == NULL |
| 221 || BN_bin2bn(d->buffer, d->size, bnD) == NULL) |
| 222 FAIL(FATAL_ERROR_INTERNAL); |
| 223 |
| 224 // Check for divide by zero. |
| 225 if(BN_num_bits(bnD) == 0) |
| 226 FAIL(FATAL_ERROR_DIVIDE_ZERO); |
| 227 |
| 228 // Perform the division |
| 229 if (BN_div(bnQ, bnR, bnN, bnD, context) != 1) |
| 230 FAIL(FATAL_ERROR_INTERNAL); |
| 231 |
| 232 // Convert the BIGNUM result back to our format |
| 233 if(q != NULL) // If the quotient is being returned |
| 234 { |
| 235 if(!BnTo2B(q, bnQ, q->size)) |
| 236 { |
| 237 retVal = CRYPT_UNDERFLOW; |
| 238 goto Done; |
| 239 } |
| 240 } |
| 241 if(r != NULL) // If the remainder is being returned |
| 242 { |
| 243 if(!BnTo2B(r, bnR, r->size)) |
| 244 retVal = CRYPT_UNDERFLOW; |
| 245 } |
| 246 |
| 247 Done: |
| 248 BN_CTX_end(context); |
| 249 BN_CTX_free(context); |
| 250 |
| 251 return retVal; |
| 252 } |
| |
| |
| B.5.2.8. _math__uComp() |
| |
| This function compare two unsigned values. |
| |
| Return Value Meaning |
| |
| 1 if (a > b) |
| 0 if (a = b) |
| -1 if (a < b) |
| |
| 253 LIB_EXPORT int |
| 254 _math__uComp( |
| 255 const UINT32 aSize, // IN: size of a |
| 256 const BYTE *a, // IN: a |
| |
| Page 370 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 257 const UINT32 bSize, // IN: size of b |
| 258 const BYTE *b // IN: b |
| 259 ) |
| 260 { |
| 261 int borrow = 0; |
| 262 int notZero = 0; |
| 263 int i; |
| 264 // If a has more digits than b, then a is greater than b if |
| 265 // any of the more significant bytes is non zero |
| 266 if((i = (int)aSize - (int)bSize) > 0) |
| 267 for(; i > 0; i--) |
| 268 if(*a++) // means a > b |
| 269 return 1; |
| 270 // If b has more digits than a, then b is greater if any of the |
| 271 // more significant bytes is non zero |
| 272 if(i < 0) // Means that b is longer than a |
| 273 for(; i < 0; i++) |
| 274 if(*b++) // means that b > a |
| 275 return -1; |
| 276 // Either the vales are the same size or the upper bytes of a or b are |
| 277 // all zero, so compare the rest |
| 278 i = (aSize > bSize) ? bSize : aSize; |
| 279 a = &a[i-1]; |
| 280 b = &b[i-1]; |
| 281 for(; i > 0; i--) |
| 282 { |
| 283 borrow = *a-- - *b-- + borrow; |
| 284 notZero = notZero || borrow; |
| 285 borrow >>= 8; |
| 286 } |
| 287 // if there is a borrow, then b > a |
| 288 if(borrow) |
| 289 return -1; |
| 290 // either a > b or they are the same |
| 291 return notZero; |
| 292 } |
| |
| |
| B.5.2.9. _math__Comp() |
| |
| Compare two signed integers: |
| |
| Return Value Meaning |
| |
| 1 if a > b |
| 0 if a = b |
| -1 if a < b |
| |
| 293 LIB_EXPORT int |
| 294 _math__Comp( |
| 295 const UINT32 aSize, // IN: size of a |
| 296 const BYTE *a, // IN: a buffer |
| 297 const UINT32 bSize, // IN: size of b |
| 298 const BYTE *b // IN: b buffer |
| 299 ) |
| 300 { |
| 301 int signA, signB; // sign of a and b |
| 302 |
| 303 // For positive or 0, sign_a is 1 |
| 304 // for negative, sign_a is 0 |
| 305 signA = ((a[0] & 0x80) == 0) ? 1 : 0; |
| 306 |
| 307 // For positive or 0, sign_b is 1 |
| 308 // for negative, sign_b is 0 |
| |
| Family "2.0" TCG Published Page 371 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 309 signB = ((b[0] & 0x80) == 0) ? 1 : 0; |
| 310 |
| 311 if(signA != signB) |
| 312 { |
| 313 return signA - signB; |
| 314 } |
| 315 |
| 316 if(signA == 1) |
| 317 // do unsigned compare function |
| 318 return _math__uComp(aSize, a, bSize, b); |
| 319 else |
| 320 // do unsigned compare the other way |
| 321 return 0 - _math__uComp(aSize, a, bSize, b); |
| 322 } |
| |
| |
| B.5.2.10. _math__ModExp |
| |
| This function is used to do modular exponentiation in support of RSA. The most typical uses are: c = m^e |
| mod n (RSA encrypt) and m = c^d mod n (RSA decrypt). When doing decryption, the e parameter of the |
| function will contain the private exponent d instead of the public exponent e. |
| If the results will not fit in the provided buffer, an error is returned (CRYPT_ERROR_UNDERFLOW). If |
| the results is smaller than the buffer, the results is de-normalized. |
| This version is intended for use with RSA and requires that m be less than n. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS exponentiation succeeded |
| CRYPT_PARAMETER number to exponentiate is larger than the modulus |
| CRYPT_UNDERFLOW result will not fit into the provided buffer |
| |
| 323 LIB_EXPORT CRYPT_RESULT |
| 324 _math__ModExp( |
| 325 UINT32 cSize, // IN: size of the result |
| 326 BYTE *c, // OUT: results buffer |
| 327 const UINT32 mSize, // IN: size of number to be exponentiated |
| 328 const BYTE *m, // IN: number to be exponentiated |
| 329 const UINT32 eSize, // IN: size of power |
| 330 const BYTE *e, // IN: power |
| 331 const UINT32 nSize, // IN: modulus size |
| 332 const BYTE *n // IN: modulu |
| 333 ) |
| 334 { |
| 335 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 336 BN_CTX *context; |
| 337 BIGNUM *bnC; |
| 338 BIGNUM *bnM; |
| 339 BIGNUM *bnE; |
| 340 BIGNUM *bnN; |
| 341 INT32 i; |
| 342 |
| 343 context = BN_CTX_new(); |
| 344 if(context == NULL) |
| 345 FAIL(FATAL_ERROR_ALLOCATION); |
| 346 BN_CTX_start(context); |
| 347 bnC = BN_CTX_get(context); |
| 348 bnM = BN_CTX_get(context); |
| 349 bnE = BN_CTX_get(context); |
| 350 bnN = BN_CTX_get(context); |
| 351 |
| 352 // Errors for BN_CTX_get are sticky so only need to check last allocation |
| 353 if(bnN == NULL) |
| |
| Page 372 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 354 FAIL(FATAL_ERROR_ALLOCATION); |
| 355 |
| 356 //convert arguments |
| 357 if ( BN_bin2bn(m, mSize, bnM) == NULL |
| 358 || BN_bin2bn(e, eSize, bnE) == NULL |
| 359 || BN_bin2bn(n, nSize, bnN) == NULL) |
| 360 FAIL(FATAL_ERROR_INTERNAL); |
| 361 |
| 362 // Don't do exponentiation if the number being exponentiated is |
| 363 // larger than the modulus. |
| 364 if(BN_ucmp(bnM, bnN) >= 0) |
| 365 { |
| 366 retVal = CRYPT_PARAMETER; |
| 367 goto Cleanup; |
| 368 } |
| 369 // Perform the exponentiation |
| 370 if(!(BN_mod_exp(bnC, bnM, bnE, bnN, context))) |
| 371 FAIL(FATAL_ERROR_INTERNAL); |
| 372 |
| 373 // Convert the results |
| 374 // Make sure that the results will fit in the provided buffer. |
| 375 if((unsigned)BN_num_bytes(bnC) > cSize) |
| 376 { |
| 377 retVal = CRYPT_UNDERFLOW; |
| 378 goto Cleanup; |
| 379 } |
| 380 i = cSize - BN_num_bytes(bnC); |
| 381 BN_bn2bin(bnC, &c[i]); |
| 382 memset(c, 0, i); |
| 383 |
| 384 Cleanup: |
| 385 // Free up allocated BN values |
| 386 BN_CTX_end(context); |
| 387 BN_CTX_free(context); |
| 388 return retVal; |
| 389 } |
| |
| |
| B.5.2.11. _math__IsPrime() |
| |
| Check if an 32-bit integer is a prime. |
| |
| Return Value Meaning |
| |
| TRUE if the integer is probably a prime |
| FALSE if the integer is definitely not a prime |
| |
| 390 LIB_EXPORT BOOL |
| 391 _math__IsPrime( |
| 392 const UINT32 prime |
| 393 ) |
| 394 { |
| 395 int isPrime; |
| 396 BIGNUM *p; |
| 397 |
| 398 // Assume the size variables are not overflow, which should not happen in |
| 399 // the contexts that this function will be called. |
| 400 if((p = BN_new()) == NULL) |
| 401 FAIL(FATAL_ERROR_ALLOCATION); |
| 402 if(!BN_set_word(p, prime)) |
| 403 FAIL(FATAL_ERROR_INTERNAL); |
| 404 |
| 405 // |
| 406 // BN_is_prime returning -1 means that it ran into an error. |
| |
| |
| Family "2.0" TCG Published Page 373 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 407 // It should only return 0 or 1 |
| 408 // |
| 409 if((isPrime = BN_is_prime_ex(p, BN_prime_checks, NULL, NULL)) < 0) |
| 410 FAIL(FATAL_ERROR_INTERNAL); |
| 411 |
| 412 if(p != NULL) |
| 413 BN_clear_free(p); |
| 414 return (isPrime == 1); |
| 415 } |
| |
| |
| |
| |
| Page 374 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.6 CpriCryptPri.c |
| |
| B.6.1. Introduction |
| |
| This file contains the interface to the initialization, startup and shutdown functions of the crypto library. |
| |
| B.6.2. Includes and Locals |
| |
| 1 #include "OsslCryptoEngine.h" |
| 2 static void Trap(const char *function, int line, int code); |
| 3 FAIL_FUNCTION TpmFailFunction = (FAIL_FUNCTION)&Trap; |
| |
| |
| B.6.3. Functions |
| |
| B.6.3.1. TpmFail() |
| |
| This is a shim function that is called when a failure occurs. It simply relays the call to the callback pointed |
| to by TpmFailFunction(). It is only defined for the sake of NO_RETURN specifier that cannot be added to |
| a function pointer with some compilers. |
| |
| 4 void |
| 5 TpmFail( |
| 6 const char *function, |
| 7 int line, |
| 8 int code) |
| 9 { |
| 10 TpmFailFunction(function, line, code); |
| 11 } |
| |
| |
| B.6.3.2. FAILURE_TRAP() |
| |
| This function is called if the caller to _cpri__InitCryptoUnits() doesn't provide a call back address. |
| |
| 12 static void |
| 13 Trap( |
| 14 const char *function, |
| 15 int line, |
| 16 int code |
| 17 ) |
| 18 { |
| 19 UNREFERENCED(function); |
| 20 UNREFERENCED(line); |
| 21 UNREFERENCED(code); |
| 22 abort(); |
| 23 } |
| |
| |
| B.6.3.3. _cpri__InitCryptoUnits() |
| |
| This function calls the initialization functions of the other crypto modules that are part of the crypto engine |
| for this implementation. This function should be called as a result of _TPM_Init(). The parameter to this |
| function is a call back function it TPM.lib that is called when the crypto engine has a failure. |
| |
| 24 LIB_EXPORT CRYPT_RESULT |
| 25 _cpri__InitCryptoUnits( |
| 26 FAIL_FUNCTION failFunction |
| 27 ) |
| 28 { |
| |
| Family "2.0" TCG Published Page 375 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 29 TpmFailFunction = failFunction; |
| 30 |
| 31 _cpri__RngStartup(); |
| 32 _cpri__HashStartup(); |
| 33 _cpri__SymStartup(); |
| 34 |
| 35 #ifdef TPM_ALG_RSA |
| 36 _cpri__RsaStartup(); |
| 37 #endif |
| 38 |
| 39 #ifdef TPM_ALG_ECC |
| 40 _cpri__EccStartup(); |
| 41 #endif |
| 42 |
| 43 return CRYPT_SUCCESS; |
| 44 } |
| |
| |
| B.6.3.4. _cpri__StopCryptoUnits() |
| |
| This function calls the shutdown functions of the other crypto modules that are part of the crypto engine |
| for this implementation. |
| |
| 45 LIB_EXPORT void |
| 46 _cpri__StopCryptoUnits( |
| 47 void |
| 48 ) |
| 49 { |
| 50 return; |
| 51 } |
| |
| |
| B.6.3.5. _cpri__Startup() |
| |
| This function calls the startup functions of the other crypto modules that are part of the crypto engine for |
| this implementation. This function should be called during processing of TPM2_Startup(). |
| |
| 52 LIB_EXPORT BOOL |
| 53 _cpri__Startup( |
| 54 void |
| 55 ) |
| 56 { |
| 57 |
| 58 return( _cpri__HashStartup() |
| 59 && _cpri__RngStartup() |
| 60 #ifdef TPM_ALG_RSA |
| 61 && _cpri__RsaStartup() |
| 62 #endif // TPM_ALG_RSA |
| 63 #ifdef TPM_ALG_ECC |
| 64 && _cpri__EccStartup() |
| 65 #endif // TPM_ALG_ECC |
| 66 && _cpri__SymStartup()); |
| 67 } |
| |
| |
| |
| |
| Page 376 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.7 CpriRNG.c |
| |
| 1 //#define __TPM_RNG_FOR_DEBUG__ |
| |
| |
| B.7.1. Introduction |
| |
| This file contains the interface to the OpenSSL() random number functions. |
| |
| B.7.2. Includes |
| |
| 2 #include "OsslCryptoEngine.h" |
| 3 int s_entropyFailure; |
| |
| |
| B.7.3. Functions |
| |
| B.7.3.1. _cpri__RngStartup() |
| |
| This function is called to initialize the random number generator. It collects entropy from the platform to |
| seed the OpenSSL() random number generator. |
| |
| 4 LIB_EXPORT BOOL |
| 5 _cpri__RngStartup(void) |
| 6 { |
| 7 UINT32 entropySize; |
| 8 BYTE entropy[MAX_RNG_ENTROPY_SIZE]; |
| 9 INT32 returnedSize = 0; |
| 10 |
| 11 // Initialize the entropy source |
| 12 s_entropyFailure = FALSE; |
| 13 _plat__GetEntropy(NULL, 0); |
| 14 |
| 15 // Collect entropy until we have enough |
| 16 for(entropySize = 0; |
| 17 entropySize < MAX_RNG_ENTROPY_SIZE && returnedSize >= 0; |
| 18 entropySize += returnedSize) |
| 19 { |
| 20 returnedSize = _plat__GetEntropy(&entropy[entropySize], |
| 21 MAX_RNG_ENTROPY_SIZE - entropySize); |
| 22 } |
| 23 // Got some entropy on the last call and did not get an error |
| 24 if(returnedSize > 0) |
| 25 { |
| 26 // Seed OpenSSL with entropy |
| 27 RAND_seed(entropy, entropySize); |
| 28 } |
| 29 else |
| 30 { |
| 31 s_entropyFailure = TRUE; |
| 32 } |
| 33 return s_entropyFailure == FALSE; |
| 34 } |
| |
| |
| B.7.3.2. _cpri__DrbgGetPutState() |
| |
| This function is used to set the state of the RNG (direction == PUT_STATE) or to recover the state of the |
| RNG (direction == GET_STATE). |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 377 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| NOTE: This not currently supported on OpenSSL() version. |
| |
| 35 LIB_EXPORT CRYPT_RESULT |
| 36 _cpri__DrbgGetPutState( |
| 37 GET_PUT direction, |
| 38 int bufferSize, |
| 39 BYTE *buffer |
| 40 ) |
| 41 { |
| 42 UNREFERENCED_PARAMETER(direction); |
| 43 UNREFERENCED_PARAMETER(bufferSize); |
| 44 UNREFERENCED_PARAMETER(buffer); |
| 45 |
| 46 return CRYPT_SUCCESS; // Function is not implemented |
| 47 } |
| |
| |
| B.7.3.3. _cpri__StirRandom() |
| |
| This function is called to add external entropy to the OpenSSL() random number generator. |
| |
| 48 LIB_EXPORT CRYPT_RESULT |
| 49 _cpri__StirRandom( |
| 50 INT32 entropySize, |
| 51 BYTE *entropy |
| 52 ) |
| 53 { |
| 54 if (entropySize >= 0) |
| 55 { |
| 56 RAND_add((const void *)entropy, (int) entropySize, 0.0); |
| 57 |
| 58 } |
| 59 return CRYPT_SUCCESS; |
| 60 } |
| |
| |
| B.7.3.4. _cpri__GenerateRandom() |
| |
| This function is called to get a string of random bytes from the OpenSSL() random number generator. The |
| return value is the number of bytes placed in the buffer. If the number of bytes returned is not equal to the |
| number of bytes requested (randomSize) it is indicative of a failure of the OpenSSL() random number |
| generator and is probably fatal. |
| |
| 61 LIB_EXPORT UINT16 |
| 62 _cpri__GenerateRandom( |
| 63 INT32 randomSize, |
| 64 BYTE *buffer |
| 65 ) |
| 66 { |
| 67 // |
| 68 // We don't do negative sizes or ones that are too large |
| 69 if (randomSize < 0 || randomSize > UINT16_MAX) |
| 70 return 0; |
| 71 // RAND_bytes uses 1 for success and we use 0 |
| 72 if(RAND_bytes(buffer, randomSize) == 1) |
| 73 return (UINT16)randomSize; |
| 74 else |
| 75 return 0; |
| 76 } |
| |
| |
| |
| |
| Page 378 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| B.7.3.4.1. _cpri__GenerateSeededRandom() |
| |
| This funciton is used to generate a pseudo-random number from some seed values This funciton returns |
| the same result each time it is called with the same parameters |
| |
| 77 LIB_EXPORT UINT16 |
| 78 _cpri__GenerateSeededRandom( |
| 79 INT32 randomSize, // IN: the size of the request |
| 80 BYTE *random, // OUT: receives the data |
| 81 TPM_ALG_ID hashAlg, // IN: used by KDF version but not here |
| 82 TPM2B *seed, // IN: the seed value |
| 83 const char *label, // IN: a label string (optional) |
| 84 TPM2B *partyU, // IN: other data (oprtional) |
| 85 TPM2B *partyV // IN: still more (optional) |
| 86 ) |
| 87 { |
| 88 |
| 89 return (_cpri__KDFa(hashAlg, seed, label, partyU, partyV, |
| 90 randomSize * 8, random, NULL, FALSE)); |
| 91 } |
| 92 #endif //% |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 379 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| B.8 CpriHash.c |
| |
| B.8.1. Description |
| |
| This file contains implementation of cryptographic functions for hashing. |
| |
| B.8.2. Includes, Defines, and Types |
| |
| 1 #include "OsslCryptoEngine.h" |
| 2 #include "CpriHashData.c" |
| 3 #define OSSL_HASH_STATE_DATA_SIZE (MAX_HASH_STATE_SIZE - 8) |
| 4 typedef struct { |
| 5 union { |
| 6 EVP_MD_CTX context; |
| 7 BYTE data[OSSL_HASH_STATE_DATA_SIZE]; |
| 8 } u; |
| 9 INT16 copySize; |
| 10 } OSSL_HASH_STATE; |
| |
| Temporary aliasing of SM3 to SHA256 until SM3 is available |
| |
| 11 #define EVP_sm3_256 EVP_sha256 |
| |
| |
| B.8.3. Static Functions |
| |
| B.8.3.1. GetHashServer() |
| |
| This function returns the address of the hash server function |
| |
| 12 static EVP_MD * |
| 13 GetHashServer( |
| 14 TPM_ALG_ID hashAlg |
| 15 ) |
| 16 { |
| 17 switch (hashAlg) |
| 18 { |
| 19 #ifdef TPM_ALG_SHA1 |
| 20 case TPM_ALG_SHA1: |
| 21 return (EVP_MD *)EVP_sha1(); |
| 22 break; |
| 23 #endif |
| 24 #ifdef TPM_ALG_SHA256 |
| 25 case TPM_ALG_SHA256: |
| 26 return (EVP_MD *)EVP_sha256(); |
| 27 break; |
| 28 #endif |
| 29 #ifdef TPM_ALG_SHA384 |
| 30 case TPM_ALG_SHA384: |
| 31 return (EVP_MD *)EVP_sha384(); |
| 32 break; |
| 33 #endif |
| 34 #ifdef TPM_ALG_SHA512 |
| 35 case TPM_ALG_SHA512: |
| 36 return (EVP_MD *)EVP_sha512(); |
| 37 break; |
| 38 #endif |
| 39 #ifdef TPM_ALG_SM3_256 |
| 40 case TPM_ALG_SM3_256: |
| 41 return (EVP_MD *)EVP_sm3_256(); |
| 42 break; |
| |
| Page 380 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 43 #endif |
| 44 case TPM_ALG_NULL: |
| 45 return NULL; |
| 46 default: |
| 47 FAIL(FATAL_ERROR_INTERNAL); |
| 48 } |
| 49 } |
| |
| |
| B.8.3.2. MarshalHashState() |
| |
| This function copies an OpenSSL() hash context into a caller provided buffer. |
| |
| Return Value Meaning |
| |
| >0 the number of bytes of buf used. |
| |
| 50 static UINT16 |
| 51 MarshalHashState( |
| 52 EVP_MD_CTX *ctxt, // IN: Context to marshal |
| 53 BYTE *buf // OUT: The buffer that will receive the |
| 54 // context. This buffer is at least |
| 55 // MAX_HASH_STATE_SIZE byte |
| 56 ) |
| 57 { |
| 58 // make sure everything will fit |
| 59 pAssert(ctxt->digest->ctx_size <= OSSL_HASH_STATE_DATA_SIZE); |
| 60 |
| 61 // Copy the context data |
| 62 memcpy(buf, (void*) ctxt->md_data, ctxt->digest->ctx_size); |
| 63 |
| 64 return (UINT16)ctxt->digest->ctx_size; |
| 65 } |
| |
| |
| B.8.3.3. GetHashState() |
| |
| This function will unmarshal a caller provided buffer into an OpenSSL() hash context. The function returns |
| the number of bytes copied (which may be zero). |
| |
| 66 static UINT16 |
| 67 GetHashState( |
| 68 EVP_MD_CTX *ctxt, // OUT: The context structure to receive the |
| 69 // result of unmarshaling. |
| 70 TPM_ALG_ID algType, // IN: The hash algorithm selector |
| 71 BYTE *buf // IN: Buffer containing marshaled hash data |
| 72 ) |
| 73 { |
| 74 EVP_MD *evpmdAlgorithm = NULL; |
| 75 |
| 76 pAssert(ctxt != NULL); |
| 77 |
| 78 EVP_MD_CTX_init(ctxt); |
| 79 |
| 80 evpmdAlgorithm = GetHashServer(algType); |
| 81 if(evpmdAlgorithm == NULL) |
| 82 return 0; |
| 83 |
| 84 // This also allocates the ctxt->md_data |
| 85 if((EVP_DigestInit_ex(ctxt, evpmdAlgorithm, NULL)) != 1) |
| 86 FAIL(FATAL_ERROR_INTERNAL); |
| 87 |
| 88 pAssert(ctxt->digest->ctx_size < sizeof(ALIGNED_HASH_STATE)); |
| 89 memcpy(ctxt->md_data, buf, ctxt->digest->ctx_size); |
| |
| |
| Family "2.0" TCG Published Page 381 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 90 return (UINT16)ctxt->digest->ctx_size; |
| 91 } |
| |
| |
| B.8.3.4. GetHashInfoPointer() |
| |
| This function returns a pointer to the hash info for the algorithm. If the algorithm is not supported, function |
| returns a pointer to the data block associated with TPM_ALG_NULL. |
| |
| 92 static const HASH_INFO * |
| 93 GetHashInfoPointer( |
| 94 TPM_ALG_ID hashAlg |
| 95 ) |
| 96 { |
| 97 UINT32 i, tableSize; |
| 98 |
| 99 // Get the table size of g_hashData |
| 100 tableSize = sizeof(g_hashData) / sizeof(g_hashData[0]); |
| 101 |
| 102 for(i = 0; i < tableSize - 1; i++) |
| 103 { |
| 104 if(g_hashData[i].alg == hashAlg) |
| 105 return &g_hashData[i]; |
| 106 } |
| 107 return &g_hashData[tableSize-1]; |
| 108 } |
| |
| |
| B.8.4. Hash Functions |
| |
| B.8.4.1. _cpri__HashStartup() |
| |
| Function that is called to initialize the hash service. In this implementation, this function does nothing but |
| it is called by the CryptUtilStartup() function and must be present. |
| |
| 109 LIB_EXPORT BOOL |
| 110 _cpri__HashStartup( |
| 111 void |
| 112 ) |
| 113 { |
| 114 // On startup, make sure that the structure sizes are compatible. It would |
| 115 // be nice if this could be done at compile time but I couldn't figure it out. |
| 116 CPRI_HASH_STATE *cpriState = NULL; |
| 117 // NUMBYTES evpCtxSize = sizeof(EVP_MD_CTX); |
| 118 NUMBYTES cpriStateSize = sizeof(cpriState->state); |
| 119 // OSSL_HASH_STATE *osslState; |
| 120 NUMBYTES osslStateSize = sizeof(OSSL_HASH_STATE); |
| 121 // int dataSize = sizeof(osslState->u.data); |
| 122 pAssert(cpriStateSize >= osslStateSize); |
| 123 |
| 124 return TRUE; |
| 125 } |
| |
| |
| B.8.4.2. _cpri__GetHashAlgByIndex() |
| |
| This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are |
| not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first |
| implemented hash and and index of 2 will return the last. All other index values will return |
| TPM_ALG_NULL. |
| |
| |
| |
| |
| Page 382 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| TPM_ALG_xxx() a hash algorithm |
| TPM_ALG_NULL this can be used as a stop value |
| |
| 126 LIB_EXPORT TPM_ALG_ID |
| 127 _cpri__GetHashAlgByIndex( |
| 128 UINT32 index // IN: the index |
| 129 ) |
| 130 { |
| 131 if(index >= HASH_COUNT) |
| 132 return TPM_ALG_NULL; |
| 133 return g_hashData[index].alg; |
| 134 } |
| |
| |
| B.8.4.3. _cpri__GetHashBlockSize() |
| |
| Returns the size of the block used for the hash |
| |
| Return Value Meaning |
| |
| <0 the algorithm is not a supported hash |
| >= the digest size (0 for TPM_ALG_NULL) |
| |
| 135 LIB_EXPORT UINT16 |
| 136 _cpri__GetHashBlockSize( |
| 137 TPM_ALG_ID hashAlg // IN: hash algorithm to look up |
| 138 ) |
| 139 { |
| 140 return GetHashInfoPointer(hashAlg)->blockSize; |
| 141 } |
| |
| |
| B.8.4.4. _cpri__GetHashDER |
| |
| This function returns a pointer to the DER string for the algorithm and indicates its size. |
| |
| 142 LIB_EXPORT UINT16 |
| 143 _cpri__GetHashDER( |
| 144 TPM_ALG_ID hashAlg, // IN: the algorithm to look up |
| 145 const BYTE **p |
| 146 ) |
| 147 { |
| 148 const HASH_INFO *q; |
| 149 q = GetHashInfoPointer(hashAlg); |
| 150 *p = &q->der[0]; |
| 151 return q->derSize; |
| 152 } |
| |
| |
| B.8.4.5. _cpri__GetDigestSize() |
| |
| Gets the digest size of the algorithm. The algorithm is required to be supported. |
| |
| Return Value Meaning |
| |
| =0 the digest size for TPM_ALG_NULL |
| >0 the digest size of a hash algorithm |
| |
| 153 LIB_EXPORT UINT16 |
| |
| Family "2.0" TCG Published Page 383 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 154 _cpri__GetDigestSize( |
| 155 TPM_ALG_ID hashAlg // IN: hash algorithm to look up |
| 156 ) |
| 157 { |
| 158 return GetHashInfoPointer(hashAlg)->digestSize; |
| 159 } |
| |
| |
| B.8.4.6. _cpri__GetContextAlg() |
| |
| This function returns the algorithm associated with a hash context |
| |
| 160 LIB_EXPORT TPM_ALG_ID |
| 161 _cpri__GetContextAlg( |
| 162 CPRI_HASH_STATE *hashState // IN: the hash context |
| 163 ) |
| 164 { |
| 165 return hashState->hashAlg; |
| 166 } |
| |
| |
| B.8.4.7. _cpri__CopyHashState |
| |
| This function is used to clone a CPRI_HASH_STATE. The return value is the size of the state. |
| |
| 167 LIB_EXPORT UINT16 |
| 168 _cpri__CopyHashState ( |
| 169 CPRI_HASH_STATE *out, // OUT: destination of the state |
| 170 CPRI_HASH_STATE *in // IN: source of the state |
| 171 ) |
| 172 { |
| 173 OSSL_HASH_STATE *i = (OSSL_HASH_STATE *)&in->state; |
| 174 OSSL_HASH_STATE *o = (OSSL_HASH_STATE *)&out->state; |
| 175 pAssert(sizeof(i) <= sizeof(in->state)); |
| 176 |
| 177 EVP_MD_CTX_init(&o->u.context); |
| 178 EVP_MD_CTX_copy_ex(&o->u.context, &i->u.context); |
| 179 o->copySize = i->copySize; |
| 180 out->hashAlg = in->hashAlg; |
| 181 return sizeof(CPRI_HASH_STATE); |
| 182 } |
| |
| |
| B.8.4.8. _cpri__StartHash() |
| |
| Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, the value of |
| stateSize in hashState is updated to indicate the number of bytes of state that were saved. This function |
| calls GetHashServer() and that function will put the TPM into failure mode if the hash algorithm is not |
| supported. |
| |
| Return Value Meaning |
| |
| 0 hash is TPM_ALG_NULL |
| >0 digest size |
| |
| 183 LIB_EXPORT UINT16 |
| 184 _cpri__StartHash( |
| 185 TPM_ALG_ID hashAlg, // IN: hash algorithm |
| 186 BOOL sequence, // IN: TRUE if the state should be saved |
| 187 CPRI_HASH_STATE *hashState // OUT: the state of hash stack. |
| 188 ) |
| 189 { |
| 190 EVP_MD_CTX localState; |
| |
| Page 384 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 191 OSSL_HASH_STATE *state = (OSSL_HASH_STATE *)&hashState->state; |
| 192 BYTE *stateData = state->u.data; |
| 193 EVP_MD_CTX *context; |
| 194 EVP_MD *evpmdAlgorithm = NULL; |
| 195 UINT16 retVal = 0; |
| 196 |
| 197 if(sequence) |
| 198 context = &localState; |
| 199 else |
| 200 context = &state->u.context; |
| 201 |
| 202 hashState->hashAlg = hashAlg; |
| 203 |
| 204 EVP_MD_CTX_init(context); |
| 205 evpmdAlgorithm = GetHashServer(hashAlg); |
| 206 if(evpmdAlgorithm == NULL) |
| 207 goto Cleanup; |
| 208 |
| 209 if(EVP_DigestInit_ex(context, evpmdAlgorithm, NULL) != 1) |
| 210 FAIL(FATAL_ERROR_INTERNAL); |
| 211 retVal = (CRYPT_RESULT)EVP_MD_CTX_size(context); |
| 212 |
| 213 Cleanup: |
| 214 if(retVal > 0) |
| 215 { |
| 216 if (sequence) |
| 217 { |
| 218 if((state->copySize = MarshalHashState(context, stateData)) == 0) |
| 219 { |
| 220 // If MarshalHashState returns a negative number, it is an error |
| 221 // code and not a hash size so copy the error code to be the return |
| 222 // from this function and set the actual stateSize to zero. |
| 223 retVal = state->copySize; |
| 224 state->copySize = 0; |
| 225 } |
| 226 // Do the cleanup |
| 227 EVP_MD_CTX_cleanup(context); |
| 228 } |
| 229 else |
| 230 state->copySize = -1; |
| 231 } |
| 232 else |
| 233 state->copySize = 0; |
| 234 return retVal; |
| 235 } |
| |
| |
| B.8.4.9. _cpri__UpdateHash() |
| |
| Add data to a hash or HMAC stack. |
| |
| 236 LIB_EXPORT void |
| 237 _cpri__UpdateHash( |
| 238 CPRI_HASH_STATE *hashState, // IN: the hash context information |
| 239 UINT32 dataSize, // IN: the size of data to be added to the |
| 240 // digest |
| 241 BYTE *data // IN: data to be hashed |
| 242 ) |
| 243 { |
| 244 EVP_MD_CTX localContext; |
| 245 OSSL_HASH_STATE *state = (OSSL_HASH_STATE *)&hashState->state; |
| 246 BYTE *stateData = state->u.data; |
| 247 EVP_MD_CTX *context; |
| 248 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 249 |
| |
| |
| Family "2.0" TCG Published Page 385 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 250 // If there is no context, return |
| 251 if(state->copySize == 0) |
| 252 return; |
| 253 if(state->copySize > 0) |
| 254 { |
| 255 context = &localContext; |
| 256 if((retVal = GetHashState(context, hashState->hashAlg, stateData)) <= 0) |
| 257 return; |
| 258 } |
| 259 else |
| 260 context = &state->u.context; |
| 261 |
| 262 if(EVP_DigestUpdate(context, data, dataSize) != 1) |
| 263 FAIL(FATAL_ERROR_INTERNAL); |
| 264 else if( state->copySize > 0 |
| 265 && (retVal= MarshalHashState(context, stateData)) >= 0) |
| 266 { |
| 267 // retVal is the size of the marshaled data. Make sure that it is consistent |
| 268 // by ensuring that we didn't get more than allowed |
| 269 if(retVal < state->copySize) |
| 270 FAIL(FATAL_ERROR_INTERNAL); |
| 271 else |
| 272 EVP_MD_CTX_cleanup(context); |
| 273 } |
| 274 return; |
| 275 } |
| |
| |
| B.8.4.10. _cpri__CompleteHash() |
| |
| Complete a hash or HMAC computation. This function will place the smaller of digestSize or the size of |
| the digest in dOut. The number of bytes in the placed in the buffer is returned. If there is a failure, the |
| returned value is <= 0. |
| |
| Return Value Meaning |
| |
| 0 no data returned |
| >0 the number of bytes in the digest |
| |
| 276 LIB_EXPORT UINT16 |
| 277 _cpri__CompleteHash( |
| 278 CPRI_HASH_STATE *hashState, // IN: the state of hash stack |
| 279 UINT32 dOutSize, // IN: size of digest buffer |
| 280 BYTE *dOut // OUT: hash digest |
| 281 ) |
| 282 { |
| 283 EVP_MD_CTX localState; |
| 284 OSSL_HASH_STATE *state = (OSSL_HASH_STATE *)&hashState->state; |
| 285 BYTE *stateData = state->u.data; |
| 286 EVP_MD_CTX *context; |
| 287 UINT16 retVal; |
| 288 int hLen; |
| 289 BYTE temp[MAX_DIGEST_SIZE]; |
| 290 BYTE *rBuffer = dOut; |
| 291 |
| 292 if(state->copySize == 0) |
| 293 return 0; |
| 294 if(state->copySize > 0) |
| 295 { |
| 296 context = &localState; |
| 297 if((retVal = GetHashState(context, hashState->hashAlg, stateData)) <= 0) |
| 298 goto Cleanup; |
| 299 } |
| 300 else |
| |
| Page 386 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 301 context = &state->u.context; |
| 302 |
| 303 hLen = EVP_MD_CTX_size(context); |
| 304 if((unsigned)hLen > dOutSize) |
| 305 rBuffer = temp; |
| 306 if(EVP_DigestFinal_ex(context, rBuffer, NULL) == 1) |
| 307 { |
| 308 if(rBuffer != dOut) |
| 309 { |
| 310 if(dOut != NULL) |
| 311 { |
| 312 memcpy(dOut, temp, dOutSize); |
| 313 } |
| 314 retVal = (UINT16)dOutSize; |
| 315 } |
| 316 else |
| 317 { |
| 318 retVal = (UINT16)hLen; |
| 319 } |
| 320 state->copySize = 0; |
| 321 } |
| 322 else |
| 323 { |
| 324 retVal = 0; // Indicate that no data is returned |
| 325 } |
| 326 Cleanup: |
| 327 EVP_MD_CTX_cleanup(context); |
| 328 return retVal; |
| 329 } |
| |
| |
| B.8.4.11. _cpri__ImportExportHashState() |
| |
| This function is used to import or export the hash state. This function would be called to export state when |
| a sequence object was being prepared for export |
| |
| 330 LIB_EXPORT void |
| 331 _cpri__ImportExportHashState( |
| 332 CPRI_HASH_STATE *osslFmt, // IN/OUT: the hash state formated for use |
| 333 // by openSSL |
| 334 EXPORT_HASH_STATE *externalFmt, // IN/OUT: the exported hash state |
| 335 IMPORT_EXPORT direction // |
| 336 ) |
| 337 { |
| 338 UNREFERENCED_PARAMETER(direction); |
| 339 UNREFERENCED_PARAMETER(externalFmt); |
| 340 UNREFERENCED_PARAMETER(osslFmt); |
| 341 return; |
| 342 |
| 343 #if 0 |
| 344 if(direction == IMPORT_STATE) |
| 345 { |
| 346 // don't have the import export functions yet so just copy |
| 347 _cpri__CopyHashState(osslFmt, (CPRI_HASH_STATE *)externalFmt); |
| 348 } |
| 349 else |
| 350 { |
| 351 _cpri__CopyHashState((CPRI_HASH_STATE *)externalFmt, osslFmt); |
| 352 } |
| 353 #endif |
| 354 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 387 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.8.4.12. _cpri__HashBlock() |
| |
| Start a hash, hash a single block, update digest and return the size of the results. |
| The digestSize parameter can be smaller than the digest. If so, only the more significant bytes are |
| returned. |
| |
| Return Value Meaning |
| |
| >= 0 number of bytes in digest (may be zero) |
| |
| 355 LIB_EXPORT UINT16 |
| 356 _cpri__HashBlock( |
| 357 TPM_ALG_ID hashAlg, // IN: The hash algorithm |
| 358 UINT32 dataSize, // IN: size of buffer to hash |
| 359 BYTE *data, // IN: the buffer to hash |
| 360 UINT32 digestSize, // IN: size of the digest buffer |
| 361 BYTE *digest // OUT: hash digest |
| 362 ) |
| 363 { |
| 364 EVP_MD_CTX hashContext; |
| 365 EVP_MD *hashServer = NULL; |
| 366 UINT16 retVal = 0; |
| 367 BYTE b[MAX_DIGEST_SIZE]; // temp buffer in case digestSize not |
| 368 // a full digest |
| 369 unsigned int dSize = _cpri__GetDigestSize(hashAlg); |
| 370 |
| 371 // If there is no digest to compute return |
| 372 if(dSize == 0) |
| 373 return 0; |
| 374 |
| 375 // After the call to EVP_MD_CTX_init(), will need to call EVP_MD_CTX_cleanup() |
| 376 EVP_MD_CTX_init(&hashContext); // Initialize the local hash context |
| 377 hashServer = GetHashServer(hashAlg); // Find the hash server |
| 378 |
| 379 // It is an error if the digest size is non-zero but there is no server |
| 380 if( (hashServer == NULL) |
| 381 || (EVP_DigestInit_ex(&hashContext, hashServer, NULL) != 1) |
| 382 || (EVP_DigestUpdate(&hashContext, data, dataSize) != 1)) |
| 383 FAIL(FATAL_ERROR_INTERNAL); |
| 384 else |
| 385 { |
| 386 // If the size of the digest produced (dSize) is larger than the available |
| 387 // buffer (digestSize), then put the digest in a temp buffer and only copy |
| 388 // the most significant part into the available buffer. |
| 389 if(dSize > digestSize) |
| 390 { |
| 391 if(EVP_DigestFinal_ex(&hashContext, b, &dSize) != 1) |
| 392 FAIL(FATAL_ERROR_INTERNAL); |
| 393 memcpy(digest, b, digestSize); |
| 394 retVal = (UINT16)digestSize; |
| 395 } |
| 396 else |
| 397 { |
| 398 if((EVP_DigestFinal_ex(&hashContext, digest, &dSize)) != 1) |
| 399 FAIL(FATAL_ERROR_INTERNAL); |
| 400 retVal = (UINT16) dSize; |
| 401 } |
| 402 } |
| 403 EVP_MD_CTX_cleanup(&hashContext); |
| 404 return retVal; |
| 405 } |
| |
| |
| |
| |
| Page 388 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| B.8.5. HMAC Functions |
| |
| B.8.5.1. _cpri__StartHMAC |
| |
| This function is used to start an HMAC using a temp hash context. The function does the initialization of |
| the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. |
| The function returns the number of bytes in a digest produced by hashAlg. |
| |
| Return Value Meaning |
| |
| >= 0 number of bytes in digest produced by hashAlg (may be zero) |
| |
| 406 LIB_EXPORT UINT16 |
| 407 _cpri__StartHMAC( |
| 408 TPM_ALG_ID hashAlg, // IN: the algorithm to use |
| 409 BOOL sequence, // IN: indicates if the state should be |
| 410 // saved |
| 411 CPRI_HASH_STATE *state, // IN/OUT: the state buffer |
| 412 UINT16 keySize, // IN: the size of the HMAC key |
| 413 BYTE *key, // IN: the HMAC key |
| 414 TPM2B *oPadKey // OUT: the key prepared for the oPad round |
| 415 ) |
| 416 { |
| 417 CPRI_HASH_STATE localState; |
| 418 UINT16 blockSize = _cpri__GetHashBlockSize(hashAlg); |
| 419 UINT16 digestSize; |
| 420 BYTE *pb; // temp pointer |
| 421 UINT32 i; |
| 422 |
| 423 // If the key size is larger than the block size, then the hash of the key |
| 424 // is used as the key |
| 425 if(keySize > blockSize) |
| 426 { |
| 427 // large key so digest |
| 428 if((digestSize = _cpri__StartHash(hashAlg, FALSE, &localState)) == 0) |
| 429 return 0; |
| 430 _cpri__UpdateHash(&localState, keySize, key); |
| 431 _cpri__CompleteHash(&localState, digestSize, oPadKey->buffer); |
| 432 oPadKey->size = digestSize; |
| 433 } |
| 434 else |
| 435 { |
| 436 // key size is ok |
| 437 memcpy(oPadKey->buffer, key, keySize); |
| 438 oPadKey->size = keySize; |
| 439 } |
| 440 // XOR the key with iPad (0x36) |
| 441 pb = oPadKey->buffer; |
| 442 for(i = oPadKey->size; i > 0; i--) |
| 443 *pb++ ^= 0x36; |
| 444 |
| 445 // if the keySize is smaller than a block, fill the rest with 0x36 |
| 446 for(i = blockSize - oPadKey->size; i > 0; i--) |
| 447 *pb++ = 0x36; |
| 448 |
| 449 // Increase the oPadSize to a full block |
| 450 oPadKey->size = blockSize; |
| 451 |
| 452 // Start a new hash with the HMAC key |
| 453 // This will go in the caller's state structure and may be a sequence or not |
| 454 |
| 455 if((digestSize = _cpri__StartHash(hashAlg, sequence, state)) > 0) |
| 456 { |
| |
| Family "2.0" TCG Published Page 389 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 457 |
| 458 _cpri__UpdateHash(state, oPadKey->size, oPadKey->buffer); |
| 459 |
| 460 // XOR the key block with 0x5c ^ 0x36 |
| 461 for(pb = oPadKey->buffer, i = blockSize; i > 0; i--) |
| 462 *pb++ ^= (0x5c ^ 0x36); |
| 463 } |
| 464 |
| 465 return digestSize; |
| 466 } |
| |
| |
| B.8.5.2. _cpri_CompleteHMAC() |
| |
| This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will |
| then add the oPadKey and the completed digest and return the results in dOut. It will not return more than |
| dOutSize bytes. |
| |
| Return Value Meaning |
| |
| >= 0 number of bytes in dOut (may be zero) |
| |
| 467 LIB_EXPORT UINT16 |
| 468 _cpri__CompleteHMAC( |
| 469 CPRI_HASH_STATE *hashState, // IN: the state of hash stack |
| 470 TPM2B *oPadKey, // IN: the HMAC key in oPad format |
| 471 UINT32 dOutSize, // IN: size of digest buffer |
| 472 BYTE *dOut // OUT: hash digest |
| 473 ) |
| 474 { |
| 475 BYTE digest[MAX_DIGEST_SIZE]; |
| 476 CPRI_HASH_STATE *state = (CPRI_HASH_STATE *)hashState; |
| 477 CPRI_HASH_STATE localState; |
| 478 UINT16 digestSize = _cpri__GetDigestSize(state->hashAlg); |
| 479 |
| 480 _cpri__CompleteHash(hashState, digestSize, digest); |
| 481 |
| 482 // Using the local hash state, do a hash with the oPad |
| 483 if(_cpri__StartHash(state->hashAlg, FALSE, &localState) != digestSize) |
| 484 return 0; |
| 485 |
| 486 _cpri__UpdateHash(&localState, oPadKey->size, oPadKey->buffer); |
| 487 _cpri__UpdateHash(&localState, digestSize, digest); |
| 488 return _cpri__CompleteHash(&localState, dOutSize, dOut); |
| 489 } |
| |
| |
| B.8.6. Mask and Key Generation Functions |
| |
| B.8.6.1. _crypi_MGF1() |
| |
| This function performs MGF1 using the selected hash. MGF1 is T(n) = T(n-1) || H(seed || counter). This |
| function returns the length of the mask produced which could be zero if the digest algorithm is not |
| supported |
| |
| Return Value Meaning |
| |
| 0 hash algorithm not supported |
| >0 should be the same as mSize |
| |
| 490 LIB_EXPORT CRYPT_RESULT |
| 491 _cpri__MGF1( |
| |
| Page 390 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 492 UINT32 mSize, // IN: length of the mask to be produced |
| 493 BYTE *mask, // OUT: buffer to receive the mask |
| 494 TPM_ALG_ID hashAlg, // IN: hash to use |
| 495 UINT32 sSize, // IN: size of the seed |
| 496 BYTE *seed // IN: seed size |
| 497 ) |
| 498 { |
| 499 EVP_MD_CTX hashContext; |
| 500 EVP_MD *hashServer = NULL; |
| 501 CRYPT_RESULT retVal = 0; |
| 502 BYTE b[MAX_DIGEST_SIZE]; // temp buffer in case mask is not an |
| 503 // even multiple of a full digest |
| 504 CRYPT_RESULT dSize = _cpri__GetDigestSize(hashAlg); |
| 505 unsigned int digestSize = (UINT32)dSize; |
| 506 UINT32 remaining; |
| 507 UINT32 counter; |
| 508 BYTE swappedCounter[4]; |
| 509 |
| 510 // Parameter check |
| 511 if(mSize > (1024*16)) // Semi-arbitrary maximum |
| 512 FAIL(FATAL_ERROR_INTERNAL); |
| 513 |
| 514 // If there is no digest to compute return |
| 515 if(dSize <= 0) |
| 516 return 0; |
| 517 |
| 518 EVP_MD_CTX_init(&hashContext); // Initialize the local hash context |
| 519 hashServer = GetHashServer(hashAlg); // Find the hash server |
| 520 if(hashServer == NULL) |
| 521 // If there is no server, then there is no digest |
| 522 return 0; |
| 523 |
| 524 for(counter = 0, remaining = mSize; remaining > 0; counter++) |
| 525 { |
| 526 // Because the system may be either Endian... |
| 527 UINT32_TO_BYTE_ARRAY(counter, swappedCounter); |
| 528 |
| 529 // Start the hash and include the seed and counter |
| 530 if( (EVP_DigestInit_ex(&hashContext, hashServer, NULL) != 1) |
| 531 || (EVP_DigestUpdate(&hashContext, seed, sSize) != 1) |
| 532 || (EVP_DigestUpdate(&hashContext, swappedCounter, 4) != 1) |
| 533 ) |
| 534 FAIL(FATAL_ERROR_INTERNAL); |
| 535 |
| 536 // Handling the completion depends on how much space remains in the mask |
| 537 // buffer. If it can hold the entire digest, put it there. If not |
| 538 // put the digest in a temp buffer and only copy the amount that |
| 539 // will fit into the mask buffer. |
| 540 if(remaining < (unsigned)dSize) |
| 541 { |
| 542 if(EVP_DigestFinal_ex(&hashContext, b, &digestSize) != 1) |
| 543 FAIL(FATAL_ERROR_INTERNAL); |
| 544 memcpy(mask, b, remaining); |
| 545 break; |
| 546 } |
| 547 else |
| 548 { |
| 549 if(EVP_DigestFinal_ex(&hashContext, mask, &digestSize) != 1) |
| 550 FAIL(FATAL_ERROR_INTERNAL); |
| 551 remaining -= dSize; |
| 552 mask = &mask[dSize]; |
| 553 } |
| 554 retVal = (CRYPT_RESULT)mSize; |
| 555 } |
| 556 |
| 557 EVP_MD_CTX_cleanup(&hashContext); |
| |
| Family "2.0" TCG Published Page 391 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 558 return retVal; |
| 559 } |
| |
| |
| B.8.6.2. _cpri_KDFa() |
| |
| This function performs the key generation according to Part 1 of the TPM specification. |
| This function returns the number of bytes generated which may be zero. |
| The key and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. |
| The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). |
| The once parameter is set to allow incremental generation of a large value. If this flag is TRUE, |
| sizeInBits will be used in the HMAC computation but only one iteration of the KDF is performed. This |
| would be used for XOR obfuscation so that the mask value can be generated in digest-sized chunks |
| rather than having to be generated all at once in an arbitrarily large buffer and then XORed() into the |
| result. If once is TRUE, then sizeInBits must be a multiple of 8. |
| Any error in the processing of this command is considered fatal. |
| |
| Return Value Meaning |
| |
| 0 hash algorithm is not supported or is TPM_ALG_NULL |
| >0 the number of bytes in the keyStream buffer |
| |
| 560 LIB_EXPORT UINT16 |
| 561 _cpri__KDFa( |
| 562 TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC |
| 563 TPM2B *key, // IN: HMAC key |
| 564 const char *label, // IN: a 0-byte terminated label used in KDF |
| 565 TPM2B *contextU, // IN: context U |
| 566 TPM2B *contextV, // IN: context V |
| 567 UINT32 sizeInBits, // IN: size of generated key in bit |
| 568 BYTE *keyStream, // OUT: key buffer |
| 569 UINT32 *counterInOut, // IN/OUT: caller may provide the iteration |
| 570 // counter for incremental operations to |
| 571 // avoid large intermediate buffers. |
| 572 BOOL once // IN: TRUE if only one iteration is performed |
| 573 // FALSE if iteration count determined by |
| 574 // "sizeInBits" |
| 575 ) |
| 576 { |
| 577 UINT32 counter = 0; // counter value |
| 578 INT32 lLen = 0; // length of the label |
| 579 INT16 hLen; // length of the hash |
| 580 INT16 bytes; // number of bytes to produce |
| 581 BYTE *stream = keyStream; |
| 582 BYTE marshaledUint32[4]; |
| 583 CPRI_HASH_STATE hashState; |
| 584 TPM2B_MAX_HASH_BLOCK hmacKey; |
| 585 |
| 586 pAssert(key != NULL && keyStream != NULL); |
| 587 pAssert(once == FALSE || (sizeInBits & 7) == 0); |
| 588 |
| 589 if(counterInOut != NULL) |
| 590 counter = *counterInOut; |
| 591 |
| 592 // Prepare label buffer. Calculate its size and keep the last 0 byte |
| 593 if(label != NULL) |
| 594 for(lLen = 0; label[lLen++] != 0; ); |
| 595 |
| 596 // Get the hash size. If it is less than or 0, either the |
| 597 // algorithm is not supported or the hash is TPM_ALG_NULL |
| |
| |
| Page 392 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 598 // In either case the digest size is zero. This is the only return |
| 599 // other than the one at the end. All other exits from this function |
| 600 // are fatal errors. After we check that the algorithm is supported |
| 601 // anything else that goes wrong is an implementation flaw. |
| 602 if((hLen = (INT16) _cpri__GetDigestSize(hashAlg)) == 0) |
| 603 return 0; |
| 604 |
| 605 // If the size of the request is larger than the numbers will handle, |
| 606 // it is a fatal error. |
| 607 pAssert(((sizeInBits + 7)/ 8) <= INT16_MAX); |
| 608 |
| 609 bytes = once ? hLen : (INT16)((sizeInBits + 7) / 8); |
| 610 |
| 611 // Generate required bytes |
| 612 for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) |
| 613 { |
| 614 if(bytes < hLen) |
| 615 hLen = bytes; |
| 616 |
| 617 counter++; |
| 618 // Start HMAC |
| 619 if(_cpri__StartHMAC(hashAlg, |
| 620 FALSE, |
| 621 &hashState, |
| 622 key->size, |
| 623 &key->buffer[0], |
| 624 &hmacKey.b) <= 0) |
| 625 FAIL(FATAL_ERROR_INTERNAL); |
| 626 |
| 627 // Adding counter |
| 628 UINT32_TO_BYTE_ARRAY(counter, marshaledUint32); |
| 629 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); |
| 630 |
| 631 // Adding label |
| 632 if(label != NULL) |
| 633 _cpri__UpdateHash(&hashState, lLen, (BYTE *)label); |
| 634 |
| 635 // Adding contextU |
| 636 if(contextU != NULL) |
| 637 _cpri__UpdateHash(&hashState, contextU->size, contextU->buffer); |
| 638 |
| 639 // Adding contextV |
| 640 if(contextV != NULL) |
| 641 _cpri__UpdateHash(&hashState, contextV->size, contextV->buffer); |
| 642 |
| 643 // Adding size in bits |
| 644 UINT32_TO_BYTE_ARRAY(sizeInBits, marshaledUint32); |
| 645 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); |
| 646 |
| 647 // Compute HMAC. At the start of each iteration, hLen is set |
| 648 // to the smaller of hLen and bytes. This causes bytes to decrement |
| 649 // exactly to zero to complete the loop |
| 650 _cpri__CompleteHMAC(&hashState, &hmacKey.b, hLen, stream); |
| 651 } |
| 652 |
| 653 // Mask off bits if the required bits is not a multiple of byte size |
| 654 if((sizeInBits % 8) != 0) |
| 655 keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); |
| 656 if(counterInOut != NULL) |
| 657 *counterInOut = counter; |
| 658 return (CRYPT_RESULT)((sizeInBits + 7)/8); |
| 659 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 393 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| B.8.6.3. _cpri__KDFe() |
| |
| KDFe() as defined in TPM specification part 1. |
| This function returns the number of bytes generated which may be zero. |
| The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. The |
| value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any error in the processing |
| of this command is considered fatal. |
| |
| Return Value Meaning |
| |
| 0 hash algorithm is not supported or is TPM_ALG_NULL |
| >0 the number of bytes in the keyStream buffer |
| |
| 660 LIB_EXPORT UINT16 |
| 661 _cpri__KDFe( |
| 662 TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC |
| 663 TPM2B *Z, // IN: Z |
| 664 const char *label, // IN: a 0 terminated label using in KDF |
| 665 TPM2B *partyUInfo, // IN: PartyUInfo |
| 666 TPM2B *partyVInfo, // IN: PartyVInfo |
| 667 UINT32 sizeInBits, // IN: size of generated key in bit |
| 668 BYTE *keyStream // OUT: key buffer |
| 669 ) |
| 670 { |
| 671 UINT32 counter = 0; // counter value |
| 672 UINT32 lSize = 0; |
| 673 BYTE *stream = keyStream; |
| 674 CPRI_HASH_STATE hashState; |
| 675 INT16 hLen = (INT16) _cpri__GetDigestSize(hashAlg); |
| 676 INT16 bytes; // number of bytes to generate |
| 677 BYTE marshaledUint32[4]; |
| 678 |
| 679 pAssert( keyStream != NULL |
| 680 && Z != NULL |
| 681 && ((sizeInBits + 7) / 8) < INT16_MAX); |
| 682 |
| 683 if(hLen == 0) |
| 684 return 0; |
| 685 |
| 686 bytes = (INT16)((sizeInBits + 7) / 8); |
| 687 |
| 688 // Prepare label buffer. Calculate its size and keep the last 0 byte |
| 689 if(label != NULL) |
| 690 for(lSize = 0; label[lSize++] != 0;); |
| 691 |
| 692 // Generate required bytes |
| 693 //The inner loop of that KDF uses: |
| 694 // Hashi := H(counter | Z | OtherInfo) (5) |
| 695 // Where: |
| 696 // Hashi the hash generated on the i-th iteration of the loop. |
| 697 // H() an approved hash function |
| 698 // counter a 32-bit counter that is initialized to 1 and incremented |
| 699 // on each iteration |
| 700 // Z the X coordinate of the product of a public ECC key and a |
| 701 // different private ECC key. |
| 702 // OtherInfo a collection of qualifying data for the KDF defined below. |
| 703 // In this specification, OtherInfo will be constructed by: |
| 704 // OtherInfo := Use | PartyUInfo | PartyVInfo |
| 705 for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) |
| 706 { |
| 707 if(bytes < hLen) |
| 708 hLen = bytes; |
| |
| |
| Page 394 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 709 |
| 710 counter++; |
| 711 // Start hash |
| 712 if(_cpri__StartHash(hashAlg, FALSE, &hashState) == 0) |
| 713 return 0; |
| 714 |
| 715 // Add counter |
| 716 UINT32_TO_BYTE_ARRAY(counter, marshaledUint32); |
| 717 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); |
| 718 |
| 719 // Add Z |
| 720 if(Z != NULL) |
| 721 _cpri__UpdateHash(&hashState, Z->size, Z->buffer); |
| 722 |
| 723 // Add label |
| 724 if(label != NULL) |
| 725 _cpri__UpdateHash(&hashState, lSize, (BYTE *)label); |
| 726 else |
| 727 |
| 728 // The SP800-108 specification requires a zero between the label |
| 729 // and the context. |
| 730 _cpri__UpdateHash(&hashState, 1, (BYTE *)""); |
| 731 |
| 732 // Add PartyUInfo |
| 733 if(partyUInfo != NULL) |
| 734 _cpri__UpdateHash(&hashState, partyUInfo->size, partyUInfo->buffer); |
| 735 |
| 736 // Add PartyVInfo |
| 737 if(partyVInfo != NULL) |
| 738 _cpri__UpdateHash(&hashState, partyVInfo->size, partyVInfo->buffer); |
| 739 |
| 740 // Compute Hash. hLen was changed to be the smaller of bytes or hLen |
| 741 // at the start of each iteration. |
| 742 _cpri__CompleteHash(&hashState, hLen, stream); |
| 743 } |
| 744 |
| 745 // Mask off bits if the required bits is not a multiple of byte size |
| 746 if((sizeInBits % 8) != 0) |
| 747 keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); |
| 748 |
| 749 return (CRYPT_RESULT)((sizeInBits + 7) / 8); |
| 750 |
| 751 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 395 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| B.9 CpriHashData.c |
| |
| This file should be included by the library hash module. |
| |
| 1 const HASH_INFO g_hashData[HASH_COUNT + 1] = { |
| 2 #ifdef TPM_ALG_SHA1 |
| 3 {TPM_ALG_SHA1, SHA1_DIGEST_SIZE, SHA1_BLOCK_SIZE, |
| 4 SHA1_DER_SIZE, SHA1_DER}, |
| 5 #endif |
| 6 #ifdef TPM_ALG_SHA256 |
| 7 {TPM_ALG_SHA256, SHA256_DIGEST_SIZE, SHA256_BLOCK_SIZE, |
| 8 SHA256_DER_SIZE, SHA256_DER}, |
| 9 #endif |
| 10 #ifdef TPM_ALG_SHA384 |
| 11 {TPM_ALG_SHA384, SHA384_DIGEST_SIZE, SHA384_BLOCK_SIZE, |
| 12 SHA384_DER_SIZE, SHA384_DER}, |
| 13 #endif |
| 14 #ifdef TPM_ALG_SM3_256 |
| 15 {TPM_ALG_SM3_256, SM3_256_DIGEST_SIZE, SM3_256_BLOCK_SIZE, |
| 16 SM3_256_DER_SIZE, SM3_256_DER}, |
| 17 #endif |
| 18 #ifdef TPM_ALG_SHA512 |
| 19 {TPM_ALG_SHA512, SHA512_DIGEST_SIZE, SHA512_BLOCK_SIZE, |
| 20 SHA512_DER_SIZE, SHA512_DER}, |
| 21 #endif |
| 22 {TPM_ALG_NULL,0,0,0,{0}} |
| 23 }; |
| |
| |
| |
| |
| Page 396 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.10 CpriMisc.c |
| |
| B.10.1. Includes |
| |
| 1 #include "OsslCryptoEngine.h" |
| |
| |
| B.10.2. Functions |
| |
| B.10.2.1. BnTo2B() |
| |
| This function is used to convert a BigNum() to a byte array of the specified size. If the number is too large |
| to fit, then 0 is returned. Otherwise, the number is converted into the low-order bytes of the provided array |
| and the upper bytes are set to zero. |
| |
| Return Value Meaning |
| |
| 0 failure (probably fatal) |
| 1 conversion successful |
| |
| 2 BOOL |
| 3 BnTo2B( |
| 4 TPM2B *outVal, // OUT: place for the result |
| 5 BIGNUM *inVal, // IN: number to convert |
| 6 UINT16 size // IN: size of the output. |
| 7 ) |
| 8 { |
| 9 BYTE *pb = outVal->buffer; |
| 10 |
| 11 outVal->size = size; |
| 12 |
| 13 size = size - (((UINT16) BN_num_bits(inVal) + 7) / 8); |
| 14 if(size < 0) |
| 15 return FALSE; |
| 16 for(;size > 0; size--) |
| 17 *pb++ = 0; |
| 18 BN_bn2bin(inVal, pb); |
| 19 return TRUE; |
| 20 } |
| |
| |
| B.10.2.2. Copy2B() |
| |
| This function copies a TPM2B structure. The compiler can't generate a copy of a TPM2B generic |
| structure because the actual size is not known. This function performs the copy on any TPM2B pair. The |
| size of the destination should have been checked before this call to make sure that it will hold the TPM2B |
| being copied. |
| This replicates the functionality in the MemoryLib.c. |
| |
| 21 void |
| 22 Copy2B( |
| 23 TPM2B *out, // OUT: The TPM2B to receive the copy |
| 24 TPM2B *in // IN: the TPM2B to copy |
| 25 ) |
| 26 { |
| 27 BYTE *pIn = in->buffer; |
| 28 BYTE *pOut = out->buffer; |
| 29 int count; |
| 30 out->size = in->size; |
| 31 for(count = in->size; count > 0; count--) |
| |
| Family "2.0" TCG Published Page 397 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 32 *pOut++ = *pIn++; |
| 33 return; |
| 34 } |
| |
| |
| B.10.2.3. BnFrom2B() |
| |
| This function creates a BIGNUM from a TPM2B and fails if the conversion fails. |
| |
| 35 BIGNUM * |
| 36 BnFrom2B( |
| 37 BIGNUM *out, // OUT: The BIGNUM |
| 38 const TPM2B *in // IN: the TPM2B to copy |
| 39 ) |
| 40 { |
| 41 if(BN_bin2bn(in->buffer, in->size, out) == NULL) |
| 42 FAIL(FATAL_ERROR_INTERNAL); |
| 43 return out; |
| 44 } |
| |
| |
| |
| |
| Page 398 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.11 CpriSym.c |
| |
| B.11.1. Introduction |
| |
| This file contains the implementation of the symmetric block cipher modes allowed for a TPM. These |
| function only use the single block encryption and decryption functions of OpesnSSL(). |
| Currently, this module only supports AES encryption. The SM4 code actually calls an AES routine |
| |
| B.11.2. Includes, Defines, and Typedefs |
| |
| 1 #include "OsslCryptoEngine.h" |
| |
| The following sets of defines are used to allow use of the SM4 algorithm identifier while waiting for the |
| SM4 implementation code to appear. |
| |
| 2 typedef AES_KEY SM4_KEY; |
| 3 #define SM4_set_encrypt_key AES_set_encrypt_key |
| 4 #define SM4_set_decrypt_key AES_set_decrypt_key |
| 5 #define SM4_decrypt AES_decrypt |
| 6 #define SM4_encrypt AES_encrypt |
| |
| |
| B.11.3. Utility Functions |
| |
| B.11.3.1. _cpri_SymStartup() |
| |
| 7 LIB_EXPORT BOOL |
| 8 _cpri__SymStartup( |
| 9 void |
| 10 ) |
| 11 { |
| 12 return TRUE; |
| 13 } |
| |
| |
| B.11.3.2. _cpri__GetSymmetricBlockSize() |
| |
| This function returns the block size of the algorithm. |
| |
| Return Value Meaning |
| |
| <= 0 cipher not supported |
| >0 the cipher block size in bytes |
| |
| 14 LIB_EXPORT INT16 |
| 15 _cpri__GetSymmetricBlockSize( |
| 16 TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm |
| 17 UINT16 keySizeInBits // IN: the key size |
| 18 ) |
| 19 { |
| 20 switch (symmetricAlg) |
| 21 { |
| 22 #ifdef TPM_ALG_AES |
| 23 case TPM_ALG_AES: |
| 24 #endif |
| 25 #ifdef TPM_ALG_SM4 // Both AES and SM4 use the same block size |
| 26 case TPM_ALG_SM4: |
| 27 #endif |
| 28 if(keySizeInBits != 0) // This is mostly to have a reference to |
| |
| Family "2.0" TCG Published Page 399 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 29 // keySizeInBits for the compiler |
| 30 return 16; |
| 31 else |
| 32 return 0; |
| 33 break; |
| 34 |
| 35 default: |
| 36 return 0; |
| 37 } |
| 38 } |
| |
| |
| B.11.4. AES Encryption |
| |
| B.11.4.1. _cpri__AESEncryptCBC() |
| |
| This function performs AES encryption in CBC chain mode. The input dIn buffer is encrypted into dOut. |
| The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to |
| be a multiple of the block size. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS if success |
| CRYPT_PARAMETER dInSize is not a multiple of the block size |
| |
| 39 LIB_EXPORT CRYPT_RESULT |
| 40 _cpri__AESEncryptCBC( |
| 41 BYTE *dOut, // OUT: |
| 42 UINT32 keySizeInBits, // IN: key size in bit |
| 43 BYTE *key, // IN: key buffer. The size of this buffer in |
| 44 // bytes is (keySizeInBits + 7) / 8 |
| 45 BYTE *iv, // IN/OUT: IV for decryption. |
| 46 UINT32 dInSize, // IN: data size (is required to be a multiple |
| 47 // of 16 bytes) |
| 48 BYTE *dIn // IN: data buffer |
| 49 ) |
| 50 { |
| 51 AES_KEY AesKey; |
| 52 BYTE *pIv; |
| 53 INT32 dSize; // Need a signed version |
| 54 int i; |
| 55 |
| 56 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 57 |
| 58 if(dInSize == 0) |
| 59 return CRYPT_SUCCESS; |
| 60 |
| 61 pAssert(dInSize <= INT32_MAX); |
| 62 dSize = (INT32)dInSize; |
| 63 |
| 64 // For CBC, the data size must be an even multiple of the |
| 65 // cipher block size |
| 66 if((dSize % 16) != 0) |
| 67 return CRYPT_PARAMETER; |
| 68 |
| 69 // Create AES encrypt key schedule |
| 70 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 71 FAIL(FATAL_ERROR_INTERNAL); |
| 72 |
| 73 // XOR the data block into the IV, encrypt the IV into the IV |
| 74 // and then copy the IV to the output |
| 75 for(; dSize > 0; dSize -= 16) |
| 76 { |
| |
| Page 400 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 77 pIv = iv; |
| 78 for(i = 16; i > 0; i--) |
| 79 *pIv++ ^= *dIn++; |
| 80 AES_encrypt(iv, iv, &AesKey); |
| 81 pIv = iv; |
| 82 for(i = 16; i > 0; i--) |
| 83 *dOut++ = *pIv++; |
| 84 } |
| 85 return CRYPT_SUCCESS; |
| 86 } |
| |
| |
| B.11.4.2. _cpri__AESDecryptCBC() |
| |
| This function performs AES decryption in CBC chain mode. The input dIn buffer is decrypted into dOut. |
| The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to |
| be a multiple of the block size. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS if success |
| CRYPT_PARAMETER dInSize is not a multiple of the block size |
| |
| 87 LIB_EXPORT CRYPT_RESULT |
| 88 _cpri__AESDecryptCBC( |
| 89 BYTE *dOut, // OUT: the decrypted data |
| 90 UINT32 keySizeInBits, // IN: key size in bit |
| 91 BYTE *key, // IN: key buffer. The size of this buffer in |
| 92 // bytes is (keySizeInBits + 7) / 8 |
| 93 BYTE *iv, // IN/OUT: IV for decryption. The size of this |
| 94 // buffer is 16 byte |
| 95 UINT32 dInSize, // IN: data size |
| 96 BYTE *dIn // IN: data buffer |
| 97 ) |
| 98 { |
| 99 AES_KEY AesKey; |
| 100 BYTE *pIv; |
| 101 int i; |
| 102 BYTE tmp[16]; |
| 103 BYTE *pT = NULL; |
| 104 INT32 dSize; |
| 105 |
| 106 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 107 |
| 108 if(dInSize == 0) |
| 109 return CRYPT_SUCCESS; |
| 110 |
| 111 pAssert(dInSize <= INT32_MAX); |
| 112 dSize = (INT32)dInSize; |
| 113 |
| 114 // For CBC, the data size must be an even multiple of the |
| 115 // cipher block size |
| 116 if((dSize % 16) != 0) |
| 117 return CRYPT_PARAMETER; |
| 118 |
| 119 // Create AES key schedule |
| 120 if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 121 FAIL(FATAL_ERROR_INTERNAL); |
| 122 |
| 123 // Copy the input data to a temp buffer, decrypt the buffer into the output; |
| 124 // XOR in the IV, and copy the temp buffer to the IV and repeat. |
| 125 for(; dSize > 0; dSize -= 16) |
| 126 { |
| |
| |
| Family "2.0" TCG Published Page 401 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 127 pT = tmp; |
| 128 for(i = 16; i> 0; i--) |
| 129 *pT++ = *dIn++; |
| 130 AES_decrypt(tmp, dOut, &AesKey); |
| 131 pIv = iv; |
| 132 pT = tmp; |
| 133 for(i = 16; i> 0; i--) |
| 134 { |
| 135 *dOut++ ^= *pIv; |
| 136 *pIv++ = *pT++; |
| 137 } |
| 138 } |
| 139 return CRYPT_SUCCESS; |
| 140 } |
| |
| |
| B.11.4.3. _cpri__AESEncryptCFB() |
| |
| This function performs AES encryption in CFB chain mode. The dOut buffer receives the values |
| encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will |
| be modified to contain the last encrypted block. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 141 LIB_EXPORT CRYPT_RESULT |
| 142 _cpri__AESEncryptCFB( |
| 143 BYTE *dOut, // OUT: the encrypted |
| 144 UINT32 keySizeInBits, // IN: key size in bit |
| 145 BYTE *key, // IN: key buffer. The size of this buffer in |
| 146 // bytes is (keySizeInBits + 7) / 8 |
| 147 BYTE *iv, // IN/OUT: IV for decryption. |
| 148 UINT32 dInSize, // IN: data size |
| 149 BYTE *dIn // IN: data buffer |
| 150 ) |
| 151 { |
| 152 BYTE *pIv = NULL; |
| 153 AES_KEY AesKey; |
| 154 INT32 dSize; // Need a signed version of dInSize |
| 155 int i; |
| 156 |
| 157 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 158 |
| 159 if(dInSize == 0) |
| 160 return CRYPT_SUCCESS; |
| 161 |
| 162 pAssert(dInSize <= INT32_MAX); |
| 163 dSize = (INT32)dInSize; |
| 164 |
| 165 // Create AES encryption key schedule |
| 166 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 167 FAIL(FATAL_ERROR_INTERNAL); |
| 168 |
| 169 // Encrypt the IV into the IV, XOR in the data, and copy to output |
| 170 for(; dSize > 0; dSize -= 16) |
| 171 { |
| 172 // Encrypt the current value of the IV |
| 173 AES_encrypt(iv, iv, &AesKey); |
| 174 pIv = iv; |
| 175 for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--) |
| 176 // XOR the data into the IV to create the cipher text |
| 177 // and put into the output |
| 178 *dOut++ = *pIv++ ^= *dIn++; |
| 179 } |
| |
| Page 402 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 180 // If the inner loop (i loop) was smaller than 16, then dSize would have been |
| 181 // smaller than 16 and it is now negative. If it is negative, then it indicates |
| 182 // how many bytes are needed to pad out the IV for the next round. |
| 183 for(; dSize < 0; dSize++) |
| 184 *pIv++ = 0; |
| 185 return CRYPT_SUCCESS; |
| 186 } |
| |
| |
| B.11.4.4. _cpri__AESDecryptCFB() |
| |
| This function performs AES decrypt in CFB chain mode. The dOut buffer receives the values decrypted |
| from dIn. |
| The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to |
| contain the last decoded block, padded with zeros |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 187 LIB_EXPORT CRYPT_RESULT |
| 188 _cpri__AESDecryptCFB( |
| 189 BYTE *dOut, // OUT: the decrypted data |
| 190 UINT32 keySizeInBits, // IN: key size in bit |
| 191 BYTE *key, // IN: key buffer. The size of this buffer in |
| 192 // bytes is (keySizeInBits + 7) / 8 |
| 193 BYTE *iv, // IN/OUT: IV for decryption. |
| 194 UINT32 dInSize, // IN: data size |
| 195 BYTE *dIn // IN: data buffer |
| 196 ) |
| 197 { |
| 198 BYTE *pIv = NULL; |
| 199 BYTE tmp[16]; |
| 200 int i; |
| 201 BYTE *pT; |
| 202 AES_KEY AesKey; |
| 203 INT32 dSize; |
| 204 |
| 205 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 206 |
| 207 if(dInSize == 0) |
| 208 return CRYPT_SUCCESS; |
| 209 |
| 210 pAssert(dInSize <= INT32_MAX); |
| 211 dSize = (INT32)dInSize; |
| 212 |
| 213 // Create AES encryption key schedule |
| 214 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 215 FAIL(FATAL_ERROR_INTERNAL); |
| 216 |
| 217 for(; dSize > 0; dSize -= 16) |
| 218 { |
| 219 // Encrypt the IV into the temp buffer |
| 220 AES_encrypt(iv, tmp, &AesKey); |
| 221 pT = tmp; |
| 222 pIv = iv; |
| 223 for(i = (dSize < 16) ? dSize : 16; i > 0; i--) |
| 224 // Copy the current cipher text to IV, XOR |
| 225 // with the temp buffer and put into the output |
| 226 *dOut++ = *pT++ ^ (*pIv++ = *dIn++); |
| 227 } |
| 228 // If the inner loop (i loop) was smaller than 16, then dSize |
| 229 // would have been smaller than 16 and it is now negative |
| 230 // If it is negative, then it indicates how may fill bytes |
| |
| Family "2.0" TCG Published Page 403 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 231 // are needed to pad out the IV for the next round. |
| 232 for(; dSize < 0; dSize++) |
| 233 *pIv++ = 0; |
| 234 |
| 235 return CRYPT_SUCCESS; |
| 236 } |
| |
| |
| B.11.4.5. _cpri__AESEncryptCTR() |
| |
| This function performs AES encryption/decryption in CTR chain mode. The dIn buffer is encrypted into |
| dOut. The input iv buffer is assumed to have a size equal to the AES block size (16 bytes). The iv will be |
| incremented by the number of blocks (full and partial) that were encrypted. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 237 LIB_EXPORT CRYPT_RESULT |
| 238 _cpri__AESEncryptCTR( |
| 239 BYTE *dOut, // OUT: the encrypted data |
| 240 UINT32 keySizeInBits, // IN: key size in bit |
| 241 BYTE *key, // IN: key buffer. The size of this buffer in |
| 242 // bytes is (keySizeInBits + 7) / 8 |
| 243 BYTE *iv, // IN/OUT: IV for decryption. |
| 244 UINT32 dInSize, // IN: data size |
| 245 BYTE *dIn // IN: data buffer |
| 246 ) |
| 247 { |
| 248 BYTE tmp[16]; |
| 249 BYTE *pT; |
| 250 AES_KEY AesKey; |
| 251 int i; |
| 252 INT32 dSize; |
| 253 |
| 254 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 255 |
| 256 if(dInSize == 0) |
| 257 return CRYPT_SUCCESS; |
| 258 |
| 259 pAssert(dInSize <= INT32_MAX); |
| 260 dSize = (INT32)dInSize; |
| 261 |
| 262 // Create AES encryption schedule |
| 263 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 264 FAIL(FATAL_ERROR_INTERNAL); |
| 265 |
| 266 for(; dSize > 0; dSize -= 16) |
| 267 { |
| 268 // Encrypt the current value of the IV(counter) |
| 269 AES_encrypt(iv, (BYTE *)tmp, &AesKey); |
| 270 |
| 271 //increment the counter (counter is big-endian so start at end) |
| 272 for(i = 15; i >= 0; i--) |
| 273 if((iv[i] += 1) != 0) |
| 274 break; |
| 275 |
| 276 // XOR the encrypted counter value with input and put into output |
| 277 pT = tmp; |
| 278 for(i = (dSize < 16) ? dSize : 16; i > 0; i--) |
| 279 *dOut++ = *dIn++ ^ *pT++; |
| 280 } |
| 281 return CRYPT_SUCCESS; |
| 282 } |
| |
| |
| Page 404 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| B.11.4.6. _cpri__AESDecryptCTR() |
| |
| Counter mode decryption uses the same algorithm as encryption. The _cpri__AESDecryptCTR() function |
| is implemented as a macro call to _cpri__AESEncryptCTR(). (skip) |
| |
| 283 //% #define _cpri__AESDecryptCTR(dOut, keySize, key, iv, dInSize, dIn) \ |
| 284 //% _cpri__AESEncryptCTR( \ |
| 285 //% ((BYTE *)dOut), \ |
| 286 //% ((UINT32)keySize), \ |
| 287 //% ((BYTE *)key), \ |
| 288 //% ((BYTE *)iv), \ |
| 289 //% ((UINT32)dInSize), \ |
| 290 //% ((BYTE *)dIn) \ |
| 291 //% ) |
| 292 //% |
| 293 // The //% is used by the prototype extraction program to cause it to include the |
| 294 // line in the prototype file after removing the //%. Need an extra line with |
| |
| nothing on it so that a blank line will separate this macro from the next definition. |
| |
| B.11.4.7. _cpri__AESEncryptECB() |
| |
| AES encryption in ECB mode. The data buffer is modified to contain the cipher text. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 295 LIB_EXPORT CRYPT_RESULT |
| 296 _cpri__AESEncryptECB( |
| 297 BYTE *dOut, // OUT: encrypted data |
| 298 UINT32 keySizeInBits, // IN: key size in bit |
| 299 BYTE *key, // IN: key buffer. The size of this buffer in |
| 300 // bytes is (keySizeInBits + 7) / 8 |
| 301 UINT32 dInSize, // IN: data size |
| 302 BYTE *dIn // IN: clear text buffer |
| 303 ) |
| 304 { |
| 305 AES_KEY AesKey; |
| 306 INT32 dSize; |
| 307 |
| 308 pAssert(dOut != NULL && key != NULL && dIn != NULL); |
| 309 |
| 310 if(dInSize == 0) |
| 311 return CRYPT_SUCCESS; |
| 312 |
| 313 pAssert(dInSize <= INT32_MAX); |
| 314 dSize = (INT32)dInSize; |
| 315 |
| 316 // For ECB, the data size must be an even multiple of the |
| 317 // cipher block size |
| 318 if((dSize % 16) != 0) |
| 319 return CRYPT_PARAMETER; |
| 320 // Create AES encrypting key schedule |
| 321 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 322 FAIL(FATAL_ERROR_INTERNAL); |
| 323 |
| 324 for(; dSize > 0; dSize -= 16) |
| 325 { |
| 326 AES_encrypt(dIn, dOut, &AesKey); |
| 327 dIn = &dIn[16]; |
| 328 dOut = &dOut[16]; |
| 329 } |
| |
| Family "2.0" TCG Published Page 405 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 330 return CRYPT_SUCCESS; |
| 331 } |
| |
| |
| B.11.4.8. _cpri__AESDecryptECB() |
| |
| This function performs AES decryption using ECB (not recommended). The cipher text dIn is decrypted |
| into dOut. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 332 LIB_EXPORT CRYPT_RESULT |
| 333 _cpri__AESDecryptECB( |
| 334 BYTE *dOut, // OUT: the clear text data |
| 335 UINT32 keySizeInBits, // IN: key size in bit |
| 336 BYTE *key, // IN: key buffer. The size of this buffer in |
| 337 // bytes is (keySizeInBits + 7) / 8 |
| 338 UINT32 dInSize, // IN: data size |
| 339 BYTE *dIn // IN: cipher text buffer |
| 340 ) |
| 341 { |
| 342 AES_KEY AesKey; |
| 343 INT32 dSize; |
| 344 |
| 345 pAssert(dOut != NULL && key != NULL && dIn != NULL); |
| 346 |
| 347 if(dInSize == 0) |
| 348 return CRYPT_SUCCESS; |
| 349 |
| 350 pAssert(dInSize <= INT32_MAX); |
| 351 dSize = (INT32)dInSize; |
| 352 |
| 353 // For ECB, the data size must be an even multiple of the |
| 354 // cipher block size |
| 355 if((dSize % 16) != 0) |
| 356 return CRYPT_PARAMETER; |
| 357 |
| 358 // Create AES decryption key schedule |
| 359 if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 360 FAIL(FATAL_ERROR_INTERNAL); |
| 361 |
| 362 for(; dSize > 0; dSize -= 16) |
| 363 { |
| 364 AES_decrypt(dIn, dOut, &AesKey); |
| 365 dIn = &dIn[16]; |
| 366 dOut = &dOut[16]; |
| 367 } |
| 368 return CRYPT_SUCCESS; |
| 369 } |
| |
| |
| B.11.4.9. _cpri__AESEncryptOFB() |
| |
| This function performs AES encryption/decryption in OFB chain mode. The dIn buffer is modified to |
| contain the encrypted/decrypted text. |
| The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv |
| will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream. |
| |
| |
| |
| |
| Page 406 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 370 LIB_EXPORT CRYPT_RESULT |
| 371 _cpri__AESEncryptOFB( |
| 372 BYTE *dOut, // OUT: the encrypted/decrypted data |
| 373 UINT32 keySizeInBits, // IN: key size in bit |
| 374 BYTE *key, // IN: key buffer. The size of this buffer in |
| 375 // bytes is (keySizeInBits + 7) / 8 |
| 376 BYTE *iv, // IN/OUT: IV for decryption. The size of this |
| 377 // buffer is 16 byte |
| 378 UINT32 dInSize, // IN: data size |
| 379 BYTE *dIn // IN: data buffer |
| 380 ) |
| 381 { |
| 382 BYTE *pIv; |
| 383 AES_KEY AesKey; |
| 384 INT32 dSize; |
| 385 int i; |
| 386 |
| 387 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 388 |
| 389 if(dInSize == 0) |
| 390 return CRYPT_SUCCESS; |
| 391 |
| 392 pAssert(dInSize <= INT32_MAX); |
| 393 dSize = (INT32)dInSize; |
| 394 |
| 395 // Create AES key schedule |
| 396 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0) |
| 397 FAIL(FATAL_ERROR_INTERNAL); |
| 398 |
| 399 // This is written so that dIn and dOut may be the same |
| 400 |
| 401 for(; dSize > 0; dSize -= 16) |
| 402 { |
| 403 // Encrypt the current value of the "IV" |
| 404 AES_encrypt(iv, iv, &AesKey); |
| 405 |
| 406 // XOR the encrypted IV into dIn to create the cipher text (dOut) |
| 407 pIv = iv; |
| 408 for(i = (dSize < 16) ? dSize : 16; i > 0; i--) |
| 409 *dOut++ = (*pIv++ ^ *dIn++); |
| 410 } |
| 411 return CRYPT_SUCCESS; |
| 412 } |
| |
| |
| B.11.4.10. _cpri__AESDecryptOFB() |
| |
| OFB encryption and decryption use the same algorithms for both. The _cpri__AESDecryptOFB() function |
| is implemented as a macro call to _cpri__AESEncrytOFB(). (skip) |
| |
| 413 //%#define _cpri__AESDecryptOFB(dOut,keySizeInBits, key, iv, dInSize, dIn) \ |
| 414 //% _cpri__AESEncryptOFB ( \ |
| 415 //% ((BYTE *)dOut), \ |
| 416 //% ((UINT32)keySizeInBits), \ |
| 417 //% ((BYTE *)key), \ |
| 418 //% ((BYTE *)iv), \ |
| 419 //% ((UINT32)dInSize), \ |
| 420 //% ((BYTE *)dIn) \ |
| 421 //% ) |
| 422 //% |
| |
| |
| Family "2.0" TCG Published Page 407 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 423 #ifdef TPM_ALG_SM4 //% |
| |
| |
| B.11.5. SM4 Encryption |
| |
| B.11.5.1. _cpri__SM4EncryptCBC() |
| |
| This function performs SM4 encryption in CBC chain mode. The input dIn buffer is encrypted into dOut. |
| The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to |
| be a multiple of the block size. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS if success |
| CRYPT_PARAMETER dInSize is not a multiple of the block size |
| |
| 424 LIB_EXPORT CRYPT_RESULT |
| 425 _cpri__SM4EncryptCBC( |
| 426 BYTE *dOut, // OUT: |
| 427 UINT32 keySizeInBits, // IN: key size in bit |
| 428 BYTE *key, // IN: key buffer. The size of this buffer in |
| 429 // bytes is (keySizeInBits + 7) / 8 |
| 430 BYTE *iv, // IN/OUT: IV for decryption. |
| 431 UINT32 dInSize, // IN: data size (is required to be a multiple |
| 432 // of 16 bytes) |
| 433 BYTE *dIn // IN: data buffer |
| 434 ) |
| 435 { |
| 436 SM4_KEY Sm4Key; |
| 437 BYTE *pIv; |
| 438 INT32 dSize; // Need a signed version |
| 439 int i; |
| 440 |
| 441 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 442 |
| 443 if(dInSize == 0) |
| 444 return CRYPT_SUCCESS; |
| 445 |
| 446 pAssert(dInSize <= INT32_MAX); |
| 447 dSize = (INT32)dInSize; |
| 448 |
| 449 // For CBC, the data size must be an even multiple of the |
| 450 // cipher block size |
| 451 if((dSize % 16) != 0) |
| 452 return CRYPT_PARAMETER; |
| 453 |
| 454 // Create SM4 encrypt key schedule |
| 455 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 456 FAIL(FATAL_ERROR_INTERNAL); |
| 457 |
| 458 // XOR the data block into the IV, encrypt the IV into the IV |
| 459 // and then copy the IV to the output |
| 460 for(; dSize > 0; dSize -= 16) |
| 461 { |
| 462 pIv = iv; |
| 463 for(i = 16; i > 0; i--) |
| 464 *pIv++ ^= *dIn++; |
| 465 SM4_encrypt(iv, iv, &Sm4Key); |
| 466 pIv = iv; |
| 467 for(i = 16; i > 0; i--) |
| 468 *dOut++ = *pIv++; |
| 469 } |
| 470 return CRYPT_SUCCESS; |
| |
| Page 408 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 471 } |
| |
| |
| B.11.5.2. _cpri__SM4DecryptCBC() |
| |
| This function performs SM4 decryption in CBC chain mode. The input dIn buffer is decrypted into dOut. |
| The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to |
| be a multiple of the block size. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS if success |
| CRYPT_PARAMETER dInSize is not a multiple of the block size |
| |
| 472 LIB_EXPORT CRYPT_RESULT |
| 473 _cpri__SM4DecryptCBC( |
| 474 BYTE *dOut, // OUT: the decrypted data |
| 475 UINT32 keySizeInBits, // IN: key size in bit |
| 476 BYTE *key, // IN: key buffer. The size of this buffer in |
| 477 // bytes is (keySizeInBits + 7) / 8 |
| 478 BYTE *iv, // IN/OUT: IV for decryption. The size of this |
| 479 // buffer is 16 byte |
| 480 UINT32 dInSize, // IN: data size |
| 481 BYTE *dIn // IN: data buffer |
| 482 ) |
| 483 { |
| 484 SM4_KEY Sm4Key; |
| 485 BYTE *pIv; |
| 486 int i; |
| 487 BYTE tmp[16]; |
| 488 BYTE *pT = NULL; |
| 489 INT32 dSize; |
| 490 |
| 491 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 492 |
| 493 if(dInSize == 0) |
| 494 return CRYPT_SUCCESS; |
| 495 |
| 496 pAssert(dInSize <= INT32_MAX); |
| 497 dSize = (INT32)dInSize; |
| 498 |
| 499 // For CBC, the data size must be an even multiple of the |
| 500 // cipher block size |
| 501 if((dSize % 16) != 0) |
| 502 return CRYPT_PARAMETER; |
| 503 |
| 504 // Create SM4 key schedule |
| 505 if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 506 FAIL(FATAL_ERROR_INTERNAL); |
| 507 |
| 508 // Copy the input data to a temp buffer, decrypt the buffer into the output; |
| 509 // XOR in the IV, and copy the temp buffer to the IV and repeat. |
| 510 for(; dSize > 0; dSize -= 16) |
| 511 { |
| 512 pT = tmp; |
| 513 for(i = 16; i> 0; i--) |
| 514 *pT++ = *dIn++; |
| 515 SM4_decrypt(tmp, dOut, &Sm4Key); |
| 516 pIv = iv; |
| 517 pT = tmp; |
| 518 for(i = 16; i> 0; i--) |
| 519 { |
| 520 *dOut++ ^= *pIv; |
| |
| |
| Family "2.0" TCG Published Page 409 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 521 *pIv++ = *pT++; |
| 522 } |
| 523 } |
| 524 return CRYPT_SUCCESS; |
| 525 } |
| |
| |
| B.11.5.3. _cpri__SM4EncryptCFB() |
| |
| This function performs SM4 encryption in CFB chain mode. The dOut buffer receives the values |
| encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will |
| be modified to contain the last encrypted block. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 526 LIB_EXPORT CRYPT_RESULT |
| 527 _cpri__SM4EncryptCFB( |
| 528 BYTE *dOut, // OUT: the encrypted |
| 529 UINT32 keySizeInBits, // IN: key size in bit |
| 530 BYTE *key, // IN: key buffer. The size of this buffer in |
| 531 // bytes is (keySizeInBits + 7) / 8 |
| 532 BYTE *iv, // IN/OUT: IV for decryption. |
| 533 UINT32 dInSize, // IN: data size |
| 534 BYTE *dIn // IN: data buffer |
| 535 ) |
| 536 { |
| 537 BYTE *pIv; |
| 538 SM4_KEY Sm4Key; |
| 539 INT32 dSize; // Need a signed version of dInSize |
| 540 int i; |
| 541 |
| 542 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 543 |
| 544 if(dInSize == 0) |
| 545 return CRYPT_SUCCESS; |
| 546 |
| 547 pAssert(dInSize <= INT32_MAX); |
| 548 dSize = (INT32)dInSize; |
| 549 |
| 550 // Create SM4 encryption key schedule |
| 551 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 552 FAIL(FATAL_ERROR_INTERNAL); |
| 553 |
| 554 // Encrypt the IV into the IV, XOR in the data, and copy to output |
| 555 for(; dSize > 0; dSize -= 16) |
| 556 { |
| 557 // Encrypt the current value of the IV |
| 558 SM4_encrypt(iv, iv, &Sm4Key); |
| 559 pIv = iv; |
| 560 for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--) |
| 561 // XOR the data into the IV to create the cipher text |
| 562 // and put into the output |
| 563 *dOut++ = *pIv++ ^= *dIn++; |
| 564 } |
| 565 return CRYPT_SUCCESS; |
| 566 } |
| |
| |
| B.11.5.4. _cpri__SM4DecryptCFB() |
| |
| This function performs SM4 decrypt in CFB chain mode. The dOut buffer receives the values decrypted |
| from dIn. |
| |
| Page 410 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to |
| contain the last decoded block, padded with zeros |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 567 LIB_EXPORT CRYPT_RESULT |
| 568 _cpri__SM4DecryptCFB( |
| 569 BYTE *dOut, // OUT: the decrypted data |
| 570 UINT32 keySizeInBits, // IN: key size in bit |
| 571 BYTE *key, // IN: key buffer. The size of this buffer in |
| 572 // bytes is (keySizeInBits + 7) / 8 |
| 573 BYTE *iv, // IN/OUT: IV for decryption. |
| 574 UINT32 dInSize, // IN: data size |
| 575 BYTE *dIn // IN: data buffer |
| 576 ) |
| 577 { |
| 578 BYTE *pIv; |
| 579 BYTE tmp[16]; |
| 580 int i; |
| 581 BYTE *pT; |
| 582 SM4_KEY Sm4Key; |
| 583 INT32 dSize; |
| 584 |
| 585 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 586 |
| 587 if(dInSize == 0) |
| 588 return CRYPT_SUCCESS; |
| 589 |
| 590 pAssert(dInSize <= INT32_MAX); |
| 591 dSize = (INT32)dInSize; |
| 592 |
| 593 // Create SM4 encryption key schedule |
| 594 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 595 FAIL(FATAL_ERROR_INTERNAL); |
| 596 |
| 597 for(; dSize > 0; dSize -= 16) |
| 598 { |
| 599 // Encrypt the IV into the temp buffer |
| 600 SM4_encrypt(iv, tmp, &Sm4Key); |
| 601 pT = tmp; |
| 602 pIv = iv; |
| 603 for(i = (dSize < 16) ? dSize : 16; i > 0; i--) |
| 604 // Copy the current cipher text to IV, XOR |
| 605 // with the temp buffer and put into the output |
| 606 *dOut++ = *pT++ ^ (*pIv++ = *dIn++); |
| 607 } |
| 608 // If the inner loop (i loop) was smaller than 16, then dSize |
| 609 // would have been smaller than 16 and it is now negative |
| 610 // If it is negative, then it indicates how may fill bytes |
| 611 // are needed to pad out the IV for the next round. |
| 612 for(; dSize < 0; dSize++) |
| 613 *iv++ = 0; |
| 614 |
| 615 return CRYPT_SUCCESS; |
| 616 } |
| |
| |
| B.11.5.5. _cpri__SM4EncryptCTR() |
| |
| This function performs SM4 encryption/decryption in CTR chain mode. The dIn buffer is encrypted into |
| dOut. The input iv buffer is assumed to have a size equal to the SM4 block size (16 bytes). The iv will be |
| incremented by the number of blocks (full and partial) that were encrypted. |
| |
| Family "2.0" TCG Published Page 411 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 617 LIB_EXPORT CRYPT_RESULT |
| 618 _cpri__SM4EncryptCTR( |
| 619 BYTE *dOut, // OUT: the encrypted data |
| 620 UINT32 keySizeInBits, // IN: key size in bit |
| 621 BYTE *key, // IN: key buffer. The size of this buffer in |
| 622 // bytes is (keySizeInBits + 7) / 8 |
| 623 BYTE *iv, // IN/OUT: IV for decryption. |
| 624 UINT32 dInSize, // IN: data size |
| 625 BYTE *dIn // IN: data buffer |
| 626 ) |
| 627 { |
| 628 BYTE tmp[16]; |
| 629 BYTE *pT; |
| 630 SM4_KEY Sm4Key; |
| 631 int i; |
| 632 INT32 dSize; |
| 633 |
| 634 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 635 |
| 636 if(dInSize == 0) |
| 637 return CRYPT_SUCCESS; |
| 638 |
| 639 pAssert(dInSize <= INT32_MAX); |
| 640 dSize = (INT32)dInSize; |
| 641 |
| 642 // Create SM4 encryption schedule |
| 643 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 644 FAIL(FATAL_ERROR_INTERNAL); |
| 645 |
| 646 for(; dSize > 0; dSize--) |
| 647 { |
| 648 // Encrypt the current value of the IV(counter) |
| 649 SM4_encrypt(iv, (BYTE *)tmp, &Sm4Key); |
| 650 |
| 651 //increment the counter |
| 652 for(i = 0; i < 16; i++) |
| 653 if((iv[i] += 1) != 0) |
| 654 break; |
| 655 |
| 656 // XOR the encrypted counter value with input and put into output |
| 657 pT = tmp; |
| 658 for(i = (dSize < 16) ? dSize : 16; i > 0; i--) |
| 659 *dOut++ = *dIn++ ^ *pT++; |
| 660 } |
| 661 return CRYPT_SUCCESS; |
| 662 } |
| |
| |
| B.11.5.6. _cpri__SM4DecryptCTR() |
| |
| Counter mode decryption uses the same algorithm as encryption. The _cpri__SM4DecryptCTR() function |
| is implemented as a macro call to _cpri__SM4EncryptCTR(). (skip) |
| |
| 663 //% #define _cpri__SM4DecryptCTR(dOut, keySize, key, iv, dInSize, dIn) \ |
| 664 //% _cpri__SM4EncryptCTR( \ |
| 665 //% ((BYTE *)dOut), \ |
| 666 //% ((UINT32)keySize), \ |
| 667 //% ((BYTE *)key), \ |
| 668 //% ((BYTE *)iv), \ |
| 669 //% ((UINT32)dInSize), \ |
| |
| |
| Page 412 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 670 //% ((BYTE *)dIn) \ |
| 671 //% ) |
| 672 //% |
| 673 // The //% is used by the prototype extraction program to cause it to include the |
| 674 // line in the prototype file after removing the //%. Need an extra line with |
| |
| nothing on it so that a blank line will separate this macro from the next definition. |
| |
| B.11.5.7. _cpri__SM4EncryptECB() |
| |
| SM4 encryption in ECB mode. The data buffer is modified to contain the cipher text. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 675 LIB_EXPORT CRYPT_RESULT |
| 676 _cpri__SM4EncryptECB( |
| 677 BYTE *dOut, // OUT: encrypted data |
| 678 UINT32 keySizeInBits, // IN: key size in bit |
| 679 BYTE *key, // IN: key buffer. The size of this buffer in |
| 680 // bytes is (keySizeInBits + 7) / 8 |
| 681 UINT32 dInSize, // IN: data size |
| 682 BYTE *dIn // IN: clear text buffer |
| 683 ) |
| 684 { |
| 685 SM4_KEY Sm4Key; |
| 686 INT32 dSize; |
| 687 |
| 688 pAssert(dOut != NULL && key != NULL && dIn != NULL); |
| 689 |
| 690 if(dInSize == 0) |
| 691 return CRYPT_SUCCESS; |
| 692 |
| 693 pAssert(dInSize <= INT32_MAX); |
| 694 dSize = (INT32)dInSize; |
| 695 |
| 696 // For ECB, the data size must be an even multiple of the |
| 697 // cipher block size |
| 698 if((dSize % 16) != 0) |
| 699 return CRYPT_PARAMETER; |
| 700 // Create SM4 encrypting key schedule |
| 701 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 702 FAIL(FATAL_ERROR_INTERNAL); |
| 703 |
| 704 for(; dSize > 0; dSize -= 16) |
| 705 { |
| 706 SM4_encrypt(dIn, dOut, &Sm4Key); |
| 707 dIn = &dIn[16]; |
| 708 dOut = &dOut[16]; |
| 709 } |
| 710 return CRYPT_SUCCESS; |
| 711 } |
| |
| |
| B.11.5.8. _cpri__SM4DecryptECB() |
| |
| This function performs SM4 decryption using ECB (not recommended). The cipher text dIn is decrypted |
| into dOut. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 413 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 712 LIB_EXPORT CRYPT_RESULT |
| 713 _cpri__SM4DecryptECB( |
| 714 BYTE *dOut, // OUT: the clear text data |
| 715 UINT32 keySizeInBits, // IN: key size in bit |
| 716 BYTE *key, // IN: key buffer. The size of this buffer in |
| 717 // bytes is (keySizeInBits + 7) / 8 |
| 718 UINT32 dInSize, // IN: data size |
| 719 BYTE *dIn // IN: cipher text buffer |
| 720 ) |
| 721 { |
| 722 SM4_KEY Sm4Key; |
| 723 INT32 dSize; |
| 724 |
| 725 pAssert(dOut != NULL && key != NULL && dIn != NULL); |
| 726 |
| 727 if(dInSize == 0) |
| 728 return CRYPT_SUCCESS; |
| 729 |
| 730 pAssert(dInSize <= INT32_MAX); |
| 731 dSize = (INT32)dInSize; |
| 732 |
| 733 // For ECB, the data size must be an even multiple of the |
| 734 // cipher block size |
| 735 if((dSize % 16) != 0) |
| 736 return CRYPT_PARAMETER; |
| 737 |
| 738 // Create SM4 decryption key schedule |
| 739 if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 740 FAIL(FATAL_ERROR_INTERNAL); |
| 741 |
| 742 for(; dSize > 0; dSize -= 16) |
| 743 { |
| 744 SM4_decrypt(dIn, dOut, &Sm4Key); |
| 745 dIn = &dIn[16]; |
| 746 dOut = &dOut[16]; |
| 747 } |
| 748 return CRYPT_SUCCESS; |
| 749 } |
| |
| |
| B.11.5.9. _cpri__SM4EncryptOFB() |
| |
| This function performs SM4 encryption/decryption in OFB chain mode. The dIn buffer is modified to |
| contain the encrypted/decrypted text. |
| The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv |
| will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS no non-fatal errors |
| |
| 750 LIB_EXPORT CRYPT_RESULT |
| 751 _cpri__SM4EncryptOFB( |
| 752 BYTE *dOut, // OUT: the encrypted/decrypted data |
| 753 UINT32 keySizeInBits, // IN: key size in bit |
| 754 BYTE *key, // IN: key buffer. The size of this buffer in |
| 755 // bytes is (keySizeInBits + 7) / 8 |
| 756 BYTE *iv, // IN/OUT: IV for decryption. The size of this |
| 757 // buffer is 16 byte |
| |
| Page 414 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 758 UINT32 dInSize, // IN: data size |
| 759 BYTE *dIn // IN: data buffer |
| 760 ) |
| 761 { |
| 762 BYTE *pIv; |
| 763 SM4_KEY Sm4Key; |
| 764 INT32 dSize; |
| 765 int i; |
| 766 |
| 767 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL); |
| 768 |
| 769 if(dInSize == 0) |
| 770 return CRYPT_SUCCESS; |
| 771 |
| 772 pAssert(dInSize <= INT32_MAX); |
| 773 dSize = (INT32)dInSize; |
| 774 |
| 775 // Create SM4 key schedule |
| 776 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0) |
| 777 FAIL(FATAL_ERROR_INTERNAL); |
| 778 |
| 779 // This is written so that dIn and dOut may be the same |
| 780 |
| 781 for(; dSize > 0; dSize -= 16) |
| 782 { |
| 783 // Encrypt the current value of the "IV" |
| 784 SM4_encrypt(iv, iv, &Sm4Key); |
| 785 |
| 786 // XOR the encrypted IV into dIn to create the cipher text (dOut) |
| 787 pIv = iv; |
| 788 for(i = (dSize < 16) ? dSize : 16; i > 0; i--) |
| 789 *dOut++ = (*pIv++ ^ *dIn++); |
| 790 } |
| 791 return CRYPT_SUCCESS; |
| 792 } |
| |
| |
| B.11.5.10. _cpri__SM4DecryptOFB() |
| |
| OFB encryption and decryption use the same algorithms for both. The _cpri__SM4DecryptOFB() function |
| is implemented as a macro call to _cpri__SM4EncrytOFB(). (skip) |
| |
| 793 //%#define _cpri__SM4DecryptOFB(dOut,keySizeInBits, key, iv, dInSize, dIn) \ |
| 794 //% _cpri__SM4EncryptOFB ( \ |
| 795 //% ((BYTE *)dOut), \ |
| 796 //% ((UINT32)keySizeInBits), \ |
| 797 //% ((BYTE *)key), \ |
| 798 //% ((BYTE *)iv), \ |
| 799 //% ((UINT32)dInSize), \ |
| 800 //% ((BYTE *)dIn) \ |
| 801 //% ) |
| 802 //% |
| 803 #endif //% TPM_ALG_SM4 |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 415 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| B.12 RSA Files |
| |
| B.12.1. CpriRSA.c |
| |
| B.12.1.1. Introduction |
| |
| This file contains implementation of crypto primitives for RSA. This is a simulator of a crypto engine. |
| Vendors may replace the implementation in this file with their own library functions. |
| Integer format: the big integers passed in/out to the function interfaces in this library adopt the same |
| format used in TPM 2.0 specification: Integer values are considered to be an array of one or more bytes. |
| The byte at offset zero within the array is the most significant byte of the integer. The interface uses |
| TPM2B as a big number format for numeric values passed to/from CryptUtil(). |
| |
| B.12.1.2. Includes |
| |
| 1 #include "OsslCryptoEngine.h" |
| 2 #ifdef TPM_ALG_RSA |
| |
| |
| B.12.1.3. Local Functions |
| |
| B.12.1.3.1. RsaPrivateExponent() |
| |
| This function computes the private exponent de = 1 mod (p-1)*(q-1) The inputs are the public modulus |
| and one of the primes. |
| The results are returned in the key->private structure. The size of that structure is expanded to hold the |
| private exponent. If the computed value is smaller than the public modulus, the private exponent is de- |
| normalized. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS private exponent computed |
| CRYPT_PARAMETER prime is not half the size of the modulus, or the modulus is not evenly |
| divisible by the prime, or no private exponent could be computed |
| from the input parameters |
| |
| 3 static CRYPT_RESULT |
| 4 RsaPrivateExponent( |
| 5 RSA_KEY *key // IN: the key to augment with the private |
| 6 // exponent |
| 7 ) |
| 8 { |
| 9 BN_CTX *context; |
| 10 BIGNUM *bnD; |
| 11 BIGNUM *bnN; |
| 12 BIGNUM *bnP; |
| 13 BIGNUM *bnE; |
| 14 BIGNUM *bnPhi; |
| 15 BIGNUM *bnQ; |
| 16 BIGNUM *bnQr; |
| 17 UINT32 fill; |
| 18 |
| 19 CRYPT_RESULT retVal = CRYPT_SUCCESS; // Assume success |
| 20 |
| 21 pAssert(key != NULL && key->privateKey != NULL && key->publicKey != NULL); |
| 22 |
| 23 context = BN_CTX_new(); |
| |
| Page 416 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 24 if(context == NULL) |
| 25 FAIL(FATAL_ERROR_ALLOCATION); |
| 26 BN_CTX_start(context); |
| 27 bnE = BN_CTX_get(context); |
| 28 bnD = BN_CTX_get(context); |
| 29 bnN = BN_CTX_get(context); |
| 30 bnP = BN_CTX_get(context); |
| 31 bnPhi = BN_CTX_get(context); |
| 32 bnQ = BN_CTX_get(context); |
| 33 bnQr = BN_CTX_get(context); |
| 34 |
| 35 if(bnQr == NULL) |
| 36 FAIL(FATAL_ERROR_ALLOCATION); |
| 37 |
| 38 // Assume the size of the public key value is within range |
| 39 pAssert(key->publicKey->size <= MAX_RSA_KEY_BYTES); |
| 40 |
| 41 if( BN_bin2bn(key->publicKey->buffer, key->publicKey->size, bnN) == NULL |
| 42 || BN_bin2bn(key->privateKey->buffer, key->privateKey->size, bnP) == NULL) |
| 43 |
| 44 FAIL(FATAL_ERROR_INTERNAL); |
| 45 |
| 46 // If P size is not 1/2 of n size, then this is not a valid value for this |
| 47 // implementation. This will also catch the case were P is input as zero. |
| 48 // This generates a return rather than an assert because the key being loaded |
| 49 // might be SW generated and wrong. |
| 50 if(BN_num_bits(bnP) < BN_num_bits(bnN)/2) |
| 51 { |
| 52 retVal = CRYPT_PARAMETER; |
| 53 goto Cleanup; |
| 54 } |
| 55 // Get q = n/p; |
| 56 if (BN_div(bnQ, bnQr, bnN, bnP, context) != 1) |
| 57 FAIL(FATAL_ERROR_INTERNAL); |
| 58 |
| 59 // If there is a remainder, then this is not a valid n |
| 60 if(BN_num_bytes(bnQr) != 0 || BN_num_bits(bnQ) != BN_num_bits(bnP)) |
| 61 { |
| 62 retVal = CRYPT_PARAMETER; // problem may be recoverable |
| 63 goto Cleanup; |
| 64 } |
| 65 // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 |
| 66 if( BN_copy(bnPhi, bnN) == NULL |
| 67 || !BN_sub(bnPhi, bnPhi, bnP) |
| 68 || !BN_sub(bnPhi, bnPhi, bnQ) |
| 69 || !BN_add_word(bnPhi, 1)) |
| 70 FAIL(FATAL_ERROR_INTERNAL); |
| 71 |
| 72 // Compute the multiplicative inverse |
| 73 BN_set_word(bnE, key->exponent); |
| 74 if(BN_mod_inverse(bnD, bnE, bnPhi, context) == NULL) |
| 75 { |
| 76 // Going to assume that the error is caused by a bad |
| 77 // set of parameters. Specifically, an exponent that is |
| 78 // not compatible with the primes. In an implementation that |
| 79 // has better visibility to the error codes, this might be |
| 80 // refined so that failures in the library would return |
| 81 // a more informative value. Should not assume here that |
| 82 // the error codes will remain unchanged. |
| 83 |
| 84 retVal = CRYPT_PARAMETER; |
| 85 goto Cleanup; |
| 86 } |
| 87 |
| 88 fill = key->publicKey->size - BN_num_bytes(bnD); |
| 89 BN_bn2bin(bnD, &key->privateKey->buffer[fill]); |
| |
| Family "2.0" TCG Published Page 417 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 90 memset(key->privateKey->buffer, 0, fill); |
| 91 |
| 92 // Change the size of the private key so that it is known to contain |
| 93 // a private exponent rather than a prime. |
| 94 key->privateKey->size = key->publicKey->size; |
| 95 |
| 96 Cleanup: |
| 97 BN_CTX_end(context); |
| 98 BN_CTX_free(context); |
| 99 return retVal; |
| 100 } |
| |
| |
| B.12.1.3.2. _cpri__TestKeyRSA() |
| |
| This function computes the private exponent de = 1 mod (p-1)*(q-1) The inputs are the public modulus |
| and one of the primes or two primes. |
| If both primes are provided, the public modulus is computed. If only one prime is provided, the second |
| prime is computed. In either case, a private exponent is produced and placed in d. |
| If no modular inverse exists, then CRYPT_PARAMETER is returned. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS private exponent (d) was generated |
| CRYPT_PARAMETER one or more parameters are invalid |
| |
| 101 LIB_EXPORT CRYPT_RESULT |
| 102 _cpri__TestKeyRSA( |
| 103 TPM2B *d, // OUT: the address to receive the private |
| 104 // exponent |
| 105 UINT32 exponent, // IN: the public modulu |
| 106 TPM2B *publicKey, // IN/OUT: an input if only one prime is |
| 107 // provided. an output if both primes are |
| 108 // provided |
| 109 TPM2B *prime1, // IN: a first prime |
| 110 TPM2B *prime2 // IN: an optional second prime |
| 111 ) |
| 112 { |
| 113 BN_CTX *context; |
| 114 BIGNUM *bnD; |
| 115 BIGNUM *bnN; |
| 116 BIGNUM *bnP; |
| 117 BIGNUM *bnE; |
| 118 BIGNUM *bnPhi; |
| 119 BIGNUM *bnQ; |
| 120 BIGNUM *bnQr; |
| 121 UINT32 fill; |
| 122 |
| 123 CRYPT_RESULT retVal = CRYPT_SUCCESS; // Assume success |
| 124 |
| 125 pAssert(publicKey != NULL && prime1 != NULL); |
| 126 // Make sure that the sizes are within range |
| 127 pAssert( prime1->size <= MAX_RSA_KEY_BYTES/2 |
| 128 && publicKey->size <= MAX_RSA_KEY_BYTES); |
| 129 pAssert( prime2 == NULL || prime2->size < MAX_RSA_KEY_BYTES/2); |
| 130 |
| 131 if(publicKey->size/2 != prime1->size) |
| 132 return CRYPT_PARAMETER; |
| 133 |
| 134 context = BN_CTX_new(); |
| 135 if(context == NULL) |
| 136 FAIL(FATAL_ERROR_ALLOCATION); |
| 137 BN_CTX_start(context); |
| |
| Page 418 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 138 bnE = BN_CTX_get(context); // public exponent (e) |
| 139 bnD = BN_CTX_get(context); // private exponent (d) |
| 140 bnN = BN_CTX_get(context); // public modulus (n) |
| 141 bnP = BN_CTX_get(context); // prime1 (p) |
| 142 bnPhi = BN_CTX_get(context); // (p-1)(q-1) |
| 143 bnQ = BN_CTX_get(context); // prime2 (q) |
| 144 bnQr = BN_CTX_get(context); // n mod p |
| 145 |
| 146 if(bnQr == NULL) |
| 147 FAIL(FATAL_ERROR_ALLOCATION); |
| 148 |
| 149 if(BN_bin2bn(prime1->buffer, prime1->size, bnP) == NULL) |
| 150 FAIL(FATAL_ERROR_INTERNAL); |
| 151 |
| 152 // If prime2 is provided, then compute n |
| 153 if(prime2 != NULL) |
| 154 { |
| 155 // Two primes provided so use them to compute n |
| 156 if(BN_bin2bn(prime2->buffer, prime2->size, bnQ) == NULL) |
| 157 FAIL(FATAL_ERROR_INTERNAL); |
| 158 |
| 159 // Make sure that the sizes of the primes are compatible |
| 160 if(BN_num_bits(bnQ) != BN_num_bits(bnP)) |
| 161 { |
| 162 retVal = CRYPT_PARAMETER; |
| 163 goto Cleanup; |
| 164 } |
| 165 // Multiply the primes to get the public modulus |
| 166 |
| 167 if(BN_mul(bnN, bnP, bnQ, context) != 1) |
| 168 FAIL(FATAL_ERROR_INTERNAL); |
| 169 |
| 170 // if the space provided for the public modulus is large enough, |
| 171 // save the created value |
| 172 if(BN_num_bits(bnN) != (publicKey->size * 8)) |
| 173 { |
| 174 retVal = CRYPT_PARAMETER; |
| 175 goto Cleanup; |
| 176 } |
| 177 BN_bn2bin(bnN, publicKey->buffer); |
| 178 } |
| 179 else |
| 180 { |
| 181 // One prime provided so find the second prime by division |
| 182 BN_bin2bn(publicKey->buffer, publicKey->size, bnN); |
| 183 |
| 184 // Get q = n/p; |
| 185 if(BN_div(bnQ, bnQr, bnN, bnP, context) != 1) |
| 186 FAIL(FATAL_ERROR_INTERNAL); |
| 187 |
| 188 // If there is a remainder, then this is not a valid n |
| 189 if(BN_num_bytes(bnQr) != 0 || BN_num_bits(bnQ) != BN_num_bits(bnP)) |
| 190 { |
| 191 retVal = CRYPT_PARAMETER; // problem may be recoverable |
| 192 goto Cleanup; |
| 193 } |
| 194 } |
| 195 // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 |
| 196 BN_copy(bnPhi, bnN); |
| 197 BN_sub(bnPhi, bnPhi, bnP); |
| 198 BN_sub(bnPhi, bnPhi, bnQ); |
| 199 BN_add_word(bnPhi, 1); |
| 200 // Compute the multiplicative inverse |
| 201 BN_set_word(bnE, exponent); |
| 202 if(BN_mod_inverse(bnD, bnE, bnPhi, context) == NULL) |
| 203 { |
| |
| Family "2.0" TCG Published Page 419 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 204 // Going to assume that the error is caused by a bad set of parameters. |
| 205 // Specifically, an exponent that is not compatible with the primes. |
| 206 // In an implementation that has better visibility to the error codes, |
| 207 // this might be refined so that failures in the library would return |
| 208 // a more informative value. |
| 209 // Do not assume that the error codes will remain unchanged. |
| 210 retVal = CRYPT_PARAMETER; |
| 211 goto Cleanup; |
| 212 } |
| 213 // Return the private exponent. |
| 214 // Make sure it is normalized to have the correct size. |
| 215 d->size = publicKey->size; |
| 216 fill = d->size - BN_num_bytes(bnD); |
| 217 BN_bn2bin(bnD, &d->buffer[fill]); |
| 218 memset(d->buffer, 0, fill); |
| 219 Cleanup: |
| 220 BN_CTX_end(context); |
| 221 BN_CTX_free(context); |
| 222 return retVal; |
| 223 } |
| |
| |
| B.12.1.3.3. RSAEP() |
| |
| This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a value |
| (m) with the public exponent (e), modulo the public (n). |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS encryption complete |
| CRYPT_PARAMETER number to exponentiate is larger than the modulus |
| |
| 224 static CRYPT_RESULT |
| 225 RSAEP ( |
| 226 UINT32 dInOutSize, // OUT size of the encrypted block |
| 227 BYTE *dInOut, // OUT: the encrypted data |
| 228 RSA_KEY *key // IN: the key to use |
| 229 ) |
| 230 { |
| 231 UINT32 e; |
| 232 BYTE exponent[4]; |
| 233 CRYPT_RESULT retVal; |
| 234 |
| 235 e = key->exponent; |
| 236 if(e == 0) |
| 237 e = RSA_DEFAULT_PUBLIC_EXPONENT; |
| 238 UINT32_TO_BYTE_ARRAY(e, exponent); |
| 239 |
| 240 //!!! Can put check for test of RSA here |
| 241 |
| 242 retVal = _math__ModExp(dInOutSize, dInOut, dInOutSize, dInOut, 4, exponent, |
| 243 key->publicKey->size, key->publicKey->buffer); |
| 244 |
| 245 // Exponentiation result is stored in-place, thus no space shortage is possible. |
| 246 pAssert(retVal != CRYPT_UNDERFLOW); |
| 247 |
| 248 return retVal; |
| 249 } |
| |
| |
| B.12.1.3.4. RSADP() |
| |
| This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a value (c) |
| with the private exponent (d), modulo the public modulus (n). The decryption is in place. |
| |
| Page 420 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| This function also checks the size of the private key. If the size indicates that only a prime value is |
| present, the key is converted to being a private exponent. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS decryption succeeded |
| CRYPT_PARAMETER the value to decrypt is larger than the modulus |
| |
| 250 static CRYPT_RESULT |
| 251 RSADP ( |
| 252 UINT32 dInOutSize, // IN/OUT: size of decrypted data |
| 253 BYTE *dInOut, // IN/OUT: the decrypted data |
| 254 RSA_KEY *key // IN: the key |
| 255 ) |
| 256 { |
| 257 CRYPT_RESULT retVal; |
| 258 |
| 259 //!!! Can put check for RSA tested here |
| 260 |
| 261 // Make sure that the pointers are provided and that the private key is present |
| 262 // If the private key is present it is assumed to have been created by |
| 263 // so is presumed good _cpri__PrivateExponent |
| 264 pAssert(key != NULL && dInOut != NULL && |
| 265 key->publicKey->size == key->publicKey->size); |
| 266 |
| 267 // make sure that the value to be decrypted is smaller than the modulus |
| 268 // note: this check is redundant as is also performed by _math__ModExp() |
| 269 // which is optimized for use in RSA operations |
| 270 if(_math__uComp(key->publicKey->size, key->publicKey->buffer, |
| 271 dInOutSize, dInOut) <= 0) |
| 272 return CRYPT_PARAMETER; |
| 273 |
| 274 // _math__ModExp can return CRYPT_PARAMTER or CRYPT_UNDERFLOW but actual |
| 275 // underflow is not possible because everything is in the same buffer. |
| 276 retVal = _math__ModExp(dInOutSize, dInOut, dInOutSize, dInOut, |
| 277 key->privateKey->size, key->privateKey->buffer, |
| 278 key->publicKey->size, key->publicKey->buffer); |
| 279 |
| 280 // Exponentiation result is stored in-place, thus no space shortage is possible. |
| 281 pAssert(retVal != CRYPT_UNDERFLOW); |
| 282 |
| 283 return retVal; |
| 284 } |
| |
| |
| B.12.1.3.5. OaepEncode() |
| |
| This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must |
| equal the size of the modulus |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS encode successful |
| CRYPT_PARAMETER hashAlg is not valid |
| CRYPT_FAIL message size is too large |
| |
| 285 static CRYPT_RESULT |
| 286 OaepEncode( |
| 287 UINT32 paddedSize, // IN: pad value size |
| 288 BYTE *padded, // OUT: the pad data |
| 289 TPM_ALG_ID hashAlg, // IN: algorithm to use for padding |
| 290 const char *label, // IN: null-terminated string (may be NULL) |
| |
| Family "2.0" TCG Published Page 421 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 291 UINT32 messageSize, // IN: the message size |
| 292 BYTE *message // IN: the message being padded |
| 293 #ifdef TEST_RSA // |
| 294 , BYTE *testSeed // IN: optional seed used for testing. |
| 295 #endif // TEST_RSA // |
| 296 ) |
| 297 { |
| 298 UINT32 padLen; |
| 299 UINT32 dbSize; |
| 300 UINT32 i; |
| 301 BYTE mySeed[MAX_DIGEST_SIZE]; |
| 302 BYTE *seed = mySeed; |
| 303 INT32 hLen = _cpri__GetDigestSize(hashAlg); |
| 304 BYTE mask[MAX_RSA_KEY_BYTES]; |
| 305 BYTE *pp; |
| 306 BYTE *pm; |
| 307 UINT32 lSize = 0; |
| 308 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 309 |
| 310 pAssert(padded != NULL && message != NULL); |
| 311 |
| 312 // A value of zero is not allowed because the KDF can't produce a result |
| 313 // if the digest size is zero. |
| 314 if(hLen <= 0) |
| 315 return CRYPT_PARAMETER; |
| 316 |
| 317 // If a label is provided, get the length of the string, including the |
| 318 // terminator |
| 319 if(label != NULL) |
| 320 lSize = (UINT32)strlen(label) + 1; |
| 321 |
| 322 // Basic size check |
| 323 // messageSize <= k 2hLen 2 |
| 324 if(messageSize > paddedSize - 2 * hLen - 2) |
| 325 return CRYPT_FAIL; |
| 326 |
| 327 // Hash L even if it is null |
| 328 // Offset into padded leaving room for masked seed and byte of zero |
| 329 pp = &padded[hLen + 1]; |
| 330 retVal = _cpri__HashBlock(hashAlg, lSize, (BYTE *)label, hLen, pp); |
| 331 |
| 332 // concatenate PS of k mLen 2hLen 2 |
| 333 padLen = paddedSize - messageSize - (2 * hLen) - 2; |
| 334 memset(&pp[hLen], 0, padLen); |
| 335 pp[hLen+padLen] = 0x01; |
| 336 padLen += 1; |
| 337 memcpy(&pp[hLen+padLen], message, messageSize); |
| 338 |
| 339 // The total size of db = hLen + pad + mSize; |
| 340 dbSize = hLen+padLen+messageSize; |
| 341 |
| 342 // If testing, then use the provided seed. Otherwise, use values |
| 343 // from the RNG |
| 344 #ifdef TEST_RSA |
| 345 if(testSeed != NULL) |
| 346 seed = testSeed; |
| 347 else |
| 348 #endif // TEST_RSA |
| 349 _cpri__GenerateRandom(hLen, mySeed); |
| 350 |
| 351 // mask = MGF1 (seed, nSize hLen 1) |
| 352 if((retVal = _cpri__MGF1(dbSize, mask, hashAlg, hLen, seed)) < 0) |
| 353 return retVal; // Don't expect an error because hash size is not zero |
| 354 // was detected in the call to _cpri__HashBlock() above. |
| 355 |
| 356 // Create the masked db |
| |
| Page 422 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 357 pm = mask; |
| 358 for(i = dbSize; i > 0; i--) |
| 359 *pp++ ^= *pm++; |
| 360 pp = &padded[hLen + 1]; |
| 361 |
| 362 // Run the masked data through MGF1 |
| 363 if((retVal = _cpri__MGF1(hLen, &padded[1], hashAlg, dbSize, pp)) < 0) |
| 364 return retVal; // Don't expect zero here as the only case for zero |
| 365 // was detected in the call to _cpri__HashBlock() above. |
| 366 |
| 367 // Now XOR the seed to create masked seed |
| 368 pp = &padded[1]; |
| 369 pm = seed; |
| 370 for(i = hLen; i > 0; i--) |
| 371 *pp++ ^= *pm++; |
| 372 |
| 373 // Set the first byte to zero |
| 374 *padded = 0x00; |
| 375 return CRYPT_SUCCESS; |
| 376 } |
| |
| |
| B.12.1.3.6. OaepDecode() |
| |
| This function performs OAEP padding checking. The size of the buffer to receive the recovered data. If |
| the padding is not valid, the dSize size is set to zero and the function returns CRYPT_NO_RESULTS. |
| The dSize parameter is used as an input to indicate the size available in the buffer. If insufficient space is |
| available, the size is not changed and the return code is CRYPT_FAIL. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS decode complete |
| CRYPT_PARAMETER the value to decode was larger than the modulus |
| CRYPT_FAIL the padding is wrong or the buffer to receive the results is too small |
| |
| 377 static CRYPT_RESULT |
| 378 OaepDecode( |
| 379 UINT32 *dataOutSize, // IN/OUT: the recovered data size |
| 380 BYTE *dataOut, // OUT: the recovered data |
| 381 TPM_ALG_ID hashAlg, // IN: algorithm to use for padding |
| 382 const char *label, // IN: null-terminated string (may be NULL) |
| 383 UINT32 paddedSize, // IN: the size of the padded data |
| 384 BYTE *padded // IN: the padded data |
| 385 ) |
| 386 { |
| 387 UINT32 dSizeSave; |
| 388 UINT32 i; |
| 389 BYTE seedMask[MAX_DIGEST_SIZE]; |
| 390 INT32 hLen = _cpri__GetDigestSize(hashAlg); |
| 391 |
| 392 BYTE mask[MAX_RSA_KEY_BYTES]; |
| 393 BYTE *pp; |
| 394 BYTE *pm; |
| 395 UINT32 lSize = 0; |
| 396 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 397 |
| 398 // Unknown hash |
| 399 pAssert(hLen > 0 && dataOutSize != NULL && dataOut != NULL && padded != NULL); |
| 400 |
| 401 // If there is a label, get its size including the terminating 0x00 |
| 402 if(label != NULL) |
| 403 lSize = (UINT32)strlen(label) + 1; |
| 404 |
| |
| Family "2.0" TCG Published Page 423 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 405 // Set the return size to zero so that it doesn't have to be done on each |
| 406 // failure |
| 407 dSizeSave = *dataOutSize; |
| 408 *dataOutSize = 0; |
| 409 |
| 410 // Strange size (anything smaller can't be an OAEP padded block) |
| 411 // Also check for no leading 0 |
| 412 if(paddedSize < (unsigned)((2 * hLen) + 2) || *padded != 0) |
| 413 return CRYPT_FAIL; |
| 414 |
| 415 // Use the hash size to determine what to put through MGF1 in order |
| 416 // to recover the seedMask |
| 417 if((retVal = _cpri__MGF1(hLen, seedMask, hashAlg, |
| 418 paddedSize-hLen-1, &padded[hLen+1])) < 0) |
| 419 return retVal; |
| 420 |
| 421 // Recover the seed into seedMask |
| 422 pp = &padded[1]; |
| 423 pm = seedMask; |
| 424 for(i = hLen; i > 0; i--) |
| 425 *pm++ ^= *pp++; |
| 426 |
| 427 // Use the seed to generate the data mask |
| 428 if((retVal = _cpri__MGF1(paddedSize-hLen-1, mask, hashAlg, |
| 429 hLen, seedMask)) < 0) |
| 430 return retVal; |
| 431 |
| 432 // Use the mask generated from seed to recover the padded data |
| 433 pp = &padded[hLen+1]; |
| 434 pm = mask; |
| 435 for(i = paddedSize-hLen-1; i > 0; i--) |
| 436 *pm++ ^= *pp++; |
| 437 |
| 438 // Make sure that the recovered data has the hash of the label |
| 439 // Put trial value in the seed mask |
| 440 if((retVal=_cpri__HashBlock(hashAlg, lSize,(BYTE *)label, hLen, seedMask)) < 0) |
| 441 return retVal; |
| 442 |
| 443 if(memcmp(seedMask, mask, hLen) != 0) |
| 444 return CRYPT_FAIL; |
| 445 |
| 446 // find the start of the data |
| 447 pm = &mask[hLen]; |
| 448 for(i = paddedSize-(2*hLen)-1; i > 0; i--) |
| 449 { |
| 450 if(*pm++ != 0) |
| 451 break; |
| 452 } |
| 453 if(i == 0) |
| 454 return CRYPT_PARAMETER; |
| 455 |
| 456 // pm should be pointing at the first part of the data |
| 457 // and i is one greater than the number of bytes to move |
| 458 i--; |
| 459 if(i > dSizeSave) |
| 460 { |
| 461 // Restore dSize |
| 462 *dataOutSize = dSizeSave; |
| 463 return CRYPT_FAIL; |
| 464 } |
| 465 memcpy(dataOut, pm, i); |
| 466 *dataOutSize = i; |
| 467 return CRYPT_SUCCESS; |
| 468 } |
| |
| |
| |
| Page 424 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| B.12.1.3.7. PKSC1v1_5Encode() |
| |
| This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS data encoded |
| CRYPT_PARAMETER message size is too large |
| |
| 469 static CRYPT_RESULT |
| 470 RSAES_PKSC1v1_5Encode( |
| 471 UINT32 paddedSize, // IN: pad value size |
| 472 BYTE *padded, // OUT: the pad data |
| 473 UINT32 messageSize, // IN: the message size |
| 474 BYTE *message // IN: the message being padded |
| 475 ) |
| 476 { |
| 477 UINT32 ps = paddedSize - messageSize - 3; |
| 478 if(messageSize > paddedSize - 11) |
| 479 return CRYPT_PARAMETER; |
| 480 |
| 481 // move the message to the end of the buffer |
| 482 memcpy(&padded[paddedSize - messageSize], message, messageSize); |
| 483 |
| 484 // Set the first byte to 0x00 and the second to 0x02 |
| 485 *padded = 0; |
| 486 padded[1] = 2; |
| 487 |
| 488 // Fill with random bytes |
| 489 _cpri__GenerateRandom(ps, &padded[2]); |
| 490 |
| 491 // Set the delimiter for the random field to 0 |
| 492 padded[2+ps] = 0; |
| 493 |
| 494 // Now, the only messy part. Make sure that all the ps bytes are non-zero |
| 495 // In this implementation, use the value of the current index |
| 496 for(ps++; ps > 1; ps--) |
| 497 { |
| 498 if(padded[ps] == 0) |
| 499 padded[ps] = 0x55; // In the < 0.5% of the cases that the random |
| 500 // value is 0, just pick a value to put into |
| 501 // the spot. |
| 502 } |
| 503 return CRYPT_SUCCESS; |
| 504 } |
| |
| |
| B.12.1.3.8. RSAES_Decode() |
| |
| This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS decode successful |
| CRYPT_FAIL decoding error or results would no fit into provided buffer |
| |
| 505 static CRYPT_RESULT |
| 506 RSAES_Decode( |
| 507 UINT32 *messageSize, // IN/OUT: recovered message size |
| 508 BYTE *message, // OUT: the recovered message |
| 509 UINT32 codedSize, // IN: the encoded message size |
| 510 BYTE *coded // IN: the encoded message |
| 511 ) |
| |
| Family "2.0" TCG Published Page 425 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 512 { |
| 513 BOOL fail = FALSE; |
| 514 UINT32 ps; |
| 515 |
| 516 fail = (codedSize < 11); |
| 517 fail |= (coded[0] != 0x00) || (coded[1] != 0x02); |
| 518 for(ps = 2; ps < codedSize; ps++) |
| 519 { |
| 520 if(coded[ps] == 0) |
| 521 break; |
| 522 } |
| 523 ps++; |
| 524 |
| 525 // Make sure that ps has not gone over the end and that there are at least 8 |
| 526 // bytes of pad data. |
| 527 fail |= ((ps >= codedSize) || ((ps-2) < 8)); |
| 528 if((*messageSize < codedSize - ps) || fail) |
| 529 return CRYPT_FAIL; |
| 530 |
| 531 *messageSize = codedSize - ps; |
| 532 memcpy(message, &coded[ps], codedSize - ps); |
| 533 return CRYPT_SUCCESS; |
| 534 } |
| |
| |
| B.12.1.3.9. PssEncode() |
| |
| This function creates an encoded block of data that is the size of modulus. The function uses the |
| maximum salt size that will fit in the encoded block. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS encode successful |
| CRYPT_PARAMETER hashAlg is not a supported hash algorithm |
| |
| 535 static CRYPT_RESULT |
| 536 PssEncode ( |
| 537 UINT32 eOutSize, // IN: size of the encode data buffer |
| 538 BYTE *eOut, // OUT: encoded data buffer |
| 539 TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding |
| 540 UINT32 hashInSize, // IN: size of digest to encode |
| 541 BYTE *hashIn // IN: the digest |
| 542 #ifdef TEST_RSA // |
| 543 , BYTE *saltIn // IN: optional parameter for testing |
| 544 #endif // TEST_RSA // |
| 545 ) |
| 546 { |
| 547 INT32 hLen = _cpri__GetDigestSize(hashAlg); |
| 548 BYTE salt[MAX_RSA_KEY_BYTES - 1]; |
| 549 UINT16 saltSize; |
| 550 BYTE *ps = salt; |
| 551 CRYPT_RESULT retVal; |
| 552 UINT16 mLen; |
| 553 CPRI_HASH_STATE hashState; |
| 554 |
| 555 // These are fatal errors indicating bad TPM firmware |
| 556 pAssert(eOut != NULL && hLen > 0 && hashIn != NULL ); |
| 557 |
| 558 // Get the size of the mask |
| 559 mLen = (UINT16)(eOutSize - hLen - 1); |
| 560 |
| 561 // Maximum possible salt size is mask length - 1 |
| 562 saltSize = mLen - 1; |
| 563 |
| |
| Page 426 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 564 // Use the maximum salt size allowed by FIPS 186-4 |
| 565 if(saltSize > hLen) |
| 566 saltSize = (UINT16)hLen; |
| 567 |
| 568 //using eOut for scratch space |
| 569 // Set the first 8 bytes to zero |
| 570 memset(eOut, 0, 8); |
| 571 |
| 572 // Get set the salt |
| 573 #ifdef TEST_RSA |
| 574 if(saltIn != NULL) |
| 575 { |
| 576 saltSize = hLen; |
| 577 memcpy(salt, saltIn, hLen); |
| 578 } |
| 579 else |
| 580 #endif // TEST_RSA |
| 581 _cpri__GenerateRandom(saltSize, salt); |
| 582 |
| 583 // Create the hash of the pad || input hash || salt |
| 584 _cpri__StartHash(hashAlg, FALSE, &hashState); |
| 585 _cpri__UpdateHash(&hashState, 8, eOut); |
| 586 _cpri__UpdateHash(&hashState, hashInSize, hashIn); |
| 587 _cpri__UpdateHash(&hashState, saltSize, salt); |
| 588 _cpri__CompleteHash(&hashState, hLen, &eOut[eOutSize - hLen - 1]); |
| 589 |
| 590 // Create a mask |
| 591 if((retVal = _cpri__MGF1(mLen, eOut, hashAlg, hLen, &eOut[mLen])) < 0) |
| 592 { |
| 593 // Currently _cpri__MGF1 is not expected to return a CRYPT_RESULT error. |
| 594 pAssert(0); |
| 595 } |
| 596 // Since this implementation uses key sizes that are all even multiples of |
| 597 // 8, just need to make sure that the most significant bit is CLEAR |
| 598 eOut[0] &= 0x7f; |
| 599 |
| 600 // Before we mess up the eOut value, set the last byte to 0xbc |
| 601 eOut[eOutSize - 1] = 0xbc; |
| 602 |
| 603 // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed |
| 604 eOut = &eOut[mLen - saltSize - 1]; |
| 605 *eOut++ ^= 0x01; |
| 606 |
| 607 // XOR the salt data into the buffer |
| 608 for(; saltSize > 0; saltSize--) |
| 609 *eOut++ ^= *ps++; |
| 610 |
| 611 // and we are done |
| 612 return CRYPT_SUCCESS; |
| 613 } |
| |
| |
| B.12.1.3.10. PssDecode() |
| |
| This function checks that the PSS encoded block was built from the provided digest. If the check is |
| successful, CRYPT_SUCCESS is returned. Any other value indicates an error. |
| This implementation of PSS decoding is intended for the reference TPM implementation and is not at all |
| generalized. It is used to check signatures over hashes and assumptions are made about the sizes of |
| values. Those assumptions are enforce by this implementation. This implementation does allow for a |
| variable size salt value to have been used by the creator of the signature. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 427 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS decode successful |
| CRYPT_SCHEME hashAlg is not a supported hash algorithm |
| CRYPT_FAIL decode operation failed |
| |
| 614 static CRYPT_RESULT |
| 615 PssDecode( |
| 616 TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding |
| 617 UINT32 dInSize, // IN: size of the digest to compare |
| 618 BYTE *dIn, // In: the digest to compare |
| 619 UINT32 eInSize, // IN: size of the encoded data |
| 620 BYTE *eIn, // IN: the encoded data |
| 621 UINT32 saltSize // IN: the expected size of the salt |
| 622 ) |
| 623 { |
| 624 INT32 hLen = _cpri__GetDigestSize(hashAlg); |
| 625 BYTE mask[MAX_RSA_KEY_BYTES]; |
| 626 BYTE *pm = mask; |
| 627 BYTE pad[8] = {0}; |
| 628 UINT32 i; |
| 629 UINT32 mLen; |
| 630 BOOL fail = FALSE; |
| 631 CRYPT_RESULT retVal; |
| 632 CPRI_HASH_STATE hashState; |
| 633 |
| 634 // These errors are indicative of failures due to programmer error |
| 635 pAssert(dIn != NULL && eIn != NULL); |
| 636 |
| 637 // check the hash scheme |
| 638 if(hLen == 0) |
| 639 return CRYPT_SCHEME; |
| 640 |
| 641 // most significant bit must be zero |
| 642 fail = ((eIn[0] & 0x80) != 0); |
| 643 |
| 644 // last byte must be 0xbc |
| 645 fail |= (eIn[eInSize - 1] != 0xbc); |
| 646 |
| 647 // Use the hLen bytes at the end of the buffer to generate a mask |
| 648 // Doesn't start at the end which is a flag byte |
| 649 mLen = eInSize - hLen - 1; |
| 650 if((retVal = _cpri__MGF1(mLen, mask, hashAlg, hLen, &eIn[mLen])) < 0) |
| 651 return retVal; |
| 652 if(retVal == 0) |
| 653 return CRYPT_FAIL; |
| 654 |
| 655 // Clear the MSO of the mask to make it consistent with the encoding. |
| 656 mask[0] &= 0x7F; |
| 657 |
| 658 // XOR the data into the mask to recover the salt. This sequence |
| 659 // advances eIn so that it will end up pointing to the seed data |
| 660 // which is the hash of the signature data |
| 661 for(i = mLen; i > 0; i--) |
| 662 *pm++ ^= *eIn++; |
| 663 |
| 664 // Find the first byte of 0x01 after a string of all 0x00 |
| 665 for(pm = mask, i = mLen; i > 0; i--) |
| 666 { |
| 667 if(*pm == 0x01) |
| 668 break; |
| 669 else |
| 670 fail |= (*pm++ != 0); |
| 671 } |
| |
| Page 428 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 672 fail |= (i == 0); |
| 673 |
| 674 // if we have failed, will continue using the entire mask as the salt value so |
| 675 // that the timing attacks will not disclose anything (I don't think that this |
| 676 // is a problem for TPM applications but, usually, we don't fail so this |
| 677 // doesn't cost anything). |
| 678 if(fail) |
| 679 { |
| 680 i = mLen; |
| 681 pm = mask; |
| 682 } |
| 683 else |
| 684 { |
| 685 pm++; |
| 686 i--; |
| 687 } |
| 688 // If the salt size was provided, then the recovered size must match |
| 689 fail |= (saltSize != 0 && i != saltSize); |
| 690 |
| 691 // i contains the salt size and pm points to the salt. Going to use the input |
| 692 // hash and the seed to recreate the hash in the lower portion of eIn. |
| 693 _cpri__StartHash(hashAlg, FALSE, &hashState); |
| 694 |
| 695 // add the pad of 8 zeros |
| 696 _cpri__UpdateHash(&hashState, 8, pad); |
| 697 |
| 698 // add the provided digest value |
| 699 _cpri__UpdateHash(&hashState, dInSize, dIn); |
| 700 |
| 701 // and the salt |
| 702 _cpri__UpdateHash(&hashState, i, pm); |
| 703 |
| 704 // get the result |
| 705 retVal = _cpri__CompleteHash(&hashState, MAX_DIGEST_SIZE, mask); |
| 706 |
| 707 // retVal will be the size of the digest or zero. If not equal to the indicated |
| 708 // digest size, then the signature doesn't match |
| 709 fail |= (retVal != hLen); |
| 710 fail |= (memcmp(mask, eIn, hLen) != 0); |
| 711 if(fail) |
| 712 return CRYPT_FAIL; |
| 713 else |
| 714 return CRYPT_SUCCESS; |
| 715 } |
| |
| |
| B.12.1.3.11. PKSC1v1_5SignEncode() |
| |
| Encode a message using PKCS1v1().5 method. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS encode complete |
| CRYPT_SCHEME hashAlg is not a supported hash algorithm |
| CRYPT_PARAMETER eOutSize is not large enough or hInSize does not match the digest |
| size of hashAlg |
| |
| 716 static CRYPT_RESULT |
| 717 RSASSA_Encode( |
| 718 UINT32 eOutSize, // IN: the size of the resulting block |
| 719 BYTE *eOut, // OUT: the encoded block |
| 720 TPM_ALG_ID hashAlg, // IN: hash algorithm for PKSC1v1_5 |
| 721 UINT32 hInSize, // IN: size of hash to be signed |
| 722 BYTE *hIn // IN: hash buffer |
| |
| Family "2.0" TCG Published Page 429 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 723 ) |
| 724 { |
| 725 BYTE *der; |
| 726 INT32 derSize = _cpri__GetHashDER(hashAlg, &der); |
| 727 INT32 fillSize; |
| 728 |
| 729 pAssert(eOut != NULL && hIn != NULL); |
| 730 |
| 731 // Can't use this scheme if the algorithm doesn't have a DER string defined. |
| 732 if(derSize == 0 ) |
| 733 return CRYPT_SCHEME; |
| 734 |
| 735 // If the digest size of 'hashAl' doesn't match the input digest size, then |
| 736 // the DER will misidentify the digest so return an error |
| 737 if((unsigned)_cpri__GetDigestSize(hashAlg) != hInSize) |
| 738 return CRYPT_PARAMETER; |
| 739 |
| 740 fillSize = eOutSize - derSize - hInSize - 3; |
| 741 |
| 742 // Make sure that this combination will fit in the provided space |
| 743 if(fillSize < 8) |
| 744 return CRYPT_PARAMETER; |
| 745 // Start filling |
| 746 *eOut++ = 0; // initial byte of zero |
| 747 *eOut++ = 1; // byte of 0x01 |
| 748 for(; fillSize > 0; fillSize--) |
| 749 *eOut++ = 0xff; // bunch of 0xff |
| 750 *eOut++ = 0; // another 0 |
| 751 for(; derSize > 0; derSize--) |
| 752 *eOut++ = *der++; // copy the DER |
| 753 for(; hInSize > 0; hInSize--) |
| 754 *eOut++ = *hIn++; // copy the hash |
| 755 return CRYPT_SUCCESS; |
| 756 } |
| |
| |
| B.12.1.3.12. RSASSA_Decode() |
| |
| This function performs the RSASSA decoding of a signature. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS decode successful |
| CRYPT_FAIL decode unsuccessful |
| CRYPT_SCHEME haslAlg is not supported |
| |
| 757 static CRYPT_RESULT |
| 758 RSASSA_Decode( |
| 759 TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding |
| 760 UINT32 hInSize, // IN: size of the digest to compare |
| 761 BYTE *hIn, // In: the digest to compare |
| 762 UINT32 eInSize, // IN: size of the encoded data |
| 763 BYTE *eIn // IN: the encoded data |
| 764 ) |
| 765 { |
| 766 BOOL fail = FALSE; |
| 767 BYTE *der; |
| 768 INT32 derSize = _cpri__GetHashDER(hashAlg, &der); |
| 769 INT32 hashSize = _cpri__GetDigestSize(hashAlg); |
| 770 INT32 fillSize; |
| 771 |
| 772 pAssert(hIn != NULL && eIn != NULL); |
| 773 |
| 774 // Can't use this scheme if the algorithm doesn't have a DER string |
| |
| Page 430 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 775 // defined or if the provided hash isn't the right size |
| 776 if(derSize == 0 || (unsigned)hashSize != hInSize) |
| 777 return CRYPT_SCHEME; |
| 778 |
| 779 // Make sure that this combination will fit in the provided space |
| 780 // Since no data movement takes place, can just walk though this |
| 781 // and accept nearly random values. This can only be called from |
| 782 // _cpri__ValidateSignature() so eInSize is known to be in range. |
| 783 fillSize = eInSize - derSize - hashSize - 3; |
| 784 |
| 785 // Start checking |
| 786 fail |= (*eIn++ != 0); // initial byte of zero |
| 787 fail |= (*eIn++ != 1); // byte of 0x01 |
| 788 for(; fillSize > 0; fillSize--) |
| 789 fail |= (*eIn++ != 0xff); // bunch of 0xff |
| 790 fail |= (*eIn++ != 0); // another 0 |
| 791 for(; derSize > 0; derSize--) |
| 792 fail |= (*eIn++ != *der++); // match the DER |
| 793 for(; hInSize > 0; hInSize--) |
| 794 fail |= (*eIn++ != *hIn++); // match the hash |
| 795 if(fail) |
| 796 return CRYPT_FAIL; |
| 797 return CRYPT_SUCCESS; |
| 798 } |
| |
| |
| B.12.1.4. Externally Accessible Functions |
| |
| B.12.1.4.1. _cpri__RsaStartup() |
| |
| Function that is called to initialize the hash service. In this implementation, this function does nothing but |
| it is called by the CryptUtilStartup() function and must be present. |
| |
| 799 LIB_EXPORT BOOL |
| 800 _cpri__RsaStartup( |
| 801 void |
| 802 ) |
| 803 { |
| 804 return TRUE; |
| 805 } |
| |
| |
| B.12.1.4.2. _cpri__EncryptRSA() |
| |
| This is the entry point for encryption using RSA. Encryption is use of the public exponent. The padding |
| parameter determines what padding will be used. |
| The cOutSize parameter must be at least as large as the size of the key. |
| If the padding is RSA_PAD_NONE, dIn is treaded as a number. It must be lower in value than the key |
| modulus. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 431 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to dIn to make it the size of the RSA key for |
| the call to RSAEP. This is because the high order bytes of dIn might have a numeric value that is greater than |
| the value of the key modulus. If this had low-order zeros added, it would have a numeric value larger than the |
| modulus even though it started out with a lower numeric value. |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS encryption complete |
| CRYPT_PARAMETER cOutSize is too small (must be the size of the modulus) |
| CRYPT_SCHEME padType is not a supported scheme |
| |
| 806 LIB_EXPORT CRYPT_RESULT |
| 807 _cpri__EncryptRSA( |
| 808 UINT32 *cOutSize, // OUT: the size of the encrypted data |
| 809 BYTE *cOut, // OUT: the encrypted data |
| 810 RSA_KEY *key, // IN: the key to use for encryption |
| 811 TPM_ALG_ID padType, // IN: the type of padding |
| 812 UINT32 dInSize, // IN: the amount of data to encrypt |
| 813 BYTE *dIn, // IN: the data to encrypt |
| 814 TPM_ALG_ID hashAlg, // IN: in case this is needed |
| 815 const char *label // IN: in case it is needed |
| 816 ) |
| 817 { |
| 818 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 819 |
| 820 pAssert(cOutSize != NULL); |
| 821 |
| 822 // All encryption schemes return the same size of data |
| 823 if(*cOutSize < key->publicKey->size) |
| 824 return CRYPT_PARAMETER; |
| 825 *cOutSize = key->publicKey->size; |
| 826 |
| 827 switch (padType) |
| 828 { |
| 829 case TPM_ALG_NULL: // 'raw' encryption |
| 830 { |
| 831 // dIn can have more bytes than cOut as long as the extra bytes |
| 832 // are zero |
| 833 for(; dInSize > *cOutSize; dInSize--) |
| 834 { |
| 835 if(*dIn++ != 0) |
| 836 return CRYPT_PARAMETER; |
| 837 |
| 838 } |
| 839 // If dIn is smaller than cOut, fill cOut with zeros |
| 840 if(dInSize < *cOutSize) |
| 841 memset(cOut, 0, *cOutSize - dInSize); |
| 842 |
| 843 // Copy the rest of the value |
| 844 memcpy(&cOut[*cOutSize-dInSize], dIn, dInSize); |
| 845 // If the size of dIn is the same as cOut dIn could be larger than |
| 846 // the modulus. If it is, then RSAEP() will catch it. |
| 847 } |
| 848 break; |
| 849 case TPM_ALG_RSAES: |
| 850 retVal = RSAES_PKSC1v1_5Encode(*cOutSize, cOut, dInSize, dIn); |
| 851 break; |
| 852 case TPM_ALG_OAEP: |
| 853 retVal = OaepEncode(*cOutSize, cOut, hashAlg, label, dInSize, dIn |
| 854 #ifdef TEST_RSA |
| 855 ,NULL |
| 856 #endif |
| 857 ); |
| 858 break; |
| |
| Page 432 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 859 default: |
| 860 return CRYPT_SCHEME; |
| 861 } |
| 862 // All the schemes that do padding will come here for the encryption step |
| 863 // Check that the Encoding worked |
| 864 if(retVal != CRYPT_SUCCESS) |
| 865 return retVal; |
| 866 |
| 867 // Padding OK so do the encryption |
| 868 return RSAEP(*cOutSize, cOut, key); |
| 869 } |
| |
| |
| B.12.1.4.3. _cpri__DecryptRSA() |
| |
| This is the entry point for decryption using RSA. Decryption is use of the private exponent. The padType |
| parameter determines what padding was used. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS successful completion |
| CRYPT_PARAMETER cInSize is not the same as the size of the public modulus of key; or |
| numeric value of the encrypted data is greater than the modulus |
| CRYPT_FAIL dOutSize is not large enough for the result |
| CRYPT_SCHEME padType is not supported |
| |
| 870 LIB_EXPORT CRYPT_RESULT |
| 871 _cpri__DecryptRSA( |
| 872 UINT32 *dOutSize, // OUT: the size of the decrypted data |
| 873 BYTE *dOut, // OUT: the decrypted data |
| 874 RSA_KEY *key, // IN: the key to use for decryption |
| 875 TPM_ALG_ID padType, // IN: the type of padding |
| 876 UINT32 cInSize, // IN: the amount of data to decrypt |
| 877 BYTE *cIn, // IN: the data to decrypt |
| 878 TPM_ALG_ID hashAlg, // IN: in case this is needed for the scheme |
| 879 const char *label // IN: in case it is needed for the scheme |
| 880 ) |
| 881 { |
| 882 CRYPT_RESULT retVal; |
| 883 |
| 884 // Make sure that the necessary parameters are provided |
| 885 pAssert(cIn != NULL && dOut != NULL && dOutSize != NULL && key != NULL); |
| 886 |
| 887 // Size is checked to make sure that the decryption works properly |
| 888 if(cInSize != key->publicKey->size) |
| 889 return CRYPT_PARAMETER; |
| 890 |
| 891 // For others that do padding, do the decryption in place and then |
| 892 // go handle the decoding. |
| 893 if((retVal = RSADP(cInSize, cIn, key)) != CRYPT_SUCCESS) |
| 894 return retVal; // Decryption failed |
| 895 |
| 896 // Remove padding |
| 897 switch (padType) |
| 898 { |
| 899 case TPM_ALG_NULL: |
| 900 if(*dOutSize < key->publicKey->size) |
| 901 return CRYPT_FAIL; |
| 902 *dOutSize = key->publicKey->size; |
| 903 memcpy(dOut, cIn, *dOutSize); |
| 904 return CRYPT_SUCCESS; |
| 905 case TPM_ALG_RSAES: |
| 906 return RSAES_Decode(dOutSize, dOut, cInSize, cIn); |
| |
| Family "2.0" TCG Published Page 433 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 907 break; |
| 908 case TPM_ALG_OAEP: |
| 909 return OaepDecode(dOutSize, dOut, hashAlg, label, cInSize, cIn); |
| 910 break; |
| 911 default: |
| 912 return CRYPT_SCHEME; |
| 913 break; |
| 914 } |
| 915 } |
| |
| |
| B.12.1.4.4. _cpri__SignRSA() |
| |
| This function is used to generate an RSA signature of the type indicated in scheme. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS sign operation completed normally |
| CRYPT_SCHEME scheme or hashAlg are not supported |
| CRYPT_PARAMETER hInSize does not match hashAlg (for RSASSA) |
| |
| 916 LIB_EXPORT CRYPT_RESULT |
| 917 _cpri__SignRSA( |
| 918 UINT32 *sigOutSize, // OUT: size of signature |
| 919 BYTE *sigOut, // OUT: signature |
| 920 RSA_KEY *key, // IN: key to use |
| 921 TPM_ALG_ID scheme, // IN: the scheme to use |
| 922 TPM_ALG_ID hashAlg, // IN: hash algorithm for PKSC1v1_5 |
| 923 UINT32 hInSize, // IN: size of digest to be signed |
| 924 BYTE *hIn // IN: digest buffer |
| 925 ) |
| 926 { |
| 927 CRYPT_RESULT retVal; |
| 928 |
| 929 // Parameter checks |
| 930 pAssert(sigOutSize != NULL && sigOut != NULL && key != NULL && hIn != NULL); |
| 931 |
| 932 // For all signatures the size is the size of the key modulus |
| 933 *sigOutSize = key->publicKey->size; |
| 934 switch (scheme) |
| 935 { |
| 936 case TPM_ALG_NULL: |
| 937 *sigOutSize = 0; |
| 938 return CRYPT_SUCCESS; |
| 939 case TPM_ALG_RSAPSS: |
| 940 // PssEncode can return CRYPT_PARAMETER |
| 941 retVal = PssEncode(*sigOutSize, sigOut, hashAlg, hInSize, hIn |
| 942 #ifdef TEST_RSA |
| 943 , NULL |
| 944 #endif |
| 945 ); |
| 946 break; |
| 947 case TPM_ALG_RSASSA: |
| 948 // RSASSA_Encode can return CRYPT_PARAMETER or CRYPT_SCHEME |
| 949 retVal = RSASSA_Encode(*sigOutSize, sigOut, hashAlg, hInSize, hIn); |
| 950 break; |
| 951 default: |
| 952 return CRYPT_SCHEME; |
| 953 } |
| 954 if(retVal != CRYPT_SUCCESS) |
| 955 return retVal; |
| 956 // Do the encryption using the private key |
| 957 // RSADP can return CRYPT_PARAMETR |
| 958 return RSADP(*sigOutSize,sigOut, key); |
| |
| Page 434 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 959 } |
| |
| |
| B.12.1.4.5. _cpri__ValidateSignatureRSA() |
| |
| This function is used to validate an RSA signature. If the signature is valid CRYPT_SUCCESS is |
| returned. If the signature is not valid, CRYPT_FAIL is returned. Other return codes indicate either |
| parameter problems or fatal errors. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS the signature checks |
| CRYPT_FAIL the signature does not check |
| CRYPT_SCHEME unsupported scheme or hash algorithm |
| |
| 960 LIB_EXPORT CRYPT_RESULT |
| 961 _cpri__ValidateSignatureRSA( |
| 962 RSA_KEY *key, // IN: key to use |
| 963 TPM_ALG_ID scheme, // IN: the scheme to use |
| 964 TPM_ALG_ID hashAlg, // IN: hash algorithm |
| 965 UINT32 hInSize, // IN: size of digest to be checked |
| 966 BYTE *hIn, // IN: digest buffer |
| 967 UINT32 sigInSize, // IN: size of signature |
| 968 BYTE *sigIn, // IN: signature |
| 969 UINT16 saltSize // IN: salt size for PSS |
| 970 ) |
| 971 { |
| 972 CRYPT_RESULT retVal; |
| 973 |
| 974 // Fatal programming errors |
| 975 pAssert(key != NULL && sigIn != NULL && hIn != NULL); |
| 976 |
| 977 // Errors that might be caused by calling parameters |
| 978 if(sigInSize != key->publicKey->size) |
| 979 return CRYPT_FAIL; |
| 980 // Decrypt the block |
| 981 if((retVal = RSAEP(sigInSize, sigIn, key)) != CRYPT_SUCCESS) |
| 982 return CRYPT_FAIL; |
| 983 switch (scheme) |
| 984 { |
| 985 case TPM_ALG_NULL: |
| 986 return CRYPT_SCHEME; |
| 987 break; |
| 988 case TPM_ALG_RSAPSS: |
| 989 return PssDecode(hashAlg, hInSize, hIn, sigInSize, sigIn, saltSize); |
| 990 break; |
| 991 case TPM_ALG_RSASSA: |
| 992 return RSASSA_Decode(hashAlg, hInSize, hIn, sigInSize, sigIn); |
| 993 break; |
| 994 default: |
| 995 break; |
| 996 } |
| 997 return CRYPT_SCHEME; |
| 998 } |
| 999 #ifndef RSA_KEY_SIEVE |
| |
| |
| B.12.1.4.6. _cpri__GenerateKeyRSA() |
| |
| Generate an RSA key from a provided seed |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 435 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| CRYPT_FAIL exponent is not prime or is less than 3; or could not find a prime using |
| the provided parameters |
| CRYPT_CANCEL operation was canceled |
| |
| 1000 LIB_EXPORT CRYPT_RESULT |
| 1001 _cpri__GenerateKeyRSA( |
| 1002 TPM2B *n, // OUT: The public modulu |
| 1003 TPM2B *p, // OUT: One of the prime factors of n |
| 1004 UINT16 keySizeInBits, // IN: Size of the public modulus in bit |
| 1005 UINT32 e, // IN: The public exponent |
| 1006 TPM_ALG_ID hashAlg, // IN: hash algorithm to use in the key |
| 1007 // generation proce |
| 1008 TPM2B *seed, // IN: the seed to use |
| 1009 const char *label, // IN: A label for the generation process. |
| 1010 TPM2B *extra, // IN: Party 1 data for the KDF |
| 1011 UINT32 *counter // IN/OUT: Counter value to allow KFD iteration |
| 1012 // to be propagated across multiple routine |
| 1013 ) |
| 1014 { |
| 1015 UINT32 lLen; // length of the label |
| 1016 // (counting the terminating 0); |
| 1017 UINT16 digestSize = _cpri__GetDigestSize(hashAlg); |
| 1018 |
| 1019 TPM2B_HASH_BLOCK oPadKey; |
| 1020 |
| 1021 UINT32 outer; |
| 1022 UINT32 inner; |
| 1023 BYTE swapped[4]; |
| 1024 |
| 1025 CRYPT_RESULT retVal; |
| 1026 int i, fill; |
| 1027 const static char defaultLabel[] = "RSA key"; |
| 1028 BYTE *pb; |
| 1029 |
| 1030 CPRI_HASH_STATE h1; // contains the hash of the |
| 1031 // HMAC key w/ iPad |
| 1032 CPRI_HASH_STATE h2; // contains the hash of the |
| 1033 // HMAC key w/ oPad |
| 1034 CPRI_HASH_STATE h; // the working hash context |
| 1035 |
| 1036 BIGNUM *bnP; |
| 1037 BIGNUM *bnQ; |
| 1038 BIGNUM *bnT; |
| 1039 BIGNUM *bnE; |
| 1040 BIGNUM *bnN; |
| 1041 BN_CTX *context; |
| 1042 UINT32 rem; |
| 1043 |
| 1044 // Make sure that hashAlg is valid hash |
| 1045 pAssert(digestSize != 0); |
| 1046 |
| 1047 // if present, use externally provided counter |
| 1048 if(counter != NULL) |
| 1049 outer = *counter; |
| 1050 else |
| 1051 outer = 1; |
| 1052 |
| 1053 // Validate exponent |
| 1054 UINT32_TO_BYTE_ARRAY(e, swapped); |
| 1055 |
| 1056 // Need to check that the exponent is prime and not less than 3 |
| 1057 if( e != 0 && (e < 3 || !_math__IsPrime(e))) |
| |
| Page 436 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1058 return CRYPT_FAIL; |
| 1059 |
| 1060 // Get structures for the big number representations |
| 1061 context = BN_CTX_new(); |
| 1062 if(context == NULL) |
| 1063 FAIL(FATAL_ERROR_ALLOCATION); |
| 1064 BN_CTX_start(context); |
| 1065 bnP = BN_CTX_get(context); |
| 1066 bnQ = BN_CTX_get(context); |
| 1067 bnT = BN_CTX_get(context); |
| 1068 bnE = BN_CTX_get(context); |
| 1069 bnN = BN_CTX_get(context); |
| 1070 if(bnN == NULL) |
| 1071 FAIL(FATAL_ERROR_INTERNAL); |
| 1072 |
| 1073 // Set Q to zero. This is used as a flag. The prime is computed in P. When a |
| 1074 // new prime is found, Q is checked to see if it is zero. If so, P is copied |
| 1075 // to Q and a new P is found. When both P and Q are non-zero, the modulus and |
| 1076 // private exponent are computed and a trial encryption/decryption is |
| 1077 // performed. If the encrypt/decrypt fails, assume that at least one of the |
| 1078 // primes is composite. Since we don't know which one, set Q to zero and start |
| 1079 // over and find a new pair of primes. |
| 1080 BN_zero(bnQ); |
| 1081 |
| 1082 // Need to have some label |
| 1083 if(label == NULL) |
| 1084 label = (const char *)&defaultLabel; |
| 1085 // Get the label size |
| 1086 for(lLen = 0; label[lLen++] != 0;); |
| 1087 |
| 1088 // Start the hash using the seed and get the intermediate hash value |
| 1089 _cpri__StartHMAC(hashAlg, FALSE, &h1, seed->size, seed->buffer, &oPadKey.b); |
| 1090 _cpri__StartHash(hashAlg, FALSE, &h2); |
| 1091 _cpri__UpdateHash(&h2, oPadKey.b.size, oPadKey.b.buffer); |
| 1092 |
| 1093 n->size = (keySizeInBits +7)/8; |
| 1094 pAssert(n->size <= MAX_RSA_KEY_BYTES); |
| 1095 p->size = n->size / 2; |
| 1096 if(e == 0) |
| 1097 e = RSA_DEFAULT_PUBLIC_EXPONENT; |
| 1098 |
| 1099 BN_set_word(bnE, e); |
| 1100 |
| 1101 // The first test will increment the counter from zero. |
| 1102 for(outer += 1; outer != 0; outer++) |
| 1103 { |
| 1104 if(_plat__IsCanceled()) |
| 1105 { |
| 1106 retVal = CRYPT_CANCEL; |
| 1107 goto Cleanup; |
| 1108 } |
| 1109 |
| 1110 // Need to fill in the candidate with the hash |
| 1111 fill = digestSize; |
| 1112 pb = p->buffer; |
| 1113 |
| 1114 // Reset the inner counter |
| 1115 inner = 0; |
| 1116 for(i = p->size; i > 0; i -= digestSize) |
| 1117 { |
| 1118 inner++; |
| 1119 // Initialize the HMAC with saved state |
| 1120 _cpri__CopyHashState(&h, &h1); |
| 1121 |
| 1122 // Hash the inner counter (the one that changes on each HMAC iteration) |
| 1123 UINT32_TO_BYTE_ARRAY(inner, swapped); |
| |
| Family "2.0" TCG Published Page 437 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1124 _cpri__UpdateHash(&h, 4, swapped); |
| 1125 _cpri__UpdateHash(&h, lLen, (BYTE *)label); |
| 1126 |
| 1127 // Is there any party 1 data |
| 1128 if(extra != NULL) |
| 1129 _cpri__UpdateHash(&h, extra->size, extra->buffer); |
| 1130 |
| 1131 // Include the outer counter (the one that changes on each prime |
| 1132 // prime candidate generation |
| 1133 UINT32_TO_BYTE_ARRAY(outer, swapped); |
| 1134 _cpri__UpdateHash(&h, 4, swapped); |
| 1135 _cpri__UpdateHash(&h, 2, (BYTE *)&keySizeInBits); |
| 1136 if(i < fill) |
| 1137 fill = i; |
| 1138 _cpri__CompleteHash(&h, fill, pb); |
| 1139 |
| 1140 // Restart the oPad hash |
| 1141 _cpri__CopyHashState(&h, &h2); |
| 1142 |
| 1143 // Add the last hashed data |
| 1144 _cpri__UpdateHash(&h, fill, pb); |
| 1145 |
| 1146 // gives a completed HMAC |
| 1147 _cpri__CompleteHash(&h, fill, pb); |
| 1148 pb += fill; |
| 1149 } |
| 1150 // Set the Most significant 2 bits and the low bit of the candidate |
| 1151 p->buffer[0] |= 0xC0; |
| 1152 p->buffer[p->size - 1] |= 1; |
| 1153 |
| 1154 // Convert the candidate to a BN |
| 1155 BN_bin2bn(p->buffer, p->size, bnP); |
| 1156 |
| 1157 // If this is the second prime, make sure that it differs from the |
| 1158 // first prime by at least 2^100 |
| 1159 if(!BN_is_zero(bnQ)) |
| 1160 { |
| 1161 // bnQ is non-zero if we already found it |
| 1162 if(BN_ucmp(bnP, bnQ) < 0) |
| 1163 BN_sub(bnT, bnQ, bnP); |
| 1164 else |
| 1165 BN_sub(bnT, bnP, bnQ); |
| 1166 if(BN_num_bits(bnT) < 100) // Difference has to be at least 100 bits |
| 1167 continue; |
| 1168 } |
| 1169 // Make sure that the prime candidate (p) is not divisible by the exponent |
| 1170 // and that (p-1) is not divisible by the exponent |
| 1171 // Get the remainder after dividing by the modulus |
| 1172 rem = BN_mod_word(bnP, e); |
| 1173 if(rem == 0) // evenly divisible so add two keeping the number odd and |
| 1174 // making sure that 1 != p mod e |
| 1175 BN_add_word(bnP, 2); |
| 1176 else if(rem == 1) // leaves a remainder of 1 so subtract two keeping the |
| 1177 // number odd and making (e-1) = p mod e |
| 1178 BN_sub_word(bnP, 2); |
| 1179 |
| 1180 // Have a candidate, check for primality |
| 1181 if((retVal = (CRYPT_RESULT)BN_is_prime_ex(bnP, |
| 1182 BN_prime_checks, NULL, NULL)) < 0) |
| 1183 FAIL(FATAL_ERROR_INTERNAL); |
| 1184 |
| 1185 if(retVal != 1) |
| 1186 continue; |
| 1187 |
| 1188 // Found a prime, is this the first or second. |
| 1189 if(BN_is_zero(bnQ)) |
| |
| Page 438 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1190 { |
| 1191 // copy p to q and compute another prime in p |
| 1192 BN_copy(bnQ, bnP); |
| 1193 continue; |
| 1194 } |
| 1195 //Form the public modulus |
| 1196 BN_mul(bnN, bnP, bnQ, context); |
| 1197 if(BN_num_bits(bnN) != keySizeInBits) |
| 1198 FAIL(FATAL_ERROR_INTERNAL); |
| 1199 |
| 1200 // Save the public modulus |
| 1201 BnTo2B(n, bnN, n->size); // Will pad the buffer to the correct size |
| 1202 pAssert((n->buffer[0] & 0x80) != 0); |
| 1203 |
| 1204 // And one prime |
| 1205 BnTo2B(p, bnP, p->size); |
| 1206 pAssert((p->buffer[0] & 0x80) != 0); |
| 1207 |
| 1208 // Finish by making sure that we can form the modular inverse of PHI |
| 1209 // with respect to the public exponent |
| 1210 // Compute PHI = (p - 1)(q - 1) = n - p - q + 1 |
| 1211 // Make sure that we can form the modular inverse |
| 1212 BN_sub(bnT, bnN, bnP); |
| 1213 BN_sub(bnT, bnT, bnQ); |
| 1214 BN_add_word(bnT, 1); |
| 1215 |
| 1216 // find d such that (Phi * d) mod e ==1 |
| 1217 // If there isn't then we are broken because we took the step |
| 1218 // of making sure that the prime != 1 mod e so the modular inverse |
| 1219 // must exist |
| 1220 if(BN_mod_inverse(bnT, bnE, bnT, context) == NULL || BN_is_zero(bnT)) |
| 1221 FAIL(FATAL_ERROR_INTERNAL); |
| 1222 |
| 1223 // And, finally, do a trial encryption decryption |
| 1224 { |
| 1225 TPM2B_TYPE(RSA_KEY, MAX_RSA_KEY_BYTES); |
| 1226 TPM2B_RSA_KEY r; |
| 1227 r.t.size = sizeof(n->size); |
| 1228 |
| 1229 // If we are using a seed, then results must be reproducible on each |
| 1230 // call. Otherwise, just get a random number |
| 1231 if(seed == NULL) |
| 1232 _cpri__GenerateRandom(n->size, r.t.buffer); |
| 1233 else |
| 1234 { |
| 1235 // this this version does not have a deterministic RNG, XOR the |
| 1236 // public key and private exponent to get a deterministic value |
| 1237 // for testing. |
| 1238 int i; |
| 1239 |
| 1240 // Generate a random-ish number starting with the public modulus |
| 1241 // XORed with the MSO of the seed |
| 1242 for(i = 0; i < n->size; i++) |
| 1243 r.t.buffer[i] = n->buffer[i] ^ seed->buffer[0]; |
| 1244 } |
| 1245 // Make sure that the number is smaller than the public modulus |
| 1246 r.t.buffer[0] &= 0x7F; |
| 1247 // Convert |
| 1248 if( BN_bin2bn(r.t.buffer, r.t.size, bnP) == NULL |
| 1249 // Encrypt with the public exponent |
| 1250 || BN_mod_exp(bnQ, bnP, bnE, bnN, context) != 1 |
| 1251 // Decrypt with the private exponent |
| 1252 || BN_mod_exp(bnQ, bnQ, bnT, bnN, context) != 1) |
| 1253 FAIL(FATAL_ERROR_INTERNAL); |
| 1254 // If the starting and ending values are not the same, start over )-; |
| 1255 if(BN_ucmp(bnP, bnQ) != 0) |
| |
| Family "2.0" TCG Published Page 439 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1256 { |
| 1257 BN_zero(bnQ); |
| 1258 continue; |
| 1259 } |
| 1260 } |
| 1261 retVal = CRYPT_SUCCESS; |
| 1262 goto Cleanup; |
| 1263 } |
| 1264 retVal = CRYPT_FAIL; |
| 1265 |
| 1266 Cleanup: |
| 1267 // Close out the hash sessions |
| 1268 _cpri__CompleteHash(&h2, 0, NULL); |
| 1269 _cpri__CompleteHash(&h1, 0, NULL); |
| 1270 |
| 1271 // Free up allocated BN values |
| 1272 BN_CTX_end(context); |
| 1273 BN_CTX_free(context); |
| 1274 if(counter != NULL) |
| 1275 *counter = outer; |
| 1276 return retVal; |
| 1277 } |
| 1278 #endif // RSA_KEY_SIEVE |
| 1279 #endif // TPM_ALG_RSA |
| |
| |
| B.12.2. Alternative RSA Key Generation |
| |
| B.12.2.1. Introduction |
| |
| The files in this clause implement an alternative RSA key generation method that is about an order of |
| magnitude faster than the regular method in B.14.1 and is provided simply to speed testing of the test |
| functions. The method implemented in this clause uses a sieve rather than choosing prime candidates at |
| random and testing for primeness. In this alternative, the sieve filed starting address is chosen at random |
| and a sieve operation is performed on the field using small prime values. After sieving, the bits |
| representing values that are not divisible by the small primes tested, will be checked in a pseudo-random |
| order until a prime is found. |
| The size of the sieve field is tunable as is the value indicating the number of primes that should be |
| checked. As the size of the prime increases, the density of primes is reduced so the size of the sieve field |
| should be increased to improve the probability that the field will contain at least one prime. In addition, as |
| the sieve field increases the number of small primes that should be checked increases. Eliminating a |
| number from consideration by using division is considerably faster than eliminating the number with a |
| Miller-Rabin test. |
| |
| B.12.2.2. RSAKeySieve.h |
| |
| This header file is used to for parameterization of the Sieve and RNG used by the RSA module |
| |
| 1 #ifndef RSA_H |
| 2 #define RSA_H |
| |
| This value is used to set the size of the table that is searched by the prime iterator. This is used during |
| the generation of different primes. The smaller tables are used when generating smaller primes. |
| |
| 3 extern const UINT16 primeTableBytes; |
| |
| The following define determines how large the prime number difference table will be defined. The value of |
| 13 will allocate the maximum size table which allows generation of the first 6542 primes which is all the |
| primes less than 2^16. |
| |
| Page 440 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 4 #define PRIME_DIFF_TABLE_512_BYTE_PAGES 13 |
| |
| This set of macros used the value above to set the table size. |
| |
| 5 #ifndef PRIME_DIFF_TABLE_512_BYTE_PAGES |
| 6 # define PRIME_DIFF_TABLE_512_BYTE_PAGES 4 |
| 7 #endif |
| 8 #ifdef PRIME_DIFF_TABLE_512_BYTE_PAGES |
| 9 # if PRIME_DIFF_TABLE_512_BYTE_PAGES > 12 |
| 10 # define PRIME_DIFF_TABLE_BYTES 6542 |
| 11 # else |
| 12 # if PRIME_DIFF_TABLE_512_BYTE_PAGES <= 0 |
| 13 # define PRIME_DIFF_TABLE_BYTES 512 |
| 14 # else |
| 15 # define PRIME_DIFF_TABLE_BYTES (PRIME_DIFF_TABLE_512_BYTE_PAGES * 512) |
| 16 # endif |
| 17 # endif |
| 18 #endif |
| 19 extern const BYTE primeDiffTable [PRIME_DIFF_TABLE_BYTES]; |
| |
| This determines the number of bits in the sieve field This must be a power of two. |
| |
| 20 #define FIELD_POWER 14 // This is the only value in this group that should be |
| 21 // changed |
| 22 #define FIELD_BITS (1 << FIELD_POWER) |
| 23 #define MAX_FIELD_SIZE ((FIELD_BITS / 8) + 1) |
| |
| This is the pre-sieved table. It already has the bits for multiples of 3, 5, and 7 cleared. |
| |
| 24 #define SEED_VALUES_SIZE 105 |
| 25 const extern BYTE seedValues[SEED_VALUES_SIZE]; |
| |
| This allows determination of the number of bits that are set in a byte without having to count them |
| individually. |
| |
| 26 const extern BYTE bitsInByte[256]; |
| |
| This is the iterator structure for accessing the compressed prime number table. The expectation is that |
| values will need to be accesses sequentially. This tries to save some data access. |
| |
| 27 typedef struct { |
| 28 UINT32 lastPrime; |
| 29 UINT32 index; |
| 30 UINT32 final; |
| 31 } PRIME_ITERATOR; |
| 32 #ifdef RSA_INSTRUMENT |
| 33 # define INSTRUMENT_SET(a, b) ((a) = (b)) |
| 34 # define INSTRUMENT_ADD(a, b) (a) = (a) + (b) |
| 35 # define INSTRUMENT_INC(a) (a) = (a) + 1 |
| 36 extern UINT32 failedAtIteration[10]; |
| 37 extern UINT32 MillerRabinTrials; |
| 38 extern UINT32 totalFieldsSieved; |
| 39 extern UINT32 emptyFieldsSieved; |
| 40 extern UINT32 noPrimeFields; |
| 41 extern UINT32 primesChecked; |
| 42 extern UINT16 lastSievePrime; |
| 43 #else |
| 44 # define INSTRUMENT_SET(a, b) |
| 45 # define INSTRUMENT_ADD(a, b) |
| 46 # define INSTRUMENT_INC(a) |
| 47 #endif |
| 48 #ifdef RSA_DEBUG |
| 49 extern UINT16 defaultFieldSize; |
| |
| Family "2.0" TCG Published Page 441 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 50 #define NUM_PRIMES 2047 |
| 51 extern const __int16 primes[NUM_PRIMES]; |
| 52 #else |
| 53 #define defaultFieldSize MAX_FIELD_SIZE |
| 54 #endif |
| 55 #endif |
| |
| |
| |
| |
| Page 442 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.12.2.3. RSAKeySieve.c |
| |
| B.12.2.3.1. Includes and defines |
| |
| 1 #include "OsslCryptoEngine.h" |
| 2 #ifdef TPM_ALG_RSA |
| |
| This file produces no code unless the compile switch is set to cause it to generate code. |
| |
| 3 #ifdef RSA_KEY_SIEVE //% |
| 4 #include "RsaKeySieve.h" |
| |
| This next line will show up in the header file for this code. It will make the local functions public when |
| debugging. |
| |
| 5 //%#ifdef RSA_DEBUG |
| |
| |
| B.12.2.3.2. Bit Manipulation Functions |
| |
| B.12.2.3.2.1. Introduction |
| |
| These functions operate on a bit array. A bit array is an array of bytes with the 0th byte being the byte |
| with the lowest memory address. Within the byte, bit 0 is the least significant bit. |
| |
| B.12.2.3.2.2. ClearBit() |
| |
| This function will CLEAR a bit in a bit array. |
| |
| 6 void |
| 7 ClearBit( |
| 8 unsigned char *a, // IN: A pointer to an array of byte |
| 9 int i // IN: the number of the bit to CLEAR |
| 10 ) |
| 11 { |
| 12 a[i >> 3] &= 0xff ^ (1 << (i & 7)); |
| 13 } |
| |
| |
| B.12.2.3.2.3. SetBit() |
| |
| Function to SET a bit in a bit array. |
| |
| 14 void |
| 15 SetBit( |
| 16 unsigned char *a, // IN: A pointer to an array of byte |
| 17 int i // IN: the number of the bit to SET |
| 18 ) |
| 19 { |
| 20 a[i >> 3] |= (1 << (i & 7)); |
| 21 } |
| |
| |
| B.12.2.3.2.4. IsBitSet() |
| |
| Function to test if a bit in a bit array is SET. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 443 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| 0 bit is CLEAR |
| 1 bit is SET |
| |
| 22 UINT32 |
| 23 IsBitSet( |
| 24 unsigned char *a, // IN: A pointer to an array of byte |
| 25 int i // IN: the number of the bit to test |
| 26 ) |
| 27 { |
| 28 return ((a[i >> 3] & (1 << (i & 7))) != 0); |
| 29 } |
| |
| |
| B.12.2.3.2.5. BitsInArry() |
| |
| This function counts the number of bits set in an array of bytes. |
| |
| 30 int |
| 31 BitsInArray( |
| 32 unsigned char *a, // IN: A pointer to an array of byte |
| 33 int i // IN: the number of bytes to sum |
| 34 ) |
| 35 { |
| 36 int j = 0; |
| 37 for(; i ; i--) |
| 38 j += bitsInByte[*a++]; |
| 39 return j; |
| 40 } |
| |
| |
| B.12.2.3.2.6. FindNthSetBit() |
| |
| This function finds the nth SET bit in a bit array. The caller should check that the offset of the returned |
| value is not out of range. If called when the array does not have n bits set, it will return a fatal error |
| |
| 41 UINT32 |
| 42 FindNthSetBit( |
| 43 const UINT16 aSize, // IN: the size of the array to check |
| 44 const BYTE *a, // IN: the array to check |
| 45 const UINT32 n // IN, the number of the SET bit |
| 46 ) |
| 47 { |
| 48 UINT32 i; |
| 49 const BYTE *pA = a; |
| 50 UINT32 retValue; |
| 51 BYTE sel; |
| 52 |
| 53 (aSize); |
| 54 |
| 55 //find the bit |
| 56 for(i = 0; i < n; i += bitsInByte[*pA++]); |
| 57 |
| 58 // The chosen bit is in the byte that was just accessed |
| 59 // Compute the offset to the start of that byte |
| 60 pA--; |
| 61 retValue = (UINT32)(pA - a) * 8; |
| 62 |
| 63 // Subtract the bits in the last byte added. |
| 64 i -= bitsInByte[*pA]; |
| 65 |
| 66 // Now process the byte, one bit at a time. |
| |
| Page 444 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 67 for(sel = *pA; sel != 0 ; sel = sel >> 1) |
| 68 { |
| 69 if(sel & 1) |
| 70 { |
| 71 i += 1; |
| 72 if(i == n) |
| 73 return retValue; |
| 74 } |
| 75 retValue += 1; |
| 76 } |
| 77 FAIL(FATAL_ERROR_INTERNAL); |
| 78 } |
| |
| |
| B.12.2.3.3. Miscellaneous Functions |
| |
| B.12.2.3.3.1. RandomForRsa() |
| |
| This function uses a special form of KDFa() to produces a pseudo random sequence. It's input is a |
| structure that contains pointers to a pre-computed set of hash contexts that are set up for the HMAC |
| computations using the seed. |
| This function will test that ktx.outer will not wrap to zero if incremented. If so, the function returns FALSE. |
| Otherwise, the ktx.outer is incremented before each number is generated. |
| |
| 79 void |
| 80 RandomForRsa( |
| 81 KDFa_CONTEXT *ktx, // IN: a context for the KDF |
| 82 const char *label, // IN: a use qualifying label |
| 83 TPM2B *p // OUT: the pseudo random result |
| 84 ) |
| 85 { |
| 86 INT16 i; |
| 87 UINT32 inner; |
| 88 BYTE swapped[4]; |
| 89 UINT16 fill; |
| 90 BYTE *pb; |
| 91 UINT16 lLen = 0; |
| 92 UINT16 digestSize = _cpri__GetDigestSize(ktx->hashAlg); |
| 93 CPRI_HASH_STATE h; // the working hash context |
| 94 |
| 95 if(label != NULL) |
| 96 for(lLen = 0; label[lLen++];); |
| 97 fill = digestSize; |
| 98 pb = p->buffer; |
| 99 inner = 0; |
| 100 *(ktx->outer) += 1; |
| 101 for(i = p->size; i > 0; i -= digestSize) |
| 102 { |
| 103 inner++; |
| 104 |
| 105 // Initialize the HMAC with saved state |
| 106 _cpri__CopyHashState(&h, &(ktx->iPadCtx)); |
| 107 |
| 108 // Hash the inner counter (the one that changes on each HMAC iteration) |
| 109 UINT32_TO_BYTE_ARRAY(inner, swapped); |
| 110 _cpri__UpdateHash(&h, 4, swapped); |
| 111 if(lLen != 0) |
| 112 _cpri__UpdateHash(&h, lLen, (BYTE *)label); |
| 113 |
| 114 // Is there any party 1 data |
| 115 if(ktx->extra != NULL) |
| 116 _cpri__UpdateHash(&h, ktx->extra->size, ktx->extra->buffer); |
| 117 |
| |
| Family "2.0" TCG Published Page 445 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 118 // Include the outer counter (the one that changes on each prime |
| 119 // prime candidate generation |
| 120 UINT32_TO_BYTE_ARRAY(*(ktx->outer), swapped); |
| 121 _cpri__UpdateHash(&h, 4, swapped); |
| 122 _cpri__UpdateHash(&h, 2, (BYTE *)&ktx->keySizeInBits); |
| 123 if(i < fill) |
| 124 fill = i; |
| 125 _cpri__CompleteHash(&h, fill, pb); |
| 126 |
| 127 // Restart the oPad hash |
| 128 _cpri__CopyHashState(&h, &(ktx->oPadCtx)); |
| 129 |
| 130 // Add the last hashed data |
| 131 _cpri__UpdateHash(&h, fill, pb); |
| 132 |
| 133 // gives a completed HMAC |
| 134 _cpri__CompleteHash(&h, fill, pb); |
| 135 pb += fill; |
| 136 } |
| 137 return; |
| 138 } |
| |
| |
| B.12.2.3.3.2. MillerRabinRounds() |
| |
| Function returns the number of Miller-Rabin rounds necessary to give an error probability equal to the |
| security strength of the prime. These values are from FIPS 186-3. |
| |
| 139 UINT32 |
| 140 MillerRabinRounds( |
| 141 UINT32 bits // IN: Number of bits in the RSA prime |
| 142 ) |
| 143 { |
| 144 if(bits < 511) return 8; // don't really expect this |
| 145 if(bits < 1536) return 5; // for 512 and 1K primes |
| 146 return 4; // for 3K public modulus and greater |
| 147 } |
| |
| |
| B.12.2.3.3.3. MillerRabin() |
| |
| This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the number. I all |
| likelihood, if the number is not prime, the first test fails. |
| If a KDFa(), PRNG context is provide (ktx), then it is used to provide the random values. Otherwise, the |
| random numbers are retrieved from the random number generator. |
| |
| Return Value Meaning |
| |
| TRUE probably prime |
| FALSE composite |
| |
| 148 BOOL |
| 149 MillerRabin( |
| 150 BIGNUM *bnW, |
| 151 int iterations, |
| 152 KDFa_CONTEXT *ktx, |
| 153 BN_CTX *context |
| 154 ) |
| 155 { |
| 156 BIGNUM *bnWm1; |
| 157 BIGNUM *bnM; |
| 158 BIGNUM *bnB; |
| 159 BIGNUM *bnZ; |
| |
| Page 446 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 160 BOOL ret = FALSE; // Assumed composite for easy exit |
| 161 TPM2B_TYPE(MAX_PRIME, MAX_RSA_KEY_BYTES/2); |
| 162 TPM2B_MAX_PRIME b; |
| 163 int a; |
| 164 int j; |
| 165 int wLen; |
| 166 int i; |
| 167 |
| 168 pAssert(BN_is_bit_set(bnW, 0)); |
| 169 INSTRUMENT_INC(MillerRabinTrials); // Instrumentation |
| 170 |
| 171 BN_CTX_start(context); |
| 172 bnWm1 = BN_CTX_get(context); |
| 173 bnB = BN_CTX_get(context); |
| 174 bnZ = BN_CTX_get(context); |
| 175 bnM = BN_CTX_get(context); |
| 176 if(bnM == NULL) |
| 177 FAIL(FATAL_ERROR_ALLOCATION); |
| 178 |
| 179 // Let a be the largest integer such that 2^a divides w1. |
| 180 BN_copy(bnWm1, bnW); |
| 181 BN_sub_word(bnWm1, 1); |
| 182 // Since w is odd (w-1) is even so start at bit number 1 rather than 0 |
| 183 for(a = 1; !BN_is_bit_set(bnWm1, a); a++); |
| 184 |
| 185 // 2. m = (w1) / 2^a |
| 186 BN_rshift(bnM, bnWm1, a); |
| 187 |
| 188 // 3. wlen = len (w). |
| 189 wLen = BN_num_bits(bnW); |
| 190 pAssert((wLen & 7) == 0); |
| 191 |
| 192 // Set the size for the random number |
| 193 b.b.size = (UINT16)(wLen + 7)/8; |
| 194 |
| 195 // 4. For i = 1 to iterations do |
| 196 for(i = 0; i < iterations ; i++) |
| 197 { |
| 198 |
| 199 // 4.1 Obtain a string b of wlen bits from an RBG. |
| 200 step4point1: |
| 201 // In the reference implementation, wLen is always a multiple of 8 |
| 202 if(ktx != NULL) |
| 203 RandomForRsa(ktx, "Miller-Rabin witness", &b.b); |
| 204 else |
| 205 _cpri__GenerateRandom(b.t.size, b.t.buffer); |
| 206 |
| 207 if(BN_bin2bn(b.t.buffer, b.t.size, bnB) == NULL) |
| 208 FAIL(FATAL_ERROR_ALLOCATION); |
| 209 |
| 210 // 4.2 If ((b 1) or (b w1)), then go to step 4.1. |
| 211 if(BN_is_zero(bnB)) |
| 212 goto step4point1; |
| 213 if(BN_is_one(bnB)) |
| 214 goto step4point1; |
| 215 if(BN_ucmp(bnB, bnWm1) >= 0) |
| 216 goto step4point1; |
| 217 |
| 218 // 4.3 z = b^m mod w. |
| 219 if(BN_mod_exp(bnZ, bnB, bnM, bnW, context) != 1) |
| 220 FAIL(FATAL_ERROR_ALLOCATION); |
| 221 |
| 222 // 4.4 If ((z = 1) or (z = w 1)), then go to step 4.7. |
| 223 if(BN_is_one(bnZ) || BN_ucmp(bnZ, bnWm1) == 0) |
| 224 goto step4point7; |
| 225 |
| |
| Family "2.0" TCG Published Page 447 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 226 // 4.5 For j = 1 to a 1 do. |
| 227 for(j = 1; j < a; j++) |
| 228 { |
| 229 // 4.5.1 z = z^2 mod w. |
| 230 if(BN_mod_mul(bnZ, bnZ, bnZ, bnW, context) != 1) |
| 231 FAIL(FATAL_ERROR_ALLOCATION); |
| 232 |
| 233 // 4.5.2 If (z = w1), then go to step 4.7. |
| 234 if(BN_ucmp(bnZ, bnWm1) == 0) |
| 235 goto step4point7; |
| 236 |
| 237 // 4.5.3 If (z = 1), then go to step 4.6. |
| 238 if(BN_is_one(bnZ)) |
| 239 goto step4point6; |
| 240 } |
| 241 // 4.6 Return COMPOSITE. |
| 242 step4point6: |
| 243 if(i > 9) |
| 244 INSTRUMENT_INC(failedAtIteration[9]); |
| 245 else |
| 246 INSTRUMENT_INC(failedAtIteration[i]); |
| 247 goto end; |
| 248 |
| 249 // 4.7 Continue. Comment: Increment i for the do-loop in step 4. |
| 250 step4point7: |
| 251 continue; |
| 252 } |
| 253 // 5. Return PROBABLY PRIME |
| 254 ret = TRUE; |
| 255 |
| 256 end: |
| 257 BN_CTX_end(context); |
| 258 return ret; |
| 259 } |
| |
| |
| B.12.2.3.3.4. NextPrime() |
| |
| This function is used to access the next prime number in the sequence of primes. It requires a pre- |
| initialized iterator. |
| |
| 260 UINT32 |
| 261 NextPrime( |
| 262 PRIME_ITERATOR *iter |
| 263 ) |
| 264 { |
| 265 if(iter->index >= iter->final) |
| 266 return (iter->lastPrime = 0); |
| 267 return (iter->lastPrime += primeDiffTable[iter->index++]); |
| 268 } |
| |
| |
| B.12.2.3.3.5. AdjustNumberOfPrimes() |
| |
| Modifies the input parameter to be a valid value for the number of primes. The adjusted value is either the |
| input value rounded up to the next 512 bytes boundary or the maximum value of the implementation. If |
| the input is 0, the return is set to the maximum. |
| |
| 269 UINT32 |
| 270 AdjustNumberOfPrimes( |
| 271 UINT32 p |
| 272 ) |
| 273 { |
| 274 p = ((p + 511) / 512) * 512; |
| |
| |
| Page 448 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 275 if(p == 0 || p > PRIME_DIFF_TABLE_BYTES) |
| 276 p = PRIME_DIFF_TABLE_BYTES; |
| 277 return p; |
| 278 } |
| |
| |
| B.12.2.3.3.6. PrimeInit() |
| |
| This function is used to initialize the prime sequence generator iterator. The iterator is initialized and |
| returns the first prime that is equal to the requested starting value. If the starting value is no a prime, then |
| the iterator is initialized to the next higher prime number. |
| |
| 279 UINT32 |
| 280 PrimeInit( |
| 281 UINT32 first, // IN: the initial prime |
| 282 PRIME_ITERATOR *iter, // IN/OUT: the iterator structure |
| 283 UINT32 primes // IN: the table length |
| 284 ) |
| 285 { |
| 286 |
| 287 iter->lastPrime = 1; |
| 288 iter->index = 0; |
| 289 iter->final = AdjustNumberOfPrimes(primes); |
| 290 while(iter->lastPrime < first) |
| 291 NextPrime(iter); |
| 292 return iter->lastPrime; |
| 293 } |
| |
| |
| B.12.2.3.3.7. SetDefaultNumberOfPrimes() |
| |
| This macro sets the default number of primes to the indicated value. |
| |
| 294 //%#define SetDefaultNumberOfPrimes(p) (primeTableBytes = AdjustNumberOfPrimes(p)) |
| |
| |
| B.12.2.3.3.8. IsPrimeWord() |
| |
| Checks to see if a UINT32 is prime |
| |
| Return Value Meaning |
| |
| TRUE number is prime |
| FAIL number is not prime |
| |
| 295 BOOL |
| 296 IsPrimeWord( |
| 297 UINT32 p // IN: number to test |
| 298 ) |
| 299 { |
| 300 #if defined RSA_KEY_SIEVE && (PRIME_DIFF_TABLE_BYTES >= 6542) |
| 301 |
| 302 UINT32 test; |
| 303 UINT32 index; |
| 304 UINT32 stop; |
| 305 |
| 306 if((p & 1) == 0) |
| 307 return FALSE; |
| 308 if(p == 1 || p == 3) |
| 309 return TRUE; |
| 310 |
| 311 // Get a high value for the stopping point |
| 312 for(index = p, stop = 0; index; index >>= 2) |
| |
| Family "2.0" TCG Published Page 449 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 313 stop = (stop << 1) + 1; |
| 314 stop++; |
| 315 |
| 316 // If the full prime difference value table is present, can check here |
| 317 |
| 318 test = 3; |
| 319 for(index = 1; index < PRIME_DIFF_TABLE_BYTES; index += 1) |
| 320 { |
| 321 if((p % test) == 0) |
| 322 return (p == test); |
| 323 if(test > stop) |
| 324 return TRUE; |
| 325 test += primeDiffTable[index]; |
| 326 } |
| 327 return TRUE; |
| 328 |
| 329 #else |
| 330 |
| 331 BYTE b[4]; |
| 332 if(p == RSA_DEFAULT_PUBLIC_EXPONENT || p == 1 || p == 3 ) |
| 333 return TRUE; |
| 334 if((p & 1) == 0) |
| 335 return FALSE; |
| 336 UINT32_TO_BYTE_ARRAY(p,b); |
| 337 return _math__IsPrime(p); |
| 338 #endif |
| 339 } |
| 340 typedef struct { |
| 341 UINT16 prime; |
| 342 UINT16 count; |
| 343 } SIEVE_MARKS; |
| 344 const SIEVE_MARKS sieveMarks[5] = { |
| 345 {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}}; |
| |
| |
| B.12.2.3.3.9. PrimeSieve() |
| |
| This function does a prime sieve over the input field which has as its starting address the value in bnN. |
| Since this initializes the Sieve using a pre-computed field with the bits associated with 3, 5 and 7 already |
| turned off, the value of pnN may need to be adjusted by a few counts to allow the pre-computed field to |
| be used without modification. The fieldSize parameter must be 2^N + 1 and is probably not useful if it is |
| less than 129 bytes (1024 bits). |
| |
| 346 UINT32 |
| 347 PrimeSieve( |
| 348 BIGNUM *bnN, // IN/OUT: number to sieve |
| 349 UINT32 fieldSize, // IN: size of the field area in bytes |
| 350 BYTE *field, // IN: field |
| 351 UINT32 primes // IN: the number of primes to use |
| 352 ) |
| 353 { |
| 354 UINT32 i; |
| 355 UINT32 j; |
| 356 UINT32 fieldBits = fieldSize * 8; |
| 357 UINT32 r; |
| 358 const BYTE *p1; |
| 359 BYTE *p2; |
| 360 PRIME_ITERATOR iter; |
| 361 UINT32 adjust; |
| 362 UINT32 mark = 0; |
| 363 UINT32 count = sieveMarks[0].count; |
| 364 UINT32 stop = sieveMarks[0].prime; |
| 365 UINT32 composite; |
| 366 |
| 367 // UINT64 test; //DEBUG |
| |
| Page 450 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 368 |
| 369 pAssert(field != NULL && bnN != NULL); |
| 370 // Need to have a field that has a size of 2^n + 1 bytes |
| 371 pAssert(BitsInArray((BYTE *)&fieldSize, 2) == 2); |
| 372 |
| 373 primes = AdjustNumberOfPrimes(primes); |
| 374 |
| 375 // If the remainder is odd, then subtracting the value |
| 376 // will give an even number, but we want an odd number, |
| 377 // so subtract the 105+rem. Otherwise, just subtract |
| 378 // the even remainder. |
| 379 adjust = BN_mod_word(bnN,105); |
| 380 if(adjust & 1) |
| 381 adjust += 105; |
| 382 |
| 383 // seed the field |
| 384 // This starts the pointer at the nearest byte to the input value |
| 385 p1 = &seedValues[adjust/16]; |
| 386 |
| 387 // Reduce the number of bytes to transfer by the amount skipped |
| 388 j = sizeof(seedValues) - adjust/16; |
| 389 adjust = adjust % 16; |
| 390 BN_sub_word(bnN, adjust); |
| 391 adjust >>= 1; |
| 392 |
| 393 // This offsets the field |
| 394 p2 = field; |
| 395 for(i = fieldSize; i > 0; i--) |
| 396 { |
| 397 *p2++ = *p1++; |
| 398 if(--j == 0) |
| 399 { |
| 400 j = sizeof(seedValues); |
| 401 p1 = seedValues; |
| 402 } |
| 403 } |
| 404 // Mask the first bits in the field and the last byte in order to eliminate |
| 405 // bytes not in the field from consideration. |
| 406 field[0] &= 0xff << adjust; |
| 407 field[fieldSize-1] &= 0xff >> (8 - adjust); |
| 408 |
| 409 // Cycle through the primes, clearing bits |
| 410 // Have already done 3, 5, and 7 |
| 411 PrimeInit(7, &iter, primes); |
| 412 |
| 413 // Get the next N primes where N is determined by the mark in the sieveMarks |
| 414 while((composite = NextPrime(&iter)) != 0) |
| 415 { |
| 416 UINT32 pList[8]; |
| 417 UINT32 next = 0; |
| 418 i = count; |
| 419 pList[i--] = composite; |
| 420 for(; i > 0; i--) |
| 421 { |
| 422 next = NextPrime(&iter); |
| 423 pList[i] = next; |
| 424 if(next != 0) |
| 425 composite *= next; |
| 426 } |
| 427 composite = BN_mod_word(bnN, composite); |
| 428 for(i = count; i > 0; i--) |
| 429 { |
| 430 next = pList[i]; |
| 431 if(next == 0) |
| 432 goto done; |
| 433 r = composite % next; |
| |
| Family "2.0" TCG Published Page 451 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 434 if(r & 1) j = (next - r)/2; |
| 435 else if(r == 0) j = 0; |
| 436 else j = next - r/2; |
| 437 for(; j < fieldBits; j += next) |
| 438 ClearBit(field, j); |
| 439 } |
| 440 if(next >= stop) |
| 441 { |
| 442 mark++; |
| 443 count = sieveMarks[mark].count; |
| 444 stop = sieveMarks[mark].prime; |
| 445 } |
| 446 } |
| 447 done: |
| 448 INSTRUMENT_INC(totalFieldsSieved); |
| 449 i = BitsInArray(field, fieldSize); |
| 450 if(i == 0) INSTRUMENT_INC(emptyFieldsSieved); |
| 451 return i; |
| 452 } |
| |
| |
| B.12.2.3.3.10. PrimeSelectWithSieve() |
| |
| This function will sieve the field around the input prime candidate. If the sieve field is not empty, one of |
| the one bits in the field is chosen for testing with Miller-Rabin. If the value is prime, pnP is updated with |
| this value and the function returns success. If this value is not prime, another pseudo-random candidate |
| is chosen and tested. This process repeats until all values in the field have been checked. If all bits in the |
| field have been checked and none is prime, the function returns FALSE and a new random value needs |
| to be chosen. |
| |
| 453 BOOL |
| 454 PrimeSelectWithSieve( |
| 455 BIGNUM *bnP, // IN/OUT: The candidate to filter |
| 456 KDFa_CONTEXT *ktx, // IN: KDFa iterator structure |
| 457 UINT32 e, // IN: the exponent |
| 458 BN_CTX *context // IN: the big number context to play in |
| 459 #ifdef RSA_DEBUG //% |
| 460 ,UINT16 fieldSize, // IN: number of bytes in the field, as |
| 461 // determined by the caller |
| 462 UINT16 primes // IN: number of primes to use. |
| 463 #endif //% |
| 464 ) |
| 465 { |
| 466 BYTE field[MAX_FIELD_SIZE]; |
| 467 UINT32 first; |
| 468 UINT32 ones; |
| 469 INT32 chosen; |
| 470 UINT32 rounds = MillerRabinRounds(BN_num_bits(bnP)); |
| 471 #ifndef RSA_DEBUG |
| 472 UINT32 primes; |
| 473 UINT32 fieldSize; |
| 474 // Adjust the field size and prime table list to fit the size of the prime |
| 475 // being tested. |
| 476 primes = BN_num_bits(bnP); |
| 477 if(primes <= 512) |
| 478 { |
| 479 primes = AdjustNumberOfPrimes(2048); |
| 480 fieldSize = 65; |
| 481 } |
| 482 else if(primes <= 1024) |
| 483 { |
| 484 primes = AdjustNumberOfPrimes(4096); |
| 485 fieldSize = 129; |
| 486 } |
| |
| |
| Page 452 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 487 else |
| 488 { |
| 489 primes = AdjustNumberOfPrimes(0); // Set to the maximum |
| 490 fieldSize = MAX_FIELD_SIZE; |
| 491 } |
| 492 if(fieldSize > MAX_FIELD_SIZE) |
| 493 fieldSize = MAX_FIELD_SIZE; |
| 494 #endif |
| 495 |
| 496 // Save the low-order word to use as a search generator and make sure that |
| 497 // it has some interesting range to it |
| 498 first = bnP->d[0] | 0x80000000; |
| 499 |
| 500 // Align to field boundary |
| 501 bnP->d[0] &= ~((UINT32)(fieldSize-3)); |
| 502 pAssert(BN_is_bit_set(bnP, 0)); |
| 503 bnP->d[0] &= (UINT32_MAX << (FIELD_POWER + 1)) + 1; |
| 504 ones = PrimeSieve(bnP, fieldSize, field, primes); |
| 505 #ifdef RSA_FILTER_DEBUG |
| 506 pAssert(ones == BitsInArray(field, defaultFieldSize)); |
| 507 #endif |
| 508 for(; ones > 0; ones--) |
| 509 { |
| 510 #ifdef RSA_FILTER_DEBUG |
| 511 if(ones != BitsInArray(field, defaultFieldSize)) |
| 512 FAIL(FATAL_ERROR_INTERNAL); |
| 513 #endif |
| 514 // Decide which bit to look at and find its offset |
| 515 if(ones == 1) |
| 516 ones = ones; |
| 517 chosen = FindNthSetBit(defaultFieldSize, field,((first % ones) + 1)); |
| 518 if(chosen >= ((defaultFieldSize) * 8)) |
| 519 FAIL(FATAL_ERROR_INTERNAL); |
| 520 |
| 521 // Set this as the trial prime |
| 522 BN_add_word(bnP, chosen * 2); |
| 523 |
| 524 // Use MR to see if this is prime |
| 525 if(MillerRabin(bnP, rounds, ktx, context)) |
| 526 { |
| 527 // Final check is to make sure that 0 != (p-1) mod e |
| 528 // This is the same as -1 != p mod e ; or |
| 529 // (e - 1) != p mod e |
| 530 if((e <= 3) || (BN_mod_word(bnP, e) != (e-1))) |
| 531 return TRUE; |
| 532 } |
| 533 // Back out the bit number |
| 534 BN_sub_word(bnP, chosen * 2); |
| 535 |
| 536 // Clear the bit just tested |
| 537 ClearBit(field, chosen); |
| 538 } |
| 539 // Ran out of bits and couldn't find a prime in this field |
| 540 INSTRUMENT_INC(noPrimeFields); |
| 541 return FALSE; |
| 542 } |
| |
| |
| B.12.2.3.3.11. AdjustPrimeCandiate() |
| |
| This function adjusts the candidate prime so that it is odd and > root(2)/2. This allows the product of these |
| two numbers to be .5, which, in fixed point notation means that the most significant bit is 1. For this |
| routine, the root(2)/2 is approximated with 0xB505 which is, in fixed point is 0.7071075439453125 or an |
| error of 0.0001%. Just setting the upper two bits would give a value > 0.75 which is an error of > 6%. |
| |
| |
| Family "2.0" TCG Published Page 453 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Given the amount of time all the other computations take, reducing the error is not much of a cost, but it |
| isn't totally required either. |
| The function also puts the number on a field boundary. |
| |
| 543 void |
| 544 AdjustPrimeCandidate( |
| 545 BYTE *a, |
| 546 UINT16 len |
| 547 ) |
| 548 { |
| 549 UINT16 highBytes; |
| 550 |
| 551 highBytes = BYTE_ARRAY_TO_UINT16(a); |
| 552 // This is fixed point arithmetic on 16-bit values |
| 553 highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16; |
| 554 highBytes += 0xB505; |
| 555 UINT16_TO_BYTE_ARRAY(highBytes, a); |
| 556 a[len-1] |= 1; |
| 557 } |
| |
| |
| B.12.2.3.3.12. GeneratateRamdomPrime() |
| |
| 558 void |
| 559 GenerateRandomPrime( |
| 560 TPM2B *p, |
| 561 BN_CTX *ctx |
| 562 #ifdef RSA_DEBUG //% |
| 563 ,UINT16 field, |
| 564 UINT16 primes |
| 565 #endif //% |
| 566 ) |
| 567 { |
| 568 BIGNUM *bnP; |
| 569 BN_CTX *context; |
| 570 |
| 571 if(ctx == NULL) context = BN_CTX_new(); |
| 572 else context = ctx; |
| 573 if(context == NULL) |
| 574 FAIL(FATAL_ERROR_ALLOCATION); |
| 575 BN_CTX_start(context); |
| 576 bnP = BN_CTX_get(context); |
| 577 |
| 578 while(TRUE) |
| 579 { |
| 580 _cpri__GenerateRandom(p->size, p->buffer); |
| 581 p->buffer[p->size-1] |= 1; |
| 582 p->buffer[0] |= 0x80; |
| 583 BN_bin2bn(p->buffer, p->size, bnP); |
| 584 #ifdef RSA_DEBUG |
| 585 if(PrimeSelectWithSieve(bnP, NULL, 0, context, field, primes)) |
| 586 #else |
| 587 if(PrimeSelectWithSieve(bnP, NULL, 0, context)) |
| 588 #endif |
| 589 break; |
| 590 } |
| 591 BnTo2B(p, bnP, (UINT16)BN_num_bytes(bnP)); |
| 592 BN_CTX_end(context); |
| 593 if(ctx == NULL) |
| 594 BN_CTX_free(context); |
| 595 return; |
| 596 } |
| 597 KDFa_CONTEXT * |
| 598 KDFaContextStart( |
| |
| Page 454 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 599 KDFa_CONTEXT *ktx, // IN/OUT: the context structure to initialize |
| 600 TPM2B *seed, // IN: the seed for the digest proce |
| 601 TPM_ALG_ID hashAlg, // IN: the hash algorithm |
| 602 TPM2B *extra, // IN: the extra data |
| 603 UINT32 *outer, // IN: the outer iteration counter |
| 604 UINT16 keySizeInBit |
| 605 ) |
| 606 { |
| 607 UINT16 digestSize = _cpri__GetDigestSize(hashAlg); |
| 608 TPM2B_HASH_BLOCK oPadKey; |
| 609 |
| 610 if(seed == NULL) |
| 611 return NULL; |
| 612 |
| 613 pAssert(ktx != NULL && outer != NULL && digestSize != 0); |
| 614 |
| 615 // Start the hash using the seed and get the intermediate hash value |
| 616 _cpri__StartHMAC(hashAlg, FALSE, &(ktx->iPadCtx), seed->size, seed->buffer, |
| 617 &oPadKey.b); |
| 618 _cpri__StartHash(hashAlg, FALSE, &(ktx->oPadCtx)); |
| 619 _cpri__UpdateHash(&(ktx->oPadCtx), oPadKey.b.size, oPadKey.b.buffer); |
| 620 ktx->extra = extra; |
| 621 ktx->hashAlg = hashAlg; |
| 622 ktx->outer = outer; |
| 623 ktx->keySizeInBits = keySizeInBits; |
| 624 return ktx; |
| 625 } |
| 626 void |
| 627 KDFaContextEnd( |
| 628 KDFa_CONTEXT *ktx // IN/OUT: the context structure to close |
| 629 ) |
| 630 { |
| 631 if(ktx != NULL) |
| 632 { |
| 633 // Close out the hash sessions |
| 634 _cpri__CompleteHash(&(ktx->iPadCtx), 0, NULL); |
| 635 _cpri__CompleteHash(&(ktx->oPadCtx), 0, NULL); |
| 636 } |
| 637 } |
| 638 //%#endif |
| |
| |
| B.12.2.3.4. Public Function |
| |
| B.12.2.3.4.1. Introduction |
| |
| This is the external entry for this replacement function. All this file provides is the substitute function to |
| generate an RSA key. If the compiler settings are set appropriately, this this function will be used instead |
| of the similarly named function in CpriRSA.c. |
| |
| B.12.2.3.4.2. _cpri__GenerateKeyRSA() |
| |
| Generate an RSA key from a provided seed |
| |
| Return Value Meaning |
| |
| CRYPT_FAIL exponent is not prime or is less than 3; or could not find a prime using |
| the provided parameters |
| CRYPT_CANCEL operation was canceled |
| |
| 639 LIB_EXPORT CRYPT_RESULT |
| 640 _cpri__GenerateKeyRSA( |
| |
| Family "2.0" TCG Published Page 455 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 641 TPM2B *n, // OUT: The public modulus |
| 642 TPM2B *p, // OUT: One of the prime factors of n |
| 643 UINT16 keySizeInBits, // IN: Size of the public modulus in bits |
| 644 UINT32 e, // IN: The public exponent |
| 645 TPM_ALG_ID hashAlg, // IN: hash algorithm to use in the key |
| 646 // generation process |
| 647 TPM2B *seed, // IN: the seed to use |
| 648 const char *label, // IN: A label for the generation process. |
| 649 TPM2B *extra, // IN: Party 1 data for the KDF |
| 650 UINT32 *counter // IN/OUT: Counter value to allow KDF |
| 651 // iteration to be propagated across |
| 652 // multiple routines |
| 653 #ifdef RSA_DEBUG //% |
| 654 ,UINT16 primes, // IN: number of primes to test |
| 655 UINT16 fieldSize // IN: the field size to use |
| 656 #endif //% |
| 657 ) |
| 658 { |
| 659 CRYPT_RESULT retVal; |
| 660 UINT32 myCounter = 0; |
| 661 UINT32 *pCtr = (counter == NULL) ? &myCounter : counter; |
| 662 |
| 663 KDFa_CONTEXT ktx; |
| 664 KDFa_CONTEXT *ktxPtr; |
| 665 UINT32 i; |
| 666 BIGNUM *bnP; |
| 667 BIGNUM *bnQ; |
| 668 BIGNUM *bnT; |
| 669 BIGNUM *bnE; |
| 670 BIGNUM *bnN; |
| 671 BN_CTX *context; |
| 672 |
| 673 // Make sure that the required pointers are provided |
| 674 pAssert(n != NULL && p != NULL); |
| 675 |
| 676 // If the seed is provided, then use KDFa for generation of the 'random' |
| 677 // values |
| 678 ktxPtr = KDFaContextStart(&ktx, seed, hashAlg, extra, pCtr, keySizeInBits); |
| 679 |
| 680 n->size = keySizeInBits/8; |
| 681 p->size = n->size / 2; |
| 682 |
| 683 // Validate exponent |
| 684 if(e == 0 || e == RSA_DEFAULT_PUBLIC_EXPONENT) |
| 685 e = RSA_DEFAULT_PUBLIC_EXPONENT; |
| 686 else |
| 687 if(!IsPrimeWord(e)) |
| 688 return CRYPT_FAIL; |
| 689 |
| 690 // Get structures for the big number representations |
| 691 context = BN_CTX_new(); |
| 692 BN_CTX_start(context); |
| 693 bnP = BN_CTX_get(context); |
| 694 bnQ = BN_CTX_get(context); |
| 695 bnT = BN_CTX_get(context); |
| 696 bnE = BN_CTX_get(context); |
| 697 bnN = BN_CTX_get(context); |
| 698 if(bnN == NULL) |
| 699 FAIL(FATAL_ERROR_INTERNAL); |
| 700 |
| 701 // Set Q to zero. This is used as a flag. The prime is computed in P. When a |
| 702 // new prime is found, Q is checked to see if it is zero. If so, P is copied |
| 703 // to Q and a new P is found. When both P and Q are non-zero, the modulus and |
| 704 // private exponent are computed and a trial encryption/decryption is |
| 705 // performed. If the encrypt/decrypt fails, assume that at least one of the |
| 706 // primes is composite. Since we don't know which one, set Q to zero and start |
| |
| Page 456 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 707 // over and find a new pair of primes. |
| 708 BN_zero(bnQ); |
| 709 BN_set_word(bnE, e); |
| 710 |
| 711 // Each call to generate a random value will increment ktx.outer |
| 712 // it doesn't matter if ktx.outer wraps. This lets the caller |
| 713 // use the initial value of the counter for additional entropy. |
| 714 for(i = 0; i < UINT32_MAX; i++) |
| 715 { |
| 716 if(_plat__IsCanceled()) |
| 717 { |
| 718 retVal = CRYPT_CANCEL; |
| 719 goto end; |
| 720 } |
| 721 // Get a random prime candidate. |
| 722 if(seed == NULL) |
| 723 _cpri__GenerateRandom(p->size, p->buffer); |
| 724 else |
| 725 RandomForRsa(&ktx, label, p); |
| 726 AdjustPrimeCandidate(p->buffer, p->size); |
| 727 |
| 728 // Convert the candidate to a BN |
| 729 if(BN_bin2bn(p->buffer, p->size, bnP) == NULL) |
| 730 FAIL(FATAL_ERROR_INTERNAL); |
| 731 // If this is the second prime, make sure that it differs from the |
| 732 // first prime by at least 2^100. Since BIGNUMS use words, the check |
| 733 // below will make sure they are different by at least 128 bits |
| 734 if(!BN_is_zero(bnQ)) |
| 735 { // bnQ is non-zero, we have a first value |
| 736 UINT32 *pP = (UINT32 *)(&bnP->d[4]); |
| 737 UINT32 *pQ = (UINT32 *)(&bnQ->d[4]); |
| 738 INT32 k = ((INT32)bnP->top) - 4; |
| 739 for(;k > 0; k--) |
| 740 if(*pP++ != *pQ++) |
| 741 break; |
| 742 // Didn't find any difference so go get a new value |
| 743 if(k == 0) |
| 744 continue; |
| 745 } |
| 746 // If PrimeSelectWithSieve returns success, bnP is a prime, |
| 747 #ifdef RSA_DEBUG |
| 748 if(!PrimeSelectWithSieve(bnP, ktxPtr, e, context, fieldSize, primes)) |
| 749 #else |
| 750 if(!PrimeSelectWithSieve(bnP, ktxPtr, e, context)) |
| 751 #endif |
| 752 continue; // If not, get another |
| 753 |
| 754 // Found a prime, is this the first or second. |
| 755 if(BN_is_zero(bnQ)) |
| 756 { // copy p to q and compute another prime in p |
| 757 BN_copy(bnQ, bnP); |
| 758 continue; |
| 759 } |
| 760 //Form the public modulus |
| 761 if( BN_mul(bnN, bnP, bnQ, context) != 1 |
| 762 || BN_num_bits(bnN) != keySizeInBits) |
| 763 FAIL(FATAL_ERROR_INTERNAL); |
| 764 // Save the public modulus |
| 765 BnTo2B(n, bnN, n->size); |
| 766 // And one prime |
| 767 BnTo2B(p, bnP, p->size); |
| 768 |
| 769 #ifdef EXTENDED_CHECKS |
| 770 // Finish by making sure that we can form the modular inverse of PHI |
| 771 // with respect to the public exponent |
| 772 // Compute PHI = (p - 1)(q - 1) = n - p - q + 1 |
| |
| Family "2.0" TCG Published Page 457 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 773 // Make sure that we can form the modular inverse |
| 774 if( BN_sub(bnT, bnN, bnP) != 1 |
| 775 || BN_sub(bnT, bnT, bnQ) != 1 |
| 776 || BN_add_word(bnT, 1) != 1) |
| 777 FAIL(FATAL_ERROR_INTERNAL); |
| 778 |
| 779 // find d such that (Phi * d) mod e ==1 |
| 780 // If there isn't then we are broken because we took the step |
| 781 // of making sure that the prime != 1 mod e so the modular inverse |
| 782 // must exist |
| 783 if( BN_mod_inverse(bnT, bnE, bnT, context) == NULL |
| 784 || BN_is_zero(bnT)) |
| 785 FAIL(FATAL_ERROR_INTERNAL); |
| 786 |
| 787 // And, finally, do a trial encryption decryption |
| 788 { |
| 789 TPM2B_TYPE(RSA_KEY, MAX_RSA_KEY_BYTES); |
| 790 TPM2B_RSA_KEY r; |
| 791 r.t.size = sizeof(r.t.buffer); |
| 792 // If we are using a seed, then results must be reproducible on each |
| 793 // call. Otherwise, just get a random number |
| 794 if(seed == NULL) |
| 795 _cpri__GenerateRandom(keySizeInBits/8, r.t.buffer); |
| 796 else |
| 797 RandomForRsa(&ktx, label, &r.b); |
| 798 |
| 799 // Make sure that the number is smaller than the public modulus |
| 800 r.t.buffer[0] &= 0x7F; |
| 801 // Convert |
| 802 if( BN_bin2bn(r.t.buffer, r.t.size, bnP) == NULL |
| 803 // Encrypt with the public exponent |
| 804 || BN_mod_exp(bnQ, bnP, bnE, bnN, context) != 1 |
| 805 // Decrypt with the private exponent |
| 806 || BN_mod_exp(bnQ, bnQ, bnT, bnN, context) != 1) |
| 807 FAIL(FATAL_ERROR_INTERNAL); |
| 808 // If the starting and ending values are not the same, start over )-; |
| 809 if(BN_ucmp(bnP, bnQ) != 0) |
| 810 { |
| 811 BN_zero(bnQ); |
| 812 continue; |
| 813 } |
| 814 } |
| 815 #endif // EXTENDED_CHECKS |
| 816 retVal = CRYPT_SUCCESS; |
| 817 goto end; |
| 818 } |
| 819 retVal = CRYPT_FAIL; |
| 820 |
| 821 end: |
| 822 KDFaContextEnd(&ktx); |
| 823 |
| 824 // Free up allocated BN values |
| 825 BN_CTX_end(context); |
| 826 BN_CTX_free(context); |
| 827 return retVal; |
| 828 } |
| 829 #else |
| 830 static void noFuntion( |
| 831 void |
| 832 ) |
| 833 { |
| 834 pAssert(1); |
| 835 } |
| 836 #endif //% |
| 837 #endif // TPM_ALG_RSA |
| |
| |
| Page 458 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.12.2.4. RSAData.c |
| |
| 1 #include "OsslCryptoEngine.h" |
| 2 #ifdef RSA_KEY_SIEVE |
| 3 #include "RsaKeySieve.h" |
| 4 #ifdef RSA_DEBUG |
| 5 UINT16 defaultFieldSize = MAX_FIELD_SIZE; |
| 6 #endif |
| |
| This table contains a pre-sieved table. It has the bits for 3, 5, and 7 removed. Because of the factors, it |
| needs to be aligned to 105 and has a repeat of 105. |
| |
| 7 const BYTE seedValues[SEED_VALUES_SIZE] = { |
| 8 0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c, |
| 9 0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96, |
| 10 0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d, 0x99, |
| 11 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96, 0x69, |
| 12 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6, |
| 13 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb, |
| 14 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c, |
| 15 0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9, 0x34, |
| 16 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c, 0x1b, |
| 17 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45, |
| 18 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6, |
| 19 0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2, |
| 20 0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6, 0x29, |
| 21 0xd1}; |
| 22 const BYTE bitsInByte[256] = { |
| 23 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, |
| 24 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, |
| 25 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, |
| 26 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 27 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, |
| 28 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 29 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 30 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 31 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, |
| 32 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 33 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 34 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 35 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 36 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 37 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 38 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, |
| 39 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, |
| 40 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 41 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 42 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 43 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 44 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 45 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 46 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, |
| 47 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, |
| 48 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 49 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 50 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, |
| 51 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, |
| 52 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, |
| 53 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, |
| 54 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 |
| 55 }; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 459 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Following table contains a byte that is the difference between two successive primes. This reduces the |
| table size by a factor of two. It is optimized for sequential access to the prime table which is the most |
| common case. |
| When the table size is at its max, the table will have all primes less than 2^16. This is 6542 primes in |
| 6542 bytes. |
| |
| 56 const UINT16 primeTableBytes = PRIME_DIFF_TABLE_BYTES; |
| 57 #if PRIME_DIFF_TABLE_BYTES > 0 |
| 58 const BYTE primeDiffTable [PRIME_DIFF_TABLE_BYTES] = { |
| 59 0x02,0x02,0x02,0x04,0x02,0x04,0x02,0x04,0x06,0x02,0x06,0x04,0x02,0x04,0x06,0x06, |
| 60 0x02,0x06,0x04,0x02,0x06,0x04,0x06,0x08,0x04,0x02,0x04,0x02,0x04,0x0E,0x04,0x06, |
| 61 0x02,0x0A,0x02,0x06,0x06,0x04,0x06,0x06,0x02,0x0A,0x02,0x04,0x02,0x0C,0x0C,0x04, |
| 62 0x02,0x04,0x06,0x02,0x0A,0x06,0x06,0x06,0x02,0x06,0x04,0x02,0x0A,0x0E,0x04,0x02, |
| 63 0x04,0x0E,0x06,0x0A,0x02,0x04,0x06,0x08,0x06,0x06,0x04,0x06,0x08,0x04,0x08,0x0A, |
| 64 0x02,0x0A,0x02,0x06,0x04,0x06,0x08,0x04,0x02,0x04,0x0C,0x08,0x04,0x08,0x04,0x06, |
| 65 0x0C,0x02,0x12,0x06,0x0A,0x06,0x06,0x02,0x06,0x0A,0x06,0x06,0x02,0x06,0x06,0x04, |
| 66 0x02,0x0C,0x0A,0x02,0x04,0x06,0x06,0x02,0x0C,0x04,0x06,0x08,0x0A,0x08,0x0A,0x08, |
| 67 0x06,0x06,0x04,0x08,0x06,0x04,0x08,0x04,0x0E,0x0A,0x0C,0x02,0x0A,0x02,0x04,0x02, |
| 68 0x0A,0x0E,0x04,0x02,0x04,0x0E,0x04,0x02,0x04,0x14,0x04,0x08,0x0A,0x08,0x04,0x06, |
| 69 0x06,0x0E,0x04,0x06,0x06,0x08,0x06,0x0C,0x04,0x06,0x02,0x0A,0x02,0x06,0x0A,0x02, |
| 70 0x0A,0x02,0x06,0x12,0x04,0x02,0x04,0x06,0x06,0x08,0x06,0x06,0x16,0x02,0x0A,0x08, |
| 71 0x0A,0x06,0x06,0x08,0x0C,0x04,0x06,0x06,0x02,0x06,0x0C,0x0A,0x12,0x02,0x04,0x06, |
| 72 0x02,0x06,0x04,0x02,0x04,0x0C,0x02,0x06,0x22,0x06,0x06,0x08,0x12,0x0A,0x0E,0x04, |
| 73 0x02,0x04,0x06,0x08,0x04,0x02,0x06,0x0C,0x0A,0x02,0x04,0x02,0x04,0x06,0x0C,0x0C, |
| 74 0x08,0x0C,0x06,0x04,0x06,0x08,0x04,0x08,0x04,0x0E,0x04,0x06,0x02,0x04,0x06,0x02 |
| 75 #endif |
| 76 // 256 |
| 77 #if PRIME_DIFF_TABLE_BYTES > 256 |
| 78 ,0x06,0x0A,0x14,0x06,0x04,0x02,0x18,0x04,0x02,0x0A,0x0C,0x02,0x0A,0x08,0x06,0x06, |
| 79 0x06,0x12,0x06,0x04,0x02,0x0C,0x0A,0x0C,0x08,0x10,0x0E,0x06,0x04,0x02,0x04,0x02, |
| 80 0x0A,0x0C,0x06,0x06,0x12,0x02,0x10,0x02,0x16,0x06,0x08,0x06,0x04,0x02,0x04,0x08, |
| 81 0x06,0x0A,0x02,0x0A,0x0E,0x0A,0x06,0x0C,0x02,0x04,0x02,0x0A,0x0C,0x02,0x10,0x02, |
| 82 0x06,0x04,0x02,0x0A,0x08,0x12,0x18,0x04,0x06,0x08,0x10,0x02,0x04,0x08,0x10,0x02, |
| 83 0x04,0x08,0x06,0x06,0x04,0x0C,0x02,0x16,0x06,0x02,0x06,0x04,0x06,0x0E,0x06,0x04, |
| 84 0x02,0x06,0x04,0x06,0x0C,0x06,0x06,0x0E,0x04,0x06,0x0C,0x08,0x06,0x04,0x1A,0x12, |
| 85 0x0A,0x08,0x04,0x06,0x02,0x06,0x16,0x0C,0x02,0x10,0x08,0x04,0x0C,0x0E,0x0A,0x02, |
| 86 0x04,0x08,0x06,0x06,0x04,0x02,0x04,0x06,0x08,0x04,0x02,0x06,0x0A,0x02,0x0A,0x08, |
| 87 0x04,0x0E,0x0A,0x0C,0x02,0x06,0x04,0x02,0x10,0x0E,0x04,0x06,0x08,0x06,0x04,0x12, |
| 88 0x08,0x0A,0x06,0x06,0x08,0x0A,0x0C,0x0E,0x04,0x06,0x06,0x02,0x1C,0x02,0x0A,0x08, |
| 89 0x04,0x0E,0x04,0x08,0x0C,0x06,0x0C,0x04,0x06,0x14,0x0A,0x02,0x10,0x1A,0x04,0x02, |
| 90 0x0C,0x06,0x04,0x0C,0x06,0x08,0x04,0x08,0x16,0x02,0x04,0x02,0x0C,0x1C,0x02,0x06, |
| 91 0x06,0x06,0x04,0x06,0x02,0x0C,0x04,0x0C,0x02,0x0A,0x02,0x10,0x02,0x10,0x06,0x14, |
| 92 0x10,0x08,0x04,0x02,0x04,0x02,0x16,0x08,0x0C,0x06,0x0A,0x02,0x04,0x06,0x02,0x06, |
| 93 0x0A,0x02,0x0C,0x0A,0x02,0x0A,0x0E,0x06,0x04,0x06,0x08,0x06,0x06,0x10,0x0C,0x02 |
| 94 #endif |
| 95 // 512 |
| 96 #if PRIME_DIFF_TABLE_BYTES > 512 |
| 97 ,0x04,0x0E,0x06,0x04,0x08,0x0A,0x08,0x06,0x06,0x16,0x06,0x02,0x0A,0x0E,0x04,0x06, |
| 98 0x12,0x02,0x0A,0x0E,0x04,0x02,0x0A,0x0E,0x04,0x08,0x12,0x04,0x06,0x02,0x04,0x06, |
| 99 0x02,0x0C,0x04,0x14,0x16,0x0C,0x02,0x04,0x06,0x06,0x02,0x06,0x16,0x02,0x06,0x10, |
| 100 0x06,0x0C,0x02,0x06,0x0C,0x10,0x02,0x04,0x06,0x0E,0x04,0x02,0x12,0x18,0x0A,0x06, |
| 101 0x02,0x0A,0x02,0x0A,0x02,0x0A,0x06,0x02,0x0A,0x02,0x0A,0x06,0x08,0x1E,0x0A,0x02, |
| 102 0x0A,0x08,0x06,0x0A,0x12,0x06,0x0C,0x0C,0x02,0x12,0x06,0x04,0x06,0x06,0x12,0x02, |
| 103 0x0A,0x0E,0x06,0x04,0x02,0x04,0x18,0x02,0x0C,0x06,0x10,0x08,0x06,0x06,0x12,0x10, |
| 104 0x02,0x04,0x06,0x02,0x06,0x06,0x0A,0x06,0x0C,0x0C,0x12,0x02,0x06,0x04,0x12,0x08, |
| 105 0x18,0x04,0x02,0x04,0x06,0x02,0x0C,0x04,0x0E,0x1E,0x0A,0x06,0x0C,0x0E,0x06,0x0A, |
| 106 0x0C,0x02,0x04,0x06,0x08,0x06,0x0A,0x02,0x04,0x0E,0x06,0x06,0x04,0x06,0x02,0x0A, |
| 107 0x02,0x10,0x0C,0x08,0x12,0x04,0x06,0x0C,0x02,0x06,0x06,0x06,0x1C,0x06,0x0E,0x04, |
| 108 0x08,0x0A,0x08,0x0C,0x12,0x04,0x02,0x04,0x18,0x0C,0x06,0x02,0x10,0x06,0x06,0x0E, |
| 109 0x0A,0x0E,0x04,0x1E,0x06,0x06,0x06,0x08,0x06,0x04,0x02,0x0C,0x06,0x04,0x02,0x06, |
| 110 0x16,0x06,0x02,0x04,0x12,0x02,0x04,0x0C,0x02,0x06,0x04,0x1A,0x06,0x06,0x04,0x08, |
| 111 0x0A,0x20,0x10,0x02,0x06,0x04,0x02,0x04,0x02,0x0A,0x0E,0x06,0x04,0x08,0x0A,0x06, |
| 112 0x14,0x04,0x02,0x06,0x1E,0x04,0x08,0x0A,0x06,0x06,0x08,0x06,0x0C,0x04,0x06,0x02 |
| 113 #endif |
| |
| Page 460 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 114 // 768 |
| 115 #if PRIME_DIFF_TABLE_BYTES > 768 |
| 116 ,0x06,0x04,0x06,0x02,0x0A,0x02,0x10,0x06,0x14,0x04,0x0C,0x0E,0x1C,0x06,0x14,0x04, |
| 117 0x12,0x08,0x06,0x04,0x06,0x0E,0x06,0x06,0x0A,0x02,0x0A,0x0C,0x08,0x0A,0x02,0x0A, |
| 118 0x08,0x0C,0x0A,0x18,0x02,0x04,0x08,0x06,0x04,0x08,0x12,0x0A,0x06,0x06,0x02,0x06, |
| 119 0x0A,0x0C,0x02,0x0A,0x06,0x06,0x06,0x08,0x06,0x0A,0x06,0x02,0x06,0x06,0x06,0x0A, |
| 120 0x08,0x18,0x06,0x16,0x02,0x12,0x04,0x08,0x0A,0x1E,0x08,0x12,0x04,0x02,0x0A,0x06, |
| 121 0x02,0x06,0x04,0x12,0x08,0x0C,0x12,0x10,0x06,0x02,0x0C,0x06,0x0A,0x02,0x0A,0x02, |
| 122 0x06,0x0A,0x0E,0x04,0x18,0x02,0x10,0x02,0x0A,0x02,0x0A,0x14,0x04,0x02,0x04,0x08, |
| 123 0x10,0x06,0x06,0x02,0x0C,0x10,0x08,0x04,0x06,0x1E,0x02,0x0A,0x02,0x06,0x04,0x06, |
| 124 0x06,0x08,0x06,0x04,0x0C,0x06,0x08,0x0C,0x04,0x0E,0x0C,0x0A,0x18,0x06,0x0C,0x06, |
| 125 0x02,0x16,0x08,0x12,0x0A,0x06,0x0E,0x04,0x02,0x06,0x0A,0x08,0x06,0x04,0x06,0x1E, |
| 126 0x0E,0x0A,0x02,0x0C,0x0A,0x02,0x10,0x02,0x12,0x18,0x12,0x06,0x10,0x12,0x06,0x02, |
| 127 0x12,0x04,0x06,0x02,0x0A,0x08,0x0A,0x06,0x06,0x08,0x04,0x06,0x02,0x0A,0x02,0x0C, |
| 128 0x04,0x06,0x06,0x02,0x0C,0x04,0x0E,0x12,0x04,0x06,0x14,0x04,0x08,0x06,0x04,0x08, |
| 129 0x04,0x0E,0x06,0x04,0x0E,0x0C,0x04,0x02,0x1E,0x04,0x18,0x06,0x06,0x0C,0x0C,0x0E, |
| 130 0x06,0x04,0x02,0x04,0x12,0x06,0x0C,0x08,0x06,0x04,0x0C,0x02,0x0C,0x1E,0x10,0x02, |
| 131 0x06,0x16,0x0E,0x06,0x0A,0x0C,0x06,0x02,0x04,0x08,0x0A,0x06,0x06,0x18,0x0E,0x06 |
| 132 #endif |
| 133 // 1024 |
| 134 #if PRIME_DIFF_TABLE_BYTES > 1024 |
| 135 ,0x04,0x08,0x0C,0x12,0x0A,0x02,0x0A,0x02,0x04,0x06,0x14,0x06,0x04,0x0E,0x04,0x02, |
| 136 0x04,0x0E,0x06,0x0C,0x18,0x0A,0x06,0x08,0x0A,0x02,0x1E,0x04,0x06,0x02,0x0C,0x04, |
| 137 0x0E,0x06,0x22,0x0C,0x08,0x06,0x0A,0x02,0x04,0x14,0x0A,0x08,0x10,0x02,0x0A,0x0E, |
| 138 0x04,0x02,0x0C,0x06,0x10,0x06,0x08,0x04,0x08,0x04,0x06,0x08,0x06,0x06,0x0C,0x06, |
| 139 0x04,0x06,0x06,0x08,0x12,0x04,0x14,0x04,0x0C,0x02,0x0A,0x06,0x02,0x0A,0x0C,0x02, |
| 140 0x04,0x14,0x06,0x1E,0x06,0x04,0x08,0x0A,0x0C,0x06,0x02,0x1C,0x02,0x06,0x04,0x02, |
| 141 0x10,0x0C,0x02,0x06,0x0A,0x08,0x18,0x0C,0x06,0x12,0x06,0x04,0x0E,0x06,0x04,0x0C, |
| 142 0x08,0x06,0x0C,0x04,0x06,0x0C,0x06,0x0C,0x02,0x10,0x14,0x04,0x02,0x0A,0x12,0x08, |
| 143 0x04,0x0E,0x04,0x02,0x06,0x16,0x06,0x0E,0x06,0x06,0x0A,0x06,0x02,0x0A,0x02,0x04, |
| 144 0x02,0x16,0x02,0x04,0x06,0x06,0x0C,0x06,0x0E,0x0A,0x0C,0x06,0x08,0x04,0x24,0x0E, |
| 145 0x0C,0x06,0x04,0x06,0x02,0x0C,0x06,0x0C,0x10,0x02,0x0A,0x08,0x16,0x02,0x0C,0x06, |
| 146 0x04,0x06,0x12,0x02,0x0C,0x06,0x04,0x0C,0x08,0x06,0x0C,0x04,0x06,0x0C,0x06,0x02, |
| 147 0x0C,0x0C,0x04,0x0E,0x06,0x10,0x06,0x02,0x0A,0x08,0x12,0x06,0x22,0x02,0x1C,0x02, |
| 148 0x16,0x06,0x02,0x0A,0x0C,0x02,0x06,0x04,0x08,0x16,0x06,0x02,0x0A,0x08,0x04,0x06, |
| 149 0x08,0x04,0x0C,0x12,0x0C,0x14,0x04,0x06,0x06,0x08,0x04,0x02,0x10,0x0C,0x02,0x0A, |
| 150 0x08,0x0A,0x02,0x04,0x06,0x0E,0x0C,0x16,0x08,0x1C,0x02,0x04,0x14,0x04,0x02,0x04 |
| 151 #endif |
| 152 // 1280 |
| 153 #if PRIME_DIFF_TABLE_BYTES > 1280 |
| 154 ,0x0E,0x0A,0x0C,0x02,0x0C,0x10,0x02,0x1C,0x08,0x16,0x08,0x04,0x06,0x06,0x0E,0x04, |
| 155 0x08,0x0C,0x06,0x06,0x04,0x14,0x04,0x12,0x02,0x0C,0x06,0x04,0x06,0x0E,0x12,0x0A, |
| 156 0x08,0x0A,0x20,0x06,0x0A,0x06,0x06,0x02,0x06,0x10,0x06,0x02,0x0C,0x06,0x1C,0x02, |
| 157 0x0A,0x08,0x10,0x06,0x08,0x06,0x0A,0x18,0x14,0x0A,0x02,0x0A,0x02,0x0C,0x04,0x06, |
| 158 0x14,0x04,0x02,0x0C,0x12,0x0A,0x02,0x0A,0x02,0x04,0x14,0x10,0x1A,0x04,0x08,0x06, |
| 159 0x04,0x0C,0x06,0x08,0x0C,0x0C,0x06,0x04,0x08,0x16,0x02,0x10,0x0E,0x0A,0x06,0x0C, |
| 160 0x0C,0x0E,0x06,0x04,0x14,0x04,0x0C,0x06,0x02,0x06,0x06,0x10,0x08,0x16,0x02,0x1C, |
| 161 0x08,0x06,0x04,0x14,0x04,0x0C,0x18,0x14,0x04,0x08,0x0A,0x02,0x10,0x02,0x0C,0x0C, |
| 162 0x22,0x02,0x04,0x06,0x0C,0x06,0x06,0x08,0x06,0x04,0x02,0x06,0x18,0x04,0x14,0x0A, |
| 163 0x06,0x06,0x0E,0x04,0x06,0x06,0x02,0x0C,0x06,0x0A,0x02,0x0A,0x06,0x14,0x04,0x1A, |
| 164 0x04,0x02,0x06,0x16,0x02,0x18,0x04,0x06,0x02,0x04,0x06,0x18,0x06,0x08,0x04,0x02, |
| 165 0x22,0x06,0x08,0x10,0x0C,0x02,0x0A,0x02,0x0A,0x06,0x08,0x04,0x08,0x0C,0x16,0x06, |
| 166 0x0E,0x04,0x1A,0x04,0x02,0x0C,0x0A,0x08,0x04,0x08,0x0C,0x04,0x0E,0x06,0x10,0x06, |
| 167 0x08,0x04,0x06,0x06,0x08,0x06,0x0A,0x0C,0x02,0x06,0x06,0x10,0x08,0x06,0x06,0x0C, |
| 168 0x0A,0x02,0x06,0x12,0x04,0x06,0x06,0x06,0x0C,0x12,0x08,0x06,0x0A,0x08,0x12,0x04, |
| 169 0x0E,0x06,0x12,0x0A,0x08,0x0A,0x0C,0x02,0x06,0x0C,0x0C,0x24,0x04,0x06,0x08,0x04 |
| 170 #endif |
| 171 // 1536 |
| 172 #if PRIME_DIFF_TABLE_BYTES > 1536 |
| 173 ,0x06,0x02,0x04,0x12,0x0C,0x06,0x08,0x06,0x06,0x04,0x12,0x02,0x04,0x02,0x18,0x04, |
| 174 0x06,0x06,0x0E,0x1E,0x06,0x04,0x06,0x0C,0x06,0x14,0x04,0x08,0x04,0x08,0x06,0x06, |
| 175 0x04,0x1E,0x02,0x0A,0x0C,0x08,0x0A,0x08,0x18,0x06,0x0C,0x04,0x0E,0x04,0x06,0x02, |
| 176 0x1C,0x0E,0x10,0x02,0x0C,0x06,0x04,0x14,0x0A,0x06,0x06,0x06,0x08,0x0A,0x0C,0x0E, |
| 177 0x0A,0x0E,0x10,0x0E,0x0A,0x0E,0x06,0x10,0x06,0x08,0x06,0x10,0x14,0x0A,0x02,0x06, |
| 178 0x04,0x02,0x04,0x0C,0x02,0x0A,0x02,0x06,0x16,0x06,0x02,0x04,0x12,0x08,0x0A,0x08, |
| 179 0x16,0x02,0x0A,0x12,0x0E,0x04,0x02,0x04,0x12,0x02,0x04,0x06,0x08,0x0A,0x02,0x1E, |
| |
| Family "2.0" TCG Published Page 461 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 180 0x04,0x1E,0x02,0x0A,0x02,0x12,0x04,0x12,0x06,0x0E,0x0A,0x02,0x04,0x14,0x24,0x06, |
| 181 0x04,0x06,0x0E,0x04,0x14,0x0A,0x0E,0x16,0x06,0x02,0x1E,0x0C,0x0A,0x12,0x02,0x04, |
| 182 0x0E,0x06,0x16,0x12,0x02,0x0C,0x06,0x04,0x08,0x04,0x08,0x06,0x0A,0x02,0x0C,0x12, |
| 183 0x0A,0x0E,0x10,0x0E,0x04,0x06,0x06,0x02,0x06,0x04,0x02,0x1C,0x02,0x1C,0x06,0x02, |
| 184 0x04,0x06,0x0E,0x04,0x0C,0x0E,0x10,0x0E,0x04,0x06,0x08,0x06,0x04,0x06,0x06,0x06, |
| 185 0x08,0x04,0x08,0x04,0x0E,0x10,0x08,0x06,0x04,0x0C,0x08,0x10,0x02,0x0A,0x08,0x04, |
| 186 0x06,0x1A,0x06,0x0A,0x08,0x04,0x06,0x0C,0x0E,0x1E,0x04,0x0E,0x16,0x08,0x0C,0x04, |
| 187 0x06,0x08,0x0A,0x06,0x0E,0x0A,0x06,0x02,0x0A,0x0C,0x0C,0x0E,0x06,0x06,0x12,0x0A, |
| 188 0x06,0x08,0x12,0x04,0x06,0x02,0x06,0x0A,0x02,0x0A,0x08,0x06,0x06,0x0A,0x02,0x12 |
| 189 #endif |
| 190 // 1792 |
| 191 #if PRIME_DIFF_TABLE_BYTES > 1792 |
| 192 ,0x0A,0x02,0x0C,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x0C,0x04,0x08,0x0A,0x06,0x06,0x14, |
| 193 0x04,0x0E,0x10,0x0E,0x0A,0x08,0x0A,0x0C,0x02,0x12,0x06,0x0C,0x0A,0x0C,0x02,0x04, |
| 194 0x02,0x0C,0x06,0x04,0x08,0x04,0x2C,0x04,0x02,0x04,0x02,0x0A,0x0C,0x06,0x06,0x0E, |
| 195 0x04,0x06,0x06,0x06,0x08,0x06,0x24,0x12,0x04,0x06,0x02,0x0C,0x06,0x06,0x06,0x04, |
| 196 0x0E,0x16,0x0C,0x02,0x12,0x0A,0x06,0x1A,0x18,0x04,0x02,0x04,0x02,0x04,0x0E,0x04, |
| 197 0x06,0x06,0x08,0x10,0x0C,0x02,0x2A,0x04,0x02,0x04,0x18,0x06,0x06,0x02,0x12,0x04, |
| 198 0x0E,0x06,0x1C,0x12,0x0E,0x06,0x0A,0x0C,0x02,0x06,0x0C,0x1E,0x06,0x04,0x06,0x06, |
| 199 0x0E,0x04,0x02,0x18,0x04,0x06,0x06,0x1A,0x0A,0x12,0x06,0x08,0x06,0x06,0x1E,0x04, |
| 200 0x0C,0x0C,0x02,0x10,0x02,0x06,0x04,0x0C,0x12,0x02,0x06,0x04,0x1A,0x0C,0x06,0x0C, |
| 201 0x04,0x18,0x18,0x0C,0x06,0x02,0x0C,0x1C,0x08,0x04,0x06,0x0C,0x02,0x12,0x06,0x04, |
| 202 0x06,0x06,0x14,0x10,0x02,0x06,0x06,0x12,0x0A,0x06,0x02,0x04,0x08,0x06,0x06,0x18, |
| 203 0x10,0x06,0x08,0x0A,0x06,0x0E,0x16,0x08,0x10,0x06,0x02,0x0C,0x04,0x02,0x16,0x08, |
| 204 0x12,0x22,0x02,0x06,0x12,0x04,0x06,0x06,0x08,0x0A,0x08,0x12,0x06,0x04,0x02,0x04, |
| 205 0x08,0x10,0x02,0x0C,0x0C,0x06,0x12,0x04,0x06,0x06,0x06,0x02,0x06,0x0C,0x0A,0x14, |
| 206 0x0C,0x12,0x04,0x06,0x02,0x10,0x02,0x0A,0x0E,0x04,0x1E,0x02,0x0A,0x0C,0x02,0x18, |
| 207 0x06,0x10,0x08,0x0A,0x02,0x0C,0x16,0x06,0x02,0x10,0x14,0x0A,0x02,0x0C,0x0C,0x00 |
| 208 #endif |
| 209 // 2048 |
| 210 #if PRIME_DIFF_TABLE_BYTES > 2048 |
| 211 ,0x12,0x0A,0x0C,0x06,0x02,0x0A,0x02,0x06,0x0A,0x12,0x02,0x0C,0x06,0x04,0x06,0x02, |
| 212 0x18,0x1C,0x02,0x04,0x02,0x0A,0x02,0x10,0x0C,0x08,0x16,0x02,0x06,0x04,0x02,0x0A, |
| 213 0x06,0x14,0x0C,0x0A,0x08,0x0C,0x06,0x06,0x06,0x04,0x12,0x02,0x04,0x0C,0x12,0x02, |
| 214 0x0C,0x06,0x04,0x02,0x10,0x0C,0x0C,0x0E,0x04,0x08,0x12,0x04,0x0C,0x0E,0x06,0x06, |
| 215 0x04,0x08,0x06,0x04,0x14,0x0C,0x0A,0x0E,0x04,0x02,0x10,0x02,0x0C,0x1E,0x04,0x06, |
| 216 0x18,0x14,0x18,0x0A,0x08,0x0C,0x0A,0x0C,0x06,0x0C,0x0C,0x06,0x08,0x10,0x0E,0x06, |
| 217 0x04,0x06,0x24,0x14,0x0A,0x1E,0x0C,0x02,0x04,0x02,0x1C,0x0C,0x0E,0x06,0x16,0x08, |
| 218 0x04,0x12,0x06,0x0E,0x12,0x04,0x06,0x02,0x06,0x22,0x12,0x02,0x10,0x06,0x12,0x02, |
| 219 0x18,0x04,0x02,0x06,0x0C,0x06,0x0C,0x0A,0x08,0x06,0x10,0x0C,0x08,0x0A,0x0E,0x28, |
| 220 0x06,0x02,0x06,0x04,0x0C,0x0E,0x04,0x02,0x04,0x02,0x04,0x08,0x06,0x0A,0x06,0x06, |
| 221 0x02,0x06,0x06,0x06,0x0C,0x06,0x18,0x0A,0x02,0x0A,0x06,0x0C,0x06,0x06,0x0E,0x06, |
| 222 0x06,0x34,0x14,0x06,0x0A,0x02,0x0A,0x08,0x0A,0x0C,0x0C,0x02,0x06,0x04,0x0E,0x10, |
| 223 0x08,0x0C,0x06,0x16,0x02,0x0A,0x08,0x06,0x16,0x02,0x16,0x06,0x08,0x0A,0x0C,0x0C, |
| 224 0x02,0x0A,0x06,0x0C,0x02,0x04,0x0E,0x0A,0x02,0x06,0x12,0x04,0x0C,0x08,0x12,0x0C, |
| 225 0x06,0x06,0x04,0x06,0x06,0x0E,0x04,0x02,0x0C,0x0C,0x04,0x06,0x12,0x12,0x0C,0x02, |
| 226 0x10,0x0C,0x08,0x12,0x0A,0x1A,0x04,0x06,0x08,0x06,0x06,0x04,0x02,0x0A,0x14,0x04 |
| 227 #endif |
| 228 // 2304 |
| 229 #if PRIME_DIFF_TABLE_BYTES > 2304 |
| 230 ,0x06,0x08,0x04,0x14,0x0A,0x02,0x22,0x02,0x04,0x18,0x02,0x0C,0x0C,0x0A,0x06,0x02, |
| 231 0x0C,0x1E,0x06,0x0C,0x10,0x0C,0x02,0x16,0x12,0x0C,0x0E,0x0A,0x02,0x0C,0x0C,0x04, |
| 232 0x02,0x04,0x06,0x0C,0x02,0x10,0x12,0x02,0x28,0x08,0x10,0x06,0x08,0x0A,0x02,0x04, |
| 233 0x12,0x08,0x0A,0x08,0x0C,0x04,0x12,0x02,0x12,0x0A,0x02,0x04,0x02,0x04,0x08,0x1C, |
| 234 0x02,0x06,0x16,0x0C,0x06,0x0E,0x12,0x04,0x06,0x08,0x06,0x06,0x0A,0x08,0x04,0x02, |
| 235 0x12,0x0A,0x06,0x14,0x16,0x08,0x06,0x1E,0x04,0x02,0x04,0x12,0x06,0x1E,0x02,0x04, |
| 236 0x08,0x06,0x04,0x06,0x0C,0x0E,0x22,0x0E,0x06,0x04,0x02,0x06,0x04,0x0E,0x04,0x02, |
| 237 0x06,0x1C,0x02,0x04,0x06,0x08,0x0A,0x02,0x0A,0x02,0x0A,0x02,0x04,0x1E,0x02,0x0C, |
| 238 0x0C,0x0A,0x12,0x0C,0x0E,0x0A,0x02,0x0C,0x06,0x0A,0x06,0x0E,0x0C,0x04,0x0E,0x04, |
| 239 0x12,0x02,0x0A,0x08,0x04,0x08,0x0A,0x0C,0x12,0x12,0x08,0x06,0x12,0x10,0x0E,0x06, |
| 240 0x06,0x0A,0x0E,0x04,0x06,0x02,0x0C,0x0C,0x04,0x06,0x06,0x0C,0x02,0x10,0x02,0x0C, |
| 241 0x06,0x04,0x0E,0x06,0x04,0x02,0x0C,0x12,0x04,0x24,0x12,0x0C,0x0C,0x02,0x04,0x02, |
| 242 0x04,0x08,0x0C,0x04,0x24,0x06,0x12,0x02,0x0C,0x0A,0x06,0x0C,0x18,0x08,0x06,0x06, |
| 243 0x10,0x0C,0x02,0x12,0x0A,0x14,0x0A,0x02,0x06,0x12,0x04,0x02,0x28,0x06,0x02,0x10, |
| 244 0x02,0x04,0x08,0x12,0x0A,0x0C,0x06,0x02,0x0A,0x08,0x04,0x06,0x0C,0x02,0x0A,0x12, |
| 245 0x08,0x06,0x04,0x14,0x04,0x06,0x24,0x06,0x02,0x0A,0x06,0x18,0x06,0x0E,0x10,0x06 |
| |
| Page 462 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 246 #endif |
| 247 // 2560 |
| 248 #if PRIME_DIFF_TABLE_BYTES > 2560 |
| 249 ,0x12,0x02,0x0A,0x14,0x0A,0x08,0x06,0x04,0x06,0x02,0x0A,0x02,0x0C,0x04,0x02,0x04, |
| 250 0x08,0x0A,0x06,0x0C,0x12,0x0E,0x0C,0x10,0x08,0x06,0x10,0x08,0x04,0x02,0x06,0x12, |
| 251 0x18,0x12,0x0A,0x0C,0x02,0x04,0x0E,0x0A,0x06,0x06,0x06,0x12,0x0C,0x02,0x1C,0x12, |
| 252 0x0E,0x10,0x0C,0x0E,0x18,0x0C,0x16,0x06,0x02,0x0A,0x08,0x04,0x02,0x04,0x0E,0x0C, |
| 253 0x06,0x04,0x06,0x0E,0x04,0x02,0x04,0x1E,0x06,0x02,0x06,0x0A,0x02,0x1E,0x16,0x02, |
| 254 0x04,0x06,0x08,0x06,0x06,0x10,0x0C,0x0C,0x06,0x08,0x04,0x02,0x18,0x0C,0x04,0x06, |
| 255 0x08,0x06,0x06,0x0A,0x02,0x06,0x0C,0x1C,0x0E,0x06,0x04,0x0C,0x08,0x06,0x0C,0x04, |
| 256 0x06,0x0E,0x06,0x0C,0x0A,0x06,0x06,0x08,0x06,0x06,0x04,0x02,0x04,0x08,0x0C,0x04, |
| 257 0x0E,0x12,0x0A,0x02,0x10,0x06,0x14,0x06,0x0A,0x08,0x04,0x1E,0x24,0x0C,0x08,0x16, |
| 258 0x0C,0x02,0x06,0x0C,0x10,0x06,0x06,0x02,0x12,0x04,0x1A,0x04,0x08,0x12,0x0A,0x08, |
| 259 0x0A,0x06,0x0E,0x04,0x14,0x16,0x12,0x0C,0x08,0x1C,0x0C,0x06,0x06,0x08,0x06,0x0C, |
| 260 0x18,0x10,0x0E,0x04,0x0E,0x0C,0x06,0x0A,0x0C,0x14,0x06,0x04,0x08,0x12,0x0C,0x12, |
| 261 0x0A,0x02,0x04,0x14,0x0A,0x0E,0x04,0x06,0x02,0x0A,0x18,0x12,0x02,0x04,0x14,0x10, |
| 262 0x0E,0x0A,0x0E,0x06,0x04,0x06,0x14,0x06,0x0A,0x06,0x02,0x0C,0x06,0x1E,0x0A,0x08, |
| 263 0x06,0x04,0x06,0x08,0x28,0x02,0x04,0x02,0x0C,0x12,0x04,0x06,0x08,0x0A,0x06,0x12, |
| 264 0x12,0x02,0x0C,0x10,0x08,0x06,0x04,0x06,0x06,0x02,0x34,0x0E,0x04,0x14,0x10,0x02 |
| 265 #endif |
| 266 // 2816 |
| 267 #if PRIME_DIFF_TABLE_BYTES > 2816 |
| 268 ,0x04,0x06,0x0C,0x02,0x06,0x0C,0x0C,0x06,0x04,0x0E,0x0A,0x06,0x06,0x0E,0x0A,0x0E, |
| 269 0x10,0x08,0x06,0x0C,0x04,0x08,0x16,0x06,0x02,0x12,0x16,0x06,0x02,0x12,0x06,0x10, |
| 270 0x0E,0x0A,0x06,0x0C,0x02,0x06,0x04,0x08,0x12,0x0C,0x10,0x02,0x04,0x0E,0x04,0x08, |
| 271 0x0C,0x0C,0x1E,0x10,0x08,0x04,0x02,0x06,0x16,0x0C,0x08,0x0A,0x06,0x06,0x06,0x0E, |
| 272 0x06,0x12,0x0A,0x0C,0x02,0x0A,0x02,0x04,0x1A,0x04,0x0C,0x08,0x04,0x12,0x08,0x0A, |
| 273 0x0E,0x10,0x06,0x06,0x08,0x0A,0x06,0x08,0x06,0x0C,0x0A,0x14,0x0A,0x08,0x04,0x0C, |
| 274 0x1A,0x12,0x04,0x0C,0x12,0x06,0x1E,0x06,0x08,0x06,0x16,0x0C,0x02,0x04,0x06,0x06, |
| 275 0x02,0x0A,0x02,0x04,0x06,0x06,0x02,0x06,0x16,0x12,0x06,0x12,0x0C,0x08,0x0C,0x06, |
| 276 0x0A,0x0C,0x02,0x10,0x02,0x0A,0x02,0x0A,0x12,0x06,0x14,0x04,0x02,0x06,0x16,0x06, |
| 277 0x06,0x12,0x06,0x0E,0x0C,0x10,0x02,0x06,0x06,0x04,0x0E,0x0C,0x04,0x02,0x12,0x10, |
| 278 0x24,0x0C,0x06,0x0E,0x1C,0x02,0x0C,0x06,0x0C,0x06,0x04,0x02,0x10,0x1E,0x08,0x18, |
| 279 0x06,0x1E,0x0A,0x02,0x12,0x04,0x06,0x0C,0x08,0x16,0x02,0x06,0x16,0x12,0x02,0x0A, |
| 280 0x02,0x0A,0x1E,0x02,0x1C,0x06,0x0E,0x10,0x06,0x14,0x10,0x02,0x06,0x04,0x20,0x04, |
| 281 0x02,0x04,0x06,0x02,0x0C,0x04,0x06,0x06,0x0C,0x02,0x06,0x04,0x06,0x08,0x06,0x04, |
| 282 0x14,0x04,0x20,0x0A,0x08,0x10,0x02,0x16,0x02,0x04,0x06,0x08,0x06,0x10,0x0E,0x04, |
| 283 0x12,0x08,0x04,0x14,0x06,0x0C,0x0C,0x06,0x0A,0x02,0x0A,0x02,0x0C,0x1C,0x0C,0x12 |
| 284 #endif |
| 285 // 3072 |
| 286 #if PRIME_DIFF_TABLE_BYTES > 3072 |
| 287 ,0x02,0x12,0x0A,0x08,0x0A,0x30,0x02,0x04,0x06,0x08,0x0A,0x02,0x0A,0x1E,0x02,0x24, |
| 288 0x06,0x0A,0x06,0x02,0x12,0x04,0x06,0x08,0x10,0x0E,0x10,0x06,0x0E,0x04,0x14,0x04, |
| 289 0x06,0x02,0x0A,0x0C,0x02,0x06,0x0C,0x06,0x06,0x04,0x0C,0x02,0x06,0x04,0x0C,0x06, |
| 290 0x08,0x04,0x02,0x06,0x12,0x0A,0x06,0x08,0x0C,0x06,0x16,0x02,0x06,0x0C,0x12,0x04, |
| 291 0x0E,0x06,0x04,0x14,0x06,0x10,0x08,0x04,0x08,0x16,0x08,0x0C,0x06,0x06,0x10,0x0C, |
| 292 0x12,0x1E,0x08,0x04,0x02,0x04,0x06,0x1A,0x04,0x0E,0x18,0x16,0x06,0x02,0x06,0x0A, |
| 293 0x06,0x0E,0x06,0x06,0x0C,0x0A,0x06,0x02,0x0C,0x0A,0x0C,0x08,0x12,0x12,0x0A,0x06, |
| 294 0x08,0x10,0x06,0x06,0x08,0x10,0x14,0x04,0x02,0x0A,0x02,0x0A,0x0C,0x06,0x08,0x06, |
| 295 0x0A,0x14,0x0A,0x12,0x1A,0x04,0x06,0x1E,0x02,0x04,0x08,0x06,0x0C,0x0C,0x12,0x04, |
| 296 0x08,0x16,0x06,0x02,0x0C,0x22,0x06,0x12,0x0C,0x06,0x02,0x1C,0x0E,0x10,0x0E,0x04, |
| 297 0x0E,0x0C,0x04,0x06,0x06,0x02,0x24,0x04,0x06,0x14,0x0C,0x18,0x06,0x16,0x02,0x10, |
| 298 0x12,0x0C,0x0C,0x12,0x02,0x06,0x06,0x06,0x04,0x06,0x0E,0x04,0x02,0x16,0x08,0x0C, |
| 299 0x06,0x0A,0x06,0x08,0x0C,0x12,0x0C,0x06,0x0A,0x02,0x16,0x0E,0x06,0x06,0x04,0x12, |
| 300 0x06,0x14,0x16,0x02,0x0C,0x18,0x04,0x12,0x12,0x02,0x16,0x02,0x04,0x0C,0x08,0x0C, |
| 301 0x0A,0x0E,0x04,0x02,0x12,0x10,0x26,0x06,0x06,0x06,0x0C,0x0A,0x06,0x0C,0x08,0x06, |
| 302 0x04,0x06,0x0E,0x1E,0x06,0x0A,0x08,0x16,0x06,0x08,0x0C,0x0A,0x02,0x0A,0x02,0x06 |
| 303 #endif |
| 304 // 3328 |
| 305 #if PRIME_DIFF_TABLE_BYTES > 3328 |
| 306 ,0x0A,0x02,0x0A,0x0C,0x12,0x14,0x06,0x04,0x08,0x16,0x06,0x06,0x1E,0x06,0x0E,0x06, |
| 307 0x0C,0x0C,0x06,0x0A,0x02,0x0A,0x1E,0x02,0x10,0x08,0x04,0x02,0x06,0x12,0x04,0x02, |
| 308 0x06,0x04,0x1A,0x04,0x08,0x06,0x0A,0x02,0x04,0x06,0x08,0x04,0x06,0x1E,0x0C,0x02, |
| 309 0x06,0x06,0x04,0x14,0x16,0x08,0x04,0x02,0x04,0x48,0x08,0x04,0x08,0x16,0x02,0x04, |
| 310 0x0E,0x0A,0x02,0x04,0x14,0x06,0x0A,0x12,0x06,0x14,0x10,0x06,0x08,0x06,0x04,0x14, |
| 311 0x0C,0x16,0x02,0x04,0x02,0x0C,0x0A,0x12,0x02,0x16,0x06,0x12,0x1E,0x02,0x0A,0x0E, |
| |
| Family "2.0" TCG Published Page 463 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 312 0x0A,0x08,0x10,0x32,0x06,0x0A,0x08,0x0A,0x0C,0x06,0x12,0x02,0x16,0x06,0x02,0x04, |
| 313 0x06,0x08,0x06,0x06,0x0A,0x12,0x02,0x16,0x02,0x10,0x0E,0x0A,0x06,0x02,0x0C,0x0A, |
| 314 0x14,0x04,0x0E,0x06,0x04,0x24,0x02,0x04,0x06,0x0C,0x02,0x04,0x0E,0x0C,0x06,0x04, |
| 315 0x06,0x02,0x06,0x04,0x14,0x0A,0x02,0x0A,0x06,0x0C,0x02,0x18,0x0C,0x0C,0x06,0x06, |
| 316 0x04,0x18,0x02,0x04,0x18,0x02,0x06,0x04,0x06,0x08,0x10,0x06,0x02,0x0A,0x0C,0x0E, |
| 317 0x06,0x22,0x06,0x0E,0x06,0x04,0x02,0x1E,0x16,0x08,0x04,0x06,0x08,0x04,0x02,0x1C, |
| 318 0x02,0x06,0x04,0x1A,0x12,0x16,0x02,0x06,0x10,0x06,0x02,0x10,0x0C,0x02,0x0C,0x04, |
| 319 0x06,0x06,0x0E,0x0A,0x06,0x08,0x0C,0x04,0x12,0x02,0x0A,0x08,0x10,0x06,0x06,0x1E, |
| 320 0x02,0x0A,0x12,0x02,0x0A,0x08,0x04,0x08,0x0C,0x18,0x28,0x02,0x0C,0x0A,0x06,0x0C, |
| 321 0x02,0x0C,0x04,0x02,0x04,0x06,0x12,0x0E,0x0C,0x06,0x04,0x0E,0x1E,0x04,0x08,0x0A |
| 322 #endif |
| 323 // 3584 |
| 324 #if PRIME_DIFF_TABLE_BYTES > 3584 |
| 325 ,0x08,0x06,0x0A,0x12,0x08,0x04,0x0E,0x10,0x06,0x08,0x04,0x06,0x02,0x0A,0x02,0x0C, |
| 326 0x04,0x02,0x04,0x06,0x08,0x04,0x06,0x20,0x18,0x0A,0x08,0x12,0x0A,0x02,0x06,0x0A, |
| 327 0x02,0x04,0x12,0x06,0x0C,0x02,0x10,0x02,0x16,0x06,0x06,0x08,0x12,0x04,0x12,0x0C, |
| 328 0x08,0x06,0x04,0x14,0x06,0x1E,0x16,0x0C,0x02,0x06,0x12,0x04,0x3E,0x04,0x02,0x0C, |
| 329 0x06,0x0A,0x02,0x0C,0x0C,0x1C,0x02,0x04,0x0E,0x16,0x06,0x02,0x06,0x06,0x0A,0x0E, |
| 330 0x04,0x02,0x0A,0x06,0x08,0x0A,0x0E,0x0A,0x06,0x02,0x0C,0x16,0x12,0x08,0x0A,0x12, |
| 331 0x0C,0x02,0x0C,0x04,0x0C,0x02,0x0A,0x02,0x06,0x12,0x06,0x06,0x22,0x06,0x02,0x0C, |
| 332 0x04,0x06,0x12,0x12,0x02,0x10,0x06,0x06,0x08,0x06,0x0A,0x12,0x08,0x0A,0x08,0x0A, |
| 333 0x02,0x04,0x12,0x1A,0x0C,0x16,0x02,0x04,0x02,0x16,0x06,0x06,0x0E,0x10,0x06,0x14, |
| 334 0x0A,0x0C,0x02,0x12,0x2A,0x04,0x18,0x02,0x06,0x0A,0x0C,0x02,0x06,0x0A,0x08,0x04, |
| 335 0x06,0x0C,0x0C,0x08,0x04,0x06,0x0C,0x1E,0x14,0x06,0x18,0x06,0x0A,0x0C,0x02,0x0A, |
| 336 0x14,0x06,0x06,0x04,0x0C,0x0E,0x0A,0x12,0x0C,0x08,0x06,0x0C,0x04,0x0E,0x0A,0x02, |
| 337 0x0C,0x1E,0x10,0x02,0x0C,0x06,0x04,0x02,0x04,0x06,0x1A,0x04,0x12,0x02,0x04,0x06, |
| 338 0x0E,0x36,0x06,0x34,0x02,0x10,0x06,0x06,0x0C,0x1A,0x04,0x02,0x06,0x16,0x06,0x02, |
| 339 0x0C,0x0C,0x06,0x0A,0x12,0x02,0x0C,0x0C,0x0A,0x12,0x0C,0x06,0x08,0x06,0x0A,0x06, |
| 340 0x08,0x04,0x02,0x04,0x14,0x18,0x06,0x06,0x0A,0x0E,0x0A,0x02,0x16,0x06,0x0E,0x0A |
| 341 #endif |
| 342 // 3840 |
| 343 #if PRIME_DIFF_TABLE_BYTES > 3840 |
| 344 ,0x1A,0x04,0x12,0x08,0x0C,0x0C,0x0A,0x0C,0x06,0x08,0x10,0x06,0x08,0x06,0x06,0x16, |
| 345 0x02,0x0A,0x14,0x0A,0x06,0x2C,0x12,0x06,0x0A,0x02,0x04,0x06,0x0E,0x04,0x1A,0x04, |
| 346 0x02,0x0C,0x0A,0x08,0x04,0x08,0x0C,0x04,0x0C,0x08,0x16,0x08,0x06,0x0A,0x12,0x06, |
| 347 0x06,0x08,0x06,0x0C,0x04,0x08,0x12,0x0A,0x0C,0x06,0x0C,0x02,0x06,0x04,0x02,0x10, |
| 348 0x0C,0x0C,0x0E,0x0A,0x0E,0x06,0x0A,0x0C,0x02,0x0C,0x06,0x04,0x06,0x02,0x0C,0x04, |
| 349 0x1A,0x06,0x12,0x06,0x0A,0x06,0x02,0x12,0x0A,0x08,0x04,0x1A,0x0A,0x14,0x06,0x10, |
| 350 0x14,0x0C,0x0A,0x08,0x0A,0x02,0x10,0x06,0x14,0x0A,0x14,0x04,0x1E,0x02,0x04,0x08, |
| 351 0x10,0x02,0x12,0x04,0x02,0x06,0x0A,0x12,0x0C,0x0E,0x12,0x06,0x10,0x14,0x06,0x04, |
| 352 0x08,0x06,0x04,0x06,0x0C,0x08,0x0A,0x02,0x0C,0x06,0x04,0x02,0x06,0x0A,0x02,0x10, |
| 353 0x0C,0x0E,0x0A,0x06,0x08,0x06,0x1C,0x02,0x06,0x12,0x1E,0x22,0x02,0x10,0x0C,0x02, |
| 354 0x12,0x10,0x06,0x08,0x0A,0x08,0x0A,0x08,0x0A,0x2C,0x06,0x06,0x04,0x14,0x04,0x02, |
| 355 0x04,0x0E,0x1C,0x08,0x06,0x10,0x0E,0x1E,0x06,0x1E,0x04,0x0E,0x0A,0x06,0x06,0x08, |
| 356 0x04,0x12,0x0C,0x06,0x02,0x16,0x0C,0x08,0x06,0x0C,0x04,0x0E,0x04,0x06,0x02,0x04, |
| 357 0x12,0x14,0x06,0x10,0x26,0x10,0x02,0x04,0x06,0x02,0x28,0x2A,0x0E,0x04,0x06,0x02, |
| 358 0x18,0x0A,0x06,0x02,0x12,0x0A,0x0C,0x02,0x10,0x02,0x06,0x10,0x06,0x08,0x04,0x02, |
| 359 0x0A,0x06,0x08,0x0A,0x02,0x12,0x10,0x08,0x0C,0x12,0x0C,0x06,0x0C,0x0A,0x06,0x06 |
| 360 #endif |
| 361 // 4096 |
| 362 #if PRIME_DIFF_TABLE_BYTES > 4096 |
| 363 ,0x12,0x0C,0x0E,0x04,0x02,0x0A,0x14,0x06,0x0C,0x06,0x10,0x1A,0x04,0x12,0x02,0x04, |
| 364 0x20,0x0A,0x08,0x06,0x04,0x06,0x06,0x0E,0x06,0x12,0x04,0x02,0x12,0x0A,0x08,0x0A, |
| 365 0x08,0x0A,0x02,0x04,0x06,0x02,0x0A,0x2A,0x08,0x0C,0x04,0x06,0x12,0x02,0x10,0x08, |
| 366 0x04,0x02,0x0A,0x0E,0x0C,0x0A,0x14,0x04,0x08,0x0A,0x26,0x04,0x06,0x02,0x0A,0x14, |
| 367 0x0A,0x0C,0x06,0x0C,0x1A,0x0C,0x04,0x08,0x1C,0x08,0x04,0x08,0x18,0x06,0x0A,0x08, |
| 368 0x06,0x10,0x0C,0x08,0x0A,0x0C,0x08,0x16,0x06,0x02,0x0A,0x02,0x06,0x0A,0x06,0x06, |
| 369 0x08,0x06,0x04,0x0E,0x1C,0x08,0x10,0x12,0x08,0x04,0x06,0x14,0x04,0x12,0x06,0x02, |
| 370 0x18,0x18,0x06,0x06,0x0C,0x0C,0x04,0x02,0x16,0x02,0x0A,0x06,0x08,0x0C,0x04,0x14, |
| 371 0x12,0x06,0x04,0x0C,0x18,0x06,0x06,0x36,0x08,0x06,0x04,0x1A,0x24,0x04,0x02,0x04, |
| 372 0x1A,0x0C,0x0C,0x04,0x06,0x06,0x08,0x0C,0x0A,0x02,0x0C,0x10,0x12,0x06,0x08,0x06, |
| 373 0x0C,0x12,0x0A,0x02,0x36,0x04,0x02,0x0A,0x1E,0x0C,0x08,0x04,0x08,0x10,0x0E,0x0C, |
| 374 0x06,0x04,0x06,0x0C,0x06,0x02,0x04,0x0E,0x0C,0x04,0x0E,0x06,0x18,0x06,0x06,0x0A, |
| 375 0x0C,0x0C,0x14,0x12,0x06,0x06,0x10,0x08,0x04,0x06,0x14,0x04,0x20,0x04,0x0E,0x0A, |
| 376 0x02,0x06,0x0C,0x10,0x02,0x04,0x06,0x0C,0x02,0x0A,0x08,0x06,0x04,0x02,0x0A,0x0E, |
| 377 0x06,0x06,0x0C,0x12,0x22,0x08,0x0A,0x06,0x18,0x06,0x02,0x0A,0x0C,0x02,0x1E,0x0A, |
| |
| Page 464 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 378 0x0E,0x0C,0x0C,0x10,0x06,0x06,0x02,0x12,0x04,0x06,0x1E,0x0E,0x04,0x06,0x06,0x02 |
| 379 #endif |
| 380 // 4352 |
| 381 #if PRIME_DIFF_TABLE_BYTES > 4352 |
| 382 ,0x06,0x04,0x06,0x0E,0x06,0x04,0x08,0x0A,0x0C,0x06,0x20,0x0A,0x08,0x16,0x02,0x0A, |
| 383 0x06,0x18,0x08,0x04,0x1E,0x06,0x02,0x0C,0x10,0x08,0x06,0x04,0x06,0x08,0x10,0x0E, |
| 384 0x06,0x06,0x04,0x02,0x0A,0x0C,0x02,0x10,0x0E,0x04,0x02,0x04,0x14,0x12,0x0A,0x02, |
| 385 0x0A,0x06,0x0C,0x1E,0x08,0x12,0x0C,0x0A,0x02,0x06,0x06,0x04,0x0C,0x0C,0x02,0x04, |
| 386 0x0C,0x12,0x18,0x02,0x0A,0x06,0x08,0x10,0x08,0x06,0x0C,0x0A,0x0E,0x06,0x0C,0x06, |
| 387 0x06,0x04,0x02,0x18,0x04,0x06,0x08,0x06,0x04,0x02,0x04,0x06,0x0E,0x04,0x08,0x0A, |
| 388 0x18,0x18,0x0C,0x02,0x06,0x0C,0x16,0x1E,0x02,0x06,0x12,0x0A,0x06,0x06,0x08,0x04, |
| 389 0x02,0x06,0x0A,0x08,0x0A,0x06,0x08,0x10,0x06,0x0E,0x06,0x04,0x18,0x08,0x0A,0x02, |
| 390 0x0C,0x06,0x04,0x24,0x02,0x16,0x06,0x08,0x06,0x0A,0x08,0x06,0x0C,0x0A,0x0E,0x0A, |
| 391 0x06,0x12,0x0C,0x02,0x0C,0x04,0x1A,0x0A,0x0E,0x10,0x12,0x08,0x12,0x0C,0x0C,0x06, |
| 392 0x10,0x0E,0x18,0x0A,0x0C,0x08,0x16,0x06,0x02,0x0A,0x3C,0x06,0x02,0x04,0x08,0x10, |
| 393 0x0E,0x0A,0x06,0x18,0x06,0x0C,0x12,0x18,0x02,0x1E,0x04,0x02,0x0C,0x06,0x0A,0x02, |
| 394 0x04,0x0E,0x06,0x10,0x02,0x0A,0x08,0x16,0x14,0x06,0x04,0x20,0x06,0x12,0x04,0x02, |
| 395 0x04,0x02,0x04,0x08,0x34,0x0E,0x16,0x02,0x16,0x14,0x0A,0x08,0x0A,0x02,0x06,0x04, |
| 396 0x0E,0x04,0x06,0x14,0x04,0x06,0x02,0x0C,0x0C,0x06,0x0C,0x10,0x02,0x0C,0x0A,0x08, |
| 397 0x04,0x06,0x02,0x1C,0x0C,0x08,0x0A,0x0C,0x02,0x04,0x0E,0x1C,0x08,0x06,0x04,0x02 |
| 398 #endif |
| 399 // 4608 |
| 400 #if PRIME_DIFF_TABLE_BYTES > 4608 |
| 401 ,0x04,0x06,0x02,0x0C,0x3A,0x06,0x0E,0x0A,0x02,0x06,0x1C,0x20,0x04,0x1E,0x08,0x06, |
| 402 0x04,0x06,0x0C,0x0C,0x02,0x04,0x06,0x06,0x0E,0x10,0x08,0x1E,0x04,0x02,0x0A,0x08, |
| 403 0x06,0x04,0x06,0x1A,0x04,0x0C,0x02,0x0A,0x12,0x0C,0x0C,0x12,0x02,0x04,0x0C,0x08, |
| 404 0x0C,0x0A,0x14,0x04,0x08,0x10,0x0C,0x08,0x06,0x10,0x08,0x0A,0x0C,0x0E,0x06,0x04, |
| 405 0x08,0x0C,0x04,0x14,0x06,0x28,0x08,0x10,0x06,0x24,0x02,0x06,0x04,0x06,0x02,0x16, |
| 406 0x12,0x02,0x0A,0x06,0x24,0x0E,0x0C,0x04,0x12,0x08,0x04,0x0E,0x0A,0x02,0x0A,0x08, |
| 407 0x04,0x02,0x12,0x10,0x0C,0x0E,0x0A,0x0E,0x06,0x06,0x2A,0x0A,0x06,0x06,0x14,0x0A, |
| 408 0x08,0x0C,0x04,0x0C,0x12,0x02,0x0A,0x0E,0x12,0x0A,0x12,0x08,0x06,0x04,0x0E,0x06, |
| 409 0x0A,0x1E,0x0E,0x06,0x06,0x04,0x0C,0x26,0x04,0x02,0x04,0x06,0x08,0x0C,0x0A,0x06, |
| 410 0x12,0x06,0x32,0x06,0x04,0x06,0x0C,0x08,0x0A,0x20,0x06,0x16,0x02,0x0A,0x0C,0x12, |
| 411 0x02,0x06,0x04,0x1E,0x08,0x06,0x06,0x12,0x0A,0x02,0x04,0x0C,0x14,0x0A,0x08,0x18, |
| 412 0x0A,0x02,0x06,0x16,0x06,0x02,0x12,0x0A,0x0C,0x02,0x1E,0x12,0x0C,0x1C,0x02,0x06, |
| 413 0x04,0x06,0x0E,0x06,0x0C,0x0A,0x08,0x04,0x0C,0x1A,0x0A,0x08,0x06,0x10,0x02,0x0A, |
| 414 0x12,0x0E,0x06,0x04,0x06,0x0E,0x10,0x02,0x06,0x04,0x0C,0x14,0x04,0x14,0x04,0x06, |
| 415 0x0C,0x02,0x24,0x04,0x06,0x02,0x0A,0x02,0x16,0x08,0x06,0x0A,0x0C,0x0C,0x12,0x0E, |
| 416 0x18,0x24,0x04,0x14,0x18,0x0A,0x06,0x02,0x1C,0x06,0x12,0x08,0x04,0x06,0x08,0x06 |
| 417 #endif |
| 418 // 4864 |
| 419 #if PRIME_DIFF_TABLE_BYTES > 4864 |
| 420 ,0x04,0x02,0x0C,0x1C,0x12,0x0E,0x10,0x0E,0x12,0x0A,0x08,0x06,0x04,0x06,0x06,0x08, |
| 421 0x16,0x0C,0x02,0x0A,0x12,0x06,0x02,0x12,0x0A,0x02,0x0C,0x0A,0x12,0x20,0x06,0x04, |
| 422 0x06,0x06,0x08,0x06,0x06,0x0A,0x14,0x06,0x0C,0x0A,0x08,0x0A,0x0E,0x06,0x0A,0x0E, |
| 423 0x04,0x02,0x16,0x12,0x02,0x0A,0x02,0x04,0x14,0x04,0x02,0x22,0x02,0x0C,0x06,0x0A, |
| 424 0x02,0x0A,0x12,0x06,0x0E,0x0C,0x0C,0x16,0x08,0x06,0x10,0x06,0x08,0x04,0x0C,0x06, |
| 425 0x08,0x04,0x24,0x06,0x06,0x14,0x18,0x06,0x0C,0x12,0x0A,0x02,0x0A,0x1A,0x06,0x10, |
| 426 0x08,0x06,0x04,0x18,0x12,0x08,0x0C,0x0C,0x0A,0x12,0x0C,0x02,0x18,0x04,0x0C,0x12, |
| 427 0x0C,0x0E,0x0A,0x02,0x04,0x18,0x0C,0x0E,0x0A,0x06,0x02,0x06,0x04,0x06,0x1A,0x04, |
| 428 0x06,0x06,0x02,0x16,0x08,0x12,0x04,0x12,0x08,0x04,0x18,0x02,0x0C,0x0C,0x04,0x02, |
| 429 0x34,0x02,0x12,0x06,0x04,0x06,0x0C,0x02,0x06,0x0C,0x0A,0x08,0x04,0x02,0x18,0x0A, |
| 430 0x02,0x0A,0x02,0x0C,0x06,0x12,0x28,0x06,0x14,0x10,0x02,0x0C,0x06,0x0A,0x0C,0x02, |
| 431 0x04,0x06,0x0E,0x0C,0x0C,0x16,0x06,0x08,0x04,0x02,0x10,0x12,0x0C,0x02,0x06,0x10, |
| 432 0x06,0x02,0x06,0x04,0x0C,0x1E,0x08,0x10,0x02,0x12,0x0A,0x18,0x02,0x06,0x18,0x04, |
| 433 0x02,0x16,0x02,0x10,0x02,0x06,0x0C,0x04,0x12,0x08,0x04,0x0E,0x04,0x12,0x18,0x06, |
| 434 0x02,0x06,0x0A,0x02,0x0A,0x26,0x06,0x0A,0x0E,0x06,0x06,0x18,0x04,0x02,0x0C,0x10, |
| 435 0x0E,0x10,0x0C,0x02,0x06,0x0A,0x1A,0x04,0x02,0x0C,0x06,0x04,0x0C,0x08,0x0C,0x0A |
| 436 #endif |
| 437 // 5120 |
| 438 #if PRIME_DIFF_TABLE_BYTES > 5120 |
| 439 ,0x12,0x06,0x0E,0x1C,0x02,0x06,0x0A,0x02,0x04,0x0E,0x22,0x02,0x06,0x16,0x02,0x0A, |
| 440 0x0E,0x04,0x02,0x10,0x08,0x0A,0x06,0x08,0x0A,0x08,0x04,0x06,0x02,0x10,0x06,0x06, |
| 441 0x12,0x1E,0x0E,0x06,0x04,0x1E,0x02,0x0A,0x0E,0x04,0x14,0x0A,0x08,0x04,0x08,0x12, |
| 442 0x04,0x0E,0x06,0x04,0x18,0x06,0x06,0x12,0x12,0x02,0x24,0x06,0x0A,0x0E,0x0C,0x04, |
| 443 0x06,0x02,0x1E,0x06,0x04,0x02,0x06,0x1C,0x14,0x04,0x14,0x0C,0x18,0x10,0x12,0x0C, |
| |
| Family "2.0" TCG Published Page 465 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 444 0x0E,0x06,0x04,0x0C,0x20,0x0C,0x06,0x0A,0x08,0x0A,0x06,0x12,0x02,0x10,0x0E,0x06, |
| 445 0x16,0x06,0x0C,0x02,0x12,0x04,0x08,0x1E,0x0C,0x04,0x0C,0x02,0x0A,0x26,0x16,0x02, |
| 446 0x04,0x0E,0x06,0x0C,0x18,0x04,0x02,0x04,0x0E,0x0C,0x0A,0x02,0x10,0x06,0x14,0x04, |
| 447 0x14,0x16,0x0C,0x02,0x04,0x02,0x0C,0x16,0x18,0x06,0x06,0x02,0x06,0x04,0x06,0x02, |
| 448 0x0A,0x0C,0x0C,0x06,0x02,0x06,0x10,0x08,0x06,0x04,0x12,0x0C,0x0C,0x0E,0x04,0x0C, |
| 449 0x06,0x08,0x06,0x12,0x06,0x0A,0x0C,0x0E,0x06,0x04,0x08,0x16,0x06,0x02,0x1C,0x12, |
| 450 0x02,0x12,0x0A,0x06,0x0E,0x0A,0x02,0x0A,0x0E,0x06,0x0A,0x02,0x16,0x06,0x08,0x06, |
| 451 0x10,0x0C,0x08,0x16,0x02,0x04,0x0E,0x12,0x0C,0x06,0x18,0x06,0x0A,0x02,0x0C,0x16, |
| 452 0x12,0x06,0x14,0x06,0x0A,0x0E,0x04,0x02,0x06,0x0C,0x16,0x0E,0x0C,0x04,0x06,0x08, |
| 453 0x16,0x02,0x0A,0x0C,0x08,0x28,0x02,0x06,0x0A,0x08,0x04,0x2A,0x14,0x04,0x20,0x0C, |
| 454 0x0A,0x06,0x0C,0x0C,0x02,0x0A,0x08,0x06,0x04,0x08,0x04,0x1A,0x12,0x04,0x08,0x1C |
| 455 #endif |
| 456 // 5376 |
| 457 #if PRIME_DIFF_TABLE_BYTES > 5376 |
| 458 ,0x06,0x12,0x06,0x0C,0x02,0x0A,0x06,0x06,0x0E,0x0A,0x0C,0x0E,0x18,0x06,0x04,0x14, |
| 459 0x16,0x02,0x12,0x04,0x06,0x0C,0x02,0x10,0x12,0x0E,0x06,0x06,0x04,0x06,0x08,0x12, |
| 460 0x04,0x0E,0x1E,0x04,0x12,0x08,0x0A,0x02,0x04,0x08,0x0C,0x04,0x0C,0x12,0x02,0x0C, |
| 461 0x0A,0x02,0x10,0x08,0x04,0x1E,0x02,0x06,0x1C,0x02,0x0A,0x02,0x12,0x0A,0x0E,0x04, |
| 462 0x1A,0x06,0x12,0x04,0x14,0x06,0x04,0x08,0x12,0x04,0x0C,0x1A,0x18,0x04,0x14,0x16, |
| 463 0x02,0x12,0x16,0x02,0x04,0x0C,0x02,0x06,0x06,0x06,0x04,0x06,0x0E,0x04,0x18,0x0C, |
| 464 0x06,0x12,0x02,0x0C,0x1C,0x0E,0x04,0x06,0x08,0x16,0x06,0x0C,0x12,0x08,0x04,0x14, |
| 465 0x06,0x04,0x06,0x02,0x12,0x06,0x04,0x0C,0x0C,0x08,0x1C,0x06,0x08,0x0A,0x02,0x18, |
| 466 0x0C,0x0A,0x18,0x08,0x0A,0x14,0x0C,0x06,0x0C,0x0C,0x04,0x0E,0x0C,0x18,0x22,0x12, |
| 467 0x08,0x0A,0x06,0x12,0x08,0x04,0x08,0x10,0x0E,0x06,0x04,0x06,0x18,0x02,0x06,0x04, |
| 468 0x06,0x02,0x10,0x06,0x06,0x14,0x18,0x04,0x02,0x04,0x0E,0x04,0x12,0x02,0x06,0x0C, |
| 469 0x04,0x0E,0x04,0x02,0x12,0x10,0x06,0x06,0x02,0x10,0x14,0x06,0x06,0x1E,0x04,0x08, |
| 470 0x06,0x18,0x10,0x06,0x06,0x08,0x0C,0x1E,0x04,0x12,0x12,0x08,0x04,0x1A,0x0A,0x02, |
| 471 0x16,0x08,0x0A,0x0E,0x06,0x04,0x12,0x08,0x0C,0x1C,0x02,0x06,0x04,0x0C,0x06,0x18, |
| 472 0x06,0x08,0x0A,0x14,0x10,0x08,0x1E,0x06,0x06,0x04,0x02,0x0A,0x0E,0x06,0x0A,0x20, |
| 473 0x16,0x12,0x02,0x04,0x02,0x04,0x08,0x16,0x08,0x12,0x0C,0x1C,0x02,0x10,0x0C,0x12 |
| 474 #endif |
| 475 // 5632 |
| 476 #if PRIME_DIFF_TABLE_BYTES > 5632 |
| 477 ,0x0E,0x0A,0x12,0x0C,0x06,0x20,0x0A,0x0E,0x06,0x0A,0x02,0x0A,0x02,0x06,0x16,0x02, |
| 478 0x04,0x06,0x08,0x0A,0x06,0x0E,0x06,0x04,0x0C,0x1E,0x18,0x06,0x06,0x08,0x06,0x04, |
| 479 0x02,0x04,0x06,0x08,0x06,0x06,0x16,0x12,0x08,0x04,0x02,0x12,0x06,0x04,0x02,0x10, |
| 480 0x12,0x14,0x0A,0x06,0x06,0x1E,0x02,0x0C,0x1C,0x06,0x06,0x06,0x02,0x0C,0x0A,0x08, |
| 481 0x12,0x12,0x04,0x08,0x12,0x0A,0x02,0x1C,0x02,0x0A,0x0E,0x04,0x02,0x1E,0x0C,0x16, |
| 482 0x1A,0x0A,0x08,0x06,0x0A,0x08,0x10,0x0E,0x06,0x06,0x0A,0x0E,0x06,0x04,0x02,0x0A, |
| 483 0x0C,0x02,0x06,0x0A,0x08,0x04,0x02,0x0A,0x1A,0x16,0x06,0x02,0x0C,0x12,0x04,0x1A, |
| 484 0x04,0x08,0x0A,0x06,0x0E,0x0A,0x02,0x12,0x06,0x0A,0x14,0x06,0x06,0x04,0x18,0x02, |
| 485 0x04,0x08,0x06,0x10,0x0E,0x10,0x12,0x02,0x04,0x0C,0x02,0x0A,0x02,0x06,0x0C,0x0A, |
| 486 0x06,0x06,0x14,0x06,0x04,0x06,0x26,0x04,0x06,0x0C,0x0E,0x04,0x0C,0x08,0x0A,0x0C, |
| 487 0x0C,0x08,0x04,0x06,0x0E,0x0A,0x06,0x0C,0x02,0x0A,0x12,0x02,0x12,0x0A,0x08,0x0A, |
| 488 0x02,0x0C,0x04,0x0E,0x1C,0x02,0x10,0x02,0x12,0x06,0x0A,0x06,0x08,0x10,0x0E,0x1E, |
| 489 0x0A,0x14,0x06,0x0A,0x18,0x02,0x1C,0x02,0x0C,0x10,0x06,0x08,0x24,0x04,0x08,0x04, |
| 490 0x0E,0x0C,0x0A,0x08,0x0C,0x04,0x06,0x08,0x04,0x06,0x0E,0x16,0x08,0x06,0x04,0x02, |
| 491 0x0A,0x06,0x14,0x0A,0x08,0x06,0x06,0x16,0x12,0x02,0x10,0x06,0x14,0x04,0x1A,0x04, |
| 492 0x0E,0x16,0x0E,0x04,0x0C,0x06,0x08,0x04,0x06,0x06,0x1A,0x0A,0x02,0x12,0x12,0x04 |
| 493 #endif |
| 494 // 5888 |
| 495 #if PRIME_DIFF_TABLE_BYTES > 5888 |
| 496 ,0x02,0x10,0x02,0x12,0x04,0x06,0x08,0x04,0x06,0x0C,0x02,0x06,0x06,0x1C,0x26,0x04, |
| 497 0x08,0x10,0x1A,0x04,0x02,0x0A,0x0C,0x02,0x0A,0x08,0x06,0x0A,0x0C,0x02,0x0A,0x02, |
| 498 0x18,0x04,0x1E,0x1A,0x06,0x06,0x12,0x06,0x06,0x16,0x02,0x0A,0x12,0x1A,0x04,0x12, |
| 499 0x08,0x06,0x06,0x0C,0x10,0x06,0x08,0x10,0x06,0x08,0x10,0x02,0x2A,0x3A,0x08,0x04, |
| 500 0x06,0x02,0x04,0x08,0x10,0x06,0x14,0x04,0x0C,0x0C,0x06,0x0C,0x02,0x0A,0x02,0x06, |
| 501 0x16,0x02,0x0A,0x06,0x08,0x06,0x0A,0x0E,0x06,0x06,0x04,0x12,0x08,0x0A,0x08,0x10, |
| 502 0x0E,0x0A,0x02,0x0A,0x02,0x0C,0x06,0x04,0x14,0x0A,0x08,0x34,0x08,0x0A,0x06,0x02, |
| 503 0x0A,0x08,0x0A,0x06,0x06,0x08,0x0A,0x02,0x16,0x02,0x04,0x06,0x0E,0x04,0x02,0x18, |
| 504 0x0C,0x04,0x1A,0x12,0x04,0x06,0x0E,0x1E,0x06,0x04,0x06,0x02,0x16,0x08,0x04,0x06, |
| 505 0x02,0x16,0x06,0x08,0x10,0x06,0x0E,0x04,0x06,0x12,0x08,0x0C,0x06,0x0C,0x18,0x1E, |
| 506 0x10,0x08,0x22,0x08,0x16,0x06,0x0E,0x0A,0x12,0x0E,0x04,0x0C,0x08,0x04,0x24,0x06, |
| 507 0x06,0x02,0x0A,0x02,0x04,0x14,0x06,0x06,0x0A,0x0C,0x06,0x02,0x28,0x08,0x06,0x1C, |
| 508 0x06,0x02,0x0C,0x12,0x04,0x18,0x0E,0x06,0x06,0x0A,0x14,0x0A,0x0E,0x10,0x0E,0x10, |
| 509 0x06,0x08,0x24,0x04,0x0C,0x0C,0x06,0x0C,0x32,0x0C,0x06,0x04,0x06,0x06,0x08,0x06, |
| |
| Page 466 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 510 0x0A,0x02,0x0A,0x02,0x12,0x0A,0x0E,0x10,0x08,0x06,0x04,0x14,0x04,0x02,0x0A,0x06, |
| 511 0x0E,0x12,0x0A,0x26,0x0A,0x12,0x02,0x0A,0x02,0x0C,0x04,0x02,0x04,0x0E,0x06,0x0A |
| 512 #endif |
| 513 // 6144 |
| 514 #if PRIME_DIFF_TABLE_BYTES > 6144 |
| 515 ,0x08,0x28,0x06,0x14,0x04,0x0C,0x08,0x06,0x22,0x08,0x16,0x08,0x0C,0x0A,0x02,0x10, |
| 516 0x2A,0x0C,0x08,0x16,0x08,0x16,0x08,0x06,0x22,0x02,0x06,0x04,0x0E,0x06,0x10,0x02, |
| 517 0x16,0x06,0x08,0x18,0x16,0x06,0x02,0x0C,0x04,0x06,0x0E,0x04,0x08,0x18,0x04,0x06, |
| 518 0x06,0x02,0x16,0x14,0x06,0x04,0x0E,0x04,0x06,0x06,0x08,0x06,0x0A,0x06,0x08,0x06, |
| 519 0x10,0x0E,0x06,0x06,0x16,0x06,0x18,0x20,0x06,0x12,0x06,0x12,0x0A,0x08,0x1E,0x12, |
| 520 0x06,0x10,0x0C,0x06,0x0C,0x02,0x06,0x04,0x0C,0x08,0x06,0x16,0x08,0x06,0x04,0x0E, |
| 521 0x0A,0x12,0x14,0x0A,0x02,0x06,0x04,0x02,0x1C,0x12,0x02,0x0A,0x06,0x06,0x06,0x0E, |
| 522 0x28,0x18,0x02,0x04,0x08,0x0C,0x04,0x14,0x04,0x20,0x12,0x10,0x06,0x24,0x08,0x06, |
| 523 0x04,0x06,0x0E,0x04,0x06,0x1A,0x06,0x0A,0x0E,0x12,0x0A,0x06,0x06,0x0E,0x0A,0x06, |
| 524 0x06,0x0E,0x06,0x18,0x04,0x0E,0x16,0x08,0x0C,0x0A,0x08,0x0C,0x12,0x0A,0x12,0x08, |
| 525 0x18,0x0A,0x08,0x04,0x18,0x06,0x12,0x06,0x02,0x0A,0x1E,0x02,0x0A,0x02,0x04,0x02, |
| 526 0x28,0x02,0x1C,0x08,0x06,0x06,0x12,0x06,0x0A,0x0E,0x04,0x12,0x1E,0x12,0x02,0x0C, |
| 527 0x1E,0x06,0x1E,0x04,0x12,0x0C,0x02,0x04,0x0E,0x06,0x0A,0x06,0x08,0x06,0x0A,0x0C, |
| 528 0x02,0x06,0x0C,0x0A,0x02,0x12,0x04,0x14,0x04,0x06,0x0E,0x06,0x06,0x16,0x06,0x06, |
| 529 0x08,0x12,0x12,0x0A,0x02,0x0A,0x02,0x06,0x04,0x06,0x0C,0x12,0x02,0x0A,0x08,0x04, |
| 530 0x12,0x02,0x06,0x06,0x06,0x0A,0x08,0x0A,0x06,0x12,0x0C,0x08,0x0C,0x06,0x04,0x06 |
| 531 #endif |
| 532 // 6400 |
| 533 #if PRIME_DIFF_TABLE_BYTES > 6400 |
| 534 ,0x0E,0x10,0x02,0x0C,0x04,0x06,0x26,0x06,0x06,0x10,0x14,0x1C,0x14,0x0A,0x06,0x06, |
| 535 0x0E,0x04,0x1A,0x04,0x0E,0x0A,0x12,0x0E,0x1C,0x02,0x04,0x0E,0x10,0x02,0x1C,0x06, |
| 536 0x08,0x06,0x22,0x08,0x04,0x12,0x02,0x10,0x08,0x06,0x28,0x08,0x12,0x04,0x1E,0x06, |
| 537 0x0C,0x02,0x1E,0x06,0x0A,0x0E,0x28,0x0E,0x0A,0x02,0x0C,0x0A,0x08,0x04,0x08,0x06, |
| 538 0x06,0x1C,0x02,0x04,0x0C,0x0E,0x10,0x08,0x1E,0x10,0x12,0x02,0x0A,0x12,0x06,0x20, |
| 539 0x04,0x12,0x06,0x02,0x0C,0x0A,0x12,0x02,0x06,0x0A,0x0E,0x12,0x1C,0x06,0x08,0x10, |
| 540 0x02,0x04,0x14,0x0A,0x08,0x12,0x0A,0x02,0x0A,0x08,0x04,0x06,0x0C,0x06,0x14,0x04, |
| 541 0x02,0x06,0x04,0x14,0x0A,0x1A,0x12,0x0A,0x02,0x12,0x06,0x10,0x0E,0x04,0x1A,0x04, |
| 542 0x0E,0x0A,0x0C,0x0E,0x06,0x06,0x04,0x0E,0x0A,0x02,0x1E,0x12,0x16,0x02 |
| 543 #endif |
| 544 // 6542 |
| 545 #if PRIME_DIFF_TABLE_BYTES > 0 |
| 546 }; |
| 547 #endif |
| 548 #if defined RSA_INSTRUMENT || defined RSA_DEBUG |
| 549 UINT32 failedAtIteration[10]; |
| 550 UINT32 MillerRabinTrials; |
| 551 UINT32 totalFields; |
| 552 UINT32 emptyFields; |
| 553 UINT32 noPrimeFields; |
| 554 UINT16 lastSievePrime; |
| 555 UINT32 primesChecked; |
| 556 #endif |
| |
| Only want this table when doing debug of the prime number stuff This is a table of the first 2048 primes |
| and takes 4096 bytes |
| |
| 557 #ifdef RSA_DEBUG |
| 558 const __int16 primes[NUM_PRIMES]= |
| 559 { |
| 560 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, |
| 561 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, |
| 562 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, |
| 563 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, |
| 564 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, |
| 565 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, |
| 566 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, |
| 567 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, |
| 568 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, |
| 569 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, |
| 570 947, 953, 967, 971, 977, 983, 991, 997,1009,1013,1019,1021,1031,1033,1039,1049, |
| |
| Family "2.0" TCG Published Page 467 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 571 1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163, |
| 572 1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283, |
| 573 1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423, |
| 574 1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511, |
| 575 1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619, |
| 576 1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747, |
| 577 1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877, |
| 578 1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003, |
| 579 2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129, |
| 580 2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267, |
| 581 2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377, |
| 582 2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503, |
| 583 2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657, |
| 584 2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741, |
| 585 2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861, |
| 586 2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011, |
| 587 3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167, |
| 588 3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301, |
| 589 3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413, |
| 590 3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541, |
| 591 3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671, |
| 592 3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797, |
| 593 3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923, |
| 594 3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057, |
| 595 4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211, |
| 596 4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337, |
| 597 4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481, |
| 598 4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621, |
| 599 4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751, |
| 600 4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909, |
| 601 4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011, |
| 602 5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167, |
| 603 5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309, |
| 604 5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443, |
| 605 5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573, |
| 606 5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711, |
| 607 5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849, |
| 608 5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007, |
| 609 6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133, |
| 610 6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271, |
| 611 6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379, |
| 612 6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563, |
| 613 6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701, |
| 614 6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833, |
| 615 6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971, |
| 616 6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121, |
| 617 7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253, |
| 618 7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457, |
| 619 7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561, |
| 620 7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691, |
| 621 7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853, |
| 622 7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009, |
| 623 8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161, |
| 624 8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291, |
| 625 8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443, |
| 626 8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609, |
| 627 8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731, |
| 628 8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861, |
| 629 8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011, |
| 630 9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161, |
| 631 9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311, |
| 632 9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433, |
| 633 9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587, |
| 634 9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733, |
| 635 9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857, |
| 636 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, |
| |
| Page 468 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 637 9931, 9941, 9949, 9967, 9973,10007,10009,10037, |
| 638 10039,10061,10067,10069,10079,10091,10093,10099, |
| 639 10103,10111,10133,10139,10141,10151,10159,10163, |
| 640 10169,10177,10181,10193,10211,10223,10243,10247, |
| 641 10253,10259,10267,10271,10273,10289,10301,10303, |
| 642 10313,10321,10331,10333,10337,10343,10357,10369, |
| 643 10391,10399,10427,10429,10433,10453,10457,10459, |
| 644 10463,10477,10487,10499,10501,10513,10529,10531, |
| 645 10559,10567,10589,10597,10601,10607,10613,10627, |
| 646 10631,10639,10651,10657,10663,10667,10687,10691, |
| 647 10709,10711,10723,10729,10733,10739,10753,10771, |
| 648 10781,10789,10799,10831,10837,10847,10853,10859, |
| 649 10861,10867,10883,10889,10891,10903,10909,10937, |
| 650 10939,10949,10957,10973,10979,10987,10993,11003, |
| 651 11027,11047,11057,11059,11069,11071,11083,11087, |
| 652 11093,11113,11117,11119,11131,11149,11159,11161, |
| 653 11171,11173,11177,11197,11213,11239,11243,11251, |
| 654 11257,11261,11273,11279,11287,11299,11311,11317, |
| 655 11321,11329,11351,11353,11369,11383,11393,11399, |
| 656 11411,11423,11437,11443,11447,11467,11471,11483, |
| 657 11489,11491,11497,11503,11519,11527,11549,11551, |
| 658 11579,11587,11593,11597,11617,11621,11633,11657, |
| 659 11677,11681,11689,11699,11701,11717,11719,11731, |
| 660 11743,11777,11779,11783,11789,11801,11807,11813, |
| 661 11821,11827,11831,11833,11839,11863,11867,11887, |
| 662 11897,11903,11909,11923,11927,11933,11939,11941, |
| 663 11953,11959,11969,11971,11981,11987,12007,12011, |
| 664 12037,12041,12043,12049,12071,12073,12097,12101, |
| 665 12107,12109,12113,12119,12143,12149,12157,12161, |
| 666 12163,12197,12203,12211,12227,12239,12241,12251, |
| 667 12253,12263,12269,12277,12281,12289,12301,12323, |
| 668 12329,12343,12347,12373,12377,12379,12391,12401, |
| 669 12409,12413,12421,12433,12437,12451,12457,12473, |
| 670 12479,12487,12491,12497,12503,12511,12517,12527, |
| 671 12539,12541,12547,12553,12569,12577,12583,12589, |
| 672 12601,12611,12613,12619,12637,12641,12647,12653, |
| 673 12659,12671,12689,12697,12703,12713,12721,12739, |
| 674 12743,12757,12763,12781,12791,12799,12809,12821, |
| 675 12823,12829,12841,12853,12889,12893,12899,12907, |
| 676 12911,12917,12919,12923,12941,12953,12959,12967, |
| 677 12973,12979,12983,13001,13003,13007,13009,13033, |
| 678 13037,13043,13049,13063,13093,13099,13103,13109, |
| 679 13121,13127,13147,13151,13159,13163,13171,13177, |
| 680 13183,13187,13217,13219,13229,13241,13249,13259, |
| 681 13267,13291,13297,13309,13313,13327,13331,13337, |
| 682 13339,13367,13381,13397,13399,13411,13417,13421, |
| 683 13441,13451,13457,13463,13469,13477,13487,13499, |
| 684 13513,13523,13537,13553,13567,13577,13591,13597, |
| 685 13613,13619,13627,13633,13649,13669,13679,13681, |
| 686 13687,13691,13693,13697,13709,13711,13721,13723, |
| 687 13729,13751,13757,13759,13763,13781,13789,13799, |
| 688 13807,13829,13831,13841,13859,13873,13877,13879, |
| 689 13883,13901,13903,13907,13913,13921,13931,13933, |
| 690 13963,13967,13997,13999,14009,14011,14029,14033, |
| 691 14051,14057,14071,14081,14083,14087,14107,14143, |
| 692 14149,14153,14159,14173,14177,14197,14207,14221, |
| 693 14243,14249,14251,14281,14293,14303,14321,14323, |
| 694 14327,14341,14347,14369,14387,14389,14401,14407, |
| 695 14411,14419,14423,14431,14437,14447,14449,14461, |
| 696 14479,14489,14503,14519,14533,14537,14543,14549, |
| 697 14551,14557,14561,14563,14591,14593,14621,14627, |
| 698 14629,14633,14639,14653,14657,14669,14683,14699, |
| 699 14713,14717,14723,14731,14737,14741,14747,14753, |
| 700 14759,14767,14771,14779,14783,14797,14813,14821, |
| 701 14827,14831,14843,14851,14867,14869,14879,14887, |
| 702 14891,14897,14923,14929,14939,14947,14951,14957, |
| |
| Family "2.0" TCG Published Page 469 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 703 14969,14983,15013,15017,15031,15053,15061,15073, |
| 704 15077,15083,15091,15101,15107,15121,15131,15137, |
| 705 15139,15149,15161,15173,15187,15193,15199,15217, |
| 706 15227,15233,15241,15259,15263,15269,15271,15277, |
| 707 15287,15289,15299,15307,15313,15319,15329,15331, |
| 708 15349,15359,15361,15373,15377,15383,15391,15401, |
| 709 15413,15427,15439,15443,15451,15461,15467,15473, |
| 710 15493,15497,15511,15527,15541,15551,15559,15569, |
| 711 15581,15583,15601,15607,15619,15629,15641,15643, |
| 712 15647,15649,15661,15667,15671,15679,15683,15727, |
| 713 15731,15733,15737,15739,15749,15761,15767,15773, |
| 714 15787,15791,15797,15803,15809,15817,15823,15859, |
| 715 15877,15881,15887,15889,15901,15907,15913,15919, |
| 716 15923,15937,15959,15971,15973,15991,16001,16007, |
| 717 16033,16057,16061,16063,16067,16069,16073,16087, |
| 718 16091,16097,16103,16111,16127,16139,16141,16183, |
| 719 16187,16189,16193,16217,16223,16229,16231,16249, |
| 720 16253,16267,16273,16301,16319,16333,16339,16349, |
| 721 16361,16363,16369,16381,16411,16417,16421,16427, |
| 722 16433,16447,16451,16453,16477,16481,16487,16493, |
| 723 16519,16529,16547,16553,16561,16567,16573,16603, |
| 724 16607,16619,16631,16633,16649,16651,16657,16661, |
| 725 16673,16691,16693,16699,16703,16729,16741,16747, |
| 726 16759,16763,16787,16811,16823,16829,16831,16843, |
| 727 16871,16879,16883,16889,16901,16903,16921,16927, |
| 728 16931,16937,16943,16963,16979,16981,16987,16993, |
| 729 17011,17021,17027,17029,17033,17041,17047,17053, |
| 730 17077,17093,17099,17107,17117,17123,17137,17159, |
| 731 17167,17183,17189,17191,17203,17207,17209,17231, |
| 732 17239,17257,17291,17293,17299,17317,17321,17327, |
| 733 17333,17341,17351,17359,17377,17383,17387,17389, |
| 734 17393,17401,17417,17419,17431,17443,17449,17467, |
| 735 17471,17477,17483,17489,17491,17497,17509,17519, |
| 736 17539,17551,17569,17573,17579,17581,17597,17599, |
| 737 17609,17623,17627,17657,17659,17669,17681,17683, |
| 738 17707,17713,17729,17737,17747,17749,17761,17783, |
| 739 17789,17791,17807,17827,17837,17839,17851,17863 |
| 740 }; |
| 741 #endif |
| 742 #endif |
| |
| |
| |
| |
| Page 470 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.13 Elliptic Curve Files |
| |
| B.13.1. CpriDataEcc.h |
| |
| 1 #ifndef _CRYPTDATAECC_H_ |
| 2 #define _CRYPTDATAECC_H_ |
| |
| Structure for the curve parameters. This is an analog to the TPMS_ALGORITHM_DETAIL_ECC |
| |
| 3 typedef struct { |
| 4 const TPM2B *p; // a prime number |
| 5 const TPM2B *a; // linear coefficient |
| 6 const TPM2B *b; // constant term |
| 7 const TPM2B *x; // generator x coordinate |
| 8 const TPM2B *y; // generator y coordinate |
| 9 const TPM2B *n; // the order of the curve |
| 10 const TPM2B *h; // cofactor |
| 11 } ECC_CURVE_DATA; |
| 12 typedef struct |
| 13 { |
| 14 TPM_ECC_CURVE curveId; |
| 15 UINT16 keySizeBits; |
| 16 TPMT_KDF_SCHEME kdf; |
| 17 TPMT_ECC_SCHEME sign; |
| 18 const ECC_CURVE_DATA *curveData; // the address of the curve data |
| 19 } ECC_CURVE; |
| 20 extern const ECC_CURVE_DATA SM2_P256; |
| 21 extern const ECC_CURVE_DATA NIST_P256; |
| 22 extern const ECC_CURVE_DATA BN_P256; |
| 23 extern const ECC_CURVE eccCurves[]; |
| 24 extern const UINT16 ECC_CURVE_COUNT; |
| 25 #endif |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 471 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| B.13.2. CpriDataEcc.c |
| |
| Defines for the sizes of ECC parameters |
| |
| 1 #include "TPMB.h" |
| 2 TPM2B_BYTE_VALUE(1); |
| 3 TPM2B_BYTE_VALUE(16); |
| 4 TPM2B_BYTE_VALUE(2); |
| 5 TPM2B_BYTE_VALUE(24); |
| 6 TPM2B_BYTE_VALUE(28); |
| 7 TPM2B_BYTE_VALUE(32); |
| 8 TPM2B_BYTE_VALUE(4); |
| 9 TPM2B_BYTE_VALUE(48); |
| 10 TPM2B_BYTE_VALUE(64); |
| 11 TPM2B_BYTE_VALUE(66); |
| 12 TPM2B_BYTE_VALUE(8); |
| 13 TPM2B_BYTE_VALUE(80); |
| 14 #if defined ECC_NIST_P192 && ECC_NIST_P192 == YES |
| 15 const TPM2B_24_BYTE_VALUE NIST_P192_p = {24, |
| 16 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 17 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 18 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; |
| 19 const TPM2B_24_BYTE_VALUE NIST_P192_a = {24, |
| 20 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 21 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 22 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}}; |
| 23 const TPM2B_24_BYTE_VALUE NIST_P192_b = {24, |
| 24 {0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, |
| 25 0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49, |
| 26 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1}}; |
| 27 const TPM2B_24_BYTE_VALUE NIST_P192_gX = {24, |
| 28 {0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, |
| 29 0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00, |
| 30 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12}}; |
| 31 const TPM2B_24_BYTE_VALUE NIST_P192_gY = {24, |
| 32 {0x07, 0x19, 0x2B, 0x95, 0xFFC, 0x8D, 0xA7, 0x86, |
| 33 0x31, 0x01, 0x1ED, 0x6B, 0x24, 0xCD, 0xD5, 0x73, |
| 34 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11}}; |
| 35 const TPM2B_24_BYTE_VALUE NIST_P192_n = {24, |
| 36 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 37 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, |
| 38 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31}}; |
| 39 const TPM2B_1_BYTE_VALUE NIST_P192_h = {1,{1}}; |
| 40 const ECC_CURVE_DATA NIST_P192 = {&NIST_P192_p.b, &NIST_P192_a.b, &NIST_P192_b.b, |
| 41 &NIST_P192_gX.b, &NIST_P192_gY.b, &NIST_P192_n.b, |
| 42 &NIST_P192_h.b}; |
| 43 #endif // ECC_NIST_P192 |
| 44 #if defined ECC_NIST_P224 && ECC_NIST_P224 == YES |
| 45 const TPM2B_28_BYTE_VALUE NIST_P224_p = {28, |
| 46 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 47 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 49 0x00, 0x00, 0x00, 0x01}}; |
| 50 const TPM2B_28_BYTE_VALUE NIST_P224_a = {28, |
| 51 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 52 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 53 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 54 0xFF, 0xFF, 0xFF, 0xFE}}; |
| 55 const TPM2B_28_BYTE_VALUE NIST_P224_b = {28, |
| 56 {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, |
| 57 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, |
| 58 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, |
| 59 0x23, 0x55, 0xFF, 0xB4}}; |
| 60 const TPM2B_28_BYTE_VALUE NIST_P224_gX = {28, |
| 61 {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, |
| |
| Page 472 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 62 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, |
| 63 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, |
| 64 0x11, 0x5C, 0x1D, 0x21}}; |
| 65 const TPM2B_28_BYTE_VALUE NIST_P224_gY = {28, |
| 66 {0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, |
| 67 0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, 0x75, 0xA0, |
| 68 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99, |
| 69 0x85, 0x00, 0x7E, 0x34}}; |
| 70 const TPM2B_28_BYTE_VALUE NIST_P224_n = {28, |
| 71 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 72 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0xA2, |
| 73 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, |
| 74 0x5C, 0x5C, 0x2A, 0x3D}}; |
| 75 const TPM2B_1_BYTE_VALUE NIST_P224_h = {1,{1}}; |
| 76 const ECC_CURVE_DATA NIST_P224 = {&NIST_P224_p.b, &NIST_P224_a.b, &NIST_P224_b.b, |
| 77 &NIST_P224_gX.b, &NIST_P224_gY.b, &NIST_P224_n.b, |
| 78 &NIST_P224_h.b}; |
| 79 #endif // ECC_NIST_P224 |
| 80 #if defined ECC_NIST_P256 && ECC_NIST_P256 == YES |
| 81 const TPM2B_32_BYTE_VALUE NIST_P256_p = {32, |
| 82 {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, |
| 83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 84 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, |
| 85 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; |
| 86 const TPM2B_32_BYTE_VALUE NIST_P256_a = {32, |
| 87 {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, |
| 88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 89 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, |
| 90 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}}; |
| 91 const TPM2B_32_BYTE_VALUE NIST_P256_b = {32, |
| 92 {0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, |
| 93 0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, |
| 94 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, |
| 95 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B}}; |
| 96 const TPM2B_32_BYTE_VALUE NIST_P256_gX = {32, |
| 97 {0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, |
| 98 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, |
| 99 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, |
| 100 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96}}; |
| 101 const TPM2B_32_BYTE_VALUE NIST_P256_gY = {32, |
| 102 {0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, |
| 103 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, |
| 104 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, |
| 105 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5}}; |
| 106 const TPM2B_32_BYTE_VALUE NIST_P256_n = {32, |
| 107 {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, |
| 108 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 109 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, |
| 110 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}}; |
| 111 const TPM2B_1_BYTE_VALUE NIST_P256_h = {1,{1}}; |
| 112 const ECC_CURVE_DATA NIST_P256 = {&NIST_P256_p.b, &NIST_P256_a.b, &NIST_P256_b.b, |
| 113 &NIST_P256_gX.b, &NIST_P256_gY.b, &NIST_P256_n.b, |
| 114 &NIST_P256_h.b}; |
| 115 #endif // ECC_NIST_P256 |
| 116 #if defined ECC_NIST_P384 && ECC_NIST_P384 == YES |
| 117 const TPM2B_48_BYTE_VALUE NIST_P384_p = {48, |
| 118 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 119 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 120 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 121 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 122 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, |
| 123 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}}; |
| 124 const TPM2B_48_BYTE_VALUE NIST_P384_a = {48, |
| 125 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 126 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 127 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| |
| Family "2.0" TCG Published Page 473 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 128 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 129 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, |
| 130 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC}}; |
| 131 const TPM2B_48_BYTE_VALUE NIST_P384_b = {48, |
| 132 {0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, |
| 133 0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19, |
| 134 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, |
| 135 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, |
| 136 0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D, |
| 137 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF}}; |
| 138 const TPM2B_48_BYTE_VALUE NIST_P384_gX = {48, |
| 139 {0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, |
| 140 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74, |
| 141 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, |
| 142 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, |
| 143 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C, |
| 144 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7}}; |
| 145 const TPM2B_48_BYTE_VALUE NIST_P384_gY = {48, |
| 146 {0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, |
| 147 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29, |
| 148 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, |
| 149 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, |
| 150 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D, |
| 151 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F}}; |
| 152 const TPM2B_48_BYTE_VALUE NIST_P384_n = {48, |
| 153 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 154 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 155 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 156 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, |
| 157 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, |
| 158 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73}}; |
| 159 const TPM2B_1_BYTE_VALUE NIST_P384_h = {1,{1}}; |
| 160 const ECC_CURVE_DATA NIST_P384 = {&NIST_P384_p.b, &NIST_P384_a.b, &NIST_P384_b.b, |
| 161 &NIST_P384_gX.b, &NIST_P384_gY.b, &NIST_P384_n.b, |
| 162 &NIST_P384_h.b}; |
| 163 #endif // ECC_NIST_P384 |
| 164 #if defined ECC_NIST_P521 && ECC_NIST_P521 == YES |
| 165 const TPM2B_66_BYTE_VALUE NIST_P521_p = {66, |
| 166 {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 167 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 168 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 169 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 170 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 171 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 172 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 173 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 174 0xFF, 0xFF}}; |
| 175 const TPM2B_66_BYTE_VALUE NIST_P521_a = {66, |
| 176 {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 177 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 178 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 179 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 180 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 181 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 182 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 183 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 184 0xFF, 0xFC}}; |
| 185 const TPM2B_66_BYTE_VALUE NIST_P521_b = {66, |
| 186 {0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, |
| 187 0x9A, 0x1F, 0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, |
| 188 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, |
| 189 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, |
| 190 0x09, 0xE1, 0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, |
| 191 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, |
| 192 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, |
| 193 0x34, 0xF1, 0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, |
| |
| Page 474 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 194 0x3F, 0x00}}; |
| 195 const TPM2B_66_BYTE_VALUE NIST_P521_gX = {66, |
| 196 {0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, |
| 197 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, |
| 198 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, |
| 199 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, |
| 200 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, |
| 201 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, |
| 202 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, |
| 203 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, |
| 204 0xBD, 0x66}}; |
| 205 const TPM2B_66_BYTE_VALUE NIST_P521_gY = {66, |
| 206 {0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, |
| 207 0xC0, 0x04, 0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, |
| 208 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, |
| 209 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, |
| 210 0x66, 0x2C, 0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, |
| 211 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, |
| 212 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, |
| 213 0xC2, 0x40, 0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, |
| 214 0x66, 0x50}}; |
| 215 const TPM2B_66_BYTE_VALUE NIST_P521_n = {66, |
| 216 {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 217 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 218 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 219 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 220 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, |
| 221 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, |
| 222 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, |
| 223 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, |
| 224 0x64, 0x09}}; |
| 225 const TPM2B_1_BYTE_VALUE NIST_P521_h = {1,{1}}; |
| 226 const ECC_CURVE_DATA NIST_P521 = {&NIST_P521_p.b, &NIST_P521_a.b, &NIST_P521_b.b, |
| 227 &NIST_P521_gX.b, &NIST_P521_gY.b, &NIST_P521_n.b, |
| 228 &NIST_P521_h.b}; |
| 229 #endif // ECC_NIST_P521 |
| 230 #if defined ECC_BN_P256 && ECC_BN_P256 == YES |
| 231 const TPM2B_32_BYTE_VALUE BN_P256_p = {32, |
| 232 {0xFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFC, 0XF0, 0XCD, |
| 233 0X46, 0XE5, 0XF2, 0X5E, 0XEE, 0X71, 0XA4, 0X9F, |
| 234 0X0C, 0XDC, 0X65, 0XFB, 0X12, 0X98, 0X0A, 0X82, |
| 235 0XD3, 0X29, 0X2D, 0XDB, 0XAE, 0XD3, 0X30, 0X13}}; |
| 236 const TPM2B_1_BYTE_VALUE BN_P256_a = {1,{0}}; |
| 237 const TPM2B_1_BYTE_VALUE BN_P256_b = {1,{3}}; |
| 238 const TPM2B_1_BYTE_VALUE BN_P256_gX = {1,{1}}; |
| 239 const TPM2B_1_BYTE_VALUE BN_P256_gY = {1,{2}};; |
| 240 const TPM2B_32_BYTE_VALUE BN_P256_n = {32, |
| 241 {0xFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFC, 0XF0, 0XCD, |
| 242 0X46, 0XE5, 0XF2, 0X5E, 0XEE, 0X71, 0XA4, 0X9E, |
| 243 0X0C, 0XDC, 0X65, 0XFB, 0X12, 0X99, 0X92, 0X1A, |
| 244 0XF6, 0X2D, 0X53, 0X6C, 0XD1, 0X0B, 0X50, 0X0D}}; |
| 245 const TPM2B_1_BYTE_VALUE BN_P256_h = {1,{1}}; |
| 246 const ECC_CURVE_DATA BN_P256 = {&BN_P256_p.b, &BN_P256_a.b, &BN_P256_b.b, |
| 247 &BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_n.b, |
| 248 &BN_P256_h.b}; |
| 249 #endif // ECC_BN_P256 |
| 250 #if defined ECC_BN_P638 && ECC_BN_P638 == YES |
| 251 const TPM2B_80_BYTE_VALUE BN_P638_p = {80, |
| 252 {0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D, |
| 253 0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3, |
| 254 0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E, |
| 255 0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F, |
| 256 0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55, |
| 257 0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B, |
| 258 0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80, |
| 259 0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD, |
| |
| Family "2.0" TCG Published Page 475 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 260 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0, |
| 261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67}}; |
| 262 const TPM2B_1_BYTE_VALUE BN_P638_a = {1,{0}}; |
| 263 const TPM2B_2_BYTE_VALUE BN_P638_b = {2,{0x01,0x01}}; |
| 264 const TPM2B_80_BYTE_VALUE BN_P638_gX = {80, |
| 265 {0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D, |
| 266 0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3, |
| 267 0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E, |
| 268 0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F, |
| 269 0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55, |
| 270 0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B, |
| 271 0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80, |
| 272 0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD, |
| 273 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0, |
| 274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66}}; |
| 275 const TPM2B_1_BYTE_VALUE BN_P638_gY = {1,{0x10}}; |
| 276 const TPM2B_80_BYTE_VALUE BN_P638_n = {80, |
| 277 {0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D, |
| 278 0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3, |
| 279 0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E, |
| 280 0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F, |
| 281 0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55, |
| 282 0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55, |
| 283 0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0, |
| 284 0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9, |
| 285 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0, |
| 286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61}}; |
| 287 const TPM2B_1_BYTE_VALUE BN_P638_h = {1,{1}}; |
| 288 const ECC_CURVE_DATA BN_P638 = {&BN_P638_p.b, &BN_P638_a.b, &BN_P638_b.b, |
| 289 &BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_n.b, |
| 290 &BN_P638_h.b}; |
| 291 #endif // ECC_BN_P638 |
| 292 #if defined ECC_SM2_P256 && ECC_SM2_P256 == YES |
| 293 const TPM2B_32_BYTE_VALUE SM2_P256_p = {32, |
| 294 {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, |
| 295 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 296 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, |
| 297 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; |
| 298 const TPM2B_32_BYTE_VALUE SM2_P256_a = {32, |
| 299 {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, |
| 300 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 301 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, |
| 302 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}}; |
| 303 const TPM2B_32_BYTE_VALUE SM2_P256_b = {32, |
| 304 {0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34, |
| 305 0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7, |
| 306 0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92, |
| 307 0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93}}; |
| 308 const TPM2B_32_BYTE_VALUE SM2_P256_gX = {32, |
| 309 {0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19, |
| 310 0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94, |
| 311 0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1, |
| 312 0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7}}; |
| 313 const TPM2B_32_BYTE_VALUE SM2_P256_gY = {32, |
| 314 {0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C, |
| 315 0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53, |
| 316 0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40, |
| 317 0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0}}; |
| 318 const TPM2B_32_BYTE_VALUE SM2_P256_n = {32, |
| 319 {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, |
| 320 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 321 0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B, |
| 322 0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23}}; |
| 323 const TPM2B_1_BYTE_VALUE SM2_P256_h = {1,{1}}; |
| 324 const ECC_CURVE_DATA SM2_P256 = {&SM2_P256_p.b, &SM2_P256_a.b, &SM2_P256_b.b, |
| 325 &SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_n.b, |
| |
| Page 476 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 326 &SM2_P256_h.b}; |
| 327 #endif // ECC_SM2_P256 |
| 328 #define comma |
| 329 const ECC_CURVE eccCurves[] = { |
| 330 #if defined ECC_NIST_P192 && ECC_NIST_P192 == YES |
| 331 comma |
| 332 {TPM_ECC_NIST_P192, |
| 333 192, |
| 334 {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA256}, |
| 335 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 336 &NIST_P192} |
| 337 # undef comma |
| 338 # define comma , |
| 339 #endif // ECC_NIST_P192 |
| 340 #if defined ECC_NIST_P224 && ECC_NIST_P224 == YES |
| 341 comma |
| 342 {TPM_ECC_NIST_P224, |
| 343 224, |
| 344 {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA256}, |
| 345 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 346 &NIST_P224} |
| 347 # undef comma |
| 348 # define comma , |
| 349 #endif // ECC_NIST_P224 |
| 350 #if defined ECC_NIST_P256 && ECC_NIST_P256 == YES |
| 351 comma |
| 352 {TPM_ECC_NIST_P256, |
| 353 256, |
| 354 {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA256}, |
| 355 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 356 &NIST_P256} |
| 357 # undef comma |
| 358 # define comma , |
| 359 #endif // ECC_NIST_P256 |
| 360 #if defined ECC_NIST_P384 && ECC_NIST_P384 == YES |
| 361 comma |
| 362 {TPM_ECC_NIST_P384, |
| 363 384, |
| 364 {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA384}, |
| 365 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 366 &NIST_P384} |
| 367 # undef comma |
| 368 # define comma , |
| 369 #endif // ECC_NIST_P384 |
| 370 #if defined ECC_NIST_P521 && ECC_NIST_P521 == YES |
| 371 comma |
| 372 {TPM_ECC_NIST_P521, |
| 373 521, |
| 374 {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SHA512}, |
| 375 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 376 &NIST_P521} |
| 377 # undef comma |
| 378 # define comma , |
| 379 #endif // ECC_NIST_P521 |
| 380 #if defined ECC_BN_P256 && ECC_BN_P256 == YES |
| 381 comma |
| 382 {TPM_ECC_BN_P256, |
| 383 256, |
| 384 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 385 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 386 &BN_P256} |
| 387 # undef comma |
| 388 # define comma , |
| 389 #endif // ECC_BN_P256 |
| 390 #if defined ECC_BN_P638 && ECC_BN_P638 == YES |
| 391 comma |
| |
| Family "2.0" TCG Published Page 477 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 392 {TPM_ECC_BN_P638, |
| 393 638, |
| 394 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 395 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 396 &BN_P638} |
| 397 # undef comma |
| 398 # define comma , |
| 399 #endif // ECC_BN_P638 |
| 400 #if defined ECC_SM2_P256 && ECC_SM2_P256 == YES |
| 401 comma |
| 402 {TPM_ECC_SM2_P256, |
| 403 256, |
| 404 {TPM_ALG_KDF1_SP800_56A,TPM_ALG_SM3_256}, |
| 405 {TPM_ALG_NULL,TPM_ALG_NULL}, |
| 406 &SM2_P256} |
| 407 # undef comma |
| 408 # define comma , |
| 409 #endif // ECC_SM2_P256 |
| 410 }; |
| 411 const UINT16 ECC_CURVE_COUNT = sizeof(eccCurves) / sizeof(ECC_CURVE); |
| |
| |
| |
| |
| Page 478 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| B.13.3. CpriECC.c |
| |
| B.13.3.1. Includes and Defines |
| |
| Need to include OsslCryptEngine.h to determine if ECC is defined for this Implementation |
| |
| 1 #include "OsslCryptoEngine.h" |
| 2 #ifdef TPM_ALG_ECC |
| 3 #include "CpriDataEcc.h" |
| 4 #include "CpriDataEcc.c" |
| |
| |
| B.13.3.2. Functions |
| |
| B.13.3.2.1. _cpri__EccStartup() |
| |
| This function is called at TPM Startup to initialize the crypto units. |
| In this implementation, no initialization is performed at startup but a future version may initialize the self- |
| test functions here. |
| |
| 5 LIB_EXPORT BOOL |
| 6 _cpri__EccStartup( |
| 7 void |
| 8 ) |
| 9 { |
| 10 return TRUE; |
| 11 } |
| |
| |
| B.13.3.2.2. _cpri__GetCurveIdByIndex() |
| |
| This function returns the number of the i-th implemented curve. The normal use would be to call this |
| function with i starting at 0. When the i is greater than or equal to the number of implemented curves, |
| TPM_ECC_NONE is returned. |
| |
| 12 LIB_EXPORT TPM_ECC_CURVE |
| 13 _cpri__GetCurveIdByIndex( |
| 14 UINT16 i |
| 15 ) |
| 16 { |
| 17 if(i >= ECC_CURVE_COUNT) |
| 18 return TPM_ECC_NONE; |
| 19 return eccCurves[i].curveId; |
| 20 } |
| 21 LIB_EXPORT UINT32 |
| 22 _cpri__EccGetCurveCount( |
| 23 void |
| 24 ) |
| 25 { |
| 26 return ECC_CURVE_COUNT; |
| 27 } |
| |
| |
| B.13.3.2.3. _cpri__EccGetParametersByCurveId() |
| |
| This function returns a pointer to the curve data that is associated with the indicated curveId. If there is no |
| curve with the indicated ID, the function returns NULL. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 479 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| NULL curve with the indicated TPM_ECC_CURVE value is not |
| implemented |
| non-NULL pointer to the curve data |
| |
| 28 LIB_EXPORT const ECC_CURVE * |
| 29 _cpri__EccGetParametersByCurveId( |
| 30 TPM_ECC_CURVE curveId // IN: the curveID |
| 31 ) |
| 32 { |
| 33 int i; |
| 34 for(i = 0; i < ECC_CURVE_COUNT; i++) |
| 35 { |
| 36 if(eccCurves[i].curveId == curveId) |
| 37 return &eccCurves[i]; |
| 38 } |
| 39 FAIL(FATAL_ERROR_INTERNAL); |
| 40 } |
| 41 static const ECC_CURVE_DATA * |
| 42 GetCurveData( |
| 43 TPM_ECC_CURVE curveId // IN: the curveID |
| 44 ) |
| 45 { |
| 46 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
| 47 return curve->curveData; |
| 48 } |
| |
| |
| B.13.3.2.4. Point2B() |
| |
| This function makes a TPMS_ECC_POINT from a BIGNUM EC_POINT. |
| |
| 49 static BOOL |
| 50 Point2B( |
| 51 EC_GROUP *group, // IN: group for the point |
| 52 TPMS_ECC_POINT *p, // OUT: receives the converted point |
| 53 EC_POINT *ecP, // IN: the point to convert |
| 54 INT16 size, // IN: size of the coordinates |
| 55 BN_CTX *context // IN: working context |
| 56 ) |
| 57 { |
| 58 BIGNUM *bnX; |
| 59 BIGNUM *bnY; |
| 60 |
| 61 BN_CTX_start(context); |
| 62 bnX = BN_CTX_get(context); |
| 63 bnY = BN_CTX_get(context); |
| 64 |
| 65 if( bnY == NULL |
| 66 |
| 67 // Get the coordinate values |
| 68 || EC_POINT_get_affine_coordinates_GFp(group, ecP, bnX, bnY, context) != 1 |
| 69 |
| 70 // Convert x |
| 71 || (!BnTo2B(&p->x.b, bnX, size)) |
| 72 |
| 73 // Convert y |
| 74 || (!BnTo2B(&p->y.b, bnY, size)) |
| 75 ) |
| 76 FAIL(FATAL_ERROR_INTERNAL); |
| 77 |
| 78 BN_CTX_end(context); |
| 79 return TRUE; |
| |
| Page 480 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 80 } |
| |
| |
| B.13.3.2.5. EccCurveInit() |
| |
| This function initializes the OpenSSL() group definition structure |
| This function is only used within this file. |
| It is a fatal error if groupContext is not provided. |
| |
| Return Value Meaning |
| |
| NULL the TPM_ECC_CURVE is not valid |
| non-NULL points to a structure in groupContext static EC_GROUP * |
| |
| 81 static EC_GROUP * |
| 82 EccCurveInit( |
| 83 TPM_ECC_CURVE curveId, // IN: the ID of the curve |
| 84 BN_CTX *groupContext // IN: the context in which the group is to be |
| 85 // created |
| 86 ) |
| 87 { |
| 88 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 89 EC_GROUP *group = NULL; |
| 90 EC_POINT *P = NULL; |
| 91 BN_CTX *context; |
| 92 BIGNUM *bnP; |
| 93 BIGNUM *bnA; |
| 94 BIGNUM *bnB; |
| 95 BIGNUM *bnX; |
| 96 BIGNUM *bnY; |
| 97 BIGNUM *bnN; |
| 98 BIGNUM *bnH; |
| 99 int ok = FALSE; |
| 100 |
| 101 // Context must be provided and curve selector must be valid |
| 102 pAssert(groupContext != NULL && curveData != NULL); |
| 103 |
| 104 context = BN_CTX_new(); |
| 105 if(context == NULL) |
| 106 FAIL(FATAL_ERROR_ALLOCATION); |
| 107 |
| 108 BN_CTX_start(context); |
| 109 bnP = BN_CTX_get(context); |
| 110 bnA = BN_CTX_get(context); |
| 111 bnB = BN_CTX_get(context); |
| 112 bnX = BN_CTX_get(context); |
| 113 bnY = BN_CTX_get(context); |
| 114 bnN = BN_CTX_get(context); |
| 115 bnH = BN_CTX_get(context); |
| 116 |
| 117 if (bnH == NULL) |
| 118 goto Cleanup; |
| 119 |
| 120 // Convert the number formats |
| 121 |
| 122 BnFrom2B(bnP, curveData->p); |
| 123 BnFrom2B(bnA, curveData->a); |
| 124 BnFrom2B(bnB, curveData->b); |
| 125 BnFrom2B(bnX, curveData->x); |
| 126 BnFrom2B(bnY, curveData->y); |
| 127 BnFrom2B(bnN, curveData->n); |
| 128 BnFrom2B(bnH, curveData->h); |
| 129 |
| |
| Family "2.0" TCG Published Page 481 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 130 // initialize EC group, associate a generator point and initialize the point |
| 131 // from the parameter data |
| 132 ok = ( (group = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, groupContext)) != NULL |
| 133 && (P = EC_POINT_new(group)) != NULL |
| 134 && EC_POINT_set_affine_coordinates_GFp(group, P, bnX, bnY, groupContext) |
| 135 && EC_GROUP_set_generator(group, P, bnN, bnH) |
| 136 ); |
| 137 Cleanup: |
| 138 if (!ok && group != NULL) |
| 139 { |
| 140 EC_GROUP_free(group); |
| 141 group = NULL; |
| 142 } |
| 143 if(P != NULL) |
| 144 EC_POINT_free(P); |
| 145 BN_CTX_end(context); |
| 146 BN_CTX_free(context); |
| 147 return group; |
| 148 } |
| |
| |
| B.13.3.2.6. PointFrom2B() |
| |
| This function sets the coordinates of an existing BN Point from a TPMS_ECC_POINT. |
| |
| 149 static EC_POINT * |
| 150 PointFrom2B( |
| 151 EC_GROUP *group, // IN: the group for the point |
| 152 EC_POINT *ecP, // IN: an existing BN point in the group |
| 153 TPMS_ECC_POINT *p, // IN: the 2B coordinates of the point |
| 154 BN_CTX *context // IN: the BIGNUM context |
| 155 ) |
| 156 { |
| 157 BIGNUM *bnX; |
| 158 BIGNUM *bnY; |
| 159 |
| 160 // If the point is not allocated then just return a NULL |
| 161 if(ecP == NULL) |
| 162 return NULL; |
| 163 |
| 164 BN_CTX_start(context); |
| 165 bnX = BN_CTX_get(context); |
| 166 bnY = BN_CTX_get(context); |
| 167 if( // Set the coordinates of the point |
| 168 bnY == NULL |
| 169 || BN_bin2bn(p->x.t.buffer, p->x.t.size, bnX) == NULL |
| 170 || BN_bin2bn(p->y.t.buffer, p->y.t.size, bnY) == NULL |
| 171 || !EC_POINT_set_affine_coordinates_GFp(group, ecP, bnX, bnY, context) |
| 172 ) |
| 173 FAIL(FATAL_ERROR_INTERNAL); |
| 174 |
| 175 BN_CTX_end(context); |
| 176 return ecP; |
| 177 } |
| |
| |
| B.13.3.2.7. EccInitPoint2B() |
| |
| This function allocates a point in the provided group and initializes it with the values in a |
| TPMS_ECC_POINT. |
| |
| 178 static EC_POINT * |
| 179 EccInitPoint2B( |
| 180 EC_GROUP *group, // IN: group for the point |
| 181 TPMS_ECC_POINT *p, // IN: the coordinates for the point |
| |
| Page 482 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 182 BN_CTX *context // IN: the BIGNUM context |
| 183 ) |
| 184 { |
| 185 EC_POINT *ecP; |
| 186 |
| 187 BN_CTX_start(context); |
| 188 ecP = EC_POINT_new(group); |
| 189 |
| 190 if(PointFrom2B(group, ecP, p, context) == NULL) |
| 191 FAIL(FATAL_ERROR_INTERNAL); |
| 192 |
| 193 BN_CTX_end(context); |
| 194 return ecP; |
| 195 } |
| |
| |
| B.13.3.2.8. PointMul() |
| |
| This function does a point multiply and checks for the result being the point at infinity. Q = ([A]G + [B]P) |
| |
| Return Value Meaning |
| |
| CRYPT_NO_RESULT point is at infinity |
| CRYPT_SUCCESS point not at infinity |
| |
| 196 static CRYPT_RESULT |
| 197 PointMul( |
| 198 EC_GROUP *group, // IN: group curve |
| 199 EC_POINT *ecpQ, // OUT: result |
| 200 BIGNUM *bnA, // IN: scalar for [A]G |
| 201 EC_POINT *ecpP, // IN: point for [B]P |
| 202 BIGNUM *bnB, // IN: scalar for [B]P |
| 203 BN_CTX *context // IN: working context |
| 204 ) |
| 205 { |
| 206 if(EC_POINT_mul(group, ecpQ, bnA, ecpP, bnB, context) != 1) |
| 207 FAIL(FATAL_ERROR_INTERNAL); |
| 208 if(EC_POINT_is_at_infinity(group, ecpQ)) |
| 209 return CRYPT_NO_RESULT; |
| 210 return CRYPT_SUCCESS; |
| 211 } |
| |
| |
| B.13.3.2.9. GetRandomPrivate() |
| |
| This function gets a random value (d) to use as a private ECC key and then qualifies the key so that it is |
| between 0 < d < n. |
| It is a fatal error if dOut or pIn is not provided or if the size of pIn is larger than MAX_ECC_KEY_BYTES |
| (the largest buffer size of a TPM2B_ECC_PARAMETER) |
| |
| 212 static void |
| 213 GetRandomPrivate( |
| 214 TPM2B_ECC_PARAMETER *dOut, // OUT: the qualified random value |
| 215 const TPM2B *pIn // IN: the maximum value for the key |
| 216 ) |
| 217 { |
| 218 int i; |
| 219 BYTE *pb; |
| 220 |
| 221 pAssert(pIn != NULL && dOut != NULL && pIn->size <= MAX_ECC_KEY_BYTES); |
| 222 |
| 223 // Set the size of the output |
| 224 dOut->t.size = pIn->size; |
| |
| Family "2.0" TCG Published Page 483 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 225 // Get some random bits |
| 226 while(TRUE) |
| 227 { |
| 228 _cpri__GenerateRandom(dOut->t.size, dOut->t.buffer); |
| 229 // See if the d < n |
| 230 if(memcmp(dOut->t.buffer, pIn->buffer, pIn->size) < 0) |
| 231 { |
| 232 // dOut < n so make sure that 0 < dOut |
| 233 for(pb = dOut->t.buffer, i = dOut->t.size; i > 0; i--) |
| 234 { |
| 235 if(*pb++ != 0) |
| 236 return; |
| 237 } |
| 238 } |
| 239 } |
| 240 } |
| |
| |
| B.13.3.2.10. Mod2B() |
| |
| Function does modular reduction of TPM2B values. |
| |
| 241 static CRYPT_RESULT |
| 242 Mod2B( |
| 243 TPM2B *x, // IN/OUT: value to reduce |
| 244 const TPM2B *n // IN: mod |
| 245 ) |
| 246 { |
| 247 int compare; |
| 248 compare = _math__uComp(x->size, x->buffer, n->size, n->buffer); |
| 249 if(compare < 0) |
| 250 // if x < n, then mod is x |
| 251 return CRYPT_SUCCESS; |
| 252 if(compare == 0) |
| 253 { |
| 254 // if x == n then mod is 0 |
| 255 x->size = 0; |
| 256 x->buffer[0] = 0; |
| 257 return CRYPT_SUCCESS; |
| 258 } |
| 259 return _math__Div(x, n, NULL, x); |
| 260 } |
| |
| |
| B.13.3.2.11. _cpri__EccPointMultiply |
| |
| This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are points on |
| the specified curve and G is the default generator of the curve. |
| The xOut and yOut parameters are optional and may be set to NULL if not used. |
| It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be provided. If dIn and |
| QIn are specified but uIn is not provided, then R = [dIn]QIn. |
| If the multiply produces the point at infinity, the CRYPT_NO_RESULT is returned. |
| The sizes of xOut and yOut' will be set to be the size of the degree of the curve |
| It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is unspecified. |
| |
| |
| |
| |
| Page 484 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS point multiplication succeeded |
| CRYPT_POINT the point Qin is not on the curve |
| CRYPT_NO_RESULT the product point is at infinity |
| |
| 261 LIB_EXPORT CRYPT_RESULT |
| 262 _cpri__EccPointMultiply( |
| 263 TPMS_ECC_POINT *Rout, // OUT: the product point R |
| 264 TPM_ECC_CURVE curveId, // IN: the curve to use |
| 265 TPM2B_ECC_PARAMETER *dIn, // IN: value to multiply against the |
| 266 // curve generator |
| 267 TPMS_ECC_POINT *Qin, // IN: point Q |
| 268 TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier |
| 269 // of Q |
| 270 ) |
| 271 { |
| 272 BN_CTX *context; |
| 273 BIGNUM *bnD; |
| 274 BIGNUM *bnU; |
| 275 EC_GROUP *group; |
| 276 EC_POINT *R = NULL; |
| 277 EC_POINT *Q = NULL; |
| 278 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 279 |
| 280 // Validate that the required parameters are provided. |
| 281 pAssert((dIn != NULL || uIn != NULL) && (Qin != NULL || dIn != NULL)); |
| 282 |
| 283 // If a point is provided for the multiply, make sure that it is on the curve |
| 284 if(Qin != NULL && !_cpri__EccIsPointOnCurve(curveId, Qin)) |
| 285 return CRYPT_POINT; |
| 286 |
| 287 context = BN_CTX_new(); |
| 288 if(context == NULL) |
| 289 FAIL(FATAL_ERROR_ALLOCATION); |
| 290 |
| 291 BN_CTX_start(context); |
| 292 bnU = BN_CTX_get(context); |
| 293 bnD = BN_CTX_get(context); |
| 294 group = EccCurveInit(curveId, context); |
| 295 |
| 296 // There should be no path for getting a bad curve ID into this function. |
| 297 pAssert(group != NULL); |
| 298 |
| 299 // check allocations should have worked and allocate R |
| 300 if( bnD == NULL |
| 301 || (R = EC_POINT_new(group)) == NULL) |
| 302 FAIL(FATAL_ERROR_ALLOCATION); |
| 303 |
| 304 // If Qin is present, create the point |
| 305 if(Qin != NULL) |
| 306 { |
| 307 // Assume the size variables do not overflow. This should not happen in |
| 308 // the contexts in which this function will be called. |
| 309 assert2Bsize(Qin->x.t); |
| 310 assert2Bsize(Qin->x.t); |
| 311 Q = EccInitPoint2B(group, Qin, context); |
| 312 |
| 313 } |
| 314 if(dIn != NULL) |
| 315 { |
| 316 // Assume the size variables do not overflow, which should not happen in |
| 317 // the contexts that this function will be called. |
| 318 assert2Bsize(dIn->t); |
| |
| Family "2.0" TCG Published Page 485 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 319 BnFrom2B(bnD, &dIn->b); |
| 320 } |
| 321 else |
| 322 bnD = NULL; |
| 323 |
| 324 // If uIn is specified, initialize its BIGNUM |
| 325 if(uIn != NULL) |
| 326 { |
| 327 // Assume the size variables do not overflow, which should not happen in |
| 328 // the contexts that this function will be called. |
| 329 assert2Bsize(uIn->t); |
| 330 BnFrom2B(bnU, &uIn->b); |
| 331 } |
| 332 // If uIn is not specified but Q is, then we are going to |
| 333 // do R = [d]Q |
| 334 else if(Qin != NULL) |
| 335 { |
| 336 bnU = bnD; |
| 337 bnD = NULL; |
| 338 } |
| 339 // If neither Q nor u is specified, then null this pointer |
| 340 else |
| 341 bnU = NULL; |
| 342 |
| 343 // Use the generator of the curve |
| 344 if((retVal = PointMul(group, R, bnD, Q, bnU, context)) == CRYPT_SUCCESS) |
| 345 Point2B(group, Rout, R, (INT16) BN_num_bytes(&group->field), context); |
| 346 |
| 347 if (Q) |
| 348 EC_POINT_free(Q); |
| 349 if(R) |
| 350 EC_POINT_free(R); |
| 351 if(group) |
| 352 EC_GROUP_free(group); |
| 353 BN_CTX_end(context); |
| 354 BN_CTX_free(context); |
| 355 return retVal; |
| 356 } |
| |
| |
| B.13.3.2.12. ClearPoint2B() |
| |
| Initialize the size values of a point |
| |
| 357 static void |
| 358 ClearPoint2B( |
| 359 TPMS_ECC_POINT *p // IN: the point |
| 360 ) |
| 361 { |
| 362 if(p != NULL) { |
| 363 p->x.t.size = 0; |
| 364 p->y.t.size = 0; |
| 365 } |
| 366 } |
| 367 #if defined TPM_ALG_ECDAA || defined TPM_ALG_SM2 //% |
| |
| |
| B.13.3.2.13. _cpri__EccCommitCompute() |
| |
| This function performs the point multiply operations required by TPM2_Commit(). |
| If B or M is provided, they must be on the curve defined by curveId. This routine does not check that they |
| are on the curve and results are unpredictable if they are not. |
| |
| |
| |
| Page 486 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| It is a fatal error if r or d is NULL. If B is not NULL, then it is a fatal error if K and L are both NULL. If M is |
| not NULL, then it is a fatal error if E is NULL. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS computations completed normally |
| CRYPT_NO_RESULT if K, L or E was computed to be the point at infinity |
| CRYPT_CANCEL a cancel indication was asserted during this function |
| |
| 368 LIB_EXPORT CRYPT_RESULT |
| 369 _cpri__EccCommitCompute( |
| 370 TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q |
| 371 TPMS_ECC_POINT *L, // OUT: [r]B |
| 372 TPMS_ECC_POINT *E, // OUT: [r]M |
| 373 TPM_ECC_CURVE curveId, // IN: the curve for the computations |
| 374 TPMS_ECC_POINT *M, // IN: M (optional) |
| 375 TPMS_ECC_POINT *B, // IN: B (optional) |
| 376 TPM2B_ECC_PARAMETER *d, // IN: d (required) |
| 377 TPM2B_ECC_PARAMETER *r // IN: the computed r value (required) |
| 378 ) |
| 379 { |
| 380 BN_CTX *context; |
| 381 BIGNUM *bnX, *bnY, *bnR, *bnD; |
| 382 EC_GROUP *group; |
| 383 EC_POINT *pK = NULL, *pL = NULL, *pE = NULL, *pM = NULL, *pB = NULL; |
| 384 UINT16 keySizeInBytes; |
| 385 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 386 |
| 387 // Validate that the required parameters are provided. |
| 388 // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do |
| 389 // E := [r]Q if both M and B are NULL. |
| 390 pAssert( r != NULL && (K != NULL || B == NULL) && (L != NULL || B == NULL) |
| 391 || (E != NULL || (M == NULL && B != NULL))); |
| 392 |
| 393 context = BN_CTX_new(); |
| 394 if(context == NULL) |
| 395 FAIL(FATAL_ERROR_ALLOCATION); |
| 396 BN_CTX_start(context); |
| 397 bnR = BN_CTX_get(context); |
| 398 bnD = BN_CTX_get(context); |
| 399 bnX = BN_CTX_get(context); |
| 400 bnY = BN_CTX_get(context); |
| 401 if(bnY == NULL) |
| 402 FAIL(FATAL_ERROR_ALLOCATION); |
| 403 |
| 404 // Initialize the output points in case they are not computed |
| 405 ClearPoint2B(K); |
| 406 ClearPoint2B(L); |
| 407 ClearPoint2B(E); |
| 408 |
| 409 if((group = EccCurveInit(curveId, context)) == NULL) |
| 410 { |
| 411 retVal = CRYPT_PARAMETER; |
| 412 goto Cleanup2; |
| 413 } |
| 414 keySizeInBytes = (UINT16) BN_num_bytes(&group->field); |
| 415 |
| 416 // Sizes of the r and d parameters may not be zero |
| 417 pAssert(((int) r->t.size > 0) && ((int) d->t.size > 0)); |
| 418 |
| 419 // Convert scalars to BIGNUM |
| 420 BnFrom2B(bnR, &r->b); |
| 421 BnFrom2B(bnD, &d->b); |
| 422 |
| |
| Family "2.0" TCG Published Page 487 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 423 // If B is provided, compute K=[d]B and L=[r]B |
| 424 if(B != NULL) |
| 425 { |
| 426 // Allocate the points to receive the value |
| 427 if( (pK = EC_POINT_new(group)) == NULL |
| 428 || (pL = EC_POINT_new(group)) == NULL) |
| 429 FAIL(FATAL_ERROR_ALLOCATION); |
| 430 // need to compute K = [d]B |
| 431 // Allocate and initialize BIGNUM version of B |
| 432 pB = EccInitPoint2B(group, B, context); |
| 433 |
| 434 // do the math for K = [d]B |
| 435 if((retVal = PointMul(group, pK, NULL, pB, bnD, context)) != CRYPT_SUCCESS) |
| 436 goto Cleanup; |
| 437 |
| 438 // Convert BN K to TPM2B K |
| 439 Point2B(group, K, pK, (INT16)keySizeInBytes, context); |
| 440 |
| 441 // compute L= [r]B after checking for cancel |
| 442 if(_plat__IsCanceled()) |
| 443 { |
| 444 retVal = CRYPT_CANCEL; |
| 445 goto Cleanup; |
| 446 } |
| 447 // compute L = [r]B |
| 448 if((retVal = PointMul(group, pL, NULL, pB, bnR, context)) != CRYPT_SUCCESS) |
| 449 goto Cleanup; |
| 450 |
| 451 // Convert BN L to TPM2B L |
| 452 Point2B(group, L, pL, (INT16)keySizeInBytes, context); |
| 453 } |
| 454 if(M != NULL || B == NULL) |
| 455 { |
| 456 // if this is the third point multiply, check for cancel first |
| 457 if(B != NULL && _plat__IsCanceled()) |
| 458 { |
| 459 retVal = CRYPT_CANCEL; |
| 460 goto Cleanup; |
| 461 } |
| 462 |
| 463 // Allocate E |
| 464 if((pE = EC_POINT_new(group)) == NULL) |
| 465 FAIL(FATAL_ERROR_ALLOCATION); |
| 466 |
| 467 // Create BIGNUM version of M unless M is NULL |
| 468 if(M != NULL) |
| 469 { |
| 470 // M provided so initialize a BIGNUM M and compute E = [r]M |
| 471 pM = EccInitPoint2B(group, M, context); |
| 472 retVal = PointMul(group, pE, NULL, pM, bnR, context); |
| 473 } |
| 474 else |
| 475 // compute E = [r]G (this is only done if M and B are both NULL |
| 476 retVal = PointMul(group, pE, bnR, NULL, NULL, context); |
| 477 |
| 478 if(retVal == CRYPT_SUCCESS) |
| 479 // Convert E to 2B format |
| 480 Point2B(group, E, pE, (INT16)keySizeInBytes, context); |
| 481 } |
| 482 Cleanup: |
| 483 EC_GROUP_free(group); |
| 484 if(pK != NULL) EC_POINT_free(pK); |
| 485 if(pL != NULL) EC_POINT_free(pL); |
| 486 if(pE != NULL) EC_POINT_free(pE); |
| 487 if(pM != NULL) EC_POINT_free(pM); |
| 488 if(pB != NULL) EC_POINT_free(pB); |
| |
| Page 488 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 489 Cleanup2: |
| 490 BN_CTX_end(context); |
| 491 BN_CTX_free(context); |
| 492 return retVal; |
| 493 } |
| 494 #endif //% |
| |
| |
| B.13.3.2.14. _cpri__EccIsPointOnCurve() |
| |
| This function is used to test if a point is on a defined curve. It does this by checking that y^2 mod p = x^3 |
| + a*x + b mod p |
| It is a fatal error if Q is not specified (is NULL). |
| |
| Return Value Meaning |
| |
| TRUE point is on curve |
| FALSE point is not on curve or curve is not supported |
| |
| 495 LIB_EXPORT BOOL |
| 496 _cpri__EccIsPointOnCurve( |
| 497 TPM_ECC_CURVE curveId, // IN: the curve selector |
| 498 TPMS_ECC_POINT *Q // IN: the point. |
| 499 ) |
| 500 { |
| 501 BN_CTX *context; |
| 502 BIGNUM *bnX; |
| 503 BIGNUM *bnY; |
| 504 BIGNUM *bnA; |
| 505 BIGNUM *bnB; |
| 506 BIGNUM *bnP; |
| 507 BIGNUM *bn3; |
| 508 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 509 BOOL retVal; |
| 510 |
| 511 pAssert(Q != NULL && curveData != NULL); |
| 512 |
| 513 if((context = BN_CTX_new()) == NULL) |
| 514 FAIL(FATAL_ERROR_ALLOCATION); |
| 515 BN_CTX_start(context); |
| 516 bnX = BN_CTX_get(context); |
| 517 bnY = BN_CTX_get(context); |
| 518 bnA = BN_CTX_get(context); |
| 519 bnB = BN_CTX_get(context); |
| 520 bn3 = BN_CTX_get(context); |
| 521 bnP = BN_CTX_get(context); |
| 522 if(bnP == NULL) |
| 523 FAIL(FATAL_ERROR_ALLOCATION); |
| 524 |
| 525 // Convert values |
| 526 if ( !BN_bin2bn(Q->x.t.buffer, Q->x.t.size, bnX) |
| 527 || !BN_bin2bn(Q->y.t.buffer, Q->y.t.size, bnY) |
| 528 || !BN_bin2bn(curveData->p->buffer, curveData->p->size, bnP) |
| 529 || !BN_bin2bn(curveData->a->buffer, curveData->a->size, bnA) |
| 530 || !BN_set_word(bn3, 3) |
| 531 || !BN_bin2bn(curveData->b->buffer, curveData->b->size, bnB) |
| 532 ) |
| 533 FAIL(FATAL_ERROR_INTERNAL); |
| 534 |
| 535 // The following sequence is probably not optimal but it seems to be correct. |
| 536 // compute x^3 + a*x + b mod p |
| 537 // first, compute a*x mod p |
| 538 if( !BN_mod_mul(bnA, bnA, bnX, bnP, context) |
| |
| |
| Family "2.0" TCG Published Page 489 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 539 // next, compute a*x + b mod p |
| 540 || !BN_mod_add(bnA, bnA, bnB, bnP, context) |
| 541 // next, compute X^3 mod p |
| 542 || !BN_mod_exp(bnX, bnX, bn3, bnP, context) |
| 543 // finally, compute x^3 + a*x + b mod p |
| 544 || !BN_mod_add(bnX, bnX, bnA, bnP, context) |
| 545 // then compute y^2 |
| 546 || !BN_mod_mul(bnY, bnY, bnY, bnP, context) |
| 547 ) |
| 548 FAIL(FATAL_ERROR_INTERNAL); |
| 549 |
| 550 retVal = BN_cmp(bnX, bnY) == 0; |
| 551 BN_CTX_end(context); |
| 552 BN_CTX_free(context); |
| 553 return retVal; |
| 554 } |
| |
| |
| B.13.3.2.15. _cpri__GenerateKeyEcc() |
| |
| This function generates an ECC key pair based on the input parameters. This routine uses KDFa() to |
| produce candidate numbers. The method is according to FIPS 186-3, section B.4.1 "GKey() Pair |
| Generation Using Extra Random Bits." According to the method in FIPS 186-3, the resulting private value |
| d should be 1 <= d < n where n is the order of the base point. In this implementation, the range of the |
| private value is further restricted to be 2^(nLen/2) <= d < n where nLen is the order of n. |
| |
| EXAMPLE: If the curve is NIST-P256, then nLen is 256 bits and d will need to be between 2^128 <= d < n |
| |
| It is a fatal error if Qout, dOut, or seed is not provided (is NULL). |
| |
| Return Value Meaning |
| |
| CRYPT_PARAMETER the hash algorithm is not supported |
| |
| 555 LIB_EXPORT CRYPT_RESULT |
| 556 _cpri__GenerateKeyEcc( |
| 557 TPMS_ECC_POINT *Qout, // OUT: the public point |
| 558 TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar |
| 559 TPM_ECC_CURVE curveId, // IN: the curve identifier |
| 560 TPM_ALG_ID hashAlg, // IN: hash algorithm to use in the key |
| 561 // generation process |
| 562 TPM2B *seed, // IN: the seed to use |
| 563 const char *label, // IN: A label for the generation |
| 564 // process. |
| 565 TPM2B *extra, // IN: Party 1 data for the KDF |
| 566 UINT32 *counter // IN/OUT: Counter value to allow KDF |
| 567 // iteration to be propagated across |
| 568 // multiple functions |
| 569 ) |
| 570 { |
| 571 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 572 INT16 keySizeInBytes; |
| 573 UINT32 count = 0; |
| 574 CRYPT_RESULT retVal; |
| 575 UINT16 hLen = _cpri__GetDigestSize(hashAlg); |
| 576 BIGNUM *bnNm1; // Order of the curve minus one |
| 577 BIGNUM *bnD; // the private scalar |
| 578 BN_CTX *context; // the context for the BIGNUM values |
| 579 BYTE withExtra[MAX_ECC_KEY_BYTES + 8]; // trial key with |
| 580 //extra bits |
| 581 TPM2B_4_BYTE_VALUE marshaledCounter = {4, {0}}; |
| 582 UINT32 totalBits; |
| 583 |
| 584 // Validate parameters (these are fatal) |
| |
| Page 490 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 585 pAssert( seed != NULL && dOut != NULL && Qout != NULL && curveData != NULL); |
| 586 |
| 587 // Non-fatal parameter checks. |
| 588 if(hLen <= 0) |
| 589 return CRYPT_PARAMETER; |
| 590 |
| 591 // allocate the local BN values |
| 592 context = BN_CTX_new(); |
| 593 if(context == NULL) |
| 594 FAIL(FATAL_ERROR_ALLOCATION); |
| 595 BN_CTX_start(context); |
| 596 bnNm1 = BN_CTX_get(context); |
| 597 bnD = BN_CTX_get(context); |
| 598 |
| 599 // The size of the input scalars is limited by the size of the size of a |
| 600 // TPM2B_ECC_PARAMETER. Make sure that it is not irrational. |
| 601 pAssert((int) curveData->n->size <= MAX_ECC_KEY_BYTES); |
| 602 |
| 603 if( bnD == NULL |
| 604 || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnNm1) == NULL |
| 605 || (keySizeInBytes = (INT16) BN_num_bytes(bnNm1)) > MAX_ECC_KEY_BYTES) |
| 606 FAIL(FATAL_ERROR_INTERNAL); |
| 607 |
| 608 // get the total number of bits |
| 609 totalBits = BN_num_bits(bnNm1) + 64; |
| 610 |
| 611 // Reduce bnNm1 from 'n' to 'n' - 1 |
| 612 BN_sub_word(bnNm1, 1); |
| 613 |
| 614 // Initialize the count value |
| 615 if(counter != NULL) |
| 616 count = *counter; |
| 617 if(count == 0) |
| 618 count = 1; |
| 619 |
| 620 // Start search for key (should be quick) |
| 621 for(; count != 0; count++) |
| 622 { |
| 623 |
| 624 UINT32_TO_BYTE_ARRAY(count, marshaledCounter.t.buffer); |
| 625 _cpri__KDFa(hashAlg, seed, label, extra, &marshaledCounter.b, |
| 626 totalBits, withExtra, NULL, FALSE); |
| 627 |
| 628 // Convert the result and modular reduce |
| 629 // Assume the size variables do not overflow, which should not happen in |
| 630 // the contexts that this function will be called. |
| 631 pAssert(keySizeInBytes <= MAX_ECC_KEY_BYTES); |
| 632 if ( BN_bin2bn(withExtra, keySizeInBytes+8, bnD) == NULL |
| 633 || BN_mod(bnD, bnD, bnNm1, context) != 1) |
| 634 FAIL(FATAL_ERROR_INTERNAL); |
| 635 |
| 636 // Add one to get 0 < d < n |
| 637 BN_add_word(bnD, 1); |
| 638 if(BnTo2B(&dOut->b, bnD, keySizeInBytes) != 1) |
| 639 FAIL(FATAL_ERROR_INTERNAL); |
| 640 |
| 641 // Do the point multiply to create the public portion of the key. If |
| 642 // the multiply generates the point at infinity (unlikely), do another |
| 643 // iteration. |
| 644 if( (retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL)) |
| 645 != CRYPT_NO_RESULT) |
| 646 break; |
| 647 } |
| 648 |
| 649 if(count == 0) // if counter wrapped, then the TPM should go into failure mode |
| 650 FAIL(FATAL_ERROR_INTERNAL); |
| |
| Family "2.0" TCG Published Page 491 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 651 |
| 652 // Free up allocated BN values |
| 653 BN_CTX_end(context); |
| 654 BN_CTX_free(context); |
| 655 if(counter != NULL) |
| 656 *counter = count; |
| 657 return retVal; |
| 658 } |
| |
| |
| B.13.3.2.16. _cpri__GetEphemeralEcc() |
| |
| This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the |
| key will be discarded |
| |
| 659 LIB_EXPORT CRYPT_RESULT |
| 660 _cpri__GetEphemeralEcc( |
| 661 TPMS_ECC_POINT *Qout, // OUT: the public point |
| 662 TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar |
| 663 TPM_ECC_CURVE curveId // IN: the curve for the key |
| 664 ) |
| 665 { |
| 666 CRYPT_RESULT retVal; |
| 667 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 668 |
| 669 pAssert(curveData != NULL); |
| 670 |
| 671 // Keep getting random values until one is found that doesn't create a point |
| 672 // at infinity. This will never, ever, ever, ever, ever, happen but if it does |
| 673 // we have to get a next random value. |
| 674 while(TRUE) |
| 675 { |
| 676 GetRandomPrivate(dOut, curveData->p); |
| 677 |
| 678 // _cpri__EccPointMultiply does not return CRYPT_ECC_POINT if no point is |
| 679 // provided. CRYPT_PARAMTER should not be returned because the curve ID |
| 680 // has to be supported. Thus the only possible error is CRYPT_NO_RESULT. |
| 681 retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL); |
| 682 if(retVal != CRYPT_NO_RESULT) |
| 683 return retVal; // Will return CRYPT_SUCCESS |
| 684 } |
| 685 } |
| 686 #ifdef TPM_ALG_ECDSA //% |
| |
| |
| B.13.3.2.17. SignEcdsa() |
| |
| This function implements the ECDSA signing algorithm. The method is described in the comments below. |
| It is a fatal error if rOut, sOut, dIn, or digest are not provided. |
| |
| 687 LIB_EXPORT CRYPT_RESULT |
| 688 SignEcdsa( |
| 689 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature |
| 690 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature |
| 691 TPM_ECC_CURVE curveId, // IN: the curve used in the signature |
| 692 // process |
| 693 TPM2B_ECC_PARAMETER *dIn, // IN: the private key |
| 694 TPM2B *digest // IN: the value to sign |
| 695 ) |
| 696 { |
| 697 BIGNUM *bnK; |
| 698 BIGNUM *bnIk; |
| 699 BIGNUM *bnN; |
| 700 BIGNUM *bnR; |
| |
| |
| Page 492 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 701 BIGNUM *bnD; |
| 702 BIGNUM *bnZ; |
| 703 TPM2B_ECC_PARAMETER k; |
| 704 TPMS_ECC_POINT R; |
| 705 BN_CTX *context; |
| 706 CRYPT_RESULT retVal = CRYPT_SUCCESS; |
| 707 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 708 |
| 709 pAssert(rOut != NULL && sOut != NULL && dIn != NULL && digest != NULL); |
| 710 |
| 711 context = BN_CTX_new(); |
| 712 if(context == NULL) |
| 713 FAIL(FATAL_ERROR_ALLOCATION); |
| 714 BN_CTX_start(context); |
| 715 bnN = BN_CTX_get(context); |
| 716 bnZ = BN_CTX_get(context); |
| 717 bnR = BN_CTX_get(context); |
| 718 bnD = BN_CTX_get(context); |
| 719 bnIk = BN_CTX_get(context); |
| 720 bnK = BN_CTX_get(context); |
| 721 // Assume the size variables do not overflow, which should not happen in |
| 722 // the contexts that this function will be called. |
| 723 pAssert(curveData->n->size <= MAX_ECC_PARAMETER_BYTES); |
| 724 if( bnK == NULL |
| 725 || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL) |
| 726 FAIL(FATAL_ERROR_INTERNAL); |
| 727 |
| 728 // The algorithm as described in "Suite B Implementer's Guide to FIPS 186-3(ECDSA)" |
| 729 // 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a per-message |
| 730 // secret number and its inverse modulo n. Since n is prime, the |
| 731 // output will be invalid only if there is a failure in the RBG. |
| 732 // 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar |
| 733 // multiplication (see [Routines]), where G is the base point included in |
| 734 // the set of domain parameters. |
| 735 // 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1. |
| 736 // 4. Use the selected hash function to compute H = Hash(M). |
| 737 // 5. Convert the bit string H to an integer e as described in Appendix B.2. |
| 738 // 6. Compute s = (k^-1 * (e + d * r)) mod n. If s = 0, return to Step 1.2. |
| 739 // 7. Return (r, s). |
| 740 |
| 741 // Generate a random value k in the range 1 <= k < n |
| 742 // Want a K value that is the same size as the curve order |
| 743 k.t.size = curveData->n->size; |
| 744 |
| 745 while(TRUE) // This implements the loop at step 6. If s is zero, start over. |
| 746 { |
| 747 while(TRUE) |
| 748 { |
| 749 // Step 1 and 2 -- generate an ephemeral key and the modular inverse |
| 750 // of the private key. |
| 751 while(TRUE) |
| 752 { |
| 753 GetRandomPrivate(&k, curveData->n); |
| 754 |
| 755 // Do the point multiply to generate a point and check to see if |
| 756 // the point it at infinity |
| 757 if( _cpri__EccPointMultiply(&R, curveId, &k, NULL, NULL) |
| 758 != CRYPT_NO_RESULT) |
| 759 break; // can only be CRYPT_SUCCESS |
| 760 } |
| 761 |
| 762 // x coordinate is mod p. Make it mod n |
| 763 // Assume the size variables do not overflow, which should not happen |
| 764 // in the contexts that this function will be called. |
| 765 assert2Bsize(R.x.t); |
| 766 BN_bin2bn(R.x.t.buffer, R.x.t.size, bnR); |
| |
| Family "2.0" TCG Published Page 493 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 767 BN_mod(bnR, bnR, bnN, context); |
| 768 |
| 769 // Make sure that it is not zero; |
| 770 if(BN_is_zero(bnR)) |
| 771 continue; |
| 772 |
| 773 // Make sure that a modular inverse exists |
| 774 // Assume the size variables do not overflow, which should not happen |
| 775 // in the contexts that this function will be called. |
| 776 assert2Bsize(k.t); |
| 777 BN_bin2bn(k.t.buffer, k.t.size, bnK); |
| 778 if( BN_mod_inverse(bnIk, bnK, bnN, context) != NULL) |
| 779 break; |
| 780 } |
| 781 |
| 782 // Set z = leftmost bits of the digest |
| 783 // NOTE: This is implemented such that the key size needs to be |
| 784 // an even number of bytes in length. |
| 785 if(digest->size > curveData->n->size) |
| 786 { |
| 787 // Assume the size variables do not overflow, which should not happen |
| 788 // in the contexts that this function will be called. |
| 789 pAssert(curveData->n->size <= MAX_ECC_KEY_BYTES); |
| 790 // digest is larger than n so truncate |
| 791 BN_bin2bn(digest->buffer, curveData->n->size, bnZ); |
| 792 } |
| 793 else |
| 794 { |
| 795 // Assume the size variables do not overflow, which should not happen |
| 796 // in the contexts that this function will be called. |
| 797 pAssert(digest->size <= MAX_DIGEST_SIZE); |
| 798 // digest is same or smaller than n so use it all |
| 799 BN_bin2bn(digest->buffer, digest->size, bnZ); |
| 800 } |
| 801 |
| 802 // Assume the size variables do not overflow, which should not happen in |
| 803 // the contexts that this function will be called. |
| 804 assert2Bsize(dIn->t); |
| 805 if( bnZ == NULL |
| 806 |
| 807 // need the private scalar of the signing key |
| 808 || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL) |
| 809 FAIL(FATAL_ERROR_INTERNAL); |
| 810 |
| 811 // NOTE: When the result of an operation is going to be reduced mod x |
| 812 // any modular multiplication is done so that the intermediate values |
| 813 // don't get too large. |
| 814 // |
| 815 // now have inverse of K (bnIk), z (bnZ), r (bnR), d (bnD) and n (bnN) |
| 816 // Compute s = k^-1 (z + r*d)(mod n) |
| 817 // first do d = r*d mod n |
| 818 if( !BN_mod_mul(bnD, bnR, bnD, bnN, context) |
| 819 |
| 820 // d = z + r * d |
| 821 || !BN_add(bnD, bnZ, bnD) |
| 822 |
| 823 // d = k^(-1)(z + r * d)(mod n) |
| 824 || !BN_mod_mul(bnD, bnIk, bnD, bnN, context) |
| 825 |
| 826 // convert to TPM2B format |
| 827 || !BnTo2B(&sOut->b, bnD, curveData->n->size) |
| 828 |
| 829 // and write the modular reduced version of r |
| 830 // NOTE: this was deferred to reduce the number of |
| 831 // error checks. |
| 832 || !BnTo2B(&rOut->b, bnR, curveData->n->size)) |
| |
| Page 494 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 833 FAIL(FATAL_ERROR_INTERNAL); |
| 834 |
| 835 if(!BN_is_zero(bnD)) |
| 836 break; // signature not zero so done |
| 837 |
| 838 // if the signature value was zero, start over |
| 839 } |
| 840 |
| 841 // Free up allocated BN values |
| 842 BN_CTX_end(context); |
| 843 BN_CTX_free(context); |
| 844 return retVal; |
| 845 } |
| 846 #endif //% |
| 847 #if defined TPM_ALG_ECDAA || defined TPM_ALG_ECSCHNORR //% |
| |
| |
| B.13.3.2.18. EcDaa() |
| |
| This function is used to perform a modified Schnorr signature for ECDAA. |
| This function performs s = k + T * d mod n where |
| a) 'k is a random, or pseudo-random value used in the commit phase |
| b) T is the digest to be signed, and |
| c) d is a private key. |
| If tIn is NULL then use tOut as T |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS signature created |
| |
| 848 static CRYPT_RESULT |
| 849 EcDaa( |
| 850 TPM2B_ECC_PARAMETER *tOut, // OUT: T component of the signature |
| 851 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature |
| 852 TPM_ECC_CURVE curveId, // IN: the curve used in signing |
| 853 TPM2B_ECC_PARAMETER *dIn, // IN: the private key |
| 854 TPM2B *tIn, // IN: the value to sign |
| 855 TPM2B_ECC_PARAMETER *kIn // IN: a random value from commit |
| 856 ) |
| 857 { |
| 858 BIGNUM *bnN, *bnK, *bnT, *bnD; |
| 859 BN_CTX *context; |
| 860 const TPM2B *n; |
| 861 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 862 BOOL OK = TRUE; |
| 863 |
| 864 // Parameter checks |
| 865 pAssert( sOut != NULL && dIn != NULL && tOut != NULL |
| 866 && kIn != NULL && curveData != NULL); |
| 867 |
| 868 // this just saves key strokes |
| 869 n = curveData->n; |
| 870 |
| 871 if(tIn != NULL) |
| 872 Copy2B(&tOut->b, tIn); |
| 873 |
| 874 // The size of dIn and kIn input scalars is limited by the size of the size |
| 875 // of a TPM2B_ECC_PARAMETER and tIn can be no larger than a digest. |
| 876 // Make sure they are within range. |
| 877 pAssert( (int) dIn->t.size <= MAX_ECC_KEY_BYTES |
| 878 && (int) kIn->t.size <= MAX_ECC_KEY_BYTES |
| |
| |
| Family "2.0" TCG Published Page 495 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 879 && (int) tOut->t.size <= MAX_DIGEST_SIZE |
| 880 ); |
| 881 |
| 882 context = BN_CTX_new(); |
| 883 if(context == NULL) |
| 884 FAIL(FATAL_ERROR_ALLOCATION); |
| 885 BN_CTX_start(context); |
| 886 bnN = BN_CTX_get(context); |
| 887 bnK = BN_CTX_get(context); |
| 888 bnT = BN_CTX_get(context); |
| 889 bnD = BN_CTX_get(context); |
| 890 |
| 891 // Check for allocation problems |
| 892 if(bnD == NULL) |
| 893 FAIL(FATAL_ERROR_ALLOCATION); |
| 894 |
| 895 // Convert values |
| 896 if( BN_bin2bn(n->buffer, n->size, bnN) == NULL |
| 897 || BN_bin2bn(kIn->t.buffer, kIn->t.size, bnK) == NULL |
| 898 || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL |
| 899 || BN_bin2bn(tOut->t.buffer, tOut->t.size, bnT) == NULL) |
| 900 |
| 901 FAIL(FATAL_ERROR_INTERNAL); |
| 902 // Compute T = T mod n |
| 903 OK = OK && BN_mod(bnT, bnT, bnN, context); |
| 904 |
| 905 // compute (s = k + T * d mod n) |
| 906 // d = T * d mod n |
| 907 OK = OK && BN_mod_mul(bnD, bnT, bnD, bnN, context) == 1; |
| 908 // d = k + T * d mod n |
| 909 OK = OK && BN_mod_add(bnD, bnK, bnD, bnN, context) == 1; |
| 910 // s = d |
| 911 OK = OK && BnTo2B(&sOut->b, bnD, n->size); |
| 912 // r = T |
| 913 OK = OK && BnTo2B(&tOut->b, bnT, n->size); |
| 914 if(!OK) |
| 915 FAIL(FATAL_ERROR_INTERNAL); |
| 916 |
| 917 // Cleanup |
| 918 BN_CTX_end(context); |
| 919 BN_CTX_free(context); |
| 920 |
| 921 return CRYPT_SUCCESS; |
| 922 } |
| 923 #endif //% |
| 924 #ifdef TPM_ALG_ECSCHNORR //% |
| |
| |
| B.13.3.2.19. SchnorrEcc() |
| |
| This function is used to perform a modified Schnorr signature. |
| This function will generate a random value k and compute |
| a) (xR, yR) = [k]G |
| b) r = hash(P || xR)(mod n) |
| c) s= k + r * ds |
| d) return the tuple T, s |
| |
| |
| |
| |
| Page 496 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS signature created |
| CRYPT_SCHEME hashAlg can't produce zero-length digest |
| |
| 925 static CRYPT_RESULT |
| 926 SchnorrEcc( |
| 927 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature |
| 928 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature |
| 929 TPM_ALG_ID hashAlg, // IN: hash algorithm used |
| 930 TPM_ECC_CURVE curveId, // IN: the curve used in signing |
| 931 TPM2B_ECC_PARAMETER *dIn, // IN: the private key |
| 932 TPM2B *digest, // IN: the digest to sign |
| 933 TPM2B_ECC_PARAMETER *kIn // IN: for testing |
| 934 ) |
| 935 { |
| 936 TPM2B_ECC_PARAMETER k; |
| 937 BIGNUM *bnR, *bnN, *bnK, *bnT, *bnD; |
| 938 BN_CTX *context; |
| 939 const TPM2B *n; |
| 940 EC_POINT *pR = NULL; |
| 941 EC_GROUP *group = NULL; |
| 942 CPRI_HASH_STATE hashState; |
| 943 UINT16 digestSize = _cpri__GetDigestSize(hashAlg); |
| 944 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 945 TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_PARAMETER_BYTES)); |
| 946 TPM2B_T T2b; |
| 947 BOOL OK = TRUE; |
| 948 |
| 949 // Parameter checks |
| 950 |
| 951 // Must have a place for the 'r' and 's' parts of the signature, a private |
| 952 // key ('d') |
| 953 pAssert( rOut != NULL && sOut != NULL && dIn != NULL |
| 954 && digest != NULL && curveData != NULL); |
| 955 |
| 956 // to save key strokes |
| 957 n = curveData->n; |
| 958 |
| 959 // If the digest does not produce a hash, then null the signature and return |
| 960 // a failure. |
| 961 if(digestSize == 0) |
| 962 { |
| 963 rOut->t.size = 0; |
| 964 sOut->t.size = 0; |
| 965 return CRYPT_SCHEME; |
| 966 } |
| 967 |
| 968 // Allocate big number values |
| 969 context = BN_CTX_new(); |
| 970 if(context == NULL) |
| 971 FAIL(FATAL_ERROR_ALLOCATION); |
| 972 BN_CTX_start(context); |
| 973 bnR = BN_CTX_get(context); |
| 974 bnN = BN_CTX_get(context); |
| 975 bnK = BN_CTX_get(context); |
| 976 bnT = BN_CTX_get(context); |
| 977 bnD = BN_CTX_get(context); |
| 978 if( bnD == NULL |
| 979 // initialize the group parameters |
| 980 || (group = EccCurveInit(curveId, context)) == NULL |
| 981 // allocate a local point |
| 982 || (pR = EC_POINT_new(group)) == NULL |
| 983 ) |
| |
| Family "2.0" TCG Published Page 497 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 984 FAIL(FATAL_ERROR_ALLOCATION); |
| 985 |
| 986 if(BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL) |
| 987 FAIL(FATAL_ERROR_INTERNAL); |
| 988 |
| 989 while(OK) |
| 990 { |
| 991 // a) set k to a random value such that 1 k n-1 |
| 992 if(kIn != NULL) |
| 993 { |
| 994 Copy2B(&k.b, &kIn->b); // copy input k if testing |
| 995 OK = FALSE; // not OK to loop |
| 996 } |
| 997 else |
| 998 // If get a random value in the correct range |
| 999 GetRandomPrivate(&k, n); |
| 1000 |
| 1001 // Convert 'k' and generate pR = ['k']G |
| 1002 BnFrom2B(bnK, &k.b); |
| 1003 |
| 1004 // b) compute E (xE, yE) [k]G |
| 1005 if(PointMul(group, pR, bnK, NULL, NULL, context) == CRYPT_NO_RESULT) |
| 1006 // c) if E is the point at infinity, go to a) |
| 1007 continue; |
| 1008 |
| 1009 // d) compute e xE (mod n) |
| 1010 // Get the x coordinate of the point |
| 1011 EC_POINT_get_affine_coordinates_GFp(group, pR, bnR, NULL, context); |
| 1012 |
| 1013 // make (mod n) |
| 1014 BN_mod(bnR, bnR, bnN, context); |
| 1015 |
| 1016 // e) if e is zero, go to a) |
| 1017 if(BN_is_zero(bnR)) |
| 1018 continue; |
| 1019 |
| 1020 // Convert xR to a string (use T as a temp) |
| 1021 BnTo2B(&T2b.b, bnR, (UINT16)(BN_num_bits(bnR)+7)/8); |
| 1022 |
| 1023 // f) compute r HschemeHash(P || e) (mod n) |
| 1024 _cpri__StartHash(hashAlg, FALSE, &hashState); |
| 1025 _cpri__UpdateHash(&hashState, digest->size, digest->buffer); |
| 1026 _cpri__UpdateHash(&hashState, T2b.t.size, T2b.t.buffer); |
| 1027 if(_cpri__CompleteHash(&hashState, digestSize, T2b.b.buffer) != digestSize) |
| 1028 FAIL(FATAL_ERROR_INTERNAL); |
| 1029 T2b.t.size = digestSize; |
| 1030 BnFrom2B(bnT, &T2b.b); |
| 1031 BN_div(NULL, bnT, bnT, bnN, context); |
| 1032 BnTo2B(&rOut->b, bnT, (UINT16)BN_num_bytes(bnT)); |
| 1033 |
| 1034 // We have a value and we are going to exit the loop successfully |
| 1035 OK = TRUE; |
| 1036 break; |
| 1037 } |
| 1038 // Cleanup |
| 1039 EC_POINT_free(pR); |
| 1040 EC_GROUP_free(group); |
| 1041 BN_CTX_end(context); |
| 1042 BN_CTX_free(context); |
| 1043 |
| 1044 // If we have a value, finish the signature |
| 1045 if(OK) |
| 1046 return EcDaa(rOut, sOut, curveId, dIn, NULL, &k); |
| 1047 else |
| 1048 return CRYPT_NO_RESULT; |
| 1049 } |
| |
| Page 498 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1050 #endif //% |
| 1051 #ifdef TPM_ALG_SM2 //% |
| 1052 #ifdef _SM2_SIGN_DEBUG //% |
| 1053 static int |
| 1054 cmp_bn2hex( |
| 1055 BIGNUM *bn, // IN: big number value |
| 1056 const char *c // IN: character string number |
| 1057 ) |
| 1058 { |
| 1059 int result; |
| 1060 BIGNUM *bnC = BN_new(); |
| 1061 pAssert(bnC != NULL); |
| 1062 |
| 1063 BN_hex2bn(&bnC, c); |
| 1064 result = BN_ucmp(bn, bnC); |
| 1065 BN_free(bnC); |
| 1066 return result; |
| 1067 } |
| 1068 static int |
| 1069 cmp_2B2hex( |
| 1070 TPM2B *a, // IN: TPM2B number to compare |
| 1071 const char *c // IN: character string |
| 1072 ) |
| 1073 { |
| 1074 int result; |
| 1075 int sl = strlen(c); |
| 1076 BIGNUM *bnA; |
| 1077 |
| 1078 result = (a->size * 2) - sl; |
| 1079 if(result != 0) |
| 1080 return result; |
| 1081 pAssert((bnA = BN_bin2bn(a->buffer, a->size, NULL)) != NULL); |
| 1082 result = cmp_bn2hex(bnA, c); |
| 1083 BN_free(bnA); |
| 1084 return result; |
| 1085 } |
| 1086 static void |
| 1087 cpy_hexTo2B( |
| 1088 TPM2B *b, // OUT: receives value |
| 1089 const char *c // IN: source string |
| 1090 ) |
| 1091 { |
| 1092 BIGNUM *bnB = BN_new(); |
| 1093 pAssert((strlen(c) & 1) == 0); // must have an even number of digits |
| 1094 b->size = strlen(c) / 2; |
| 1095 BN_hex2bn(&bnB, c); |
| 1096 pAssert(bnB != NULL); |
| 1097 BnTo2B(b, bnB, b->size); |
| 1098 BN_free(bnB); |
| 1099 |
| 1100 } |
| 1101 #endif //% _SM2_SIGN_DEBUG |
| |
| |
| B.13.3.2.20. SignSM2() |
| |
| This function signs a digest using the method defined in SM2 Part 2. The method in the standard will add |
| a header to the message to be signed that is a hash of the values that define the key. This then hashed |
| with the message to produce a digest (e) that is signed. This function signs e. |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 499 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS sign worked |
| |
| 1102 static CRYPT_RESULT |
| 1103 SignSM2( |
| 1104 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature |
| 1105 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature |
| 1106 TPM_ECC_CURVE curveId, // IN: the curve used in signing |
| 1107 TPM2B_ECC_PARAMETER *dIn, // IN: the private key |
| 1108 TPM2B *digest // IN: the digest to sign |
| 1109 ) |
| 1110 { |
| 1111 BIGNUM *bnR; |
| 1112 BIGNUM *bnS; |
| 1113 BIGNUM *bnN; |
| 1114 BIGNUM *bnK; |
| 1115 BIGNUM *bnX1; |
| 1116 BIGNUM *bnD; |
| 1117 BIGNUM *bnT; // temp |
| 1118 BIGNUM *bnE; |
| 1119 |
| 1120 BN_CTX *context; |
| 1121 TPM2B_TYPE(DIGEST, MAX_DIGEST_SIZE); |
| 1122 TPM2B_ECC_PARAMETER k; |
| 1123 TPMS_ECC_POINT p2Br; |
| 1124 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1125 |
| 1126 pAssert(curveData != NULL); |
| 1127 context = BN_CTX_new(); |
| 1128 BN_CTX_start(context); |
| 1129 bnK = BN_CTX_get(context); |
| 1130 bnR = BN_CTX_get(context); |
| 1131 bnS = BN_CTX_get(context); |
| 1132 bnX1 = BN_CTX_get(context); |
| 1133 bnN = BN_CTX_get(context); |
| 1134 bnD = BN_CTX_get(context); |
| 1135 bnT = BN_CTX_get(context); |
| 1136 bnE = BN_CTX_get(context); |
| 1137 if(bnE == NULL) |
| 1138 FAIL(FATAL_ERROR_ALLOCATION); |
| 1139 |
| 1140 BnFrom2B(bnE, digest); |
| 1141 BnFrom2B(bnN, curveData->n); |
| 1142 BnFrom2B(bnD, &dIn->b); |
| 1143 |
| 1144 #ifdef _SM2_SIGN_DEBUG |
| 1145 BN_hex2bn(&bnE, "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76"); |
| 1146 BN_hex2bn(&bnD, "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263"); |
| 1147 #endif |
| 1148 // A3: Use random number generator to generate random number 1 <= k <= n-1; |
| 1149 // NOTE: Ax: numbers are from the SM2 standard |
| 1150 k.t.size = curveData->n->size; |
| 1151 loop: |
| 1152 { |
| 1153 // Get a random number |
| 1154 _cpri__GenerateRandom(k.t.size, k.t.buffer); |
| 1155 |
| 1156 #ifdef _SM2_SIGN_DEBUG |
| 1157 BN_hex2bn(&bnK, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F"); |
| 1158 BnTo2B(&k.b,bnK, 32); |
| 1159 k.t.size = 32; |
| 1160 #endif |
| 1161 //make sure that the number is 0 < k < n |
| 1162 BnFrom2B(bnK, &k.b); |
| |
| Page 500 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1163 if( BN_ucmp(bnK, bnN) >= 0 |
| 1164 || BN_is_zero(bnK)) |
| 1165 goto loop; |
| 1166 |
| 1167 // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according |
| 1168 // to details specified in 4.2.7 in Part 1 of this document, transform the |
| 1169 // data type of x1 into an integer; |
| 1170 if( _cpri__EccPointMultiply(&p2Br, curveId, &k, NULL, NULL) |
| 1171 == CRYPT_NO_RESULT) |
| 1172 goto loop; |
| 1173 |
| 1174 BnFrom2B(bnX1, &p2Br.x.b); |
| 1175 |
| 1176 // A5: Figure out r = (e + x1) mod n, |
| 1177 if(!BN_mod_add(bnR, bnE, bnX1, bnN, context)) |
| 1178 FAIL(FATAL_ERROR_INTERNAL); |
| 1179 #ifdef _SM2_SIGN_DEBUG |
| 1180 pAssert(cmp_bn2hex(bnR, |
| 1181 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") |
| 1182 == 0); |
| 1183 #endif |
| 1184 |
| 1185 // if r=0 or r+k=n, return to A3; |
| 1186 if(!BN_add(bnT, bnK, bnR)) |
| 1187 FAIL(FATAL_ERROR_INTERNAL); |
| 1188 |
| 1189 if(BN_is_zero(bnR) || BN_ucmp(bnT, bnN) == 0) |
| 1190 goto loop; |
| 1191 |
| 1192 // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, if s=0, return to A3; |
| 1193 // compute t = (1+d)-1 |
| 1194 BN_copy(bnT, bnD); |
| 1195 if( !BN_add_word(bnT, 1) |
| 1196 || !BN_mod_inverse(bnT, bnT, bnN, context) // (1 + dA)^-1 mod n |
| 1197 ) |
| 1198 FAIL(FATAL_ERROR_INTERNAL); |
| 1199 #ifdef _SM2_SIGN_DEBUG |
| 1200 pAssert(cmp_bn2hex(bnT, |
| 1201 "79BFCF3052C80DA7B939E0C6914A18CBB2D96D8555256E83122743A7D4F5F956") |
| 1202 == 0); |
| 1203 #endif |
| 1204 // compute s = t * (k - r * dA) mod n |
| 1205 if( !BN_mod_mul(bnS, bnD, bnR, bnN, context) // (r * dA) mod n |
| 1206 || !BN_mod_sub(bnS, bnK, bnS, bnN, context) // (k - (r * dA) mod n |
| 1207 || !BN_mod_mul(bnS, bnT, bnS, bnN, context))// t * (k - (r * dA) mod n |
| 1208 FAIL(FATAL_ERROR_INTERNAL); |
| 1209 #ifdef _SM2_SIGN_DEBUG |
| 1210 pAssert(cmp_bn2hex(bnS, |
| 1211 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") |
| 1212 == 0); |
| 1213 #endif |
| 1214 |
| 1215 if(BN_is_zero(bnS)) |
| 1216 goto loop; |
| 1217 } |
| 1218 |
| 1219 // A7: According to details specified in 4.2.1 in Part 1 of this document, transform |
| 1220 // the data type of r, s into bit strings, signature of message M is (r, s). |
| 1221 |
| 1222 BnTo2B(&rOut->b, bnR, curveData->n->size); |
| 1223 BnTo2B(&sOut->b, bnS, curveData->n->size); |
| 1224 #ifdef _SM2_SIGN_DEBUG |
| 1225 pAssert(cmp_2B2hex(&rOut->b, |
| 1226 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") |
| 1227 == 0); |
| 1228 pAssert(cmp_2B2hex(&sOut->b, |
| |
| Family "2.0" TCG Published Page 501 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1229 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") |
| 1230 == 0); |
| 1231 #endif |
| 1232 BN_CTX_end(context); |
| 1233 BN_CTX_free(context); |
| 1234 return CRYPT_SUCCESS; |
| 1235 } |
| 1236 #endif //% TPM_ALG_SM2 |
| |
| |
| B.13.3.2.21. _cpri__SignEcc() |
| |
| This function is the dispatch function for the various ECC-based signing schemes. |
| |
| Return Value Meaning |
| |
| CRYPT_SCHEME scheme is not supported |
| |
| 1237 LIB_EXPORT CRYPT_RESULT |
| 1238 _cpri__SignEcc( |
| 1239 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature |
| 1240 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature |
| 1241 TPM_ALG_ID scheme, // IN: the scheme selector |
| 1242 TPM_ALG_ID hashAlg, // IN: the hash algorithm if need |
| 1243 TPM_ECC_CURVE curveId, // IN: the curve used in the signature |
| 1244 // process |
| 1245 TPM2B_ECC_PARAMETER *dIn, // IN: the private key |
| 1246 TPM2B *digest, // IN: the digest to sign |
| 1247 TPM2B_ECC_PARAMETER *kIn // IN: k for input |
| 1248 ) |
| 1249 { |
| 1250 switch (scheme) |
| 1251 { |
| 1252 case TPM_ALG_ECDSA: |
| 1253 // SignEcdsa always works |
| 1254 return SignEcdsa(rOut, sOut, curveId, dIn, digest); |
| 1255 break; |
| 1256 #ifdef TPM_ALG_ECDAA |
| 1257 case TPM_ALG_ECDAA: |
| 1258 if(rOut != NULL) |
| 1259 rOut->b.size = 0; |
| 1260 return EcDaa(rOut, sOut, curveId, dIn, digest, kIn); |
| 1261 break; |
| 1262 #endif |
| 1263 #ifdef TPM_ALG_ECSCHNORR |
| 1264 case TPM_ALG_ECSCHNORR: |
| 1265 return SchnorrEcc(rOut, sOut, hashAlg, curveId, dIn, digest, kIn); |
| 1266 break; |
| 1267 #endif |
| 1268 #ifdef TPM_ALG_SM2 |
| 1269 case TPM_ALG_SM2: |
| 1270 return SignSM2(rOut, sOut, curveId, dIn, digest); |
| 1271 break; |
| 1272 #endif |
| 1273 default: |
| 1274 return CRYPT_SCHEME; |
| 1275 } |
| 1276 } |
| 1277 #ifdef TPM_ALG_ECDSA //% |
| |
| |
| B.13.3.2.22. ValidateSignatureEcdsa() |
| |
| This function validates an ECDSA signature. rIn and sIn shoudl have been checked to make sure that |
| they are not zero. |
| |
| Page 502 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS signature valid |
| CRYPT_FAIL signature not valid |
| |
| 1278 static CRYPT_RESULT |
| 1279 ValidateSignatureEcdsa( |
| 1280 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature |
| 1281 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature |
| 1282 TPM_ECC_CURVE curveId, // IN: the curve used in the signature |
| 1283 // process |
| 1284 TPMS_ECC_POINT *Qin, // IN: the public point of the key |
| 1285 TPM2B *digest // IN: the digest that was signed |
| 1286 ) |
| 1287 { |
| 1288 TPM2B_ECC_PARAMETER U1; |
| 1289 TPM2B_ECC_PARAMETER U2; |
| 1290 TPMS_ECC_POINT R; |
| 1291 const TPM2B *n; |
| 1292 BN_CTX *context; |
| 1293 EC_POINT *pQ = NULL; |
| 1294 EC_GROUP *group = NULL; |
| 1295 BIGNUM *bnU1; |
| 1296 BIGNUM *bnU2; |
| 1297 BIGNUM *bnR; |
| 1298 BIGNUM *bnS; |
| 1299 BIGNUM *bnW; |
| 1300 BIGNUM *bnV; |
| 1301 BIGNUM *bnN; |
| 1302 BIGNUM *bnE; |
| 1303 BIGNUM *bnGx; |
| 1304 BIGNUM *bnGy; |
| 1305 BIGNUM *bnQx; |
| 1306 BIGNUM *bnQy; |
| 1307 CRYPT_RESULT retVal = CRYPT_FAIL; |
| 1308 int t; |
| 1309 |
| 1310 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1311 |
| 1312 // The curve selector should have been filtered by the unmarshaling process |
| 1313 pAssert (curveData != NULL); |
| 1314 n = curveData->n; |
| 1315 |
| 1316 // 1. If r and s are not both integers in the interval [1, n - 1], output |
| 1317 // INVALID. |
| 1318 // rIn and sIn are known to be greater than zero (was checked by the caller). |
| 1319 if( _math__uComp(rIn->t.size, rIn->t.buffer, n->size, n->buffer) >= 0 |
| 1320 || _math__uComp(sIn->t.size, sIn->t.buffer, n->size, n->buffer) >= 0 |
| 1321 ) |
| 1322 return CRYPT_FAIL; |
| 1323 |
| 1324 context = BN_CTX_new(); |
| 1325 if(context == NULL) |
| 1326 FAIL(FATAL_ERROR_ALLOCATION); |
| 1327 BN_CTX_start(context); |
| 1328 bnR = BN_CTX_get(context); |
| 1329 bnS = BN_CTX_get(context); |
| 1330 bnN = BN_CTX_get(context); |
| 1331 bnE = BN_CTX_get(context); |
| 1332 bnV = BN_CTX_get(context); |
| 1333 bnW = BN_CTX_get(context); |
| 1334 bnGx = BN_CTX_get(context); |
| 1335 bnGy = BN_CTX_get(context); |
| 1336 bnQx = BN_CTX_get(context); |
| |
| Family "2.0" TCG Published Page 503 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1337 bnQy = BN_CTX_get(context); |
| 1338 bnU1 = BN_CTX_get(context); |
| 1339 bnU2 = BN_CTX_get(context); |
| 1340 |
| 1341 // Assume the size variables do not overflow, which should not happen in |
| 1342 // the contexts that this function will be called. |
| 1343 assert2Bsize(Qin->x.t); |
| 1344 assert2Bsize(rIn->t); |
| 1345 assert2Bsize(sIn->t); |
| 1346 |
| 1347 // BN_CTX_get() is sticky so only need to check the last value to know that |
| 1348 // all worked. |
| 1349 if( bnU2 == NULL |
| 1350 |
| 1351 // initialize the group parameters |
| 1352 || (group = EccCurveInit(curveId, context)) == NULL |
| 1353 |
| 1354 // allocate a local point |
| 1355 || (pQ = EC_POINT_new(group)) == NULL |
| 1356 |
| 1357 // use the public key values (QxIn and QyIn) to initialize Q |
| 1358 || BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQx) == NULL |
| 1359 || BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQy) == NULL |
| 1360 || !EC_POINT_set_affine_coordinates_GFp(group, pQ, bnQx, bnQy, context) |
| 1361 |
| 1362 // convert the signature values |
| 1363 || BN_bin2bn(rIn->t.buffer, rIn->t.size, bnR) == NULL |
| 1364 || BN_bin2bn(sIn->t.buffer, sIn->t.size, bnS) == NULL |
| 1365 |
| 1366 // convert the curve order |
| 1367 || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL) |
| 1368 FAIL(FATAL_ERROR_INTERNAL); |
| 1369 |
| 1370 // 2. Use the selected hash function to compute H0 = Hash(M0). |
| 1371 // This is an input parameter |
| 1372 |
| 1373 // 3. Convert the bit string H0 to an integer e as described in Appendix B.2. |
| 1374 t = (digest->size > rIn->t.size) ? rIn->t.size : digest->size; |
| 1375 if(BN_bin2bn(digest->buffer, t, bnE) == NULL) |
| 1376 FAIL(FATAL_ERROR_INTERNAL); |
| 1377 |
| 1378 // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1. |
| 1379 if (BN_mod_inverse(bnW, bnS, bnN, context) == NULL) |
| 1380 FAIL(FATAL_ERROR_INTERNAL); |
| 1381 |
| 1382 // 5. Compute u1 = (e' * w) mod n, and compute u2 = (r' * w) mod n. |
| 1383 if( !BN_mod_mul(bnU1, bnE, bnW, bnN, context) |
| 1384 || !BN_mod_mul(bnU2, bnR, bnW, bnN, context)) |
| 1385 FAIL(FATAL_ERROR_INTERNAL); |
| 1386 |
| 1387 BnTo2B(&U1.b, bnU1, (INT16) BN_num_bytes(bnU1)); |
| 1388 BnTo2B(&U2.b, bnU2, (INT16) BN_num_bytes(bnU2)); |
| 1389 |
| 1390 // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC |
| 1391 // scalar multiplication and EC addition (see [Routines]). If R is equal to |
| 1392 // the point at infinity O, output INVALID. |
| 1393 if(_cpri__EccPointMultiply(&R, curveId, &U1, Qin, &U2) == CRYPT_SUCCESS) |
| 1394 { |
| 1395 // 7. Compute v = Rx mod n. |
| 1396 if( BN_bin2bn(R.x.t.buffer, R.x.t.size, bnV) == NULL |
| 1397 || !BN_mod(bnV, bnV, bnN, context)) |
| 1398 FAIL(FATAL_ERROR_INTERNAL); |
| 1399 |
| 1400 // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID |
| 1401 if(BN_cmp(bnV, bnR) == 0) |
| 1402 retVal = CRYPT_SUCCESS; |
| |
| Page 504 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1403 } |
| 1404 |
| 1405 if(pQ != NULL) EC_POINT_free(pQ); |
| 1406 if(group != NULL) EC_GROUP_free(group); |
| 1407 BN_CTX_end(context); |
| 1408 BN_CTX_free(context); |
| 1409 |
| 1410 return retVal; |
| 1411 } |
| 1412 #endif //% TPM_ALG_ECDSA |
| 1413 #ifdef TPM_ALG_ECSCHNORR //% |
| |
| |
| B.13.3.2.23. ValidateSignatureEcSchnorr() |
| |
| This function is used to validate an EC Schnorr signature. rIn and sIn are required to be greater than |
| zero. This is checked in _cpri__ValidateSignatureEcc(). |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS signature valid |
| CRYPT_FAIL signature not valid |
| CRYPT_SCHEME hashAlg is not supported |
| |
| 1414 static CRYPT_RESULT |
| 1415 ValidateSignatureEcSchnorr( |
| 1416 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature |
| 1417 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature |
| 1418 TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature |
| 1419 TPM_ECC_CURVE curveId, // IN: the curve used in the signature |
| 1420 // process |
| 1421 TPMS_ECC_POINT *Qin, // IN: the public point of the key |
| 1422 TPM2B *digest // IN: the digest that was signed |
| 1423 ) |
| 1424 { |
| 1425 TPMS_ECC_POINT pE; |
| 1426 const TPM2B *n; |
| 1427 CPRI_HASH_STATE hashState; |
| 1428 TPM2B_DIGEST rPrime; |
| 1429 TPM2B_ECC_PARAMETER minusR; |
| 1430 UINT16 digestSize = _cpri__GetDigestSize(hashAlg); |
| 1431 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1432 |
| 1433 // The curve parameter should have been filtered by unmarshaling code |
| 1434 pAssert(curveData != NULL); |
| 1435 |
| 1436 if(digestSize == 0) |
| 1437 return CRYPT_SCHEME; |
| 1438 |
| 1439 // Input parameter validation |
| 1440 pAssert(rIn != NULL && sIn != NULL && Qin != NULL && digest != NULL); |
| 1441 |
| 1442 n = curveData->n; |
| 1443 |
| 1444 // if sIn or rIn are not between 1 and N-1, signature check fails |
| 1445 // sIn and rIn were verified to be non-zero by the caller |
| 1446 if( _math__uComp(sIn->b.size, sIn->b.buffer, n->size, n->buffer) >= 0 |
| 1447 || _math__uComp(rIn->b.size, rIn->b.buffer, n->size, n->buffer) >= 0 |
| 1448 ) |
| 1449 return CRYPT_FAIL; |
| 1450 |
| 1451 //E = [s]InG - [r]InQ |
| 1452 _math__sub(n->size, n->buffer, |
| 1453 rIn->t.size, rIn->t.buffer, |
| |
| Family "2.0" TCG Published Page 505 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1454 &minusR.t.size, minusR.t.buffer); |
| 1455 if(_cpri__EccPointMultiply(&pE, curveId, sIn, Qin, &minusR) != CRYPT_SUCCESS) |
| 1456 return CRYPT_FAIL; |
| 1457 |
| 1458 // Ex = Ex mod N |
| 1459 if(Mod2B(&pE.x.b, n) != CRYPT_SUCCESS) |
| 1460 FAIL(FATAL_ERROR_INTERNAL); |
| 1461 |
| 1462 _math__Normalize2B(&pE.x.b); |
| 1463 |
| 1464 // rPrime = h(digest || pE.x) mod n; |
| 1465 _cpri__StartHash(hashAlg, FALSE, &hashState); |
| 1466 _cpri__UpdateHash(&hashState, digest->size, digest->buffer); |
| 1467 _cpri__UpdateHash(&hashState, pE.x.t.size, pE.x.t.buffer); |
| 1468 if(_cpri__CompleteHash(&hashState, digestSize, rPrime.t.buffer) != digestSize) |
| 1469 FAIL(FATAL_ERROR_INTERNAL); |
| 1470 |
| 1471 rPrime.t.size = digestSize; |
| 1472 |
| 1473 // rPrime = rPrime (mod n) |
| 1474 if(Mod2B(&rPrime.b, n) != CRYPT_SUCCESS) |
| 1475 FAIL(FATAL_ERROR_INTERNAL); |
| 1476 |
| 1477 // if the values don't match, then the signature is bad |
| 1478 if(_math__uComp(rIn->t.size, rIn->t.buffer, |
| 1479 rPrime.t.size, rPrime.t.buffer) != 0) |
| 1480 return CRYPT_FAIL; |
| 1481 else |
| 1482 return CRYPT_SUCCESS; |
| 1483 } |
| 1484 #endif //% TPM_ALG_ECSCHNORR |
| 1485 #ifdef TPM_ALG_SM2 //% |
| |
| |
| B.13.3.2.24. ValidateSignatueSM2Dsa() |
| |
| This function is used to validate an SM2 signature. |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS signature valid |
| CRYPT_FAIL signature not valid |
| |
| 1486 static CRYPT_RESULT |
| 1487 ValidateSignatureSM2Dsa( |
| 1488 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature |
| 1489 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature |
| 1490 TPM_ECC_CURVE curveId, // IN: the curve used in the signature |
| 1491 // process |
| 1492 TPMS_ECC_POINT *Qin, // IN: the public point of the key |
| 1493 TPM2B *digest // IN: the digest that was signed |
| 1494 ) |
| 1495 { |
| 1496 BIGNUM *bnR; |
| 1497 BIGNUM *bnRp; |
| 1498 BIGNUM *bnT; |
| 1499 BIGNUM *bnS; |
| 1500 BIGNUM *bnE; |
| 1501 EC_POINT *pQ; |
| 1502 BN_CTX *context; |
| 1503 EC_GROUP *group = NULL; |
| 1504 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1505 BOOL fail = FALSE; |
| 1506 |
| |
| |
| Page 506 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1507 if((context = BN_CTX_new()) == NULL || curveData == NULL) |
| 1508 FAIL(FATAL_ERROR_INTERNAL); |
| 1509 bnR = BN_CTX_get(context); |
| 1510 bnRp= BN_CTX_get(context); |
| 1511 bnE = BN_CTX_get(context); |
| 1512 bnT = BN_CTX_get(context); |
| 1513 bnS = BN_CTX_get(context); |
| 1514 if( bnS == NULL |
| 1515 || (group = EccCurveInit(curveId, context)) == NULL) |
| 1516 FAIL(FATAL_ERROR_INTERNAL); |
| 1517 |
| 1518 #ifdef _SM2_SIGN_DEBUG |
| 1519 cpy_hexTo2B(&Qin->x.b, |
| 1520 "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A"); |
| 1521 cpy_hexTo2B(&Qin->y.b, |
| 1522 "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"); |
| 1523 cpy_hexTo2B(digest, |
| 1524 "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76"); |
| 1525 #endif |
| 1526 pQ = EccInitPoint2B(group, Qin, context); |
| 1527 |
| 1528 #ifdef _SM2_SIGN_DEBUG |
| 1529 pAssert(EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, bnS, context)); |
| 1530 pAssert(cmp_bn2hex(bnT, |
| 1531 "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A") |
| 1532 == 0); |
| 1533 pAssert(cmp_bn2hex(bnS, |
| 1534 "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857") |
| 1535 == 0); |
| 1536 #endif |
| 1537 |
| 1538 BnFrom2B(bnR, &rIn->b); |
| 1539 BnFrom2B(bnS, &sIn->b); |
| 1540 BnFrom2B(bnE, digest); |
| 1541 |
| 1542 #ifdef _SM2_SIGN_DEBUG |
| 1543 // Make sure that the input signature is the test signature |
| 1544 pAssert(cmp_2B2hex(&rIn->b, |
| 1545 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") == 0); |
| 1546 pAssert(cmp_2B2hex(&sIn->b, |
| 1547 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") == 0); |
| 1548 #endif |
| 1549 |
| 1550 // a) verify that r and s are in the inclusive interval 1 to (n 1) |
| 1551 fail = (BN_ucmp(bnR, &group->order) >= 0); |
| 1552 |
| 1553 fail = (BN_ucmp(bnS, &group->order) >= 0) || fail; |
| 1554 if(fail) |
| 1555 // There is no reason to continue. Since r and s are inputs from the caller, |
| 1556 // they can know that the values are not in the proper range. So, exiting here |
| 1557 // does not disclose any information. |
| 1558 goto Cleanup; |
| 1559 |
| 1560 // b) compute t := (r + s) mod n |
| 1561 if(!BN_mod_add(bnT, bnR, bnS, &group->order, context)) |
| 1562 FAIL(FATAL_ERROR_INTERNAL); |
| 1563 #ifdef _SM2_SIGN_DEBUG |
| 1564 pAssert(cmp_bn2hex(bnT, |
| 1565 "2B75F07ED7ECE7CCC1C8986B991F441AD324D6D619FE06DD63ED32E0C997C801") |
| 1566 == 0); |
| 1567 #endif |
| 1568 |
| 1569 // c) verify that t > 0 |
| 1570 if(BN_is_zero(bnT)) { |
| 1571 fail = TRUE; |
| 1572 // set to a value that should allow rest of the computations to run without |
| |
| Family "2.0" TCG Published Page 507 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1573 // trouble |
| 1574 BN_copy(bnT, bnS); |
| 1575 } |
| 1576 // d) compute (x, y) := [s]G + [t]Q |
| 1577 if(!EC_POINT_mul(group, pQ, bnS, pQ, bnT, context)) |
| 1578 FAIL(FATAL_ERROR_INTERNAL); |
| 1579 // Get the x coordinate of the point |
| 1580 if(!EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, NULL, context)) |
| 1581 FAIL(FATAL_ERROR_INTERNAL); |
| 1582 |
| 1583 #ifdef _SM2_SIGN_DEBUG |
| 1584 pAssert(cmp_bn2hex(bnT, |
| 1585 "110FCDA57615705D5E7B9324AC4B856D23E6D9188B2AE47759514657CE25D112") |
| 1586 == 0); |
| 1587 #endif |
| 1588 |
| 1589 // e) compute r' := (e + x) mod n (the x coordinate is in bnT) |
| 1590 if(!BN_mod_add(bnRp, bnE, bnT, &group->order, context)) |
| 1591 FAIL(FATAL_ERROR_INTERNAL); |
| 1592 |
| 1593 // f) verify that r' = r |
| 1594 fail = BN_ucmp(bnR, bnRp) != 0 || fail; |
| 1595 |
| 1596 Cleanup: |
| 1597 if(pQ) EC_POINT_free(pQ); |
| 1598 if(group) EC_GROUP_free(group); |
| 1599 BN_CTX_end(context); |
| 1600 BN_CTX_free(context); |
| 1601 |
| 1602 if(fail) |
| 1603 return CRYPT_FAIL; |
| 1604 else |
| 1605 return CRYPT_SUCCESS; |
| 1606 } |
| 1607 #endif //% TPM_ALG_SM2 |
| |
| |
| B.13.3.2.25. _cpri__ValidateSignatureEcc() |
| |
| This function validates |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS signature is valid |
| CRYPT_FAIL not a valid signature |
| CRYPT_SCHEME unsupported scheme |
| |
| 1608 LIB_EXPORT CRYPT_RESULT |
| 1609 _cpri__ValidateSignatureEcc( |
| 1610 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature |
| 1611 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature |
| 1612 TPM_ALG_ID scheme, // IN: the scheme selector |
| 1613 TPM_ALG_ID hashAlg, // IN: the hash algorithm used (not used |
| 1614 // in all schemes) |
| 1615 TPM_ECC_CURVE curveId, // IN: the curve used in the signature |
| 1616 // process |
| 1617 TPMS_ECC_POINT *Qin, // IN: the public point of the key |
| 1618 TPM2B *digest // IN: the digest that was signed |
| 1619 ) |
| 1620 { |
| 1621 CRYPT_RESULT retVal; |
| 1622 |
| 1623 // return failure if either part of the signature is zero |
| 1624 if(_math__Normalize2B(&rIn->b) == 0 || _math__Normalize2B(&sIn->b) == 0) |
| |
| Page 508 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1625 return CRYPT_FAIL; |
| 1626 |
| 1627 switch (scheme) |
| 1628 { |
| 1629 case TPM_ALG_ECDSA: |
| 1630 retVal = ValidateSignatureEcdsa(rIn, sIn, curveId, Qin, digest); |
| 1631 break; |
| 1632 |
| 1633 #ifdef TPM_ALG_ECSCHNORR |
| 1634 case TPM_ALG_ECSCHNORR: |
| 1635 retVal = ValidateSignatureEcSchnorr(rIn, sIn, hashAlg, curveId, Qin, |
| 1636 digest); |
| 1637 break; |
| 1638 #endif |
| 1639 |
| 1640 #ifdef TPM_ALG_SM2 |
| 1641 case TPM_ALG_SM2: |
| 1642 retVal = ValidateSignatureSM2Dsa(rIn, sIn, curveId, Qin, digest); |
| 1643 #endif |
| 1644 default: |
| 1645 retVal = CRYPT_SCHEME; |
| 1646 break; |
| 1647 } |
| 1648 return retVal; |
| 1649 } |
| 1650 #if CC_ZGen_2Phase == YES //% |
| 1651 #ifdef TPM_ALG_ECMQV |
| |
| |
| B.13.3.2.26. avf1() |
| |
| This function does the associated value computation required by MQV key exchange. Process: |
| a) Convert xQ to an integer xqi using the convention specified in Appendix C.3. |
| b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)). |
| c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2) |
| |
| 1652 static BOOL |
| 1653 avf1( |
| 1654 BIGNUM *bnX, // IN/OUT: the reduced value |
| 1655 BIGNUM *bnN // IN: the order of the curve |
| 1656 ) |
| 1657 { |
| 1658 // compute f = 2^(ceil(ceil(log2(n)) / 2)) |
| 1659 int f = (BN_num_bits(bnN) + 1) / 2; |
| 1660 // x' = 2^f + (x mod 2^f) |
| 1661 BN_mask_bits(bnX, f); // This is mod 2*2^f but it doesn't matter because |
| 1662 // the next operation will SET the extra bit anyway |
| 1663 BN_set_bit(bnX, f); |
| 1664 return TRUE; |
| 1665 } |
| |
| |
| B.13.3.2.27. C_2_2_MQV() |
| |
| This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC MQV). |
| CAUTION: Implementation of this function may require use of essential claims in patents not owned by |
| TCG members. |
| Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly |
| catastrophically, if this is not the case. |
| |
| |
| |
| Family "2.0" TCG Published Page 509 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS results is valid |
| CRYPT_NO_RESULT the value for dsA does not give a valid point on the curve |
| |
| 1666 static CRYPT_RESULT |
| 1667 C_2_2_MQV( |
| 1668 TPMS_ECC_POINT *outZ, // OUT: the computed point |
| 1669 TPM_ECC_CURVE curveId, // IN: the curve for the computations |
| 1670 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key |
| 1671 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key |
| 1672 TPMS_ECC_POINT *QsB, // IN: static public party B key |
| 1673 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key |
| 1674 ) |
| 1675 { |
| 1676 BN_CTX *context; |
| 1677 EC_POINT *pQeA = NULL; |
| 1678 EC_POINT *pQeB = NULL; |
| 1679 EC_POINT *pQsB = NULL; |
| 1680 EC_GROUP *group = NULL; |
| 1681 BIGNUM *bnTa; |
| 1682 BIGNUM *bnDeA; |
| 1683 BIGNUM *bnDsA; |
| 1684 BIGNUM *bnXeA; // x coordinate of ephemeral party A key |
| 1685 BIGNUM *bnH; |
| 1686 BIGNUM *bnN; |
| 1687 BIGNUM *bnXeB; |
| 1688 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1689 CRYPT_RESULT retVal; |
| 1690 |
| 1691 pAssert( curveData != NULL && outZ != NULL && dsA != NULL |
| 1692 && deA != NULL && QsB != NULL && QeB != NULL); |
| 1693 |
| 1694 context = BN_CTX_new(); |
| 1695 if(context == NULL || curveData == NULL) |
| 1696 FAIL(FATAL_ERROR_ALLOCATION); |
| 1697 BN_CTX_start(context); |
| 1698 bnTa = BN_CTX_get(context); |
| 1699 bnDeA = BN_CTX_get(context); |
| 1700 bnDsA = BN_CTX_get(context); |
| 1701 bnXeA = BN_CTX_get(context); |
| 1702 bnH = BN_CTX_get(context); |
| 1703 bnN = BN_CTX_get(context); |
| 1704 bnXeB = BN_CTX_get(context); |
| 1705 if(bnXeB == NULL) |
| 1706 FAIL(FATAL_ERROR_ALLOCATION); |
| 1707 |
| 1708 // Process: |
| 1709 // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. |
| 1710 // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). |
| 1711 // 3. If P = O, output an error indicator. |
| 1712 // 4. Z=xP, where xP is the x-coordinate of P. |
| 1713 |
| 1714 // Initialize group parameters and local values of input |
| 1715 if((group = EccCurveInit(curveId, context)) == NULL) |
| 1716 FAIL(FATAL_ERROR_INTERNAL); |
| 1717 |
| 1718 if((pQeA = EC_POINT_new(group)) == NULL) |
| 1719 FAIL(FATAL_ERROR_ALLOCATION); |
| 1720 |
| 1721 BnFrom2B(bnDeA, &deA->b); |
| 1722 BnFrom2B(bnDsA, &dsA->b); |
| 1723 BnFrom2B(bnH, curveData->h); |
| 1724 BnFrom2B(bnN, curveData->n); |
| |
| Page 510 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1725 BnFrom2B(bnXeB, &QeB->x.b); |
| 1726 pQeB = EccInitPoint2B(group, QeB, context); |
| 1727 pQsB = EccInitPoint2B(group, QsB, context); |
| 1728 |
| 1729 // Compute the public ephemeral key pQeA = [de,A]G |
| 1730 if( (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context)) |
| 1731 != CRYPT_SUCCESS) |
| 1732 goto Cleanup; |
| 1733 |
| 1734 if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1) |
| 1735 FAIL(FATAL_ERROR_INTERNAL); |
| 1736 |
| 1737 // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. |
| 1738 // tA := (ds,A + de,A avf(Xe,A)) mod n (3) |
| 1739 // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n |
| 1740 // Ta = avf(XeA); |
| 1741 BN_copy(bnTa, bnXeA); |
| 1742 avf1(bnTa, bnN); |
| 1743 if(// do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n |
| 1744 !BN_mod_mul(bnTa, bnDsA, bnTa, bnN, context) |
| 1745 |
| 1746 // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n |
| 1747 || !BN_mod_add(bnTa, bnDeA, bnTa, bnN, context) |
| 1748 ) |
| 1749 FAIL(FATAL_ERROR_INTERNAL); |
| 1750 |
| 1751 // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). |
| 1752 // Put this in because almost every case of h is == 1 so skip the call when |
| 1753 // not necessary. |
| 1754 if(!BN_is_one(bnH)) |
| 1755 { |
| 1756 // Cofactor is not 1 so compute Ta := Ta * h mod n |
| 1757 if(!BN_mul(bnTa, bnTa, bnH, context)) |
| 1758 FAIL(FATAL_ERROR_INTERNAL); |
| 1759 } |
| 1760 |
| 1761 // Now that 'tA' is (h * 'tA' mod n) |
| 1762 // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B). |
| 1763 |
| 1764 // first, compute XeB = avf(XeB) |
| 1765 avf1(bnXeB, bnN); |
| 1766 |
| 1767 // QsB := [XeB]QsB |
| 1768 if( !EC_POINT_mul(group, pQsB, NULL, pQsB, bnXeB, context) |
| 1769 |
| 1770 // QeB := QsB + QeB |
| 1771 || !EC_POINT_add(group, pQeB, pQeB, pQsB, context) |
| 1772 ) |
| 1773 FAIL(FATAL_ERROR_INTERNAL); |
| 1774 |
| 1775 // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity |
| 1776 if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS) |
| 1777 // Convert BIGNUM E to TPM2B E |
| 1778 Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context); |
| 1779 |
| 1780 Cleanup: |
| 1781 if(pQeA != NULL) EC_POINT_free(pQeA); |
| 1782 if(pQeB != NULL) EC_POINT_free(pQeB); |
| 1783 if(pQsB != NULL) EC_POINT_free(pQsB); |
| 1784 if(group != NULL) EC_GROUP_free(group); |
| 1785 BN_CTX_end(context); |
| 1786 BN_CTX_free(context); |
| 1787 |
| 1788 return retVal; |
| 1789 |
| 1790 } |
| |
| Family "2.0" TCG Published Page 511 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1791 #endif // TPM_ALG_ECMQV |
| 1792 #ifdef TPM_ALG_SM2 //% |
| |
| |
| B.13.3.2.28. avfSm2() |
| |
| This function does the associated value computation required by SM2 key exchange. This is different |
| form the avf() in the international standards because it returns a value that is half the size of the value |
| returned by the standard avf. For example, if n is 15, Ws (w in the standard) is 2 but the W here is 1. This |
| means that an input value of 14 (1110b) would return a value of 110b with the standard but 10b with the |
| scheme in SM2. |
| |
| 1793 static BOOL |
| 1794 avfSm2( |
| 1795 BIGNUM *bnX, // IN/OUT: the reduced value |
| 1796 BIGNUM *bnN // IN: the order of the curve |
| 1797 ) |
| 1798 { |
| 1799 // a) set w := ceil(ceil(log2(n)) / 2) - 1 |
| 1800 int w = ((BN_num_bits(bnN) + 1) / 2) - 1; |
| 1801 |
| 1802 // b) set x' := 2^w + ( x & (2^w - 1)) |
| 1803 // This is just like the avf for MQV where x' = 2^w + (x mod 2^w) |
| 1804 BN_mask_bits(bnX, w); // as wiht avf1, this is too big by a factor of 2 but |
| 1805 // it doesn't matter becasue we SET the extra bit anyway |
| 1806 BN_set_bit(bnX, w); |
| 1807 return TRUE; |
| 1808 } |
| |
| SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to compute |
| tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA + |
| [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral private |
| key. All points are required to be on the curve of inQsA. The function will fail catastrophically if this is not |
| the case |
| |
| Return Value Meaning |
| |
| CRYPT_SUCCESS results is valid |
| CRYPT_NO_RESULT the value for dsA does not give a valid point on the curve |
| |
| 1809 static CRYPT_RESULT |
| 1810 SM2KeyExchange( |
| 1811 TPMS_ECC_POINT *outZ, // OUT: the computed point |
| 1812 TPM_ECC_CURVE curveId, // IN: the curve for the computations |
| 1813 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key |
| 1814 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key |
| 1815 TPMS_ECC_POINT *QsB, // IN: static public party B key |
| 1816 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key |
| 1817 ) |
| 1818 { |
| 1819 BN_CTX *context; |
| 1820 EC_POINT *pQeA = NULL; |
| 1821 EC_POINT *pQeB = NULL; |
| 1822 EC_POINT *pQsB = NULL; |
| 1823 EC_GROUP *group = NULL; |
| 1824 BIGNUM *bnTa; |
| 1825 BIGNUM *bnDeA; |
| 1826 BIGNUM *bnDsA; |
| 1827 BIGNUM *bnXeA; // x coordinate of ephemeral party A key |
| 1828 BIGNUM *bnH; |
| 1829 BIGNUM *bnN; |
| 1830 BIGNUM *bnXeB; |
| |
| |
| Page 512 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1831 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1832 CRYPT_RESULT retVal; |
| 1833 |
| 1834 pAssert( curveData != NULL && outZ != NULL && dsA != NULL |
| 1835 && deA != NULL && QsB != NULL && QeB != NULL); |
| 1836 |
| 1837 context = BN_CTX_new(); |
| 1838 if(context == NULL || curveData == NULL) |
| 1839 FAIL(FATAL_ERROR_ALLOCATION); |
| 1840 BN_CTX_start(context); |
| 1841 bnTa = BN_CTX_get(context); |
| 1842 bnDeA = BN_CTX_get(context); |
| 1843 bnDsA = BN_CTX_get(context); |
| 1844 bnXeA = BN_CTX_get(context); |
| 1845 bnH = BN_CTX_get(context); |
| 1846 bnN = BN_CTX_get(context); |
| 1847 bnXeB = BN_CTX_get(context); |
| 1848 if(bnXeB == NULL) |
| 1849 FAIL(FATAL_ERROR_ALLOCATION); |
| 1850 |
| 1851 // Initialize group parameters and local values of input |
| 1852 if((group = EccCurveInit(curveId, context)) == NULL) |
| 1853 FAIL(FATAL_ERROR_INTERNAL); |
| 1854 |
| 1855 if((pQeA = EC_POINT_new(group)) == NULL) |
| 1856 FAIL(FATAL_ERROR_ALLOCATION); |
| 1857 |
| 1858 BnFrom2B(bnDeA, &deA->b); |
| 1859 BnFrom2B(bnDsA, &dsA->b); |
| 1860 BnFrom2B(bnH, curveData->h); |
| 1861 BnFrom2B(bnN, curveData->n); |
| 1862 BnFrom2B(bnXeB, &QeB->x.b); |
| 1863 pQeB = EccInitPoint2B(group, QeB, context); |
| 1864 pQsB = EccInitPoint2B(group, QsB, context); |
| 1865 |
| 1866 // Compute the public ephemeral key pQeA = [de,A]G |
| 1867 if( (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context)) |
| 1868 != CRYPT_SUCCESS) |
| 1869 goto Cleanup; |
| 1870 |
| 1871 if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1) |
| 1872 FAIL(FATAL_ERROR_INTERNAL); |
| 1873 |
| 1874 // tA := (ds,A + de,A avf(Xe,A)) mod n (3) |
| 1875 // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n |
| 1876 // Ta = avf(XeA); |
| 1877 BN_copy(bnTa, bnXeA); |
| 1878 avfSm2(bnTa, bnN); |
| 1879 if(// do Ta = de,A * Ta mod n = deA * avf(XeA) mod n |
| 1880 !BN_mod_mul(bnTa, bnDeA, bnTa, bnN, context) |
| 1881 |
| 1882 // now Ta = dsA + Ta mod n = dsA + deA * avf(XeA) mod n |
| 1883 || !BN_mod_add(bnTa, bnDsA, bnTa, bnN, context) |
| 1884 ) |
| 1885 FAIL(FATAL_ERROR_INTERNAL); |
| 1886 |
| 1887 // outZ ? [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4) |
| 1888 // Put this in because almost every case of h is == 1 so skip the call when |
| 1889 // not necessary. |
| 1890 if(!BN_is_one(bnH)) |
| 1891 { |
| 1892 // Cofactor is not 1 so compute Ta := Ta * h mod n |
| 1893 if(!BN_mul(bnTa, bnTa, bnH, context)) |
| 1894 FAIL(FATAL_ERROR_INTERNAL); |
| 1895 } |
| 1896 |
| |
| Family "2.0" TCG Published Page 513 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 1897 // Now that 'tA' is (h * 'tA' mod n) |
| 1898 // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)). |
| 1899 |
| 1900 // first, compute XeB = avf(XeB) |
| 1901 avfSm2(bnXeB, bnN); |
| 1902 |
| 1903 // QeB := [XeB]QeB |
| 1904 if( !EC_POINT_mul(group, pQeB, NULL, pQeB, bnXeB, context) |
| 1905 |
| 1906 // QeB := QsB + QeB |
| 1907 || !EC_POINT_add(group, pQeB, pQeB, pQsB, context) |
| 1908 ) |
| 1909 FAIL(FATAL_ERROR_INTERNAL); |
| 1910 |
| 1911 // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity |
| 1912 if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS) |
| 1913 // Convert BIGNUM E to TPM2B E |
| 1914 Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context); |
| 1915 |
| 1916 Cleanup: |
| 1917 if(pQeA != NULL) EC_POINT_free(pQeA); |
| 1918 if(pQeB != NULL) EC_POINT_free(pQeB); |
| 1919 if(pQsB != NULL) EC_POINT_free(pQsB); |
| 1920 if(group != NULL) EC_GROUP_free(group); |
| 1921 BN_CTX_end(context); |
| 1922 BN_CTX_free(context); |
| 1923 |
| 1924 return retVal; |
| 1925 |
| 1926 } |
| 1927 #endif //% TPM_ALG_SM2 |
| |
| |
| B.13.3.2.29. C_2_2_ECDH() |
| |
| This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified Model, |
| C(2, 2, ECC CDH). |
| |
| 1928 static CRYPT_RESULT |
| 1929 C_2_2_ECDH( |
| 1930 TPMS_ECC_POINT *outZ1, // OUT: Zs |
| 1931 TPMS_ECC_POINT *outZ2, // OUT: Ze |
| 1932 TPM_ECC_CURVE curveId, // IN: the curve for the computations |
| 1933 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key |
| 1934 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key |
| 1935 TPMS_ECC_POINT *QsB, // IN: static public party B key |
| 1936 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key |
| 1937 ) |
| 1938 { |
| 1939 BN_CTX *context; |
| 1940 EC_POINT *pQ = NULL; |
| 1941 EC_GROUP *group = NULL; |
| 1942 BIGNUM *bnD; |
| 1943 INT16 size; |
| 1944 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); |
| 1945 |
| 1946 context = BN_CTX_new(); |
| 1947 if(context == NULL || curveData == NULL) |
| 1948 FAIL(FATAL_ERROR_ALLOCATION); |
| 1949 BN_CTX_start(context); |
| 1950 if((bnD = BN_CTX_get(context)) == NULL) |
| 1951 FAIL(FATAL_ERROR_INTERNAL); |
| 1952 |
| 1953 // Initialize group parameters and local values of input |
| 1954 if((group = EccCurveInit(curveId, context)) == NULL) |
| |
| Page 514 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 1955 FAIL(FATAL_ERROR_INTERNAL); |
| 1956 size = (INT16)BN_num_bytes(&group->order); |
| 1957 |
| 1958 // Get the static private key of A |
| 1959 BnFrom2B(bnD, &dsA->b); |
| 1960 |
| 1961 // Initialize the static public point from B |
| 1962 pQ = EccInitPoint2B(group, QsB, context); |
| 1963 |
| 1964 // Do the point multiply for the Zs value |
| 1965 if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT) |
| 1966 // Convert the Zs value |
| 1967 Point2B(group, outZ1, pQ, size, context); |
| 1968 |
| 1969 // Get the ephemeral private key of A |
| 1970 BnFrom2B(bnD, &deA->b); |
| 1971 |
| 1972 // Initalize the ephemeral public point from B |
| 1973 PointFrom2B(group, pQ, QeB, context); |
| 1974 |
| 1975 // Do the point multiply for the Ze value |
| 1976 if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT) |
| 1977 // Convert the Ze value. |
| 1978 Point2B(group, outZ2, pQ, size, context); |
| 1979 |
| 1980 if(pQ != NULL) EC_POINT_free(pQ); |
| 1981 if(group != NULL) EC_GROUP_free(group); |
| 1982 BN_CTX_end(context); |
| 1983 BN_CTX_free(context); |
| 1984 return CRYPT_SUCCESS; |
| 1985 } |
| |
| |
| B.13.3.2.30. _cpri__C_2_2_KeyExchange() |
| |
| This function is the dispatch routine for the EC key exchange function that use two ephemeral and two |
| static keys. |
| |
| Return Value Meaning |
| |
| CRYPT_SCHEME scheme is not defined |
| |
| 1986 LIB_EXPORT CRYPT_RESULT |
| 1987 _cpri__C_2_2_KeyExchange( |
| 1988 TPMS_ECC_POINT *outZ1, // OUT: a computed point |
| 1989 TPMS_ECC_POINT *outZ2, // OUT: and optional second point |
| 1990 TPM_ECC_CURVE curveId, // IN: the curve for the computations |
| 1991 TPM_ALG_ID scheme, // IN: the key exchange scheme |
| 1992 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key |
| 1993 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key |
| 1994 TPMS_ECC_POINT *QsB, // IN: static public party B key |
| 1995 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key |
| 1996 ) |
| 1997 { |
| 1998 pAssert( outZ1 != NULL |
| 1999 && dsA != NULL && deA != NULL |
| 2000 && QsB != NULL && QeB != NULL); |
| 2001 |
| 2002 // Initalize the output points so that they are empty until one of the |
| 2003 // functions decides otherwise |
| 2004 outZ1->x.b.size = 0; |
| 2005 outZ1->y.b.size = 0; |
| 2006 if(outZ2 != NULL) |
| 2007 { |
| 2008 outZ2->x.b.size = 0; |
| |
| Family "2.0" TCG Published Page 515 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 2009 outZ2->y.b.size = 0; |
| 2010 } |
| 2011 |
| 2012 switch (scheme) |
| 2013 { |
| 2014 case TPM_ALG_ECDH: |
| 2015 return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB); |
| 2016 break; |
| 2017 #ifdef TPM_ALG_ECMQV |
| 2018 case TPM_ALG_ECMQV: |
| 2019 return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB); |
| 2020 break; |
| 2021 #endif |
| 2022 #ifdef TPM_ALG_SM2 |
| 2023 case TPM_ALG_SM2: |
| 2024 return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB); |
| 2025 break; |
| 2026 #endif |
| 2027 default: |
| 2028 return CRYPT_SCHEME; |
| 2029 } |
| 2030 } |
| 2031 #else //% |
| |
| Stub used when the 2-phase key exchange is not defined so that the linker has something to associate |
| with the value in the .def file. |
| |
| 2032 LIB_EXPORT CRYPT_RESULT |
| 2033 _cpri__C_2_2_KeyExchange( |
| 2034 void |
| 2035 ) |
| 2036 { |
| 2037 return CRYPT_FAIL; |
| 2038 } |
| 2039 #endif //% CC_ZGen_2Phase |
| 2040 #endif // TPM_ALG_ECC |
| |
| |
| |
| |
| Page 516 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Annex C |
| (informative) |
| Simulation Environment |
| |
| C.1 Introduction |
| |
| These files are used to simulate some of the implementation-dependent hardware of a TPM. These files |
| are provided to allow creation of a simulation environment for the TPM. These files are not expected to be |
| part of a hardware TPM implementation. |
| |
| C.2 Cancel.c |
| |
| C.2.1. Introduction |
| |
| This module simulates the cancel pins on the TPM. |
| |
| C.2.2. Includes, Typedefs, Structures, and Defines |
| |
| 1 #include "PlatformData.h" |
| |
| |
| C.2.3. Functions |
| |
| C.2.3.1. _plat__IsCanceled() |
| |
| Check if the cancel flag is set |
| |
| Return Value Meaning |
| |
| TRUE if cancel flag is set |
| FALSE if cancel flag is not set |
| |
| 2 LIB_EXPORT BOOL |
| 3 _plat__IsCanceled( |
| 4 void |
| 5 ) |
| 6 { |
| 7 // return cancel flag |
| 8 return s_isCanceled; |
| 9 } |
| |
| |
| C.2.3.2. _plat__SetCancel() |
| |
| Set cancel flag. |
| |
| 10 LIB_EXPORT void |
| 11 _plat__SetCancel( |
| 12 void |
| 13 ) |
| 14 { |
| 15 s_isCanceled = TRUE; |
| 16 return; |
| 17 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 517 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| C.2.3.3. _plat__ClearCancel() |
| |
| Clear cancel flag |
| |
| 18 LIB_EXPORT void |
| 19 _plat__ClearCancel( |
| 20 void |
| 21 ) |
| 22 { |
| 23 s_isCanceled = FALSE; |
| 24 return; |
| 25 } |
| |
| |
| |
| |
| Page 518 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.3 Clock.c |
| |
| C.3.1. Introduction |
| |
| This file contains the routines that are used by the simulator to mimic a hardware clock on a TPM. In this |
| implementation, all the time values are measured in millisecond. However, the precision of the clock |
| functions may be implementation dependent. |
| |
| C.3.2. Includes and Data Definitions |
| |
| 1 #include <time.h> |
| 2 #include "PlatformData.h" |
| 3 #include "Platform.h" |
| |
| |
| C.3.3. Functions |
| |
| C.3.3.1. _plat__ClockReset() |
| |
| Set the current clock time as initial time. This function is called at a power on event to reset the clock |
| |
| 4 LIB_EXPORT void |
| 5 _plat__ClockReset( |
| 6 void |
| 7 ) |
| 8 { |
| 9 // Implementation specific: Microsoft C set CLOCKS_PER_SEC to be 1/1000, |
| 10 // so here the measurement of clock() is in millisecond. |
| 11 s_initClock = clock(); |
| 12 s_adjustRate = CLOCK_NOMINAL; |
| 13 |
| 14 return; |
| 15 } |
| |
| |
| C.3.3.2. _plat__ClockTimeFromStart() |
| |
| Function returns the compensated time from the start of the command when |
| _plat__ClockTimeFromStart() was called. |
| |
| 16 unsigned long long |
| 17 _plat__ClockTimeFromStart( |
| 18 void |
| 19 ) |
| 20 { |
| 21 unsigned long long currentClock = clock(); |
| 22 return ((currentClock - s_initClock) * CLOCK_NOMINAL) / s_adjustRate; |
| 23 } |
| |
| |
| C.3.3.3. _plat__ClockTimeElapsed() |
| |
| Get the time elapsed from current to the last time the _plat__ClockTimeElapsed() is called. For the first |
| _plat__ClockTimeElapsed() call after a power on event, this call report the elapsed time from power on to |
| the current call |
| |
| 24 LIB_EXPORT unsigned long long |
| 25 _plat__ClockTimeElapsed( |
| 26 void |
| |
| |
| Family "2.0" TCG Published Page 519 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 27 ) |
| 28 { |
| 29 unsigned long long elapsed; |
| 30 unsigned long long currentClock = clock(); |
| 31 elapsed = ((currentClock - s_initClock) * CLOCK_NOMINAL) / s_adjustRate; |
| 32 s_initClock += (elapsed * s_adjustRate) / CLOCK_NOMINAL; |
| 33 |
| 34 #ifdef DEBUGGING_TIME |
| 35 // Put this in so that TPM time will pass much faster than real time when |
| 36 // doing debug. |
| 37 // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second |
| 38 // A good value might be 100 |
| 39 elapsed *= DEBUG_TIME_MULTIPLIER |
| 40 #endif |
| 41 return elapsed; |
| 42 } |
| |
| |
| C.3.3.4. _plat__ClockAdjustRate() |
| |
| Adjust the clock rate |
| |
| 43 LIB_EXPORT void |
| 44 _plat__ClockAdjustRate( |
| 45 int adjust // IN: the adjust number. It could be positive |
| 46 // or negative |
| 47 ) |
| 48 { |
| 49 // We expect the caller should only use a fixed set of constant values to |
| 50 // adjust the rate |
| 51 switch(adjust) |
| 52 { |
| 53 case CLOCK_ADJUST_COARSE: |
| 54 s_adjustRate += CLOCK_ADJUST_COARSE; |
| 55 break; |
| 56 case -CLOCK_ADJUST_COARSE: |
| 57 s_adjustRate -= CLOCK_ADJUST_COARSE; |
| 58 break; |
| 59 case CLOCK_ADJUST_MEDIUM: |
| 60 s_adjustRate += CLOCK_ADJUST_MEDIUM; |
| 61 break; |
| 62 case -CLOCK_ADJUST_MEDIUM: |
| 63 s_adjustRate -= CLOCK_ADJUST_MEDIUM; |
| 64 break; |
| 65 case CLOCK_ADJUST_FINE: |
| 66 s_adjustRate += CLOCK_ADJUST_FINE; |
| 67 break; |
| 68 case -CLOCK_ADJUST_FINE: |
| 69 s_adjustRate -= CLOCK_ADJUST_FINE; |
| 70 break; |
| 71 default: |
| 72 // ignore any other values; |
| 73 break; |
| 74 } |
| 75 |
| 76 if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) |
| 77 s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; |
| 78 if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) |
| 79 s_adjustRate = CLOCK_NOMINAL-CLOCK_ADJUST_LIMIT; |
| 80 |
| 81 return; |
| 82 } |
| |
| |
| |
| |
| Page 520 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.4 Entropy.c |
| |
| C.4.1. Includes |
| |
| 1 #define _CRT_RAND_S |
| 2 #include <stdlib.h> |
| 3 #include <stdint.h> |
| 4 #include <memory.h> |
| 5 #include "TpmBuildSwitches.h" |
| |
| |
| C.4.2. Local values |
| |
| This is the last 32-bits of hardware entropy produced. We have to check to see that two consecutive 32- |
| bit values are not the same because (according to FIPS 140-2, annex C |
| “If each call to a RNG produces blocks of n bits (where n > 15), the first n-bit block generated after |
| power-up, initialization, or reset shall not be used, but shall be saved for comparison with the next n- |
| bit block to be generated. Each subsequent generation of an n-bit block shall be compared with the |
| previously generated block. The test shall fail if any two compared n-bit blocks are equal.” |
| |
| 6 extern uint32_t lastEntropy; |
| 7 extern int firstValue; |
| |
| |
| C.4.3. _plat__GetEntropy() |
| |
| This function is used to get available hardware entropy. In a hardware implementation of this function, |
| there would be no call to the system to get entropy. If the caller does not ask for any entropy, then this is |
| a startup indication and firstValue should be reset. |
| |
| Return Value Meaning |
| |
| <0 hardware failure of the entropy generator, this is sticky |
| >= 0 the returned amount of entropy (bytes) |
| |
| 8 LIB_EXPORT int32_t |
| 9 _plat__GetEntropy( |
| 10 unsigned char *entropy, // output buffer |
| 11 uint32_t amount // amount requested |
| 12 ) |
| 13 { |
| 14 uint32_t rndNum; |
| 15 int OK = 1; |
| 16 |
| 17 if(amount == 0) |
| 18 { |
| 19 firstValue = 1; |
| 20 return 0; |
| 21 } |
| 22 |
| 23 // Only provide entropy 32 bits at a time to test the ability |
| 24 // of the caller to deal with partial results. |
| 25 OK = rand_s(&rndNum) == 0; |
| 26 if(OK) |
| 27 { |
| 28 if(firstValue) |
| 29 firstValue = 0; |
| 30 else |
| 31 OK = (rndNum != lastEntropy); |
| 32 } |
| |
| |
| Family "2.0" TCG Published Page 521 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 33 if(OK) |
| 34 { |
| 35 lastEntropy = rndNum; |
| 36 if(amount > sizeof(rndNum)) |
| 37 amount = sizeof(rndNum); |
| 38 memcpy(entropy, &rndNum, amount); |
| 39 } |
| 40 return (OK) ? (int32_t)amount : -1; |
| 41 } |
| |
| |
| |
| |
| Page 522 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.5 LocalityPlat.c |
| |
| C.5.1. Includes |
| |
| 1 #include "PlatformData.h" |
| 2 #include "TpmError.h" |
| |
| |
| C.5.2. Functions |
| |
| C.5.2.1. _plat__LocalityGet() |
| |
| Get the most recent command locality in locality value form. This is an integer value for locality and not a |
| locality structure The locality can be 0-4 or 32-255. 5-31 is not allowed. |
| |
| 3 LIB_EXPORT unsigned char |
| 4 _plat__LocalityGet( |
| 5 void |
| 6 ) |
| 7 { |
| 8 return s_locality; |
| 9 } |
| |
| |
| C.5.2.2. _plat__LocalitySet() |
| |
| Set the most recent command locality in locality value form |
| |
| 10 LIB_EXPORT void |
| 11 _plat__LocalitySet( |
| 12 unsigned char locality |
| 13 ) |
| 14 { |
| 15 if(locality > 4 && locality < 32) |
| 16 locality = 0; |
| 17 s_locality = locality; |
| 18 return; |
| 19 } |
| |
| |
| C.5.2.3. _plat__IsRsaKeyCacheEnabled() |
| |
| This function is used to check if the RSA key cache is enabled or not. |
| |
| 20 LIB_EXPORT int |
| 21 _plat__IsRsaKeyCacheEnabled( |
| 22 void |
| 23 ) |
| 24 { |
| 25 return s_RsaKeyCacheEnabled; |
| 26 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 523 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| C.6 NVMem.c |
| |
| C.6.1. Introduction |
| |
| This file contains the NV read and write access methods. This implementation uses RAM/file and does |
| not manage the RAM/file as NV blocks. The implementation may become more sophisticated over time. |
| |
| C.6.2. Includes |
| |
| 1 #include <memory.h> |
| 2 #include <string.h> |
| 3 #include "PlatformData.h" |
| 4 #include "TpmError.h" |
| 5 #include "assert.h" |
| |
| |
| C.6.3. Functions |
| |
| C.6.3.1. _plat__NvErrors() |
| |
| This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the |
| NV loading process |
| |
| 6 LIB_EXPORT void |
| 7 _plat__NvErrors( |
| 8 BOOL recoverable, |
| 9 BOOL unrecoverable |
| 10 ) |
| 11 { |
| 12 s_NV_unrecoverable = unrecoverable; |
| 13 s_NV_recoverable = recoverable; |
| 14 } |
| |
| |
| C.6.3.2. _plat__NVEnable() |
| |
| Enable NV memory. |
| This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the |
| integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV |
| state would be read in, decrypted and integrity checked. |
| The recovery from an integrity failure depends on where the error occurred. It it was in the state that is |
| discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go |
| into failure mode. |
| |
| Return Value Meaning |
| |
| 0 if success |
| >0 if receive recoverable error |
| <0 if unrecoverable error |
| |
| 15 LIB_EXPORT int |
| 16 _plat__NVEnable( |
| 17 void *platParameter // IN: platform specific parameter |
| 18 ) |
| 19 { |
| 20 (platParameter); // to keep compiler quiet |
| 21 // Start assuming everything is OK |
| |
| Page 524 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 22 s_NV_unrecoverable = FALSE; |
| 23 s_NV_recoverable = FALSE; |
| 24 |
| 25 #ifdef FILE_BACKED_NV |
| 26 |
| 27 if(s_NVFile != NULL) return 0; |
| 28 |
| 29 // Try to open an exist NVChip file for read/write |
| 30 if(0 != fopen_s(&s_NVFile, "NVChip", "r+b")) |
| 31 s_NVFile = NULL; |
| 32 |
| 33 if(NULL != s_NVFile) |
| 34 { |
| 35 // See if the NVChip file is empty |
| 36 fseek(s_NVFile, 0, SEEK_END); |
| 37 if(0 == ftell(s_NVFile)) |
| 38 s_NVFile = NULL; |
| 39 } |
| 40 |
| 41 if(s_NVFile == NULL) |
| 42 { |
| 43 // Initialize all the byte in the new file to 0 |
| 44 memset(s_NV, 0, NV_MEMORY_SIZE); |
| 45 |
| 46 // If NVChip file does not exist, try to create it for read/write |
| 47 fopen_s(&s_NVFile, "NVChip", "w+b"); |
| 48 // Start initialize at the end of new file |
| 49 fseek(s_NVFile, 0, SEEK_END); |
| 50 // Write 0s to NVChip file |
| 51 fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile); |
| 52 } |
| 53 else |
| 54 { |
| 55 // If NVChip file exist, assume the size is correct |
| 56 fseek(s_NVFile, 0, SEEK_END); |
| 57 assert(ftell(s_NVFile) == NV_MEMORY_SIZE); |
| 58 // read NV file data to memory |
| 59 fseek(s_NVFile, 0, SEEK_SET); |
| 60 fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile); |
| 61 } |
| 62 #endif |
| 63 // NV contents have been read and the error checks have been performed. For |
| 64 // simulation purposes, use the signaling interface to indicate if an error is |
| 65 // to be simulated and the type of the error. |
| 66 if(s_NV_unrecoverable) |
| 67 return -1; |
| 68 return s_NV_recoverable; |
| 69 } |
| |
| |
| C.6.3.3. _plat__NVDisable() |
| |
| Disable NV memory |
| |
| 70 LIB_EXPORT void |
| 71 _plat__NVDisable( |
| 72 void |
| 73 ) |
| 74 { |
| 75 #ifdef FILE_BACKED_NV |
| 76 |
| 77 assert(s_NVFile != NULL); |
| 78 // Close NV file |
| 79 fclose(s_NVFile); |
| 80 // Set file handle to NULL |
| |
| |
| Family "2.0" TCG Published Page 525 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 81 s_NVFile = NULL; |
| 82 |
| 83 #endif |
| 84 |
| 85 return; |
| 86 } |
| |
| |
| C.6.3.4. _plat__IsNvAvailable() |
| |
| Check if NV is available |
| |
| Return Value Meaning |
| |
| 0 NV is available |
| 1 NV is not available due to write failure |
| 2 NV is not available due to rate limit |
| |
| 87 LIB_EXPORT int |
| 88 _plat__IsNvAvailable( |
| 89 void |
| 90 ) |
| 91 { |
| 92 // NV is not available if the TPM is in failure mode |
| 93 if(!s_NvIsAvailable) |
| 94 return 1; |
| 95 |
| 96 #ifdef FILE_BACKED_NV |
| 97 if(s_NVFile == NULL) |
| 98 return 1; |
| 99 #endif |
| 100 |
| 101 return 0; |
| 102 |
| 103 } |
| |
| |
| C.6.3.5. _plat__NvMemoryRead() |
| |
| Function: Read a chunk of NV memory |
| |
| 104 LIB_EXPORT void |
| 105 _plat__NvMemoryRead( |
| 106 unsigned int startOffset, // IN: read start |
| 107 unsigned int size, // IN: size of bytes to read |
| 108 void *data // OUT: data buffer |
| 109 ) |
| 110 { |
| 111 assert(startOffset + size <= NV_MEMORY_SIZE); |
| 112 |
| 113 // Copy data from RAM |
| 114 memcpy(data, &s_NV[startOffset], size); |
| 115 return; |
| 116 } |
| |
| |
| C.6.3.6. _plat__NvIsDifferent() |
| |
| This function checks to see if the NV is different from the test value. This is so that NV will not be written if |
| it has not changed. |
| |
| |
| |
| |
| Page 526 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| Return Value Meaning |
| |
| TRUE the NV location is different from the test value |
| FALSE the NV location is the same as the test value |
| |
| 117 LIB_EXPORT BOOL |
| 118 _plat__NvIsDifferent( |
| 119 unsigned int startOffset, // IN: read start |
| 120 unsigned int size, // IN: size of bytes to read |
| 121 void *data // IN: data buffer |
| 122 ) |
| 123 { |
| 124 return (memcmp(&s_NV[startOffset], data, size) != 0); |
| 125 } |
| |
| |
| C.6.3.7. _plat__NvMemoryWrite() |
| |
| This function is used to update NV memory. The write is to a memory copy of NV. At the end of the |
| current command, any changes are written to the actual NV memory. |
| |
| 126 LIB_EXPORT void |
| 127 _plat__NvMemoryWrite( |
| 128 unsigned int startOffset, // IN: write start |
| 129 unsigned int size, // IN: size of bytes to write |
| 130 void *data // OUT: data buffer |
| 131 ) |
| 132 { |
| 133 assert(startOffset + size <= NV_MEMORY_SIZE); |
| 134 |
| 135 // Copy the data to the NV image |
| 136 memcpy(&s_NV[startOffset], data, size); |
| 137 } |
| |
| |
| C.6.3.8. _plat__NvMemoryMove() |
| |
| Function: Move a chunk of NV memory from source to destination This function should ensure that if |
| there overlap, the original data is copied before it is written |
| |
| 138 LIB_EXPORT void |
| 139 _plat__NvMemoryMove( |
| 140 unsigned int sourceOffset, // IN: source offset |
| 141 unsigned int destOffset, // IN: destination offset |
| 142 unsigned int size // IN: size of data being moved |
| 143 ) |
| 144 { |
| 145 assert(sourceOffset + size <= NV_MEMORY_SIZE); |
| 146 assert(destOffset + size <= NV_MEMORY_SIZE); |
| 147 |
| 148 // Move data in RAM |
| 149 memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); |
| 150 |
| 151 return; |
| 152 } |
| |
| |
| C.6.3.9. _plat__NvCommit() |
| |
| Update NV chip |
| |
| |
| |
| Family "2.0" TCG Published Page 527 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| 0 NV write success |
| non-0 NV write fail |
| |
| 153 LIB_EXPORT int |
| 154 _plat__NvCommit( |
| 155 void |
| 156 ) |
| 157 { |
| 158 #ifdef FILE_BACKED_NV |
| 159 // If NV file is not available, return failure |
| 160 if(s_NVFile == NULL) |
| 161 return 1; |
| 162 |
| 163 // Write RAM data to NV |
| 164 fseek(s_NVFile, 0, SEEK_SET); |
| 165 fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile); |
| 166 return 0; |
| 167 #else |
| 168 return 0; |
| 169 #endif |
| 170 |
| 171 } |
| |
| |
| C.6.3.10. _plat__SetNvAvail() |
| |
| Set the current NV state to available. This function is for testing purpose only. It is not part of the |
| platform NV logic |
| |
| 172 LIB_EXPORT void |
| 173 _plat__SetNvAvail( |
| 174 void |
| 175 ) |
| 176 { |
| 177 s_NvIsAvailable = TRUE; |
| 178 return; |
| 179 } |
| |
| |
| C.6.3.11. _plat__ClearNvAvail() |
| |
| Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the |
| platform NV logic |
| |
| 180 LIB_EXPORT void |
| 181 _plat__ClearNvAvail( |
| 182 void |
| 183 ) |
| 184 { |
| 185 s_NvIsAvailable = FALSE; |
| 186 return; |
| 187 } |
| |
| |
| |
| |
| Page 528 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.7 PowerPlat.c |
| |
| C.7.1. Includes and Function Prototypes |
| |
| 1 #include "PlatformData.h" |
| 2 #include "Platform.h" |
| |
| |
| C.7.2. Functions |
| |
| C.7.2.1. _plat__Signal_PowerOn() |
| |
| Signal platform power on |
| |
| 3 LIB_EXPORT int |
| 4 _plat__Signal_PowerOn( |
| 5 void |
| 6 ) |
| 7 { |
| 8 // Start clock |
| 9 _plat__ClockReset(); |
| 10 |
| 11 // Initialize locality |
| 12 s_locality = 0; |
| 13 |
| 14 // Command cancel |
| 15 s_isCanceled = FALSE; |
| 16 |
| 17 // Need to indicate that we lost power |
| 18 s_powerLost = TRUE; |
| 19 |
| 20 return 0; |
| 21 } |
| |
| |
| C.7.2.2. _plat__WasPowerLost() |
| |
| Test whether power was lost before a _TPM_Init() |
| |
| 22 LIB_EXPORT BOOL |
| 23 _plat__WasPowerLost( |
| 24 BOOL clear |
| 25 ) |
| 26 { |
| 27 BOOL retVal = s_powerLost; |
| 28 if(clear) |
| 29 s_powerLost = FALSE; |
| 30 return retVal; |
| 31 } |
| |
| |
| C.7.2.3. _plat_Signal_Reset() |
| |
| This a TPM reset without a power loss. |
| |
| 32 LIB_EXPORT int |
| 33 _plat__Signal_Reset( |
| 34 void |
| 35 ) |
| 36 { |
| 37 // Need to reset the clock |
| 38 _plat__ClockReset(); |
| |
| Family "2.0" TCG Published Page 529 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 39 |
| 40 // if we are doing reset but did not have a power failure, then we should |
| 41 // not need to reload NV ... |
| 42 return 0; |
| 43 } |
| |
| |
| C.7.2.4. _plat__Signal_PowerOff() |
| |
| Signal platform power off |
| |
| 44 LIB_EXPORT void |
| 45 _plat__Signal_PowerOff( |
| 46 void |
| 47 ) |
| 48 { |
| 49 // Prepare NV memory for power off |
| 50 _plat__NVDisable(); |
| 51 |
| 52 return; |
| 53 } |
| |
| |
| |
| |
| Page 530 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.8 Platform.h |
| |
| 1 #ifndef PLATFORM_H |
| 2 #define PLATFORM_H |
| |
| |
| C.8.1. Includes and Defines |
| |
| 3 #include "bool.h" |
| 4 #include "stdint.h" |
| 5 #include "TpmError.h" |
| 6 #include "TpmBuildSwitches.h" |
| 7 #define UNREFERENCED(a) ((void)(a)) |
| |
| |
| C.8.2. Power Functions |
| |
| C.8.2.1. _plat__Signal_PowerOn |
| |
| Signal power on This signal is simulate by a RPC call |
| |
| 8 LIB_EXPORT int |
| 9 _plat__Signal_PowerOn(void); |
| |
| |
| C.8.2.2. _plat__Signal_Reset |
| |
| Signal reset This signal is simulate by a RPC call |
| |
| 10 LIB_EXPORT int |
| 11 _plat__Signal_Reset(void); |
| |
| |
| C.8.2.3. _plat__WasPowerLost() |
| |
| Indicates if the power was lost before a _TPM__Init(). |
| |
| 12 LIB_EXPORT BOOL |
| 13 _plat__WasPowerLost(BOOL clear); |
| |
| |
| C.8.2.4. _plat__Signal_PowerOff() |
| |
| Signal power off This signal is simulate by a RPC call |
| |
| 14 LIB_EXPORT void |
| 15 _plat__Signal_PowerOff(void); |
| |
| |
| C.8.3. Physical Presence Functions |
| |
| C.8.3.1. _plat__PhysicalPresenceAsserted() |
| |
| Check if physical presence is signaled |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 531 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| TRUE if physical presence is signaled |
| FALSE if physical presence is not signaled |
| |
| 16 LIB_EXPORT BOOL |
| 17 _plat__PhysicalPresenceAsserted(void); |
| |
| |
| C.8.3.2. _plat__Signal_PhysicalPresenceOn |
| |
| Signal physical presence on This signal is simulate by a RPC call |
| |
| 18 LIB_EXPORT void |
| 19 _plat__Signal_PhysicalPresenceOn(void); |
| |
| |
| C.8.3.3. _plat__Signal_PhysicalPresenceOff() |
| |
| Signal physical presence off This signal is simulate by a RPC call |
| |
| 20 LIB_EXPORT void |
| 21 _plat__Signal_PhysicalPresenceOff(void); |
| |
| |
| C.8.4. Command Canceling Functions |
| |
| C.8.4.1. _plat__IsCanceled() |
| |
| Check if the cancel flag is set |
| |
| Return Value Meaning |
| |
| TRUE if cancel flag is set |
| FALSE if cancel flag is not set |
| |
| 22 LIB_EXPORT BOOL |
| 23 _plat__IsCanceled(void); |
| |
| |
| C.8.4.2. _plat__SetCancel() |
| |
| Set cancel flag. |
| |
| 24 LIB_EXPORT void |
| 25 _plat__SetCancel(void); |
| |
| |
| C.8.4.3. _plat__ClearCancel() |
| |
| Clear cancel flag |
| |
| 26 LIB_EXPORT void |
| 27 _plat__ClearCancel( void); |
| |
| |
| |
| |
| Page 532 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| C.8.5. NV memory functions |
| |
| C.8.5.1. _plat__NvErrors() |
| |
| This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the |
| NV loading process |
| |
| 28 LIB_EXPORT void |
| 29 _plat__NvErrors( |
| 30 BOOL recoverable, |
| 31 BOOL unrecoverable |
| 32 ); |
| |
| |
| C.8.5.2. _plat__NVEnable() |
| |
| Enable platform NV memory NV memory is automatically enabled at power on event. This function is |
| mostly for TPM_Manufacture() to access NV memory without a power on event |
| |
| Return Value Meaning |
| |
| 0 if success |
| non-0 if fail |
| |
| 33 LIB_EXPORT int |
| 34 _plat__NVEnable( |
| 35 void *platParameter // IN: platform specific parameters |
| 36 ); |
| |
| |
| C.8.5.3. _plat__NVDisable() |
| |
| Disable platform NV memory NV memory is automatically disabled at power off event. This function is |
| mostly for TPM_Manufacture() to disable NV memory without a power off event |
| |
| 37 LIB_EXPORT void |
| 38 _plat__NVDisable(void); |
| |
| |
| C.8.5.4. _plat__IsNvAvailable() |
| |
| Check if NV is available |
| |
| Return Value Meaning |
| |
| 0 NV is available |
| 1 NV is not available due to write failure |
| 2 NV is not available due to rate limit |
| |
| 39 LIB_EXPORT int |
| 40 _plat__IsNvAvailable(void); |
| |
| |
| C.8.5.5. _plat__NvCommit() |
| |
| Update NV chip |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 533 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Return Value Meaning |
| |
| 0 NV write success |
| non-0 NV write fail |
| |
| 41 LIB_EXPORT int |
| 42 _plat__NvCommit(void); |
| |
| |
| C.8.5.6. _plat__NvMemoryRead() |
| |
| Read a chunk of NV memory |
| |
| 43 LIB_EXPORT void |
| 44 _plat__NvMemoryRead( |
| 45 unsigned int startOffset, // IN: read start |
| 46 unsigned int size, // IN: size of bytes to read |
| 47 void *data // OUT: data buffer |
| 48 ); |
| |
| |
| C.8.5.7. _plat__NvIsDifferent() |
| |
| This function checks to see if the NV is different from the test value. This is so that NV will not be written if |
| it has not changed. |
| |
| Return Value Meaning |
| |
| TRUE the NV location is different from the test value |
| FALSE the NV location is the same as the test value |
| |
| 49 LIB_EXPORT BOOL |
| 50 _plat__NvIsDifferent( |
| 51 unsigned int startOffset, // IN: read start |
| 52 unsigned int size, // IN: size of bytes to compare |
| 53 void *data // IN: data buffer |
| 54 ); |
| |
| |
| C.8.5.8. _plat__NvMemoryWrite() |
| |
| Write a chunk of NV memory |
| |
| 55 LIB_EXPORT void |
| 56 _plat__NvMemoryWrite( |
| 57 unsigned int startOffset, // IN: read start |
| 58 unsigned int size, // IN: size of bytes to read |
| 59 void *data // OUT: data buffer |
| 60 ); |
| |
| |
| C.8.5.9. _plat__NvMemoryMove() |
| |
| Move a chunk of NV memory from source to destination This function should ensure that if there overlap, |
| the original data is copied before it is written |
| |
| 61 LIB_EXPORT void |
| 62 _plat__NvMemoryMove( |
| 63 unsigned int sourceOffset, // IN: source offset |
| 64 unsigned int destOffset, // IN: destination offset |
| 65 unsigned int size // IN: size of data being moved |
| |
| Page 534 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 66 ); |
| |
| |
| C.8.5.10. _plat__SetNvAvail() |
| |
| Set the current NV state to available. This function is for testing purposes only. It is not part of the |
| platform NV logic |
| |
| 67 LIB_EXPORT void |
| 68 _plat__SetNvAvail(void); |
| |
| |
| C.8.5.11. _plat__ClearNvAvail() |
| |
| Set the current NV state to unavailable. This function is for testing purposes only. It is not part of the |
| platform NV logic |
| |
| 69 LIB_EXPORT void |
| 70 _plat__ClearNvAvail(void); |
| |
| |
| C.8.6. Locality Functions |
| |
| C.8.6.1. _plat__LocalityGet() |
| |
| Get the most recent command locality in locality value form |
| |
| 71 LIB_EXPORT unsigned char |
| 72 _plat__LocalityGet(void); |
| |
| |
| C.8.6.2. _plat__LocalitySet() |
| |
| Set the most recent command locality in locality value form |
| |
| 73 LIB_EXPORT void |
| 74 _plat__LocalitySet( |
| 75 unsigned char locality |
| 76 ); |
| |
| |
| C.8.6.3. _plat__IsRsaKeyCacheEnabled() |
| |
| This function is used to check if the RSA key cache is enabled or not. |
| |
| 77 LIB_EXPORT int |
| 78 _plat__IsRsaKeyCacheEnabled( |
| 79 void |
| 80 ); |
| |
| |
| C.8.7. Clock Constants and Functions |
| |
| Assume that the nominal divisor is 30000 |
| |
| 81 #define CLOCK_NOMINAL 30000 |
| |
| A 1% change in rate is 300 counts |
| |
| 82 #define CLOCK_ADJUST_COARSE 300 |
| |
| |
| Family "2.0" TCG Published Page 535 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| A .1 change in rate is 30 counts |
| |
| 83 #define CLOCK_ADJUST_MEDIUM 30 |
| |
| A minimum change in rate is 1 count |
| |
| 84 #define CLOCK_ADJUST_FINE 1 |
| |
| The clock tolerance is +/-15% (4500 counts) Allow some guard band (16.7%) |
| |
| 85 #define CLOCK_ADJUST_LIMIT 5000 |
| |
| |
| C.8.7.1. _plat__ClockReset() |
| |
| This function sets the current clock time as initial time. This function is called at a power on event to reset |
| the clock |
| |
| 86 LIB_EXPORT void |
| 87 _plat__ClockReset(void); |
| |
| |
| C.8.7.2. _plat__ClockTimeFromStart() |
| |
| Function returns the compensated time from the start of the command when |
| _plat__ClockTimeFromStart() was called. |
| |
| 88 LIB_EXPORT unsigned long long |
| 89 _plat__ClockTimeFromStart( |
| 90 void |
| 91 ); |
| |
| |
| C.8.7.3. _plat__ClockTimeElapsed() |
| |
| Get the time elapsed from current to the last time the _plat__ClockTimeElapsed() is called. For the first |
| _plat__ClockTimeElapsed() call after a power on event, this call report the elapsed time from power on to |
| the current call |
| |
| 92 LIB_EXPORT unsigned long long |
| 93 _plat__ClockTimeElapsed(void); |
| |
| |
| C.8.7.4. _plat__ClockAdjustRate() |
| |
| Adjust the clock rate |
| |
| 94 LIB_EXPORT void |
| 95 _plat__ClockAdjustRate( |
| 96 int adjust // IN: the adjust number. It could be |
| 97 // positive or negative |
| 98 ); |
| |
| |
| |
| |
| Page 536 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| C.8.8. Single Function Files |
| |
| C.8.8.1. _plat__GetEntropy() |
| |
| This function is used to get available hardware entropy. In a hardware implementation of this function, |
| there would be no call to the system to get entropy. If the caller does not ask for any entropy, then this is |
| a startup indication and firstValue should be reset. |
| |
| Return Value Meaning |
| |
| <0 hardware failure of the entropy generator, this is sticky |
| >= 0 the returned amount of entropy (bytes) |
| |
| 99 LIB_EXPORT int32_t |
| 100 _plat__GetEntropy( |
| 101 unsigned char *entropy, // output buffer |
| 102 uint32_t amount // amount requested |
| 103 ); |
| 104 #endif |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 537 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| C.9 PlatformData.h |
| |
| This file contains the instance data for the Platform module. It is collected in this file so that the state of |
| the module is easier to manage. |
| |
| 1 #ifndef _PLATFORM_DATA_H_ |
| 2 #define _PLATFORM_DATA_H_ |
| 3 #include "TpmBuildSwitches.h" |
| 4 #include "Implementation.h" |
| 5 #include "bool.h" |
| |
| From Cancel.c Cancel flag. It is initialized as FALSE, which indicate the command is not being canceled |
| |
| 6 extern BOOL s_isCanceled; |
| |
| From Clock.c This variable records the time when _plat__ClockReset() is called. This mechanism allow |
| us to subtract the time when TPM is power off from the total time reported by clock() function |
| |
| 7 extern unsigned long long s_initClock; |
| 8 extern unsigned int s_adjustRate; |
| |
| From LocalityPlat.c Locality of current command |
| |
| 9 extern unsigned char s_locality; |
| |
| From NVMem.c Choose if the NV memory should be backed by RAM or by file. If this macro is defined, |
| then a file is used as NV. If it is not defined, then RAM is used to back NV memory. Comment out to use |
| RAM. |
| |
| 10 #define FILE_BACKED_NV |
| 11 #if defined FILE_BACKED_NV |
| 12 #include <stdio.h> |
| |
| A file to emulate NV storage |
| |
| 13 extern FILE* s_NVFile; |
| 14 #endif |
| 15 extern unsigned char s_NV[NV_MEMORY_SIZE]; |
| 16 extern BOOL s_NvIsAvailable; |
| 17 extern BOOL s_NV_unrecoverable; |
| 18 extern BOOL s_NV_recoverable; |
| |
| From PPPlat.c Physical presence. It is initialized to FALSE |
| |
| 19 extern BOOL s_physicalPresence; |
| |
| From Power |
| |
| 20 extern BOOL s_powerLost; |
| |
| From Entropy.c |
| |
| 21 extern uint32_t lastEntropy; |
| 22 extern int firstValue; |
| 23 #endif // _PLATFORM_DATA_H_ |
| |
| |
| |
| |
| Page 538 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.10 PlatformData.c |
| |
| C.10.1. Description |
| |
| This file will instance the TPM variables that are not stack allocated. The descriptions for these variables |
| is in Global.h for this project. |
| |
| C.10.2. Includes |
| |
| This include is required to set the NV memory size consistently across all parts of the implementation. |
| |
| 1 #include "Implementation.h" |
| 2 #include "Platform.h" |
| 3 #include "PlatformData.h" |
| |
| From Cancel.c |
| |
| 4 BOOL s_isCanceled; |
| |
| From Clock.c |
| |
| 5 unsigned long long s_initClock; |
| 6 unsigned int s_adjustRate; |
| |
| From LocalityPlat.c |
| |
| 7 unsigned char s_locality; |
| |
| From Power.c |
| |
| 8 BOOL s_powerLost; |
| |
| From Entropy.c |
| |
| 9 uint32_t lastEntropy; |
| 10 int firstValue; |
| |
| From NVMem.c |
| |
| 11 #ifdef VTPM |
| 12 # undef FILE_BACKED_NV |
| 13 #endif |
| 14 #ifdef FILE_BACKED_NV |
| 15 FILE *s_NVFile = NULL; |
| 16 #endif |
| 17 unsigned char s_NV[NV_MEMORY_SIZE]; |
| 18 BOOL s_NvIsAvailable; |
| 19 BOOL s_NV_unrecoverable; |
| 20 BOOL s_NV_recoverable; |
| |
| From PPPlat.c |
| |
| 21 BOOL s_physicalPresence; |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 539 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| C.11 PPPlat.c |
| |
| C.11.1. Description |
| |
| This module simulates the physical present interface pins on the TPM. |
| |
| C.11.2. Includes |
| |
| 1 #include "PlatformData.h" |
| |
| |
| C.11.3. Functions |
| |
| C.11.3.1. _plat__PhysicalPresenceAsserted() |
| |
| Check if physical presence is signaled |
| |
| Return Value Meaning |
| |
| TRUE if physical presence is signaled |
| FALSE if physical presence is not signaled |
| |
| 2 LIB_EXPORT BOOL |
| 3 _plat__PhysicalPresenceAsserted( |
| 4 void |
| 5 ) |
| 6 { |
| 7 // Do not know how to check physical presence without real hardware. |
| 8 // so always return TRUE; |
| 9 return s_physicalPresence; |
| 10 } |
| |
| |
| C.11.3.2. _plat__Signal_PhysicalPresenceOn() |
| |
| Signal physical presence on |
| |
| 11 LIB_EXPORT void |
| 12 _plat__Signal_PhysicalPresenceOn( |
| 13 void |
| 14 ) |
| 15 { |
| 16 s_physicalPresence = TRUE; |
| 17 return; |
| 18 } |
| |
| |
| C.11.3.3. _plat__Signal_PhysicalPresenceOff() |
| |
| Signal physical presence off |
| |
| 19 LIB_EXPORT void |
| 20 _plat__Signal_PhysicalPresenceOff( |
| 21 void |
| 22 ) |
| 23 { |
| 24 s_physicalPresence = FALSE; |
| 25 return; |
| 26 } |
| |
| |
| Page 540 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| C.12 Unique.c |
| |
| C.12.1. Introduction |
| |
| In some implementations of the TPM, the hardware can provide a secret value to the TPM. This secret |
| value is statistically unique to the instance of the TPM. Typical uses of this value are to provide |
| personalization to the random number generation and as a shared secret between the TPM and the |
| manufacturer. |
| |
| C.12.2. Includes |
| |
| 1 #include "stdint.h" |
| 2 #include "TpmBuildSwitches.h" |
| 3 const char notReallyUnique[] = |
| 4 "This is not really a unique value. A real unique value should" |
| 5 " be generated by the platform."; |
| |
| |
| C.12.3. _plat__GetUnique() |
| |
| This function is used to access the platform-specific unique value. This function places the unique value |
| in the provided buffer (b) and returns the number of bytes transferred. The function will not copy more |
| data than bSize. |
| |
| NOTE: If a platform unique value has unequal distribution of uniqueness and bSize is smaller than the size of the |
| unique value, the bSize portion with the most uniqueness should be returned. |
| |
| 6 LIB_EXPORT uint32_t |
| 7 _plat__GetUnique( |
| 8 uint32_t which, // authorities (0) or details |
| 9 uint32_t bSize, // size of the buffer |
| 10 unsigned char *b // output buffer |
| 11 ) |
| 12 { |
| 13 const char *from = notReallyUnique; |
| 14 uint32_t retVal = 0; |
| 15 |
| 16 if(which == 0) // the authorities value |
| 17 { |
| 18 for(retVal = 0; |
| 19 *from != 0 && retVal < bSize; |
| 20 retVal++) |
| 21 { |
| 22 *b++ = *from++; |
| 23 } |
| 24 } |
| 25 else |
| 26 { |
| 27 #define uSize sizeof(notReallyUnique) |
| 28 b = &b[((bSize < uSize) ? bSize : uSize) - 1]; |
| 29 for(retVal = 0; |
| 30 *from != 0 && retVal < bSize; |
| 31 retVal++) |
| 32 { |
| 33 *b-- = *from++; |
| 34 } |
| 35 } |
| 36 return retVal; |
| 37 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 541 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| Annex D |
| (informative) |
| Remote Procedure Interface |
| |
| D.1 Introduction |
| |
| These files provide an RPC interface for a TPM simulation. |
| The simulation uses two ports: a command port and a hardware simulation port. Only TPM commands |
| defined in TPM 2.0 Part 3 are sent to the TPM on the command port. The hardware simulation port is |
| used to simulate hardware events such as power on/off and locality; and indications such as |
| _TPM_HashStart. |
| |
| |
| |
| |
| Page 542 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| |
| D.2 TpmTcpProtocol.h |
| |
| D.2.1. Introduction |
| |
| TPM commands are communicated as BYTE streams on a TCP connection. The TPM command |
| protocol is enveloped with the interface protocol described in this file. The command is indicated by a |
| UINT32 with one of the values below. Most commands take no parameters return no TPM errors. In |
| these cases the TPM interface protocol acknowledges that command processing is complete by returning |
| a UINT32=0. The command TPM_SIGNAL_HASH_DATA takes a UINT32-prepended variable length |
| BYTE array and the interface protocol acknowledges command completion with a UINT32=0. Most TPM |
| commands are enveloped using the TPM_SEND_COMMAND interface command. The parameters are |
| as indicated below. The interface layer also appends a UIN32=0 to the TPM response for regularity. |
| |
| D.2.2. Typedefs and Defines |
| |
| 1 #ifndef TCP_TPM_PROTOCOL_H |
| 2 #define TCP_TPM_PROTOCOL_H |
| |
| TPM Commands. All commands acknowledge processing by returning a UINT32 == 0 except where |
| noted |
| |
| 3 #define TPM_SIGNAL_POWER_ON 1 |
| 4 #define TPM_SIGNAL_POWER_OFF 2 |
| 5 #define TPM_SIGNAL_PHYS_PRES_ON 3 |
| 6 #define TPM_SIGNAL_PHYS_PRES_OFF 4 |
| 7 #define TPM_SIGNAL_HASH_START 5 |
| 8 #define TPM_SIGNAL_HASH_DATA 6 |
| 9 // {UINT32 BufferSize, BYTE[BufferSize] Buffer} |
| 10 #define TPM_SIGNAL_HASH_END 7 |
| 11 #define TPM_SEND_COMMAND 8 |
| 12 // {BYTE Locality, UINT32 InBufferSize, BYTE[InBufferSize] InBuffer} -> |
| 13 // {UINT32 OutBufferSize, BYTE[OutBufferSize] OutBuffer} |
| 14 #define TPM_SIGNAL_CANCEL_ON 9 |
| 15 #define TPM_SIGNAL_CANCEL_OFF 10 |
| 16 #define TPM_SIGNAL_NV_ON 11 |
| 17 #define TPM_SIGNAL_NV_OFF 12 |
| 18 #define TPM_SIGNAL_KEY_CACHE_ON 13 |
| 19 #define TPM_SIGNAL_KEY_CACHE_OFF 14 |
| 20 #define TPM_REMOTE_HANDSHAKE 15 |
| 21 #define TPM_SET_ALTERNATIVE_RESULT 16 |
| 22 #define TPM_SIGNAL_RESET 17 |
| 23 #define TPM_SESSION_END 20 |
| 24 #define TPM_STOP 21 |
| 25 #define TPM_GET_COMMAND_RESPONSE_SIZES 25 |
| 26 #define TPM_TEST_FAILURE_MODE 30 |
| 27 enum TpmEndPointInfo |
| 28 { |
| 29 tpmPlatformAvailable = 0x01, |
| 30 tpmUsesTbs = 0x02, |
| 31 tpmInRawMode = 0x04, |
| 32 tpmSupportsPP = 0x08 |
| 33 }; |
| 34 |
| 35 // Existing RPC interface type definitions retained so that the implementation |
| 36 // can be re-used |
| 37 typedef struct |
| 38 { |
| 39 unsigned long BufferSize; |
| 40 unsigned char *Buffer; |
| 41 } _IN_BUFFER; |
| |
| Family "2.0" TCG Published Page 543 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 42 |
| 43 typedef unsigned char *_OUTPUT_BUFFER; |
| 44 |
| 45 typedef struct |
| 46 { |
| 47 uint32_t BufferSize; |
| 48 _OUTPUT_BUFFER Buffer; |
| 49 } _OUT_BUFFER; |
| 50 |
| 51 //** TPM Command Function Prototypes |
| 52 void _rpc__Signal_PowerOn(BOOL isReset); |
| 53 void _rpc__Signal_PowerOff(); |
| 54 void _rpc__ForceFailureMode(); |
| 55 void _rpc__Signal_PhysicalPresenceOn(); |
| 56 void _rpc__Signal_PhysicalPresenceOff(); |
| 57 void _rpc__Signal_Hash_Start(); |
| 58 void _rpc__Signal_Hash_Data( |
| 59 _IN_BUFFER input |
| 60 ); |
| 61 void _rpc__Signal_HashEnd(); |
| 62 void _rpc__Send_Command( |
| 63 unsigned char locality, |
| 64 _IN_BUFFER request, |
| 65 _OUT_BUFFER *response |
| 66 ); |
| 67 void _rpc__Signal_CancelOn(); |
| 68 void _rpc__Signal_CancelOff(); |
| 69 void _rpc__Signal_NvOn(); |
| 70 void _rpc__Signal_NvOff(); |
| 71 BOOL _rpc__InjectEPS( |
| 72 const char* seed, |
| 73 int seedSize |
| 74 ); |
| |
| start the TPM server on the indicated socket. The TPM is single-threaded and will accept connections |
| first-come-first-served. Once a connection is dropped another client can connect. |
| |
| 75 BOOL TpmServer(SOCKET ServerSocket); |
| 76 #endif |
| |
| |
| |
| |
| Page 544 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| D.3 TcpServer.c |
| |
| D.3.1. Description |
| |
| This file contains the socket interface to a TPM simulator. |
| |
| D.3.2. Includes, Locals, Defines and Function Prototypes |
| |
| 1 #include <stdio.h> |
| 2 #include <windows.h> |
| 3 #include <winsock.h> |
| 4 #include "string.h" |
| 5 #include <stdlib.h> |
| 6 #include <stdint.h> |
| 7 #include "TpmTcpProtocol.h" |
| 8 BOOL ReadBytes(SOCKET s, char* buffer, int NumBytes); |
| 9 BOOL ReadVarBytes(SOCKET s, char* buffer, UINT32* BytesReceived, int MaxLen); |
| 10 BOOL WriteVarBytes(SOCKET s, char *buffer, int BytesToSend); |
| 11 BOOL WriteBytes(SOCKET s, char* buffer, int NumBytes); |
| 12 BOOL WriteUINT32(SOCKET s, UINT32 val); |
| 13 #ifndef __IGNORE_STATE__ |
| 14 static UINT32 ServerVersion = 1; |
| 15 #define MAX_BUFFER 1048576 |
| 16 char InputBuffer[MAX_BUFFER]; //The input data buffer for the simulator. |
| 17 char OutputBuffer[MAX_BUFFER]; //The output data buffer for the simulator. |
| 18 struct { |
| 19 UINT32 largestCommandSize; |
| 20 UINT32 largestCommand; |
| 21 UINT32 largestResponseSize; |
| 22 UINT32 largestResponse; |
| 23 } CommandResponseSizes = {0}; |
| 24 #endif // __IGNORE_STATE___ |
| |
| |
| D.3.3. Functions |
| |
| D.3.3.1. CreateSocket() |
| |
| This function creates a socket listening on PortNumber. |
| |
| 25 static int |
| 26 CreateSocket( |
| 27 int PortNumber, |
| 28 SOCKET *listenSocket |
| 29 ) |
| 30 { |
| 31 WSADATA wsaData; |
| 32 struct sockaddr_in MyAddress; |
| 33 |
| 34 int res; |
| 35 |
| 36 // Initialize Winsock |
| 37 res = WSAStartup(MAKEWORD(2,2), &wsaData); |
| 38 if (res != 0) |
| 39 { |
| 40 printf("WSAStartup failed with error: %d\n", res); |
| 41 return -1; |
| 42 } |
| 43 |
| 44 // create listening socket |
| 45 *listenSocket = socket(PF_INET, SOCK_STREAM, 0); |
| |
| |
| Family "2.0" TCG Published Page 545 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 46 if(INVALID_SOCKET == *listenSocket) |
| 47 { |
| 48 printf("Cannot create server listen socket. Error is 0x%x\n", |
| 49 WSAGetLastError()); |
| 50 return -1; |
| 51 } |
| 52 |
| 53 // bind the listening socket to the specified port |
| 54 ZeroMemory(&MyAddress, sizeof(MyAddress)); |
| 55 MyAddress.sin_port=htons((short) PortNumber); |
| 56 MyAddress.sin_family=AF_INET; |
| 57 |
| 58 res= bind(*listenSocket,(struct sockaddr*) &MyAddress,sizeof(MyAddress)); |
| 59 if(res==SOCKET_ERROR) |
| 60 { |
| 61 printf("Bind error. Error is 0x%x\n", WSAGetLastError()); |
| 62 return -1; |
| 63 }; |
| 64 |
| 65 // listen/wait for server connections |
| 66 res= listen(*listenSocket,3); |
| 67 if(res==SOCKET_ERROR) |
| 68 { |
| 69 printf("Listen error. Error is 0x%x\n", WSAGetLastError()); |
| 70 return -1; |
| 71 }; |
| 72 |
| 73 return 0; |
| 74 } |
| |
| |
| D.3.3.2. PlatformServer() |
| |
| This function processes incoming platform requests. |
| |
| 75 BOOL |
| 76 PlatformServer( |
| 77 SOCKET s |
| 78 ) |
| 79 { |
| 80 BOOL ok = TRUE; |
| 81 UINT32 length = 0; |
| 82 UINT32 Command; |
| 83 |
| 84 for(;;) |
| 85 { |
| 86 ok = ReadBytes(s, (char*) &Command, 4); |
| 87 // client disconnected (or other error). We stop processing this client |
| 88 // and return to our caller who can stop the server or listen for another |
| 89 // connection. |
| 90 if(!ok) return TRUE; |
| 91 Command = ntohl(Command); |
| 92 switch(Command) |
| 93 { |
| 94 case TPM_SIGNAL_POWER_ON: |
| 95 _rpc__Signal_PowerOn(FALSE); |
| 96 break; |
| 97 |
| 98 case TPM_SIGNAL_POWER_OFF: |
| 99 _rpc__Signal_PowerOff(); |
| 100 break; |
| 101 |
| 102 case TPM_SIGNAL_RESET: |
| 103 _rpc__Signal_PowerOn(TRUE); |
| 104 break; |
| |
| |
| Page 546 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 105 |
| 106 case TPM_SIGNAL_PHYS_PRES_ON: |
| 107 _rpc__Signal_PhysicalPresenceOn(); |
| 108 break; |
| 109 |
| 110 case TPM_SIGNAL_PHYS_PRES_OFF: |
| 111 _rpc__Signal_PhysicalPresenceOff(); |
| 112 break; |
| 113 |
| 114 case TPM_SIGNAL_CANCEL_ON: |
| 115 _rpc__Signal_CancelOn(); |
| 116 break; |
| 117 |
| 118 case TPM_SIGNAL_CANCEL_OFF: |
| 119 _rpc__Signal_CancelOff(); |
| 120 break; |
| 121 |
| 122 case TPM_SIGNAL_NV_ON: |
| 123 _rpc__Signal_NvOn(); |
| 124 break; |
| 125 |
| 126 case TPM_SIGNAL_NV_OFF: |
| 127 _rpc__Signal_NvOff(); |
| 128 break; |
| 129 |
| 130 case TPM_SESSION_END: |
| 131 // Client signaled end-of-session |
| 132 return TRUE; |
| 133 |
| 134 case TPM_STOP: |
| 135 // Client requested the simulator to exit |
| 136 return FALSE; |
| 137 |
| 138 case TPM_TEST_FAILURE_MODE: |
| 139 _rpc__ForceFailureMode(); |
| 140 break; |
| 141 |
| 142 case TPM_GET_COMMAND_RESPONSE_SIZES: |
| 143 ok = WriteVarBytes(s, (char *)&CommandResponseSizes, |
| 144 sizeof(CommandResponseSizes)); |
| 145 memset(&CommandResponseSizes, 0, sizeof(CommandResponseSizes)); |
| 146 if(!ok) |
| 147 return TRUE; |
| 148 break; |
| 149 |
| 150 default: |
| 151 printf("Unrecognized platform interface command %d\n", Command); |
| 152 WriteUINT32(s, 1); |
| 153 return TRUE; |
| 154 } |
| 155 WriteUINT32(s,0); |
| 156 } |
| 157 return FALSE; |
| 158 } |
| |
| |
| D.3.3.3. PlatformSvcRoutine() |
| |
| This function is called to set up the socket interfaces to listen for commands. |
| |
| 159 DWORD WINAPI |
| 160 PlatformSvcRoutine( |
| 161 LPVOID port |
| 162 ) |
| 163 { |
| |
| |
| Family "2.0" TCG Published Page 547 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 164 int PortNumber = (int)(INT_PTR) port; |
| 165 SOCKET listenSocket, serverSocket; |
| 166 struct sockaddr_in HerAddress; |
| 167 int res; |
| 168 int length; |
| 169 BOOL continueServing; |
| 170 |
| 171 res = CreateSocket(PortNumber, &listenSocket); |
| 172 if(res != 0) |
| 173 { |
| 174 printf("Create platform service socket fail\n"); |
| 175 return res; |
| 176 } |
| 177 |
| 178 // Loop accepting connections one-by-one until we are killed or asked to stop |
| 179 // Note the platform service is single-threaded so we don't listen for a new |
| 180 // connection until the prior connection drops. |
| 181 do |
| 182 { |
| 183 printf("Platform server listening on port %d\n", PortNumber); |
| 184 |
| 185 // blocking accept |
| 186 length = sizeof(HerAddress); |
| 187 serverSocket = accept(listenSocket, |
| 188 (struct sockaddr*) &HerAddress, |
| 189 &length); |
| 190 if(serverSocket == SOCKET_ERROR) |
| 191 { |
| 192 printf("Accept error. Error is 0x%x\n", WSAGetLastError()); |
| 193 return -1; |
| 194 }; |
| 195 printf("Client accepted\n"); |
| 196 |
| 197 // normal behavior on client disconnection is to wait for a new client |
| 198 // to connect |
| 199 continueServing = PlatformServer(serverSocket); |
| 200 closesocket(serverSocket); |
| 201 } |
| 202 while(continueServing); |
| 203 |
| 204 return 0; |
| 205 } |
| |
| |
| D.3.3.4. PlatformSignalService() |
| |
| This function starts a new thread waiting for platform signals. Platform signals are processed one at a |
| time in the order in which they are received. |
| |
| 206 int |
| 207 PlatformSignalService( |
| 208 int PortNumber |
| 209 ) |
| 210 { |
| 211 HANDLE hPlatformSvc; |
| 212 int ThreadId; |
| 213 int port = PortNumber; |
| 214 |
| 215 // Create service thread for platform signals |
| 216 hPlatformSvc = CreateThread(NULL, 0, |
| 217 (LPTHREAD_START_ROUTINE)PlatformSvcRoutine, |
| 218 (LPVOID) (INT_PTR) port, 0, (LPDWORD)&ThreadId); |
| 219 if(hPlatformSvc == NULL) |
| 220 { |
| 221 printf("Thread Creation failed\n"); |
| |
| Page 548 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 222 return -1; |
| 223 } |
| 224 |
| 225 return 0; |
| 226 } |
| |
| |
| D.3.3.5. RegularCommandService() |
| |
| This funciton services regular commands. |
| |
| 227 int |
| 228 RegularCommandService( |
| 229 int PortNumber |
| 230 ) |
| 231 { |
| 232 SOCKET listenSocket; |
| 233 SOCKET serverSocket; |
| 234 struct sockaddr_in HerAddress; |
| 235 |
| 236 int res, length; |
| 237 BOOL continueServing; |
| 238 |
| 239 res = CreateSocket(PortNumber, &listenSocket); |
| 240 if(res != 0) |
| 241 { |
| 242 printf("Create platform service socket fail\n"); |
| 243 return res; |
| 244 } |
| 245 |
| 246 // Loop accepting connections one-by-one until we are killed or asked to stop |
| 247 // Note the TPM command service is single-threaded so we don't listen for |
| 248 // a new connection until the prior connection drops. |
| 249 do |
| 250 { |
| 251 printf("TPM command server listening on port %d\n", PortNumber); |
| 252 |
| 253 // blocking accept |
| 254 length = sizeof(HerAddress); |
| 255 serverSocket = accept(listenSocket, |
| 256 (struct sockaddr*) &HerAddress, |
| 257 &length); |
| 258 if(serverSocket ==SOCKET_ERROR) |
| 259 { |
| 260 printf("Accept error. Error is 0x%x\n", WSAGetLastError()); |
| 261 return -1; |
| 262 }; |
| 263 printf("Client accepted\n"); |
| 264 |
| 265 // normal behavior on client disconnection is to wait for a new client |
| 266 // to connect |
| 267 continueServing = TpmServer(serverSocket); |
| 268 closesocket(serverSocket); |
| 269 } |
| 270 while(continueServing); |
| 271 |
| 272 return 0; |
| 273 } |
| |
| |
| D.3.3.6. StartTcpServer() |
| |
| Main entry-point to the TCP server. The server listens on port specified. Note that there is no way to |
| specify the network interface in this implementation. |
| |
| |
| Family "2.0" TCG Published Page 549 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 274 int |
| 275 StartTcpServer( |
| 276 int PortNumber |
| 277 ) |
| 278 { |
| 279 int res; |
| 280 |
| 281 // Start Platform Signal Processing Service |
| 282 res = PlatformSignalService(PortNumber+1); |
| 283 if (res != 0) |
| 284 { |
| 285 printf("PlatformSignalService failed\n"); |
| 286 return res; |
| 287 } |
| 288 |
| 289 // Start Regular/DRTM TPM command service |
| 290 res = RegularCommandService(PortNumber); |
| 291 if (res != 0) |
| 292 { |
| 293 printf("RegularCommandService failed\n"); |
| 294 return res; |
| 295 } |
| 296 |
| 297 return 0; |
| 298 } |
| |
| |
| D.3.3.7. ReadBytes() |
| |
| This function reads the indicated number of bytes (NumBytes) into buffer from the indicated socket. |
| |
| 299 BOOL |
| 300 ReadBytes( |
| 301 SOCKET s, |
| 302 char *buffer, |
| 303 int NumBytes |
| 304 ) |
| 305 { |
| 306 int res; |
| 307 int numGot = 0; |
| 308 |
| 309 while(numGot<NumBytes) |
| 310 { |
| 311 res = recv(s, buffer+numGot, NumBytes-numGot, 0); |
| 312 if(res == -1) |
| 313 { |
| 314 printf("Receive error. Error is 0x%x\n", WSAGetLastError()); |
| 315 return FALSE; |
| 316 } |
| 317 if(res==0) |
| 318 { |
| 319 return FALSE; |
| 320 } |
| 321 numGot+=res; |
| 322 } |
| 323 return TRUE; |
| 324 } |
| |
| |
| D.3.3.8. WriteBytes() |
| |
| This function will send the indicated number of bytes (NumBytes) to the indicated socket |
| |
| 325 BOOL |
| 326 WriteBytes( |
| |
| Page 550 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 327 SOCKET s, |
| 328 char *buffer, |
| 329 int NumBytes |
| 330 ) |
| 331 { |
| 332 int res; |
| 333 int numSent = 0; |
| 334 while(numSent<NumBytes) |
| 335 { |
| 336 res = send(s, buffer+numSent, NumBytes-numSent, 0); |
| 337 if(res == -1) |
| 338 { |
| 339 if(WSAGetLastError() == 0x2745) |
| 340 { |
| 341 printf("Client disconnected\n"); |
| 342 } |
| 343 else |
| 344 { |
| 345 printf("Send error. Error is 0x%x\n", WSAGetLastError()); |
| 346 } |
| 347 return FALSE; |
| 348 } |
| 349 numSent+=res; |
| 350 } |
| 351 return TRUE; |
| 352 } |
| |
| |
| D.3.3.9. WriteUINT32() |
| |
| Send 4 bytes containing hton(1) |
| |
| 353 BOOL |
| 354 WriteUINT32( |
| 355 SOCKET s, |
| 356 UINT32 val |
| 357 ) |
| 358 { |
| 359 UINT32 netVal = htonl(val); |
| 360 return WriteBytes(s, (char*) &netVal, 4); |
| 361 } |
| |
| |
| D.3.3.10. ReadVarBytes() |
| |
| Get a UINT32-length-prepended binary array. Note that the 4-byte length is in network byte order (big- |
| endian). |
| |
| 362 BOOL |
| 363 ReadVarBytes( |
| 364 SOCKET s, |
| 365 char *buffer, |
| 366 UINT32 *BytesReceived, |
| 367 int MaxLen |
| 368 ) |
| 369 { |
| 370 int length; |
| 371 BOOL res; |
| 372 |
| 373 res = ReadBytes(s, (char*) &length, 4); |
| 374 if(!res) return res; |
| 375 length = ntohl(length); |
| 376 *BytesReceived = length; |
| 377 if(length>MaxLen) |
| 378 { |
| |
| Family "2.0" TCG Published Page 551 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 379 printf("Buffer too big. Client says %d\n", length); |
| 380 return FALSE; |
| 381 } |
| 382 if(length==0) return TRUE; |
| 383 res = ReadBytes(s, buffer, length); |
| 384 if(!res) return res; |
| 385 return TRUE; |
| 386 } |
| |
| |
| D.3.3.11. WriteVarBytes() |
| |
| Send a UINT32-length-prepended binary array. Note that the 4-byte length is in network byte order (big- |
| endian). |
| |
| 387 BOOL |
| 388 WriteVarBytes( |
| 389 SOCKET s, |
| 390 char *buffer, |
| 391 int BytesToSend |
| 392 ) |
| 393 { |
| 394 UINT32 netLength = htonl(BytesToSend); |
| 395 BOOL res; |
| 396 |
| 397 res = WriteBytes(s, (char*) &netLength, 4); |
| 398 if(!res) return res; |
| 399 res = WriteBytes(s, buffer, BytesToSend); |
| 400 if(!res) return res; |
| 401 return TRUE; |
| 402 } |
| |
| |
| D.3.3.12. TpmServer() |
| |
| Processing incoming TPM command requests using the protocol / interface defined above. |
| |
| 403 BOOL |
| 404 TpmServer( |
| 405 SOCKET s |
| 406 ) |
| 407 { |
| 408 UINT32 length; |
| 409 UINT32 Command; |
| 410 BYTE locality; |
| 411 BOOL ok; |
| 412 int result; |
| 413 int clientVersion; |
| 414 _IN_BUFFER InBuffer; |
| 415 _OUT_BUFFER OutBuffer; |
| 416 |
| 417 for(;;) |
| 418 { |
| 419 ok = ReadBytes(s, (char*) &Command, 4); |
| 420 // client disconnected (or other error). We stop processing this client |
| 421 // and return to our caller who can stop the server or listen for another |
| 422 // connection. |
| 423 if(!ok) |
| 424 return TRUE; |
| 425 Command = ntohl(Command); |
| 426 switch(Command) |
| 427 { |
| 428 case TPM_SIGNAL_HASH_START: |
| 429 _rpc__Signal_Hash_Start(); |
| 430 break; |
| |
| Page 552 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 431 |
| 432 case TPM_SIGNAL_HASH_END: |
| 433 _rpc__Signal_HashEnd(); |
| 434 break; |
| 435 |
| 436 case TPM_SIGNAL_HASH_DATA: |
| 437 ok = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER); |
| 438 if(!ok) return TRUE; |
| 439 InBuffer.Buffer = (BYTE*) InputBuffer; |
| 440 InBuffer.BufferSize = length; |
| 441 _rpc__Signal_Hash_Data(InBuffer); |
| 442 break; |
| 443 |
| 444 case TPM_SEND_COMMAND: |
| 445 ok = ReadBytes(s, (char*) &locality, 1); |
| 446 if(!ok) |
| 447 return TRUE; |
| 448 |
| 449 ok = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER); |
| 450 if(!ok) |
| 451 return TRUE; |
| 452 InBuffer.Buffer = (BYTE*) InputBuffer; |
| 453 InBuffer.BufferSize = length; |
| 454 OutBuffer.BufferSize = MAX_BUFFER; |
| 455 OutBuffer.Buffer = (_OUTPUT_BUFFER) OutputBuffer; |
| 456 // record the number of bytes in the command if it is the largest |
| 457 // we have seen so far. |
| 458 if(InBuffer.BufferSize > CommandResponseSizes.largestCommandSize) |
| 459 { |
| 460 CommandResponseSizes.largestCommandSize = InBuffer.BufferSize; |
| 461 memcpy(&CommandResponseSizes.largestCommand, |
| 462 &InputBuffer[6], sizeof(UINT32)); |
| 463 } |
| 464 |
| 465 _rpc__Send_Command(locality, InBuffer, &OutBuffer); |
| 466 // record the number of bytes in the response if it is the largest |
| 467 // we have seen so far. |
| 468 if(OutBuffer.BufferSize > CommandResponseSizes.largestResponseSize) |
| 469 { |
| 470 CommandResponseSizes.largestResponseSize |
| 471 = OutBuffer.BufferSize; |
| 472 memcpy(&CommandResponseSizes.largestResponse, |
| 473 &OutputBuffer[6], sizeof(UINT32)); |
| 474 } |
| 475 ok = WriteVarBytes(s, |
| 476 (char*) OutBuffer.Buffer, |
| 477 OutBuffer.BufferSize); |
| 478 if(!ok) |
| 479 return TRUE; |
| 480 break; |
| 481 |
| 482 case TPM_REMOTE_HANDSHAKE: |
| 483 ok = ReadBytes(s, (char*)&clientVersion, 4); |
| 484 if(!ok) |
| 485 return TRUE; |
| 486 if( clientVersion == 0 ) |
| 487 { |
| 488 printf("Unsupported client version (0).\n"); |
| 489 return TRUE; |
| 490 } |
| 491 ok &= WriteUINT32(s, ServerVersion); |
| 492 ok &= WriteUINT32(s, |
| 493 tpmInRawMode | tpmPlatformAvailable | tpmSupportsPP); |
| 494 break; |
| 495 |
| 496 case TPM_SET_ALTERNATIVE_RESULT: |
| |
| Family "2.0" TCG Published Page 553 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 497 ok = ReadBytes(s, (char*)&result, 4); |
| 498 if(!ok) |
| 499 return TRUE; |
| 500 // Alternative result is not applicable to the simulator. |
| 501 break; |
| 502 |
| 503 case TPM_SESSION_END: |
| 504 // Client signaled end-of-session |
| 505 return TRUE; |
| 506 |
| 507 case TPM_STOP: |
| 508 // Client requested the simulator to exit |
| 509 return FALSE; |
| 510 default: |
| 511 printf("Unrecognized TPM interface command %d\n", Command); |
| 512 return TRUE; |
| 513 } |
| 514 ok = WriteUINT32(s,0); |
| 515 if(!ok) |
| 516 return TRUE; |
| 517 } |
| 518 return FALSE; |
| 519 } |
| |
| |
| |
| |
| Page 554 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| |
| D.4 TPMCmdp.c |
| |
| D.4.1. Description |
| |
| This file contains the functions that process the commands received on the control port or the command |
| port of the simulator. The control port is used to allow simulation of hardware events (such as, |
| _TPM_Hash_Start()) to test the simulated TPM's reaction to those events. This improves code coverage |
| of the testing. |
| |
| D.4.2. Includes and Data Definitions |
| |
| 1 #define _SWAP_H // Preclude inclusion of unnecessary simulator header |
| 2 #include <stdlib.h> |
| 3 #include <stdio.h> |
| 4 #include <stdint.h> |
| 5 #include <setjmp.h> |
| 6 #include "bool.h" |
| 7 #include "Platform.h" |
| 8 #include "ExecCommand_fp.h" |
| 9 #include "Manufacture_fp.h" |
| 10 #include "DRTM_fp.h" |
| 11 #include "_TPM_Init_fp.h" |
| 12 #include "TpmFail_fp.h" |
| 13 #include <windows.h> |
| 14 #include "TpmTcpProtocol.h" |
| 15 static BOOL s_isPowerOn = FALSE; |
| |
| |
| D.4.3. Functions |
| |
| D.4.3.1. Signal_PowerOn() |
| |
| This function processes a power-on indicataion. Amoung other things, it calls the _TPM_Init() hangler. |
| |
| 16 void |
| 17 _rpc__Signal_PowerOn( |
| 18 BOOL isReset |
| 19 ) |
| 20 { |
| 21 // if power is on and this is not a call to do TPM reset then return |
| 22 if(s_isPowerOn && !isReset) |
| 23 return; |
| 24 |
| 25 // If this is a reset but power is not on, then return |
| 26 if(isReset && !s_isPowerOn) |
| 27 return; |
| 28 |
| 29 // Pass power on signal to platform |
| 30 if(isReset) |
| 31 _plat__Signal_Reset(); |
| 32 else |
| 33 _plat__Signal_PowerOn(); |
| 34 |
| 35 // Pass power on signal to TPM |
| 36 _TPM_Init(); |
| 37 |
| 38 // Set state as power on |
| 39 s_isPowerOn = TRUE; |
| 40 } |
| |
| |
| |
| Family "2.0" TCG Published Page 555 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| D.4.3.2. Signal_PowerOff() |
| |
| This function processes the power off indication. Its primary funtion is to set a flag indicating that the next |
| power on indication should cause _TPM_Init() to be called. |
| |
| 41 void |
| 42 _rpc__Signal_PowerOff( |
| 43 void |
| 44 ) |
| 45 { |
| 46 if(!s_isPowerOn) return; |
| 47 |
| 48 // Pass power off signal to platform |
| 49 _plat__Signal_PowerOff(); |
| 50 |
| 51 s_isPowerOn = FALSE; |
| 52 |
| 53 return; |
| 54 } |
| |
| |
| D.4.3.3. _rpc__ForceFailureMode() |
| |
| This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM code such |
| that the next call to TPM2_SelfTest() will result in a failure, putting the TPM into Failure Mode. |
| |
| 55 void |
| 56 _rpc__ForceFailureMode( |
| 57 void |
| 58 ) |
| 59 { |
| 60 SetForceFailureMode(); |
| 61 } |
| |
| |
| D.4.3.4. _rpc__Signal_PhysicalPresenceOn() |
| |
| This function is called to simulate activation of the physical presence pin. |
| |
| 62 void |
| 63 _rpc__Signal_PhysicalPresenceOn( |
| 64 void |
| 65 ) |
| 66 { |
| 67 // If TPM is power off, reject this signal |
| 68 if(!s_isPowerOn) return; |
| 69 |
| 70 // Pass physical presence on to platform |
| 71 _plat__Signal_PhysicalPresenceOn(); |
| 72 |
| 73 return; |
| 74 } |
| |
| |
| D.4.3.5. _rpc__Signal_PhysicalPresenceOff() |
| |
| This function is called to simulate deactivation of the physical presence pin. |
| |
| 75 void |
| 76 _rpc__Signal_PhysicalPresenceOff( |
| 77 void |
| 78 ) |
| 79 { |
| |
| Page 556 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 80 // If TPM is power off, reject this signal |
| 81 if(!s_isPowerOn) return; |
| 82 |
| 83 // Pass physical presence off to platform |
| 84 _plat__Signal_PhysicalPresenceOff(); |
| 85 |
| 86 return; |
| 87 } |
| |
| |
| D.4.3.6. _rpc__Signal_Hash_Start() |
| |
| This function is called to simulate a _TPM_Hash_Start() event. It will call |
| |
| 88 void |
| 89 _rpc__Signal_Hash_Start( |
| 90 void |
| 91 ) |
| 92 { |
| 93 // If TPM is power off, reject this signal |
| 94 if(!s_isPowerOn) return; |
| 95 |
| 96 // Pass _TPM_Hash_Start signal to TPM |
| 97 Signal_Hash_Start(); |
| 98 return; |
| 99 } |
| |
| |
| D.4.3.7. _rpc__Signal_Hash_Data() |
| |
| This function is called to simulate a _TPM_Hash_Data() event. |
| |
| 100 void |
| 101 _rpc__Signal_Hash_Data( |
| 102 _IN_BUFFER input |
| 103 ) |
| 104 { |
| 105 // If TPM is power off, reject this signal |
| 106 if(!s_isPowerOn) return; |
| 107 |
| 108 // Pass _TPM_Hash_Data signal to TPM |
| 109 Signal_Hash_Data(input.BufferSize, input.Buffer); |
| 110 return; |
| 111 } |
| |
| |
| D.4.3.8. _rpc__Signal_HashEnd() |
| |
| This function is called to simulate a _TPM_Hash_End() event. |
| |
| 112 void |
| 113 _rpc__Signal_HashEnd( |
| 114 void |
| 115 ) |
| 116 { |
| 117 // If TPM is power off, reject this signal |
| 118 if(!s_isPowerOn) return; |
| 119 |
| 120 // Pass _TPM_HashEnd signal to TPM |
| 121 Signal_Hash_End(); |
| 122 return; |
| 123 } |
| |
| Command interface Entry of a RPC call |
| |
| Family "2.0" TCG Published Page 557 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| 124 void |
| 125 _rpc__Send_Command( |
| 126 unsigned char locality, |
| 127 _IN_BUFFER request, |
| 128 _OUT_BUFFER *response |
| 129 ) |
| 130 { |
| 131 // If TPM is power off, reject any commands. |
| 132 if(!s_isPowerOn) { |
| 133 response->BufferSize = 0; |
| 134 return; |
| 135 } |
| 136 // Set the locality of the command so that it doesn't change during the command |
| 137 _plat__LocalitySet(locality); |
| 138 // Do implementation-specific command dispatch |
| 139 ExecuteCommand(request.BufferSize, request.Buffer, |
| 140 &response->BufferSize, &response->Buffer); |
| 141 return; |
| 142 |
| 143 } |
| |
| |
| D.4.3.9. _rpc__Signal_CancelOn() |
| |
| This function is used to turn on the indication to cancel a command in process. An executing command is |
| not interrupted. The command code may perodically check this indication to see if it should abort the |
| current command processing and returned TPM_RC_CANCELLED. |
| |
| 144 void |
| 145 _rpc__Signal_CancelOn( |
| 146 void |
| 147 ) |
| 148 { |
| 149 // If TPM is power off, reject this signal |
| 150 if(!s_isPowerOn) return; |
| 151 |
| 152 // Set the platform canceling flag. |
| 153 _plat__SetCancel(); |
| 154 |
| 155 return; |
| 156 } |
| |
| |
| D.4.3.10. _rpc__Signal_CancelOff() |
| |
| This function is used to turn off the indication to cancel a command in process. |
| |
| 157 void |
| 158 _rpc__Signal_CancelOff( |
| 159 void |
| 160 ) |
| 161 { |
| 162 // If TPM is power off, reject this signal |
| 163 if(!s_isPowerOn) return; |
| 164 |
| 165 // Set the platform canceling flag. |
| 166 _plat__ClearCancel(); |
| 167 |
| 168 return; |
| 169 } |
| |
| |
| |
| |
| Page 558 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| D.4.3.11. _rpc__Signal_NvOn() |
| |
| In a system where the NV memory used by the TPM is not within the TPM, the NV may not always be |
| available. This function turns on the indicator that indicates that NV is available. |
| |
| 170 void |
| 171 _rpc__Signal_NvOn( |
| 172 void |
| 173 ) |
| 174 { |
| 175 // If TPM is power off, reject this signal |
| 176 if(!s_isPowerOn) return; |
| 177 |
| 178 _plat__SetNvAvail(); |
| 179 return; |
| 180 } |
| |
| |
| D.4.3.12. _rpc__Signal_NvOff() |
| |
| This function is used to set the indication that NV memory is no longer available. |
| |
| 181 void |
| 182 _rpc__Signal_NvOff( |
| 183 void |
| 184 ) |
| 185 { |
| 186 // If TPM is power off, reject this signal |
| 187 if(!s_isPowerOn) return; |
| 188 |
| 189 _plat__ClearNvAvail(); |
| 190 return; |
| 191 } |
| |
| |
| D.4.3.13. _rpc__Shutdown() |
| |
| This function is used to stop the TPM simulator. |
| |
| 192 void |
| 193 _rpc__Shutdown( |
| 194 void |
| 195 ) |
| 196 { |
| 197 RPC_STATUS status; |
| 198 |
| 199 // Stop TPM |
| 200 TPM_TearDown(); |
| 201 |
| 202 status = RpcMgmtStopServerListening(NULL); |
| 203 if (status != RPC_S_OK) |
| 204 { |
| 205 printf_s("RpcMgmtStopServerListening returned: 0x%x\n", status); |
| 206 exit(status); |
| 207 } |
| 208 |
| 209 status = RpcServerUnregisterIf(NULL, NULL, FALSE); |
| 210 if (status != RPC_S_OK) |
| 211 { |
| 212 printf_s("RpcServerUnregisterIf returned 0x%x\n", status); |
| 213 exit(status); |
| 214 } |
| 215 } |
| |
| |
| Family "2.0" TCG Published Page 559 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| Trusted Platform Module Library Part 4: Supporting Routines |
| |
| |
| D.5 TPMCmds.c |
| |
| D.5.1. Description |
| |
| This file contains the entry point for the simulator. |
| |
| D.5.2. Includes, Defines, Data Definitions, and Function Prototypes |
| |
| 1 #include <stdlib.h> |
| 2 #include <stdio.h> |
| 3 #include <stdint.h> |
| 4 #include <ctype.h> |
| 5 #include <windows.h> |
| 6 #include <strsafe.h> |
| 7 #include "string.h" |
| 8 #include "TpmTcpProtocol.h" |
| 9 #include "..\tpm\include\TpmBuildSwitches.h" |
| 10 #include "..\tpm\include\prototypes\Manufacture_fp.h" |
| 11 #define PURPOSE \ |
| 12 "TPM Reference Simulator.\nCopyright Microsoft 2010, 2011.\n" |
| 13 #define DEFAULT_TPM_PORT 2321 |
| 14 void* MainPointer; |
| 15 int _plat__NVEnable(void* platParameters); |
| 16 void _plat__NVDisable(); |
| 17 int StartTcpServer(int PortNumber); |
| |
| |
| D.5.3. Functions |
| |
| D.5.3.1. Usage() |
| |
| This function prints the proper calling sequence for the simulator. |
| |
| 18 void |
| 19 Usage( |
| 20 char *pszProgramName |
| 21 ) |
| 22 { |
| 23 fprintf_s(stderr, "%s", PURPOSE); |
| 24 fprintf_s(stderr, "Usage:\n"); |
| 25 fprintf_s(stderr, "%s - Starts the TPM server listening on port %d\n", |
| 26 pszProgramName, DEFAULT_TPM_PORT); |
| 27 fprintf_s(stderr, |
| 28 "%s PortNum - Starts the TPM server listening on port PortNum\n", |
| 29 pszProgramName); |
| 30 fprintf_s(stderr, "%s ? - This message\n", pszProgramName); |
| 31 exit(1); |
| 32 } |
| |
| |
| D.5.3.2. main() |
| |
| This is the main entry point for the simulator. |
| main: register the interface, start listening for clients |
| |
| 33 void __cdecl |
| 34 main( |
| 35 int argc, |
| 36 char *argv[] |
| 37 ) |
| |
| Page 560 TCG Published Family "2.0" |
| October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
| Part 4: Supporting Routines Trusted Platform Module Library |
| |
| 38 { |
| 39 int portNum = DEFAULT_TPM_PORT; |
| 40 if(argc>2) |
| 41 { |
| 42 Usage(argv[0]); |
| 43 } |
| 44 |
| 45 if(argc==2) |
| 46 { |
| 47 if(strcmp(argv[1], "?") ==0) |
| 48 { |
| 49 Usage(argv[0]); |
| 50 } |
| 51 portNum = atoi(argv[1]); |
| 52 if(portNum <=0 || portNum>65535) |
| 53 { |
| 54 Usage(argv[0]); |
| 55 } |
| 56 } |
| 57 _plat__NVEnable(NULL); |
| 58 if(TPM_Manufacture(1) != 0) |
| 59 { |
| 60 exit(1); |
| 61 } |
| 62 // Coverage test - repeated manufacturing attempt |
| 63 if(TPM_Manufacture(0) != 1) |
| 64 { |
| 65 exit(2); |
| 66 } |
| 67 // Coverage test - re-manufacturing |
| 68 TPM_TearDown(); |
| 69 if(TPM_Manufacture(1) != 0) |
| 70 { |
| 71 exit(3); |
| 72 } |
| 73 // Disable NV memory |
| 74 _plat__NVDisable(); |
| 75 |
| 76 StartTcpServer(portNum); |
| 77 return; |
| 78 } |
| |
| |
| |
| |
| Family "2.0" TCG Published Page 561 |
| Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014 |
| |