Trusted Platform Module LibraryPart 4: Supporting Routines

Family “2.0”Level 00 Revision 01.55
April 15, 2019

Committee Draft

Work in ProgressThis document is an intermediate draft for comment
only and is subject to change without notice. Readers
should not design products based on this document.
Contact: admin@trustedcomputinggroup.org

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

TCG

Trusted Platform Module LibraryPart 4: Supporting Routines

Licenses and Notices
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 toreproduce, create derivative works, distribute, display and perform the Source Code andderivative 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 ofdeveloping products based on such documents.

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.

Disclaimers:•

THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF
LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITHRESPECT 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 WARRANTIESWHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OFINTELLECTUAL 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 theimplementation 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 owners.

Page ii
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

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
4.2.2

Introduction .......................................................................................................... 2
Unmarshaling Code Prototype .............................................................................. 2

4.2.3

Marshaling Code Function Prototypes .................................................................. 4

4.3
4.4
4.5
5

Part 3 Parsing ............................................................................................................. 5
Function Prototypes .................................................................................................... 5
Portability .................................................................................................................... 6

Header Files ......................................................................................................................... 7
5.1 Introduction ................................................................................................................. 7
5.2 BaseTypes.h ............................................................................................................... 7
5.3 Capabilities.h .............................................................................................................. 8
5.4 CommandAttributeData.h ............................................................................................ 9
5.5 CommandAttributes.h ................................................................................................ 23
5.6 CommandDispatchData.h .......................................................................................... 24
5.7 Commands.h ............................................................................................................. 92
5.8 CompilerDependencies.h .......................................................................................... 99
5.9 Global.h .................................................................................................................. 101
5.9.1
5.9.2
5.9.3

Description ....................................................................................................... 101
Includes ........................................................................................................... 101
Loaded Object Structures ................................................................................. 102

5.9.4
5.9.5

AUTH_DUP Types ............................................................................................ 104
Active Session Context ..................................................................................... 104

5.9.6

PCR ................................................................................................................. 106

5.9.7
5.9.8

STARTUP_TYPE .............................................................................................. 107
NV .................................................................................................................... 108

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page iii
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

5.9.9
COMMIT_INDEX_MASK ................................................................................... 108
5.9.10 RAM Global Values .......................................................................................... 109

5.9.11 Persistent Global Values .................................................................................. 112

5.9.12
5.9.135.9.145.9.155.9.16

NV Layout ........................................................................................................ 118
Global Macro Definitions .................................................................................. 118
From CryptTest.c .............................................................................................. 120
From Manufacture.c ......................................................................................... 120
Private data ...................................................................................................... 120

5.10 GpMacros.h ............................................................................................................. 125
5.10.1
5.10.25.10.35.10.45.10.5Introduction ...................................................................................................... 125
For Self-test ..................................................................................................... 125
For Failures ...................................................................................................... 125
Derived from Vendor-specific values ................................................................ 126
Compile-time Checks ....................................................................................... 126

5.11 InternalRoutines.h ................................................................................................... 130
5.12 LibSupport.h ............................................................................................................ 132
Page iv
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

5.13 NV.h ........................................................................................................................ 133
5.13.1 Index Type Definitions ...................................................................................... 133
5.13.2 Attribute Macros ............................................................................................... 133
5.13.3 Orderly RAM Values ......................................................................................... 134
5.14 PRNG_TestVectors.h .............................................................................................. 136
5.15 SelfTest.h ................................................................................................................ 137
5.15.1 Introduction ...................................................................................................... 137
5.15.2 Defines ............................................................................................................. 137
5.16 SupportLibraryFunctionPrototypes_fp.h ................................................................... 139
5.16.1 Introduction ...................................................................................................... 139
5.16.2 SupportLibInit() ................................................................................................ 139
5.16.3 MathLibraryCompatibililtyCheck() ..................................................................... 139
5.16.4 BnModMult() ..................................................................................................... 139
5.16.5 BnMult() ........................................................................................................... 139
5.16.6 BnDiv() ............................................................................................................. 139
5.16.7 BnMod() ........................................................................................................... 140
5.16.8 BnGcd()............................................................................................................ 140
5.16.9 BnModExp() ..................................................................................................... 140
5.16.10 BnModInverse() ................................................................................................ 140
5.16.11 BnEccModMult() ............................................................................................... 140
5.16.12 BnEccModMult2() ............................................................................................. 140
5.16.13 BnEccAdd() ...................................................................................................... 140
5.16.14 BnCurveInitialize() ............................................................................................ 141

5.17
5.18
5.19
5.20
5.21
5.22
5.23
6

TPMB.h ................................................................................................................... 142
Tpm.h ...................................................................................................................... 143
TpmBuildSwitches.h ................................................................................................ 144
TpmError.h .............................................................................................................. 150
TpmTypes.h ............................................................................................................ 151
VendorString.h ........................................................................................................ 186
swap.h .................................................................................................................... 187

Main ................................................................................................................................. 189
6.1 Introduction ............................................................................................................. 189
6.2 ExecCommand.c ..................................................................................................... 189
6.2.1
6.2.2
6.2.3
6.3

CommandDispatcher.c ............................................................................................ 195

6.3.1

6.4

Introduction ...................................................................................................... 189
Includes ........................................................................................................... 189
ExecuteCommand() .......................................................................................... 189

Introduction ...................................................................................................... 195

SessionProcess.c .................................................................................................... 202

6.4.1
6.4.2
6.4.3

Introduction ...................................................................................................... 202
Includes and Data Definitions ........................................................................... 202
Authorization Support Functions ....................................................................... 202

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page v
April 15, 2019

Trusted Platform Module Library

7

Part 4: Supporting Routines

6.4.4

Session Parsing Functions ............................................................................... 209

6.4.5

Response Session Processing ......................................................................... 229

Command Support Functions ............................................................................................ 237
7.1 Introduction ............................................................................................................. 237
7.2 Attestation Command Support (Attest_spt.c) ........................................................... 237
7.2.1
7.2.2

7.3

Context Management Command Support (Context_spt.c) ........................................ 240

7.3.1
7.3.2

7.4

Includes ........................................................................................................... 237
Functions ......................................................................................................... 237

Includes ........................................................................................................... 240
Functions ......................................................................................................... 240

Policy Command Support (Policy_spt.c) .................................................................. 243

7.4.1
Page vi
April 15, 2019

Includes ........................................................................................................... 243
TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.4.2

7.5

Includes ........................................................................................................... 248
Functions ......................................................................................................... 248

Object Command Support (Object_spt.c) ................................................................. 251

7.6.1
7.6.2

Includes ........................................................................................................... 251
Local Functions ................................................................................................ 251

7.6.3

Public Functions ............................................................................................... 255

7.7
8

Functions ......................................................................................................... 243

NV Command Support (NV_spt.c) ........................................................................... 248

7.5.1
7.5.2

7.6

Trusted Platform Module Library

Encrypt Decrypt Support (EncryptDecrypt_spt.c) ..................................................... 277

Subsystem........................................................................................................................ 279
8.1 CommandAudit.c ..................................................................................................... 279
8.1.1
8.1.2
8.1.3

Introduction ...................................................................................................... 279
Includes ........................................................................................................... 279
Functions ......................................................................................................... 279

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page vii
April 15, 2019

Trusted Platform Module Library

8.2

DA.c ........................................................................................................................ 284

8.2.1
8.2.2
8.2.3

8.3

Introduction ...................................................................................................... 284
Includes and Data Definitions ........................................................................... 284
Functions ......................................................................................................... 284

Hierarchy.c .............................................................................................................. 288

8.3.1
8.3.2
8.3.3

8.4

Part 4: Supporting Routines

Introduction ...................................................................................................... 288
Includes ........................................................................................................... 288
Functions ......................................................................................................... 288

NvDynamic.c ........................................................................................................... 292

8.4.1
8.4.2
8.4.3

Introduction ...................................................................................................... 292
Includes, Defines and Data Definitions ............................................................. 292
Local Functions ................................................................................................ 292

8.4.4

RAM-based NV Index Data Access Functions ................................................... 298

Page viii
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

8.4.5

Externally Accessible Functions ....................................................................... 304

8.4.6

NV Max Counter ............................................................................................... 323

8.5

NvReserved.c .......................................................................................................... 325

8.5.1
8.5.2
8.5.3

8.6

Introduction ...................................................................................................... 325
Includes, Defines .............................................................................................. 325
Functions ......................................................................................................... 325

Object.c................................................................................................................... 329

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page ix
April 15, 2019

Trusted Platform Module Library

8.6.1
8.6.2
8.6.3

8.7

Part 4: Supporting Routines

Introduction ...................................................................................................... 329
Includes and Data Definitions ........................................................................... 329
Functions ......................................................................................................... 329

PCR.c ..................................................................................................................... 346

8.7.1
8.7.2
8.7.3

Page xApril 15, 2019

Introduction ...................................................................................................... 346
Includes, Defines, and Data Definitions ............................................................ 346
Functions ......................................................................................................... 346

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.8

PP.c ........................................................................................................................ 369

8.8.1
8.8.2
8.8.3

8.9

Trusted Platform Module Library

Introduction ...................................................................................................... 369
Includes ........................................................................................................... 369
Functions ......................................................................................................... 369

Session.c ................................................................................................................ 372

8.9.1
8.9.2
8.9.3
8.9.4
8.9.5

Introduction ...................................................................................................... 372
Includes, Defines, and Local Variables ............................................................. 373
File Scope Function -- ContextIdSetOldest() ..................................................... 373
Startup Function -- SessionStartup() ................................................................ 374
Access Functions ............................................................................................. 374

8.9.6

Utility Functions ................................................................................................ 377

8.10 Time.c ..................................................................................................................... 389
8.10.1 Introduction ...................................................................................................... 389
8.10.2 Includes ........................................................................................................... 389
8.10.3 Functions ......................................................................................................... 389

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xi
April 15, 2019

Trusted Platform Module Library

9Part 4: Supporting Routines

Support ............................................................................................................................ 394
9.1 AlgorithmCap.c ........................................................................................................ 394
9.1.1
9.1.2
9.1.3
9.1.4
9.2

Bits.c ....................................................................................................................... 398

9.2.1
9.2.2
9.2.3

9.3

Introduction ...................................................................................................... 400
Includes and Defines ........................................................................................ 400
Command Attribute Functions .......................................................................... 400

Entity.c .................................................................................................................... 410

9.4.1
9.4.2
9.4.3

9.5

Introduction ...................................................................................................... 398
Includes ........................................................................................................... 398
Functions ......................................................................................................... 398

CommandCodeAttributes.c ...................................................................................... 400

9.3.1
9.3.2
9.3.3

9.4

Description ....................................................................................................... 394
Includes and Defines ........................................................................................ 394
AlgorithmCapGetImplemented() ........................................................................ 396
AlgorithmGetImplementedVector() .................................................................... 396

Description ....................................................................................................... 410
Includes ........................................................................................................... 410
Functions ......................................................................................................... 410

Global.c................................................................................................................... 418

9.5.1
9.5.2
Page xii
April 15, 2019

Description ....................................................................................................... 418
Defines and Includes ........................................................................................ 418
TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.6

Handle.c .................................................................................................................. 419

9.6.1
9.6.2
9.6.3

9.7

Includes and Data Definitions ........................................................................... 422
Buffers and Functions ...................................................................................... 422

Locality.c ................................................................................................................. 424

9.8.1
9.8.2
9.9

Description ....................................................................................................... 419
Includes ........................................................................................................... 419
Functions ......................................................................................................... 419

IoBuffers.c ............................................................................................................... 422

9.7.1
9.7.2

9.8

Trusted Platform Module Library

Includes ........................................................................................................... 424
LocalityGetAttributes() ...................................................................................... 424

Manufacture.c ......................................................................................................... 425

9.9.1
9.9.2
9.9.3

Description ....................................................................................................... 425
Includes and Data Definitions ........................................................................... 425
Functions ......................................................................................................... 425

9.10 Marshal.c ................................................................................................................ 428
9.10.19.10.29.10.39.10.49.10.59.10.6Introduction ...................................................................................................... 428
Unmarshal and Marshal a Value ....................................................................... 428
Unmarshal and Marshal a Union ....................................................................... 429
Unmarshal and Marshal a Structure .................................................................. 431
Unmarshal and Marshal an Array ..................................................................... 432
TPM2B Handling .............................................................................................. 434

9.11 MathOnByteBuffers.c .............................................................................................. 435
9.11.1 Introduction ...................................................................................................... 435
9.11.2 Functions ......................................................................................................... 435

9.12 Memory.c ................................................................................................................ 440
9.12.1 Description ....................................................................................................... 440
9.12.2 Includes and Data Definitions ........................................................................... 440
9.12.3 Functions ......................................................................................................... 440

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xiii
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

9.13 Power.c ................................................................................................................... 445
9.13.1 Description ....................................................................................................... 445
9.13.2 Includes and Data Definitions ........................................................................... 445
9.13.3 Functions ......................................................................................................... 445

9.14 PropertyCap.c ......................................................................................................... 447
9.14.1 Description ....................................................................................................... 447
9.14.2 Includes ........................................................................................................... 447
9.14.3 Functions ......................................................................................................... 447

9.15 Response.c ............................................................................................................. 456
9.15.1 Description ....................................................................................................... 456
9.15.2 Includes and Defines ........................................................................................ 456
9.15.3 BuildResponseHeader() ................................................................................... 456
9.16 ResponseCodeProcessing.c .................................................................................... 457
9.16.1 Description ....................................................................................................... 457
9.16.2 Includes and Defines ........................................................................................ 457
9.16.3 RcSafeAddToResult() ....................................................................................... 457
9.17 TpmFail.c ................................................................................................................ 458
9.17.1 Includes, Defines, and Types ........................................................................... 458
9.17.2 Typedefs .......................................................................................................... 458
9.17.3 Local Functions ................................................................................................ 459

9.17.4 Public Functions ............................................................................................... 460

10Cryptographic Functions ................................................................................................... 465
10.1 Headers .................................................................................................................. 465

Page xiv
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.1 BnValues.h ....................................................................................................... 465

10.1.2 CryptEcc.h ....................................................................................................... 470

10.1.3 CryptHash.h ..................................................................................................... 471

10.1.4 CryptRand.h ..................................................................................................... 476

10.1.5 CryptRsa.h ....................................................................................................... 479
10.1.6 CryptTest.h ...................................................................................................... 480
10.1.7 HashTestData.h ............................................................................................... 481
10.1.8 KdfTestData.h .................................................................................................. 482
10.1.9 RsaTestData.h ................................................................................................. 483
10.1.10 SymmetricTestData.h ....................................................................................... 489
10.1.11 SymmetricTest.h .............................................................................................. 491

10.1.12 EccTestData.h .................................................................................................. 492
10.1.13 CryptSym.h ...................................................................................................... 494

10.1.14 OIDS.h ............................................................................................................. 496
10.1.15 TpmAsn1.h ....................................................................................................... 500

10.1.16 X509.h ............................................................................................................. 502

10.1.17 MinMax.h ......................................................................................................... 504
10.1.18 TpmAlgorithmDefines.h .................................................................................... 505
10.2 Source .................................................................................................................... 511
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xv
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.1 AlgorithmTests.c .............................................................................................. 511

10.2.2 BnConvert.c ..................................................................................................... 527

10.2.3 BnMath.c .......................................................................................................... 532

Page xvi
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.4 BnMemory.c ..................................................................................................... 543

10.2.5 CryptCmac.c .................................................................................................... 546

10.2.6 CryptUtil.c ........................................................................................................ 549

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xvii
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.7 CryptSelfTest.c................................................................................................. 582

10.2.8 CryptEccData.c ................................................................................................ 586
10.2.9 CryptDes.c ....................................................................................................... 595

10.2.10 CryptEccKeyExchange.c .................................................................................. 598

10.2.11 CryptEccMain.c ................................................................................................ 604

Page xviii
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.12 CryptEccSignature.c ......................................................................................... 618

10.2.13 CryptHash.c ..................................................................................................... 633

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xix
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.14 CryptPrime.c .................................................................................................... 649

10.2.15 CryptPrimeSieve.c ............................................................................................ 655

10.2.16 CryptRand.c ..................................................................................................... 664

Page xx
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.17 CryptRsa.c ....................................................................................................... 682

10.2.18 CryptSmac.c ..................................................................................................... 706
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xxi
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.19 CryptSym.c....................................................................................................... 708

10.2.20 PrimeData.c ..................................................................................................... 716
10.2.21 RsaKeyCache.c ................................................................................................ 722

10.2.22 Ticket.c ............................................................................................................ 726

10.2.23 TpmAsn1.c ....................................................................................................... 730

Page xxii
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.24 X509_ECC.c ..................................................................................................... 739

10.2.25 X509_RSA.c ..................................................................................................... 742

10.2.26 X509_spt.c ....................................................................................................... 746

10.2.27 AC_spt.c .......................................................................................................... 751

Annex A (informative) Implementation Dependent .................................................................. 754
A.1 Introduction ............................................................................................................. 754
A.2 TpmProfile.h ............................................................................................................ 754
Annex B (informative) Library-Specific .................................................................................... 767
B.1 Introduction ............................................................................................................. 767
B.2 OpenSSL-Specific Files ........................................................................................... 768
B.2.1.
B.2.2.

Introduction ...................................................................................................... 768
Header Files ..................................................................................................... 768

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xxiii
April 15, 2019

Trusted Platform Module Library

B.2.3.

Part 4: Supporting Routines

Source Files ..................................................................................................... 775

Annex C (informative) Simulation Environment ....................................................................... 790
C.1 Introduction ............................................................................................................. 790
C.2 Cancel.c .................................................................................................................. 790
C.2.1.
C.2.2.
C.2.3.

C.3

Description ....................................................................................................... 790
Includes, Typedefs, Structures, and Defines ..................................................... 790
Functions ......................................................................................................... 790

Clock.c .................................................................................................................... 792

C.3.1.
C.3.2.
C.3.3.

Description ....................................................................................................... 792
Includes and Data Definitions ........................................................................... 792
Simulator Functions .......................................................................................... 792

C.3.4.

Functions Used by TPM ................................................................................... 793

C.4

Entropy.c ................................................................................................................. 797

C.4.1.
C.4.2.

C.5

Includes and Local Values ................................................................................ 797
Functions ......................................................................................................... 797

LocalityPlat.c ........................................................................................................... 800

C.5.1.
Page xxiv
April 15, 2019

Includes ........................................................................................................... 800
TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.5.2.

C.6

Description ....................................................................................................... 801
Includes and Local ........................................................................................... 801
Functions ......................................................................................................... 801

PowerPlat.c ............................................................................................................. 808

C.7.1.
C.7.2.

C.8
C.9

Functions ......................................................................................................... 800

NVMem.c ................................................................................................................ 801

C.6.1.
C.6.2.
C.6.3.

C.7

Trusted Platform Module Library

Includes and Function Prototypes ..................................................................... 808
Functions ......................................................................................................... 808

PlatformData.h ........................................................................................................ 810
PlatformData.c ........................................................................................................ 812

C.9.1.
C.9.2.

Description ....................................................................................................... 812
Includes ........................................................................................................... 812

C.10 PPPlat.c .................................................................................................................. 813
C.10.1. Description ....................................................................................................... 813
C.10.2. Includes ........................................................................................................... 813
C.10.3. Functions ......................................................................................................... 813

C.11 RunCommand.c ....................................................................................................... 814
C.11.1. Introduction ...................................................................................................... 814
C.11.2. Includes and locals ........................................................................................... 814
C.11.3. Functions ......................................................................................................... 814

C.12 Unique.c .................................................................................................................. 815
C.12.1. Introduction ...................................................................................................... 815
C.12.2. Includes ........................................................................................................... 815
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xxv
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

C.12.3. _plat__GetUnique() .......................................................................................... 815
C.13 DebugHelpers.c....................................................................................................... 816
C.13.1. Description ....................................................................................................... 816
C.13.2. Includes and Local ........................................................................................... 816

C.14 Platform.h ............................................................................................................... 818
Annex D (informative) Remote Procedure Interface ................................................................ 819
D.1 Introduction ............................................................................................................. 819
D.2 TpmTcpProtocol.h ................................................................................................... 820
D.2.1.
D.2.2.
D.2.3.
D.2.4.
D.3

TcpServer.c ............................................................................................................. 822

D.3.1.
D.3.2.
D.3.3.

D.4

Description ....................................................................................................... 822
Includes, Locals, Defines and Function Prototypes ........................................... 822
Functions ......................................................................................................... 822

TPMCmdp.c ............................................................................................................ 832

D.4.1.
D.4.2.
D.4.3.

D.5

Introduction ...................................................................................................... 820
Typedefs and Defines ....................................................................................... 820
TPM Commands ............................................................................................... 820
Enumerations and Structures ........................................................................... 820

Description ....................................................................................................... 832
Includes and Data Definitions ........................................................................... 832
Functions ......................................................................................................... 832

TPMCmds.c............................................................................................................. 838

D.5.1.
Page xxvi
April 15, 2019

Description ....................................................................................................... 838
TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

D.5.2.
D.5.3.

Trusted Platform Module Library

Includes, Defines, Data Definitions, and Function Prototypes ........................... 838
Functions ......................................................................................................... 838

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page xxvii
April 15, 2019

Part 4: Supporting Routines

Trusted Platform Module Library

Trusted Platform Module LibraryPart 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 acomplete description of a TPM, including the supporting framework for the code that performs thecommand actions.
Any TPM 2.0 Part 4 code may be replaced by code that provides similar results when interfacing to theaction code in TPM 2.0 Part 3. The behavior of code in this document that is not included in an annex isnormative, as observed at the interfaces with TPM 2.0 Part 3 code. Code in an annex is provided forcompleteness, 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 thisspecification 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 andunmarshaling 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.
The automation produces TPM_Types.h, a header representing TPM 2.0 Part 2. It also produces, foreach major clause of Part 4, a header of the form _fp.h with the function prototypes.
EXAMPLE

4.1

The header file for SessionProcess.c is SessionProcess_fp.h.

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. Thesetables may be modified by an implementer to describe the algorithms and commands to be executed inby a specific implementation as well as to set implementation limits such as the number of PCR, sizes ofbuffers, etc.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 1
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

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.
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 codein 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 fromthe TPM.
The unmarshaling code produced by the parser uses the prototypes defined below. The unmarshalingcode 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 theonly 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 isbeing parsed or the response is being built. The prototypes and the description of the interface areintended 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*targetlocation 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 parameterin the input buffer and size is reduced by the number of octets removed from the buffer.
Page 2
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

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.
When the data type is a structure, the parser will generate code that unmarshals each of the structureelements 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 theselector for the type. The unmarshaling code for the union will unmarshal the type indicated by theselector.
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*targetlocation 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 andcode 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 toindicate 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 tounmarshal that type. flag TRUE indicates that null is accepted.
4.2.2.4

ArraysAny 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”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 3
April 15, 2019

Trusted Platform Module Library

4.2.3

Part 4: Supporting Routines

Marshaling Code Function Prototypes

4.2.3.1

Simple Types and Structures

The general form for the marshaling 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*sourcelocation in the TPM memory containing the value that is to be marshaledin to the designated buffer**buffer

location in the output buffer where the first octet of the TYPE is to beplaced*size

number of octets remaining in **buffer.

If buffer is a NULL pointer, then no data is marshaled, but the routine will compute and return the sizeof the memory required to marshal the indicated type. *size is not changed.
If buffer is not a NULL pointer, data is marshaled, *buffer is advanced to point to the first octet of thenext location in the output buffer, and the called routine will return the number of octets marshaled into**buffer. This occurs even if size is a NULL pointer. If size is a not NULL pointer *size is reducedby 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. The presumption is also thatthe size is sufficient for the source being marshaled.
When the data type is a structure, the parser will generate code that marshals each of the structureelements 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 thetype. 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 *source, BYTE **buffer, INT32 *size, UINT32 selector);

The parameters have a similar meaning as those in 4.2.2.2 but the data movement is from source tobuffer.
4.2.3.3

ArraysAny 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
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

4.3

Trusted Platform Module LibraryPart 3 Parsing

The Command / Response tables in Part 3 of this specification are processed by scripts to produce thecommand-specific data structures used by functions in this TPM 2.0 Part 4. They are:•CommandAttributeData.h -- This file contains the command attributes reported by
TPM2_GetCapability.

•

CommandAttributes.h – This file contains the definition of command attributes that are
extracted by the parsing code. The file mainly exists to ensure that the parsing code and thefunction code are using the same attributes.

•

CommandDispatchData.h – This file contains the data definitions for the table driven version of
the command dispatcher.

Part 3 parsing also produces special function prototype files as described in 4.4.
4.4

Function Prototypes

For functions that have entry definitions not defined by Part 3 tables. a script is used to extracts function
prototypes from the code. For each .c file that is not in Part 3, a file with the same name is created with asuffix of _fp.h. For example, the function prototypes for Create.c will be placed in a file called Create_fp.h.
The _fp.h is added because some files have two types of associated headers: the one containing thefunction prototypes for the file and another containing definitions that are specific to that file.
In some cases, a function will be replaced by a macro. The macro is defined in the .c file and extracted by
the function prototype processor. A special comment tag (“//%”) is used to indicate that the line is to be
included in the function prototype file. If the “//%” tag occurs at the start of the line, it is deleted. If it occurs
later in the line, it is preserved. Removing the “//%/ at the start of the line allows the macro to be placed in
the .c file with the tag as a prefix, and then show up in the _fp.h file as the actual macro. This allows thecode that includes that function prototype code to use the appropriate macro.
For files that that contain the command actions, a special _fp.h file is created from the tables in Part 3.
These files contain:•

the definition of the input and output structure of the function;•

definition of command-specific return code modifiers (parameter identifiers); and•the function prototype for the command action function.

Create_fp.h (shown below) is prototypical of the command _fp.h files.
1
2
3#if CC_Create // Command must be enabled#ifndef _Create_FP_H_#define _Create_FP_H_

Input structure definition
4
5
6
7
8
9
10

typedef struct {TPMI_DH_OBJECT
TPM2B_SENSITIVE_CREATETPM2B_PUBLIC
TPM2B_DATA
TPML_PCR_SELECTION} Create_In;

parentHandle;
inSensitive;
inPublic;outsideInfo;
creationPCR;

Output structure definition
11
12
13
14

typedef struct {TPM2B_PRIVATETPM2B_PUBLIC
TPM2B_CREATION_DATA

Family “2.0”Level 00 Revision 01.55

outPrivate;
outPublic;
creationData;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 5
April 15, 2019

Trusted Platform Module Library
15
16
17

TPM2B_DIGEST
TPMT_TK_CREATION} Create_Out;Part 4: Supporting Routines
creationHash;creationTicket;

Response code modifiers
18
19
20
21
22

#define RC_Create_parentHandle#define RC_Create_inSensitive#define RC_Create_inPublic#define RC_Create_outsideInfo#define RC_Create_creationPCR(TPM_RC_H + TPM_RC_1)(TPM_RC_P + TPM_RC_1)(TPM_RC_P + TPM_RC_2)(TPM_RC_P + TPM_RC_3)(TPM_RC_P + TPM_RC_4)

Function prototype
23
24
25
26
27
28
29

TPM_RC
TPM2_Create(
Create_In
Create_Out);#endif#endif

4.5

*in,
*out

// _Create_FP_H_// CC_Create

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 marshaledand 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
will occupy the 0th 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 thatsizeof(TPMA_SESSION) would return 4 rather than 1 (the canonical size of a TPMA_SESSION).
For a little endian machine, padding of bit fields should have little consequence since the 0th octet always
contains the 0th bit of the structure no matter how large the structure. However, for a big endian machine,
the 0th bit will be in the highest numbered octet. When unmarshaling a TPMA_SESSION, the current
unmarshaling code will place the input octet at the 0th octet of the TPMA_SESSION. Since the 0th octet ismost 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:
allocate all structures as packed to a byte boundary (this may not be possible if the processor does
not handle unaligned accesses); or
modify the code that manipulates bit fields that are not defined as being the alignment size of thesystem.
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).

Page 6
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5
5.1

Trusted Platform Module Library

Header Files
Introduction

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

BaseTypes.h#ifndef _BASE_TYPES_H_#define _BASE_TYPES_H_

NULL definition
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#ifndef NULL
#define NULL
#endiftypedef uint8_t
typedef uint8_t
typedef int8_t
typedef int
typedef uint16_t
typedef int16_t
typedef uint32_t
typedef int32_t
typedef uint64_t
typedef int64_t#endif // _BASE_TYPES_H_

Family “2.0”Level 00 Revision 01.55(0)
UINT8;
BYTE;
INT8;
BOOL;
UINT16;
INT16;UINT32;
INT32;UINT64;
INT64;TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 7
April 15, 2019

Trusted Platform Module Library

5.3

Part 4: Supporting Routines

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 modulethat supports a type that is returned by a capability will have a function that returns the capabilities of thetype.
EXAMPLE

1
2
3
4
5
6
7
8
9
10
11
12

#ifndef#define#define#define#define#define#define#define#define#define#define#endif

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

_CAPABILITIES_H_CAPABILITIES_H
MAX_CAP_DATAMAX_CAP_ALGS
MAX_CAP_HANDLESMAX_CAP_CC
MAX_TPM_PROPERTIES
MAX_PCR_PROPERTIES
MAX_ECC_CURVES
MAX_TAGGED_POLICIESMAX_AC_CAPABILITIESPage 8
April 15, 2019

(MAX_CAP_BUFFER - sizeof(TPM_CAP)-sizeof(UINT32))(MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY))(MAX_CAP_DATA / sizeof(TPM_HANDLE))(MAX_CAP_DATA / sizeof(TPM_CC))(MAX_CAP_DATA / sizeof(TPMS_TAGGED_PROPERTY))(MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT))(MAX_CAP_DATA / sizeof(TPM_ECC_CURVE))(MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY))(MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT))TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.4

Trusted Platform Module Library

CommandAttributeData.h

This file should only be included by CommandCodeAttibutes.c
1
2
3
4
5
6
7

#ifdef _COMMAND_CODE_ATTRIBUTES_#include "CommandAttributes.h"#if COMPRESSED_LISTS#
define
PAD_LIST0#else#
define
PAD_LIST
1#endifThis is the command code attribute array for GetCapability(). Both this array and s_commandAttributes
provides command code attributes, but tuned for different purpose
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

const TPMA_CC
s_ccAttr [] = {#if (PAD_LIST || CC_NV_UndefineSpaceSpecial)
TPMA_CC_INITIALIZER(0x011F, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_EvictControl)
TPMA_CC_INITIALIZER(0x0120, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_HierarchyControl)
TPMA_CC_INITIALIZER(0x0121, 0, 1, 1, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_UndefineSpace)
TPMA_CC_INITIALIZER(0x0122, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST )TPMA_CC_INITIALIZER(0x0123, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_ChangeEPS)
TPMA_CC_INITIALIZER(0x0124, 0, 1, 1, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ChangePPS)
TPMA_CC_INITIALIZER(0x0125, 0, 1, 1, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_Clear)
TPMA_CC_INITIALIZER(0x0126, 0, 1, 1, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ClearControl)
TPMA_CC_INITIALIZER(0x0127, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ClockSet)
TPMA_CC_INITIALIZER(0x0128, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_HierarchyChangeAuth)
TPMA_CC_INITIALIZER(0x0129, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_DefineSpace)
TPMA_CC_INITIALIZER(0x012A, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_Allocate)
TPMA_CC_INITIALIZER(0x012B, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_SetAuthPolicy)
TPMA_CC_INITIALIZER(0x012C, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PP_Commands)
TPMA_CC_INITIALIZER(0x012D, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_SetPrimaryPolicy)
TPMA_CC_INITIALIZER(0x012E, 0, 1, 0, 0, 1, 0, 0, 0),#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 9April 15, 2019

Trusted Platform Module Library
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

Part 4: Supporting Routines#if (PAD_LIST || CC_FieldUpgradeStart)
TPMA_CC_INITIALIZER(0x012F, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_ClockRateAdjust)
TPMA_CC_INITIALIZER(0x0130, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_CreatePrimary)
TPMA_CC_INITIALIZER(0x0131, 0, 0, 0, 0, 1, 1, 0, 0),#endif#if (PAD_LIST || CC_NV_GlobalWriteLock)
TPMA_CC_INITIALIZER(0x0132, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_GetCommandAuditDigest)
TPMA_CC_INITIALIZER(0x0133, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_Increment)
TPMA_CC_INITIALIZER(0x0134, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_SetBits)
TPMA_CC_INITIALIZER(0x0135, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_Extend)
TPMA_CC_INITIALIZER(0x0136, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_Write)
TPMA_CC_INITIALIZER(0x0137, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_WriteLock)
TPMA_CC_INITIALIZER(0x0138, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_DictionaryAttackLockReset)
TPMA_CC_INITIALIZER(0x0139, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_DictionaryAttackParameters)
TPMA_CC_INITIALIZER(0x013A, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_ChangeAuth)
TPMA_CC_INITIALIZER(0x013B, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_Event)
TPMA_CC_INITIALIZER(0x013C, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_Reset)
TPMA_CC_INITIALIZER(0x013D, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_SequenceComplete)
TPMA_CC_INITIALIZER(0x013E, 0, 0, 0, 1, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_SetAlgorithmSet)
TPMA_CC_INITIALIZER(0x013F, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_SetCommandCodeAuditStatus)
TPMA_CC_INITIALIZER(0x0140, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_FieldUpgradeData)
TPMA_CC_INITIALIZER(0x0141, 0, 1, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_IncrementalSelfTest)
TPMA_CC_INITIALIZER(0x0142, 0, 1, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_SelfTest)
TPMA_CC_INITIALIZER(0x0143, 0, 1, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_Startup)
TPMA_CC_INITIALIZER(0x0144, 0, 1, 0, 0, 0, 0, 0, 0),#endifPage 10
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

Trusted Platform Module Library#if (PAD_LIST || CC_Shutdown)
TPMA_CC_INITIALIZER(0x0145, 0, 1, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_StirRandom)
TPMA_CC_INITIALIZER(0x0146, 0, 1, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_ActivateCredential)
TPMA_CC_INITIALIZER(0x0147, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_Certify)
TPMA_CC_INITIALIZER(0x0148, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyNV)
TPMA_CC_INITIALIZER(0x0149, 0, 0, 0, 0, 3, 0, 0, 0),#endif#if (PAD_LIST || CC_CertifyCreation)
TPMA_CC_INITIALIZER(0x014A, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_Duplicate)
TPMA_CC_INITIALIZER(0x014B, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_GetTime)
TPMA_CC_INITIALIZER(0x014C, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_GetSessionAuditDigest)
TPMA_CC_INITIALIZER(0x014D, 0, 0, 0, 0, 3, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_Read)
TPMA_CC_INITIALIZER(0x014E, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_ReadLock)
TPMA_CC_INITIALIZER(0x014F, 0, 1, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_ObjectChangeAuth)
TPMA_CC_INITIALIZER(0x0150, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicySecret)
TPMA_CC_INITIALIZER(0x0151, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_Rewrap)
TPMA_CC_INITIALIZER(0x0152, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_Create)
TPMA_CC_INITIALIZER(0x0153, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ECDH_ZGen)
TPMA_CC_INITIALIZER(0x0154, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || (CC_HMAC || CC_MAC))
TPMA_CC_INITIALIZER(0x0155, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_Import)
TPMA_CC_INITIALIZER(0x0156, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_Load)
TPMA_CC_INITIALIZER(0x0157, 0, 0, 0, 0, 1, 1, 0, 0),#endif#if (PAD_LIST || CC_Quote)
TPMA_CC_INITIALIZER(0x0158, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_RSA_Decrypt)
TPMA_CC_INITIALIZER(0x0159, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST )TPMA_CC_INITIALIZER(0x015A, 0, 0, 0, 0, 0, 0, 0, 0),#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 11
April 15, 2019

Trusted Platform Module Library
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

Part 4: Supporting Routines#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start))
TPMA_CC_INITIALIZER(0x015B, 0, 0, 0, 0, 1, 1, 0, 0),#endif#if (PAD_LIST || CC_SequenceUpdate)
TPMA_CC_INITIALIZER(0x015C, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_Sign)
TPMA_CC_INITIALIZER(0x015D, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_Unseal)
TPMA_CC_INITIALIZER(0x015E, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST )TPMA_CC_INITIALIZER(0x015F, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicySigned)
TPMA_CC_INITIALIZER(0x0160, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_ContextLoad)
TPMA_CC_INITIALIZER(0x0161, 0, 0, 0, 0, 0, 1, 0, 0),#endif#if (PAD_LIST || CC_ContextSave)
TPMA_CC_INITIALIZER(0x0162, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ECDH_KeyGen)
TPMA_CC_INITIALIZER(0x0163, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_EncryptDecrypt)
TPMA_CC_INITIALIZER(0x0164, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_FlushContext)
TPMA_CC_INITIALIZER(0x0165, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST )TPMA_CC_INITIALIZER(0x0166, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_LoadExternal)
TPMA_CC_INITIALIZER(0x0167, 0, 0, 0, 0, 0, 1, 0, 0),#endif#if (PAD_LIST || CC_MakeCredential)
TPMA_CC_INITIALIZER(0x0168, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_ReadPublic)
TPMA_CC_INITIALIZER(0x0169, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyAuthorize)
TPMA_CC_INITIALIZER(0x016A, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyAuthValue)
TPMA_CC_INITIALIZER(0x016B, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyCommandCode)
TPMA_CC_INITIALIZER(0x016C, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyCounterTimer)
TPMA_CC_INITIALIZER(0x016D, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyCpHash)
TPMA_CC_INITIALIZER(0x016E, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyLocality)
TPMA_CC_INITIALIZER(0x016F, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyNameHash)
TPMA_CC_INITIALIZER(0x0170, 0, 0, 0, 0, 1, 0, 0, 0),#endifPage 12April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

Trusted Platform Module Library#if (PAD_LIST || CC_PolicyOR)
TPMA_CC_INITIALIZER(0x0171, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyTicket)
TPMA_CC_INITIALIZER(0x0172, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ReadPublic)
TPMA_CC_INITIALIZER(0x0173, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_RSA_Encrypt)
TPMA_CC_INITIALIZER(0x0174, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST )TPMA_CC_INITIALIZER(0x0175, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_StartAuthSession)
TPMA_CC_INITIALIZER(0x0176, 0, 0, 0, 0, 2, 1, 0, 0),#endif#if (PAD_LIST || CC_VerifySignature)
TPMA_CC_INITIALIZER(0x0177, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ECC_Parameters)
TPMA_CC_INITIALIZER(0x0178, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_FirmwareRead)
TPMA_CC_INITIALIZER(0x0179, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_GetCapability)
TPMA_CC_INITIALIZER(0x017A, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_GetRandom)
TPMA_CC_INITIALIZER(0x017B, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_GetTestResult)
TPMA_CC_INITIALIZER(0x017C, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_Hash)
TPMA_CC_INITIALIZER(0x017D, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_Read)
TPMA_CC_INITIALIZER(0x017E, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyPCR)
TPMA_CC_INITIALIZER(0x017F, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyRestart)
TPMA_CC_INITIALIZER(0x0180, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ReadClock)
TPMA_CC_INITIALIZER(0x0181, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_Extend)
TPMA_CC_INITIALIZER(0x0182, 0, 1, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PCR_SetAuthValue)
TPMA_CC_INITIALIZER(0x0183, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_NV_Certify)
TPMA_CC_INITIALIZER(0x0184, 0, 0, 0, 0, 3, 0, 0, 0),#endif#if (PAD_LIST || CC_EventSequenceComplete)
TPMA_CC_INITIALIZER(0x0185, 0, 1, 0, 1, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_HashSequenceStart)
TPMA_CC_INITIALIZER(0x0186, 0, 0, 0, 0, 0, 1, 0, 0),#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 13
April 15, 2019

Trusted Platform Module Library
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

Part 4: Supporting Routines#if (PAD_LIST || CC_PolicyPhysicalPresence)
TPMA_CC_INITIALIZER(0x0187, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyDuplicationSelect)
TPMA_CC_INITIALIZER(0x0188, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyGetDigest)
TPMA_CC_INITIALIZER(0x0189, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_TestParms)
TPMA_CC_INITIALIZER(0x018A, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_Commit)
TPMA_CC_INITIALIZER(0x018B, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyPassword)
TPMA_CC_INITIALIZER(0x018C, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ZGen_2Phase)
TPMA_CC_INITIALIZER(0x018D, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_EC_Ephemeral)
TPMA_CC_INITIALIZER(0x018E, 0, 0, 0, 0, 0, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyNvWritten)
TPMA_CC_INITIALIZER(0x018F, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_PolicyTemplate)
TPMA_CC_INITIALIZER(0x0190, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_CreateLoaded)
TPMA_CC_INITIALIZER(0x0191, 0, 0, 0, 0, 1, 1, 0, 0),#endif#if (PAD_LIST || CC_PolicyAuthorizeNV)
TPMA_CC_INITIALIZER(0x0192, 0, 0, 0, 0, 3, 0, 0, 0),#endif#if (PAD_LIST || CC_EncryptDecrypt2)
TPMA_CC_INITIALIZER(0x0193, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_AC_GetCapability)
TPMA_CC_INITIALIZER(0x0194, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_AC_Send)
TPMA_CC_INITIALIZER(0x0195, 0, 0, 0, 0, 3, 0, 0, 0),#endif#if (PAD_LIST || CC_Policy_AC_SendSelect)
TPMA_CC_INITIALIZER(0x0196, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_CertifyX509)
TPMA_CC_INITIALIZER(0x0197, 0, 0, 0, 0, 2, 0, 0, 0),#endif#if (PAD_LIST || CC_Vendor_TCG_Test)
TPMA_CC_INITIALIZER(0x0000, 0, 0, 0, 0, 0, 0, 1, 0),#endif{0}};This is the command code attribute structure.
377
378
379
380
381
382

const COMMAND_ATTRIBUTES
s_commandAttributes [] = {#if (PAD_LIST || CC_NV_UndefineSpaceSpecial)(COMMAND_ATTRIBUTES)(CC_NV_UndefineSpaceSpecial* // 0x011F(IS_IMPLEMENTED+HANDLE_1_ADMIN+HANDLE_2_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_EvictControl)

Page 14
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

Trusted Platform Module Library(COMMAND_ATTRIBUTES)(CC_EvictControl(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),*// 0x0120#endif#if (PAD_LIST || CC_HierarchyControl)(COMMAND_ATTRIBUTES)(CC_HierarchyControl* // 0x0121(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_NV_UndefineSpace)(COMMAND_ATTRIBUTES)(CC_NV_UndefineSpace* // 0x0122(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST )(COMMAND_ATTRIBUTES)(0),// 0x0123#endif#if (PAD_LIST || CC_ChangeEPS)(COMMAND_ATTRIBUTES)(CC_ChangeEPS* // 0x0124(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_ChangePPS)(COMMAND_ATTRIBUTES)(CC_ChangePPS* // 0x0125(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_Clear)(COMMAND_ATTRIBUTES)(CC_Clear* // 0x0126(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_ClearControl)(COMMAND_ATTRIBUTES)(CC_ClearControl* // 0x0127(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_ClockSet)(COMMAND_ATTRIBUTES)(CC_ClockSet* // 0x0128(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_HierarchyChangeAuth)(COMMAND_ATTRIBUTES)(CC_HierarchyChangeAuth* // 0x0129(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_NV_DefineSpace)(COMMAND_ATTRIBUTES)(CC_NV_DefineSpace* // 0x012A(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_PCR_Allocate)(COMMAND_ATTRIBUTES)(CC_PCR_Allocate* // 0x012B(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_PCR_SetAuthPolicy)(COMMAND_ATTRIBUTES)(CC_PCR_SetAuthPolicy* // 0x012C(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_PP_Commands)(COMMAND_ATTRIBUTES)(CC_PP_Commands* // 0x012D(IS_IMPLEMENTED+HANDLE_1_USER+PP_REQUIRED)),#endif#if (PAD_LIST || CC_SetPrimaryPolicy)(COMMAND_ATTRIBUTES)(CC_SetPrimaryPolicy* // 0x012E(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_FieldUpgradeStart)(COMMAND_ATTRIBUTES)(CC_FieldUpgradeStart* // 0x012F(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+PP_COMMAND)),#endif#if (PAD_LIST || CC_ClockRateAdjust)(COMMAND_ATTRIBUTES)(CC_ClockRateAdjust* // 0x0130(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 15
April 15, 2019

Trusted Platform Module Library
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514

Part 4: Supporting Routines#if (PAD_LIST || CC_CreatePrimary)(COMMAND_ATTRIBUTES)(CC_CreatePrimary* // 0x0131(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)),#endif#if (PAD_LIST || CC_NV_GlobalWriteLock)(COMMAND_ATTRIBUTES)(CC_NV_GlobalWriteLock* // 0x0132(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_GetCommandAuditDigest)(COMMAND_ATTRIBUTES)(CC_GetCommandAuditDigest* // 0x0133(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_NV_Increment)(COMMAND_ATTRIBUTES)(CC_NV_Increment* // 0x0134(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_SetBits)(COMMAND_ATTRIBUTES)(CC_NV_SetBits* // 0x0135(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_Extend)(COMMAND_ATTRIBUTES)(CC_NV_Extend* // 0x0136(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_Write)(COMMAND_ATTRIBUTES)(CC_NV_Write* // 0x0137(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_WriteLock)(COMMAND_ATTRIBUTES)(CC_NV_WriteLock* // 0x0138(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_DictionaryAttackLockReset)(COMMAND_ATTRIBUTES)(CC_DictionaryAttackLockReset* // 0x0139(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_DictionaryAttackParameters)(COMMAND_ATTRIBUTES)(CC_DictionaryAttackParameters * // 0x013A(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_ChangeAuth)(COMMAND_ATTRIBUTES)(CC_NV_ChangeAuth* // 0x013B(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN)),#endif#if (PAD_LIST || CC_PCR_Event)(COMMAND_ATTRIBUTES)(CC_PCR_Event* // 0x013C(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_PCR_Reset)(COMMAND_ATTRIBUTES)(CC_PCR_Reset* // 0x013D(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_SequenceComplete)(COMMAND_ATTRIBUTES)(CC_SequenceComplete* // 0x013E(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_SetAlgorithmSet)(COMMAND_ATTRIBUTES)(CC_SetAlgorithmSet* // 0x013F(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_SetCommandCodeAuditStatus)(COMMAND_ATTRIBUTES)(CC_SetCommandCodeAuditStatus* // 0x0140(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#endif#if (PAD_LIST || CC_FieldUpgradeData)(COMMAND_ATTRIBUTES)(CC_FieldUpgradeData* // 0x0141

Page 16
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580

Trusted Platform Module Library(IS_IMPLEMENTED+DECRYPT_2)),#endif#if (PAD_LIST || CC_IncrementalSelfTest)(COMMAND_ATTRIBUTES)(CC_IncrementalSelfTest* // 0x0142(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_SelfTest)(COMMAND_ATTRIBUTES)(CC_SelfTest* // 0x0143(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_Startup)(COMMAND_ATTRIBUTES)(CC_Startup* // 0x0144(IS_IMPLEMENTED+NO_SESSIONS)),#endif#if (PAD_LIST || CC_Shutdown)(COMMAND_ATTRIBUTES)(CC_Shutdown* // 0x0145(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_StirRandom)(COMMAND_ATTRIBUTES)(CC_StirRandom* // 0x0146(IS_IMPLEMENTED+DECRYPT_2)),#endif#if (PAD_LIST || CC_ActivateCredential)(COMMAND_ATTRIBUTES)(CC_ActivateCredential* // 0x0147(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Certify)(COMMAND_ATTRIBUTES)(CC_Certify* // 0x0148(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_PolicyNV)(COMMAND_ATTRIBUTES)(CC_PolicyNV* // 0x0149(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_CertifyCreation)(COMMAND_ATTRIBUTES)(CC_CertifyCreation* // 0x014A(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Duplicate)(COMMAND_ATTRIBUTES)(CC_Duplicate* // 0x014B(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+ENCRYPT_2)),#endif#if (PAD_LIST || CC_GetTime)(COMMAND_ATTRIBUTES)(CC_GetTime* // 0x014C(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_GetSessionAuditDigest)(COMMAND_ATTRIBUTES)(CC_GetSessionAuditDigest* // 0x014D(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_NV_Read)(COMMAND_ATTRIBUTES)(CC_NV_Read* // 0x014E(IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_NV_ReadLock)(COMMAND_ATTRIBUTES)(CC_NV_ReadLock* // 0x014F(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_ObjectChangeAuth)(COMMAND_ATTRIBUTES)(CC_ObjectChangeAuth* // 0x0150(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+ENCRYPT_2)),#endif#if (PAD_LIST || CC_PolicySecret)(COMMAND_ATTRIBUTES)(CC_PolicySecret* // 0x0151(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ALLOW_TRIAL+ENCRYPT_2)),#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 17
April 15, 2019

Trusted Platform Module Library
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

Part 4: Supporting Routines#if (PAD_LIST || CC_Rewrap)(COMMAND_ATTRIBUTES)(CC_Rewrap* // 0x0152(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Create)(COMMAND_ATTRIBUTES)(CC_Create* // 0x0153(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_ECDH_ZGen)(COMMAND_ATTRIBUTES)(CC_ECDH_ZGen* // 0x0154(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || (CC_HMAC || CC_MAC))(COMMAND_ATTRIBUTES)((CC_HMAC || CC_MAC)* // 0x0155(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Import)(COMMAND_ATTRIBUTES)(CC_Import* // 0x0156(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Load)(COMMAND_ATTRIBUTES)(CC_Load* // 0x0157(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2+R_HANDLE)),#endif#if (PAD_LIST || CC_Quote)(COMMAND_ATTRIBUTES)(CC_Quote* // 0x0158(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_RSA_Decrypt)(COMMAND_ATTRIBUTES)(CC_RSA_Decrypt* // 0x0159(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST )(COMMAND_ATTRIBUTES)(0),// 0x015A#endif#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start))(COMMAND_ATTRIBUTES)((CC_HMAC_Start || CC_MAC_Start) * // 0x015B(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+R_HANDLE)),#endif#if (PAD_LIST || CC_SequenceUpdate)(COMMAND_ATTRIBUTES)(CC_SequenceUpdate* // 0x015C(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_Sign)(COMMAND_ATTRIBUTES)(CC_Sign* // 0x015D(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_Unseal)(COMMAND_ATTRIBUTES)(CC_Unseal* // 0x015E(IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST )(COMMAND_ATTRIBUTES)(0),// 0x015F#endif#if (PAD_LIST || CC_PolicySigned)(COMMAND_ATTRIBUTES)(CC_PolicySigned* // 0x0160(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL+ENCRYPT_2)),#endif#if (PAD_LIST || CC_ContextLoad)(COMMAND_ATTRIBUTES)(CC_ContextLoad* // 0x0161(IS_IMPLEMENTED+NO_SESSIONS+R_HANDLE)),#endif#if (PAD_LIST || CC_ContextSave)(COMMAND_ATTRIBUTES)(CC_ContextSave* // 0x0162(IS_IMPLEMENTED+NO_SESSIONS)),#endifPage 18
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

Trusted Platform Module Library#if (PAD_LIST || CC_ECDH_KeyGen)(COMMAND_ATTRIBUTES)(CC_ECDH_KeyGen*(IS_IMPLEMENTED+ENCRYPT_2)),#endif#if (PAD_LIST || CC_EncryptDecrypt)(COMMAND_ATTRIBUTES)(CC_EncryptDecrypt*(IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_FlushContext)(COMMAND_ATTRIBUTES)(CC_FlushContext*(IS_IMPLEMENTED+NO_SESSIONS)),#endif#if (PAD_LIST )(COMMAND_ATTRIBUTES)(0),#endif#if (PAD_LIST || CC_LoadExternal)(COMMAND_ATTRIBUTES)(CC_LoadExternal*(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)),#endif#if (PAD_LIST || CC_MakeCredential)(COMMAND_ATTRIBUTES)(CC_MakeCredential*(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),#endif#if (PAD_LIST || CC_NV_ReadPublic)(COMMAND_ATTRIBUTES)(CC_NV_ReadPublic*(IS_IMPLEMENTED+ENCRYPT_2)),#endif#if (PAD_LIST || CC_PolicyAuthorize)(COMMAND_ATTRIBUTES)(CC_PolicyAuthorize*(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyAuthValue)(COMMAND_ATTRIBUTES)(CC_PolicyAuthValue*(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyCommandCode)(COMMAND_ATTRIBUTES)(CC_PolicyCommandCode*(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyCounterTimer)(COMMAND_ATTRIBUTES)(CC_PolicyCounterTimer*(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyCpHash)(COMMAND_ATTRIBUTES)(CC_PolicyCpHash*(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyLocality)(COMMAND_ATTRIBUTES)(CC_PolicyLocality*(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyNameHash)(COMMAND_ATTRIBUTES)(CC_PolicyNameHash*(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyOR)(COMMAND_ATTRIBUTES)(CC_PolicyOR*(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyTicket)(COMMAND_ATTRIBUTES)(CC_PolicyTicket*(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_ReadPublic)(COMMAND_ATTRIBUTES)(CC_ReadPublic*(IS_IMPLEMENTED+ENCRYPT_2)),

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019// 0x0163// 0x0164// 0x0165// 0x0166// 0x0167// 0x0168// 0x0169// 0x016A// 0x016B// 0x016C// 0x016D// 0x016E// 0x016F// 0x0170// 0x0171// 0x0172// 0x0173

Page 19
April 15, 2019

Trusted Platform Module Library
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

Part 4: Supporting Routines#endif#if (PAD_LIST || CC_RSA_Encrypt)(COMMAND_ATTRIBUTES)(CC_RSA_Encrypt*(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),#endif#if (PAD_LIST )(COMMAND_ATTRIBUTES)(0),#endif#if (PAD_LIST || CC_StartAuthSession)(COMMAND_ATTRIBUTES)(CC_StartAuthSession*(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)),#endif#if (PAD_LIST || CC_VerifySignature)(COMMAND_ATTRIBUTES)(CC_VerifySignature*(IS_IMPLEMENTED+DECRYPT_2)),#endif#if (PAD_LIST || CC_ECC_Parameters)(COMMAND_ATTRIBUTES)(CC_ECC_Parameters*(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_FirmwareRead)(COMMAND_ATTRIBUTES)(CC_FirmwareRead*(IS_IMPLEMENTED+ENCRYPT_2)),#endif#if (PAD_LIST || CC_GetCapability)(COMMAND_ATTRIBUTES)(CC_GetCapability*(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_GetRandom)(COMMAND_ATTRIBUTES)(CC_GetRandom*(IS_IMPLEMENTED+ENCRYPT_2)),#endif#if (PAD_LIST || CC_GetTestResult)(COMMAND_ATTRIBUTES)(CC_GetTestResult*(IS_IMPLEMENTED+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Hash)(COMMAND_ATTRIBUTES)(CC_Hash*(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),#endif#if (PAD_LIST || CC_PCR_Read)(COMMAND_ATTRIBUTES)(CC_PCR_Read*(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_PolicyPCR)(COMMAND_ATTRIBUTES)(CC_PolicyPCR*(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyRestart)(COMMAND_ATTRIBUTES)(CC_PolicyRestart*(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_ReadClock)(COMMAND_ATTRIBUTES)(CC_ReadClock*(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_PCR_Extend)(COMMAND_ATTRIBUTES)(CC_PCR_Extend*(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_PCR_SetAuthValue)(COMMAND_ATTRIBUTES)(CC_PCR_SetAuthValue*(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_Certify)(COMMAND_ATTRIBUTES)(CC_NV_Certify*

Page 20
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019// 0x0174// 0x0175// 0x0176// 0x0177// 0x0178// 0x0179// 0x017A// 0x017B// 0x017C// 0x017D// 0x017E// 0x017F// 0x0180// 0x0181// 0x0182// 0x0183// 0x0184

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

Trusted Platform Module Library(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_EventSequenceComplete)(COMMAND_ATTRIBUTES)(CC_EventSequenceComplete* // 0x0185(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER)),#endif#if (PAD_LIST || CC_HashSequenceStart)(COMMAND_ATTRIBUTES)(CC_HashSequenceStart* // 0x0186(IS_IMPLEMENTED+DECRYPT_2+R_HANDLE)),#endif#if (PAD_LIST || CC_PolicyPhysicalPresence)(COMMAND_ATTRIBUTES)(CC_PolicyPhysicalPresence* // 0x0187(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyDuplicationSelect)(COMMAND_ATTRIBUTES)(CC_PolicyDuplicationSelect* // 0x0188(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyGetDigest)(COMMAND_ATTRIBUTES)(CC_PolicyGetDigest* // 0x0189(IS_IMPLEMENTED+ALLOW_TRIAL+ENCRYPT_2)),#endif#if (PAD_LIST || CC_TestParms)(COMMAND_ATTRIBUTES)(CC_TestParms* // 0x018A(IS_IMPLEMENTED)),#endif#if (PAD_LIST || CC_Commit)(COMMAND_ATTRIBUTES)(CC_Commit* // 0x018B(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_PolicyPassword)(COMMAND_ATTRIBUTES)(CC_PolicyPassword* // 0x018C(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_ZGen_2Phase)(COMMAND_ATTRIBUTES)(CC_ZGen_2Phase* // 0x018D(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_EC_Ephemeral)(COMMAND_ATTRIBUTES)(CC_EC_Ephemeral* // 0x018E(IS_IMPLEMENTED+ENCRYPT_2)),#endif#if (PAD_LIST || CC_PolicyNvWritten)(COMMAND_ATTRIBUTES)(CC_PolicyNvWritten* // 0x018F(IS_IMPLEMENTED+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_PolicyTemplate)(COMMAND_ATTRIBUTES)(CC_PolicyTemplate* // 0x0190(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_CreateLoaded)(COMMAND_ATTRIBUTES)(CC_CreateLoaded* // 0x0191(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)),#endif#if (PAD_LIST || CC_PolicyAuthorizeNV)(COMMAND_ATTRIBUTES)(CC_PolicyAuthorizeNV* // 0x0192(IS_IMPLEMENTED+HANDLE_1_USER+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_EncryptDecrypt2)(COMMAND_ATTRIBUTES)(CC_EncryptDecrypt2* // 0x0193(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_AC_GetCapability)(COMMAND_ATTRIBUTES)(CC_AC_GetCapability* // 0x0194(IS_IMPLEMENTED)),#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 21
April 15, 2019

Trusted Platform Module Library
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863

Part 4: Supporting Routines#if (PAD_LIST || CC_AC_Send)(COMMAND_ATTRIBUTES)(CC_AC_Send* // 0x0195(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+HANDLE_2_USER)),#endif#if (PAD_LIST || CC_Policy_AC_SendSelect)(COMMAND_ATTRIBUTES)(CC_Policy_AC_SendSelect* // 0x0196(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)),#endif#if (PAD_LIST || CC_CertifyX509)(COMMAND_ATTRIBUTES)(CC_CertifyX509* // 0x0197(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)),#endif#if (PAD_LIST || CC_Vendor_TCG_Test)(COMMAND_ATTRIBUTES)(CC_Vendor_TCG_Test* // 0x0000(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),#endif0};#endif // _COMMAND_CODE_ATTRIBUTES_

Page 22
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.5

Trusted Platform Module Library

CommandAttributes.h

The attributes defined in this file are produced by the parser that creates the structure definitions fromPart 3. The attributes are defined in that parser and should track the attributes being tested inCommandCodeAttributes.c. Generally, when an attribute is added to this list, new code will be needed inCommandCodeAttributes.c to test it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#ifndef COMMAND_ATTRIBUTES_H#define COMMAND_ATTRIBUTES_H
typedef UINT16
COMMAND_ATTRIBUTES;#define NOT_IMPLEMENTED(COMMAND_ATTRIBUTES)(0)#define ENCRYPT_2((COMMAND_ATTRIBUTES)1 << 0)#define ENCRYPT_4((COMMAND_ATTRIBUTES)1 << 1)#define DECRYPT_2((COMMAND_ATTRIBUTES)1 << 2)#define DECRYPT_4((COMMAND_ATTRIBUTES)1 << 3)#define HANDLE_1_USER((COMMAND_ATTRIBUTES)1 << 4)#define HANDLE_1_ADMIN((COMMAND_ATTRIBUTES)1 << 5)#define HANDLE_1_DUP((COMMAND_ATTRIBUTES)1 << 6)#define HANDLE_2_USER((COMMAND_ATTRIBUTES)1 << 7)#define PP_COMMAND((COMMAND_ATTRIBUTES)1 << 8)#define IS_IMPLEMENTED((COMMAND_ATTRIBUTES)1 << 9)#define NO_SESSIONS((COMMAND_ATTRIBUTES)1 << 10)#define NV_COMMAND((COMMAND_ATTRIBUTES)1 << 11)#define PP_REQUIRED((COMMAND_ATTRIBUTES)1 << 12)#define R_HANDLE((COMMAND_ATTRIBUTES)1 << 13)#define ALLOW_TRIAL((COMMAND_ATTRIBUTES)1 << 14)#endif // COMMAND_ATTRIBUTES_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 23
April 15, 2019

Trusted Platform Module Library

5.6

Part 4: Supporting Routines

CommandDispatchData.h

This file should only be included by CommandCodeAttibutes.c
1#ifdef _COMMAND_TABLE_DISPATCH_

Define the stop value
2
3#define END_OF_LIST#define ADD_FLAG

0xff
0x80

These macros provide some variability in how the data is encoded. They also make the lines a little
sorter. ;-)
4
5
6
7

#
#
#
#

define UNMARSHAL_DISPATCH(name)(UNMARSHAL_t)name##_Unmarshal
define MARSHAL_DISPATCH(name)(MARSHAL_t)##name##_Marshal
define _UNMARSHAL_T_
UNMARSHAL_t
define _MARSHAL_T_
MARSHAL_t

The UnmarshalArray() contains the dispatch functions for the unmarshaling code. The defines in thisarray are used to make it easier to cross reference the unmarshaling values in the types array of eachcommand
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

const _UNMARSHAL_T_ UnmarshalArray[] = {#define TPMI_DH_CONTEXT_H_UNMARSHAL
0
UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT),#define TPMI_RH_AC_H_UNMARSHAL(TPMI_DH_CONTEXT_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_AC),#define TPMI_RH_CLEAR_H_UNMARSHAL(TPMI_RH_AC_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_CLEAR),#define TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL (TPMI_RH_CLEAR_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_AUTH),#define TPMI_RH_LOCKOUT_H_UNMARSHAL(TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_LOCKOUT),#define TPMI_RH_NV_AUTH_H_UNMARSHAL(TPMI_RH_LOCKOUT_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_NV_AUTH),#define TPMI_RH_NV_INDEX_H_UNMARSHAL(TPMI_RH_NV_AUTH_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_NV_INDEX),#define TPMI_RH_PLATFORM_H_UNMARSHAL(TPMI_RH_NV_INDEX_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_PLATFORM),#define TPMI_RH_PROVISION_H_UNMARSHAL(TPMI_RH_PLATFORM_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_PROVISION),#define TPMI_SH_HMAC_H_UNMARSHAL(TPMI_RH_PROVISION_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_SH_HMAC),#define TPMI_SH_POLICY_H_UNMARSHAL(TPMI_SH_HMAC_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_SH_POLICY),// HANDLE_FIRST_FLAG_TYPE is the first handle that needs a flag when called.
#define HANDLE_FIRST_FLAG_TYPE(TPMI_SH_POLICY_H_UNMARSHAL + 1)
#define TPMI_DH_ENTITY_H_UNMARSHAL(TPMI_SH_POLICY_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_ENTITY),#define TPMI_DH_OBJECT_H_UNMARSHAL(TPMI_DH_ENTITY_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_OBJECT),#define TPMI_DH_PARENT_H_UNMARSHAL(TPMI_DH_OBJECT_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_PARENT),#define TPMI_DH_PCR_H_UNMARSHAL(TPMI_DH_PARENT_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_PCR),#define TPMI_RH_ENDORSEMENT_H_UNMARSHAL(TPMI_DH_PCR_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_ENDORSEMENT),#define TPMI_RH_HIERARCHY_H_UNMARSHAL(TPMI_RH_ENDORSEMENT_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY),// PARAMETER_FIRST_TYPE marks the end of the handle list.
#define PARAMETER_FIRST_TYPE(TPMI_RH_HIERARCHY_H_UNMARSHAL + 1)
#define TPM2B_DATA_P_UNMARSHAL(TPMI_RH_HIERARCHY_H_UNMARSHAL + 1)

Page 24
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

Trusted Platform Module Library

UNMARSHAL_DISPATCH(TPM2B_DATA),#define TPM2B_DIGEST_P_UNMARSHAL(TPM2B_DATA_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_DIGEST),#define TPM2B_ECC_PARAMETER_P_UNMARSHAL(TPM2B_DIGEST_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_ECC_PARAMETER),#define TPM2B_ECC_POINT_P_UNMARSHAL(TPM2B_ECC_PARAMETER_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_ECC_POINT),#define TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL (TPM2B_ECC_POINT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET),#define TPM2B_EVENT_P_UNMARSHAL(TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_EVENT),#define TPM2B_ID_OBJECT_P_UNMARSHAL(TPM2B_EVENT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_ID_OBJECT),#define TPM2B_IV_P_UNMARSHAL(TPM2B_ID_OBJECT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_IV),#define TPM2B_MAX_BUFFER_P_UNMARSHAL(TPM2B_IV_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_MAX_BUFFER),#define TPM2B_MAX_NV_BUFFER_P_UNMARSHAL(TPM2B_MAX_BUFFER_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER),#define TPM2B_NAME_P_UNMARSHAL(TPM2B_MAX_NV_BUFFER_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_NAME),#define TPM2B_NV_PUBLIC_P_UNMARSHAL(TPM2B_NAME_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_NV_PUBLIC),#define TPM2B_PRIVATE_P_UNMARSHAL(TPM2B_NV_PUBLIC_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_PRIVATE),#define TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL(TPM2B_PRIVATE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA),#define TPM2B_SENSITIVE_P_UNMARSHAL(TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_SENSITIVE),#define TPM2B_SENSITIVE_CREATE_P_UNMARSHAL (TPM2B_SENSITIVE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_CREATE),#define TPM2B_SENSITIVE_DATA_P_UNMARSHAL(TPM2B_SENSITIVE_CREATE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA),#define TPM2B_TEMPLATE_P_UNMARSHAL(TPM2B_SENSITIVE_DATA_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_TEMPLATE),#define TPM2B_TIMEOUT_P_UNMARSHAL(TPM2B_TEMPLATE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_TIMEOUT),#define TPMI_DH_CONTEXT_P_UNMARSHAL(TPM2B_TIMEOUT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT),#define TPMI_DH_PERSISTENT_P_UNMARSHAL(TPMI_DH_CONTEXT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_PERSISTENT),#define TPMI_ECC_CURVE_P_UNMARSHAL(TPMI_DH_PERSISTENT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_ECC_CURVE),#define TPMI_YES_NO_P_UNMARSHAL(TPMI_ECC_CURVE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_YES_NO),#define TPML_ALG_P_UNMARSHAL(TPMI_YES_NO_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPML_ALG),#define TPML_CC_P_UNMARSHAL(TPML_ALG_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPML_CC),#define TPML_DIGEST_P_UNMARSHAL(TPML_CC_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPML_DIGEST),#define TPML_DIGEST_VALUES_P_UNMARSHAL(TPML_DIGEST_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPML_DIGEST_VALUES),#define TPML_PCR_SELECTION_P_UNMARSHAL(TPML_DIGEST_VALUES_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPML_PCR_SELECTION),#define TPMS_CONTEXT_P_UNMARSHAL(TPML_PCR_SELECTION_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMS_CONTEXT),#define TPMT_PUBLIC_PARMS_P_UNMARSHAL(TPMS_CONTEXT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_PUBLIC_PARMS),#define TPMT_TK_AUTH_P_UNMARSHAL(TPMT_PUBLIC_PARMS_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_TK_AUTH),#define TPMT_TK_CREATION_P_UNMARSHAL(TPMT_TK_AUTH_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_TK_CREATION),#define TPMT_TK_HASHCHECK_P_UNMARSHAL(TPMT_TK_CREATION_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_TK_HASHCHECK),#define TPMT_TK_VERIFIED_P_UNMARSHAL(TPMT_TK_HASHCHECK_P_UNMARSHAL + 1)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 25
April 15, 2019

Trusted Platform Module Library
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

Part 4: Supporting Routines

UNMARSHAL_DISPATCH(TPMT_TK_VERIFIED),#define TPM_AT_P_UNMARSHAL(TPMT_TK_VERIFIED_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM_AT),#define TPM_CAP_P_UNMARSHAL(TPM_AT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM_CAP),#define TPM_CLOCK_ADJUST_P_UNMARSHAL(TPM_CAP_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM_CLOCK_ADJUST),#define TPM_EO_P_UNMARSHAL(TPM_CLOCK_ADJUST_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM_EO),#define TPM_SE_P_UNMARSHAL(TPM_EO_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM_SE),#define TPM_SU_P_UNMARSHAL(TPM_SE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM_SU),#define UINT16_P_UNMARSHAL(TPM_SU_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(UINT16),#define UINT32_P_UNMARSHAL(UINT16_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(UINT32),#define UINT64_P_UNMARSHAL(UINT32_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(UINT64),#define UINT8_P_UNMARSHAL(UINT64_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(UINT8),// PARAMETER_FIRST_FLAG_TYPE is the first parameter to need a flag.
#define PARAMETER_FIRST_FLAG_TYPE(UINT8_P_UNMARSHAL + 1)
#define TPM2B_PUBLIC_P_UNMARSHAL(UINT8_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPM2B_PUBLIC),#define TPMI_ALG_CIPHER_MODE_P_UNMARSHAL(TPM2B_PUBLIC_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_ALG_CIPHER_MODE),#define TPMI_ALG_HASH_P_UNMARSHAL(TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_ALG_HASH),#define TPMI_ALG_MAC_SCHEME_P_UNMARSHAL(TPMI_ALG_HASH_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_ALG_MAC_SCHEME),#define TPMI_DH_PCR_P_UNMARSHAL(TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_DH_PCR),#define TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL(TPMI_DH_PCR_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_ECC_KEY_EXCHANGE),#define TPMI_RH_ENABLES_P_UNMARSHAL(TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_ENABLES),#define TPMI_RH_HIERARCHY_P_UNMARSHAL(TPMI_RH_ENABLES_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY),#define TPMT_RSA_DECRYPT_P_UNMARSHAL(TPMI_RH_HIERARCHY_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_RSA_DECRYPT),#define TPMT_SIGNATURE_P_UNMARSHAL(TPMT_RSA_DECRYPT_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_SIGNATURE),#define TPMT_SIG_SCHEME_P_UNMARSHAL(TPMT_SIGNATURE_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_SIG_SCHEME),#define TPMT_SYM_DEF_P_UNMARSHAL(TPMT_SIG_SCHEME_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_SYM_DEF),#define TPMT_SYM_DEF_OBJECT_P_UNMARSHAL(TPMT_SYM_DEF_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_SYM_DEF_OBJECT)// PARAMETER_LAST_TYPE is the end of the command parameter list.
#define PARAMETER_LAST_TYPE(TPMT_SYM_DEF_OBJECT_P_UNMARSHAL)};

The MarshalArray() contains the dispatch functions for the marshaling code. The defines in this array areused to make it easier to cross reference the marshaling values in the types array of each command
166
167
168
169
170
171
172
173
174

const _MARSHAL_T_ MarshalArray[] = {#define UINT32_H_MARSHAL0MARSHAL_DISPATCH(UINT32),// RESPONSE_PARAMETER_FIRST_TYPE marks the end of the response handles.
#define RESPONSE_PARAMETER_FIRST_TYPE(UINT32_H_MARSHAL + 1)
#define TPM2B_ATTEST_P_MARSHAL(UINT32_H_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_ATTEST),#define TPM2B_CREATION_DATA_P_MARSHAL(TPM2B_ATTEST_P_MARSHAL + 1)

Page 26
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

Trusted Platform Module Library

MARSHAL_DISPATCH(TPM2B_CREATION_DATA),#define TPM2B_DATA_P_MARSHAL(TPM2B_CREATION_DATA_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_DATA),#define TPM2B_DIGEST_P_MARSHAL(TPM2B_DATA_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_DIGEST),#define TPM2B_ECC_POINT_P_MARSHAL(TPM2B_DIGEST_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_ECC_POINT),#define TPM2B_ENCRYPTED_SECRET_P_MARSHAL(TPM2B_ECC_POINT_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET),#define TPM2B_ID_OBJECT_P_MARSHAL(TPM2B_ENCRYPTED_SECRET_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_ID_OBJECT),#define TPM2B_IV_P_MARSHAL(TPM2B_ID_OBJECT_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_IV),#define TPM2B_MAX_BUFFER_P_MARSHAL(TPM2B_IV_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_MAX_BUFFER),#define TPM2B_MAX_NV_BUFFER_P_MARSHAL(TPM2B_MAX_BUFFER_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER),#define TPM2B_NAME_P_MARSHAL(TPM2B_MAX_NV_BUFFER_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_NAME),#define TPM2B_NV_PUBLIC_P_MARSHAL(TPM2B_NAME_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_NV_PUBLIC),#define TPM2B_PRIVATE_P_MARSHAL(TPM2B_NV_PUBLIC_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_PRIVATE),#define TPM2B_PUBLIC_P_MARSHAL(TPM2B_PRIVATE_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_PUBLIC),#define TPM2B_PUBLIC_KEY_RSA_P_MARSHAL(TPM2B_PUBLIC_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA),#define TPM2B_SENSITIVE_DATA_P_MARSHAL(TPM2B_PUBLIC_KEY_RSA_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA),#define TPM2B_TIMEOUT_P_MARSHAL(TPM2B_SENSITIVE_DATA_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPM2B_TIMEOUT),#define UINT8_P_MARSHAL(TPM2B_TIMEOUT_P_MARSHAL + 1)
MARSHAL_DISPATCH(UINT8),#define TPML_AC_CAPABILITIES_P_MARSHAL(UINT8_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPML_AC_CAPABILITIES),#define TPML_ALG_P_MARSHAL(TPML_AC_CAPABILITIES_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPML_ALG),#define TPML_DIGEST_P_MARSHAL(TPML_ALG_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPML_DIGEST),#define TPML_DIGEST_VALUES_P_MARSHAL(TPML_DIGEST_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPML_DIGEST_VALUES),#define TPML_PCR_SELECTION_P_MARSHAL(TPML_DIGEST_VALUES_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPML_PCR_SELECTION),#define TPMS_AC_OUTPUT_P_MARSHAL(TPML_PCR_SELECTION_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMS_AC_OUTPUT),#define TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL (TPMS_AC_OUTPUT_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMS_ALGORITHM_DETAIL_ECC),#define TPMS_CAPABILITY_DATA_P_MARSHAL\(TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMS_CAPABILITY_DATA),#define TPMS_CONTEXT_P_MARSHAL(TPMS_CAPABILITY_DATA_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMS_CONTEXT),#define TPMS_TIME_INFO_P_MARSHAL(TPMS_CONTEXT_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMS_TIME_INFO),#define TPMT_HA_P_MARSHAL(TPMS_TIME_INFO_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMT_HA),#define TPMT_SIGNATURE_P_MARSHAL(TPMT_HA_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMT_SIGNATURE),#define TPMT_TK_AUTH_P_MARSHAL(TPMT_SIGNATURE_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMT_TK_AUTH),#define TPMT_TK_CREATION_P_MARSHAL(TPMT_TK_AUTH_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMT_TK_CREATION),#define TPMT_TK_HASHCHECK_P_MARSHAL(TPMT_TK_CREATION_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMT_TK_HASHCHECK),#define TPMT_TK_VERIFIED_P_MARSHAL(TPMT_TK_HASHCHECK_P_MARSHAL + 1)
MARSHAL_DISPATCH(TPMT_TK_VERIFIED),

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 27
April 15, 2019

Trusted Platform Module Library
241
242
243
244
245
246
247

Part 4: Supporting Routines#define UINT32_P_MARSHAL(TPMT_TK_VERIFIED_P_MARSHAL + 1)
MARSHAL_DISPATCH(UINT32),#define UINT16_P_MARSHAL(UINT32_P_MARSHAL + 1)
MARSHAL_DISPATCH(UINT16)// RESPONSE_PARAMETER_LAST_TYPE is the end of the response parameter list.
#define RESPONSE_PARAMETER_LAST_TYPE(UINT16_P_MARSHAL)};

This list of aliases allows the types in the _COMMAND_DESCRIPTOR_T to match the types in thecommand/response templates of part 3.
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

#define INT32_P_UNMARSHALUINT32_P_UNMARSHAL#define TPM2B_AUTH_P_UNMARSHAL
TPM2B_DIGEST_P_UNMARSHAL#define TPM2B_NONCE_P_UNMARSHAL
TPM2B_DIGEST_P_UNMARSHAL#define TPM2B_OPERAND_P_UNMARSHAL
TPM2B_DIGEST_P_UNMARSHAL#define TPMA_LOCALITY_P_UNMARSHALUINT8_P_UNMARSHAL#define TPM_CC_P_UNMARSHALUINT32_P_UNMARSHAL#define TPMI_DH_CONTEXT_H_MARSHALUINT32_H_MARSHAL#define TPMI_DH_OBJECT_H_MARSHALUINT32_H_MARSHAL#define TPMI_SH_AUTH_SESSION_H_MARSHALUINT32_H_MARSHAL#define TPM_HANDLE_H_MARSHALUINT32_H_MARSHAL#define TPM2B_NONCE_P_MARSHAL
TPM2B_DIGEST_P_MARSHAL#define TPMI_YES_NO_P_MARSHALUINT8_P_MARSHAL#define TPM_RC_P_MARSHALUINT32_P_MARSHAL#if CC_Startup#include "Startup_fp.h"
typedef TPM_RC (Startup_Entry)(
Startup_In*in);typedef const struct {Startup_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} Startup_COMMAND_DESCRIPTOR_t;
Startup_COMMAND_DESCRIPTOR_t _StartupData = {/* entry*/&TPM2_Startup,/* inSize*/(UINT16)(sizeof(Startup_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(Startup_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPM_SU_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _StartupDataAddress (&_StartupData)#else#define _StartupDataAddress 0#endif // CC_Startup#if CC_Shutdown#include "Shutdown_fp.h"
typedef TPM_RC (Shutdown_Entry)(
Shutdown_In*in);typedef const struct {Shutdown_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} Shutdown_COMMAND_DESCRIPTOR_t;
Shutdown_COMMAND_DESCRIPTOR_t _ShutdownData = {/* entry*/&TPM2_Shutdown,/* inSize*/(UINT16)(sizeof(Shutdown_In)),

Page 28
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

/* outSize*//* offsetOfTypes *//* offsets*//* types*/

Trusted Platform Module Library0,
offsetof(Shutdown_COMMAND_DESCRIPTOR_t, types),// No parameter offsets;{TPM_SU_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ShutdownDataAddress (&_ShutdownData)#else#define _ShutdownDataAddress 0#endif // CC_Shutdown#if CC_SelfTest#include "SelfTest_fp.h"
typedef TPM_RC (SelfTest_Entry)(
SelfTest_In*in);typedef const struct {SelfTest_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} SelfTest_COMMAND_DESCRIPTOR_t;
SelfTest_COMMAND_DESCRIPTOR_t _SelfTestData = {/* entry*/&TPM2_SelfTest,/* inSize*/(UINT16)(sizeof(SelfTest_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(SelfTest_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_YES_NO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _SelfTestDataAddress (&_SelfTestData)#else#define _SelfTestDataAddress 0#endif // CC_SelfTest#if CC_IncrementalSelfTest#include "IncrementalSelfTest_fp.h"
typedef TPM_RC (IncrementalSelfTest_Entry)(
IncrementalSelfTest_In*in,
IncrementalSelfTest_Out*out);
typedef const struct {IncrementalSelfTest_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} IncrementalSelfTest_COMMAND_DESCRIPTOR_t;
IncrementalSelfTest_COMMAND_DESCRIPTOR_t _IncrementalSelfTestData = {/* entry*/&TPM2_IncrementalSelfTest,/* inSize*/(UINT16)(sizeof(IncrementalSelfTest_In)),/* outSize*/(UINT16)(sizeof(IncrementalSelfTest_Out)),/* offsetOfTypes */offsetof(IncrementalSelfTest_COMMAND_DESCRIPTOR_t,
types),/* offsets*/// No parameter offsets;/* types*/{TPML_ALG_P_UNMARSHAL,END_OF_LIST,
TPML_ALG_P_MARSHAL,END_OF_LIST}};#define _IncrementalSelfTestDataAddress (&_IncrementalSelfTestData)#else#define _IncrementalSelfTestDataAddress 0#endif // CC_IncrementalSelfTest

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 29
April 15, 2019

Trusted Platform Module Library
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

Part 4: Supporting Routines#if CC_GetTestResult#include "GetTestResult_fp.h"
typedef TPM_RC (GetTestResult_Entry)(
GetTestResult_Out*out);
typedef const struct {GetTestResult_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} GetTestResult_COMMAND_DESCRIPTOR_t;
GetTestResult_COMMAND_DESCRIPTOR_t _GetTestResultData = {/* entry*/&TPM2_GetTestResult,/* inSize*/0,/* outSize*/(UINT16)(sizeof(GetTestResult_Out)),/* offsetOfTypes */offsetof(GetTestResult_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(GetTestResult_Out, testResult))},/* types*/{END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,
TPM_RC_P_MARSHAL,END_OF_LIST}};#define _GetTestResultDataAddress (&_GetTestResultData)#else#define _GetTestResultDataAddress 0#endif // CC_GetTestResult#if CC_StartAuthSession#include "StartAuthSession_fp.h"
typedef TPM_RC (StartAuthSession_Entry)(
StartAuthSession_In*in,StartAuthSession_Out*out);typedef const struct {StartAuthSession_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[7];BYTE
types[11];} StartAuthSession_COMMAND_DESCRIPTOR_t;
StartAuthSession_COMMAND_DESCRIPTOR_t _StartAuthSessionData = {/* entry*/&TPM2_StartAuthSession,/* inSize*/(UINT16)(sizeof(StartAuthSession_In)),/* outSize*/(UINT16)(sizeof(StartAuthSession_Out)),/* offsetOfTypes */offsetof(StartAuthSession_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(StartAuthSession_In, bind)),(UINT16)(offsetof(StartAuthSession_In, nonceCaller)),(UINT16)(offsetof(StartAuthSession_In, encryptedSalt)),(UINT16)(offsetof(StartAuthSession_In, sessionType)),(UINT16)(offsetof(StartAuthSession_In, symmetric)),(UINT16)(offsetof(StartAuthSession_In, authHash)),(UINT16)(offsetof(StartAuthSession_Out, nonceTPM))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,
TPMI_DH_ENTITY_H_UNMARSHAL + ADD_FLAG,TPM2B_NONCE_P_UNMARSHAL,TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL,TPM_SE_P_UNMARSHAL,
TPMT_SYM_DEF_P_UNMARSHAL + ADD_FLAG,
TPMI_ALG_HASH_P_UNMARSHAL,END_OF_LIST,
TPMI_SH_AUTH_SESSION_H_MARSHAL,TPM2B_NONCE_P_MARSHAL,END_OF_LIST}};

Page 30
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

Trusted Platform Module Library#define _StartAuthSessionDataAddress (&_StartAuthSessionData)#else#define _StartAuthSessionDataAddress 0#endif // CC_StartAuthSession#if CC_PolicyRestart#include "PolicyRestart_fp.h"
typedef TPM_RC (PolicyRestart_Entry)(
PolicyRestart_In*in);typedef const struct {PolicyRestart_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} PolicyRestart_COMMAND_DESCRIPTOR_t;
PolicyRestart_COMMAND_DESCRIPTOR_t _PolicyRestartData = {/* entry*/&TPM2_PolicyRestart,/* inSize*/(UINT16)(sizeof(PolicyRestart_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyRestart_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyRestartDataAddress (&_PolicyRestartData)#else#define _PolicyRestartDataAddress 0#endif // CC_PolicyRestart#if CC_Create#include "Create_fp.h"
typedef TPM_RC (Create_Entry)(
Create_In*in,
Create_Out*out);typedef const struct {Create_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[8];BYTE
types[12];} Create_COMMAND_DESCRIPTOR_t;
Create_COMMAND_DESCRIPTOR_t _CreateData = {/* entry*/&TPM2_Create,/* inSize*/(UINT16)(sizeof(Create_In)),/* outSize*/(UINT16)(sizeof(Create_Out)),/* offsetOfTypes */offsetof(Create_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Create_In, inSensitive)),(UINT16)(offsetof(Create_In, inPublic)),(UINT16)(offsetof(Create_In, outsideInfo)),(UINT16)(offsetof(Create_In, creationPCR)),(UINT16)(offsetof(Create_Out, outPublic)),(UINT16)(offsetof(Create_Out, creationData)),(UINT16)(offsetof(Create_Out, creationHash)),(UINT16)(offsetof(Create_Out, creationTicket))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_SENSITIVE_CREATE_P_UNMARSHAL,TPM2B_PUBLIC_P_UNMARSHAL,TPM2B_DATA_P_UNMARSHAL,
TPML_PCR_SELECTION_P_UNMARSHAL,END_OF_LIST,
TPM2B_PRIVATE_P_MARSHAL,TPM2B_PUBLIC_P_MARSHAL,TPM2B_CREATION_DATA_P_MARSHAL,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 31
April 15, 2019

Trusted Platform Module Library
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564

Part 4: Supporting Routines
TPM2B_DIGEST_P_MARSHAL,
TPMT_TK_CREATION_P_MARSHAL,END_OF_LIST}};#define _CreateDataAddress (&_CreateData)#else#define _CreateDataAddress 0#endif // CC_Create#if CC_Load#include "Load_fp.h"
typedef TPM_RC (Load_Entry)(
Load_In*in,
Load_Out*out);
typedef const struct {Load_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} Load_COMMAND_DESCRIPTOR_t;
Load_COMMAND_DESCRIPTOR_t _LoadData = {/* entry*/&TPM2_Load,/* inSize*/(UINT16)(sizeof(Load_In)),/* outSize*/(UINT16)(sizeof(Load_Out)),/* offsetOfTypes */offsetof(Load_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Load_In, inPrivate)),(UINT16)(offsetof(Load_In, inPublic)),(UINT16)(offsetof(Load_Out, name))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_PRIVATE_P_UNMARSHAL,TPM2B_PUBLIC_P_UNMARSHAL,END_OF_LIST,
TPM_HANDLE_H_MARSHAL,TPM2B_NAME_P_MARSHAL,END_OF_LIST}};#define _LoadDataAddress (&_LoadData)#else#define _LoadDataAddress 0#endif // CC_Load#if CC_LoadExternal#include "LoadExternal_fp.h"
typedef TPM_RC (LoadExternal_Entry)(
LoadExternal_In*in,
LoadExternal_Out*out);typedef const struct {LoadExternal_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} LoadExternal_COMMAND_DESCRIPTOR_t;
LoadExternal_COMMAND_DESCRIPTOR_t _LoadExternalData = {/* entry*/&TPM2_LoadExternal,/* inSize*/(UINT16)(sizeof(LoadExternal_In)),/* outSize*/(UINT16)(sizeof(LoadExternal_Out)),/* offsetOfTypes */offsetof(LoadExternal_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(LoadExternal_In, inPublic)),(UINT16)(offsetof(LoadExternal_In, hierarchy)),(UINT16)(offsetof(LoadExternal_Out, name))},/* types*/{TPM2B_SENSITIVE_P_UNMARSHAL,TPM2B_PUBLIC_P_UNMARSHAL + ADD_FLAG,

Page 32
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628

Trusted Platform Module Library
TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM_HANDLE_H_MARSHAL,TPM2B_NAME_P_MARSHAL,END_OF_LIST}};#define _LoadExternalDataAddress (&_LoadExternalData)#else#define _LoadExternalDataAddress 0#endif // CC_LoadExternal#if CC_ReadPublic#include "ReadPublic_fp.h"
typedef TPM_RC (ReadPublic_Entry)(
ReadPublic_In*in,
ReadPublic_Out*out);typedef const struct {ReadPublic_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} ReadPublic_COMMAND_DESCRIPTOR_t;
ReadPublic_COMMAND_DESCRIPTOR_t _ReadPublicData = {/* entry*/&TPM2_ReadPublic,/* inSize*/(UINT16)(sizeof(ReadPublic_In)),/* outSize*/(UINT16)(sizeof(ReadPublic_Out)),/* offsetOfTypes */offsetof(ReadPublic_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ReadPublic_Out, name)),(UINT16)(offsetof(ReadPublic_Out, qualifiedName))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,END_OF_LIST,
TPM2B_PUBLIC_P_MARSHAL,TPM2B_NAME_P_MARSHAL,TPM2B_NAME_P_MARSHAL,END_OF_LIST}};#define _ReadPublicDataAddress (&_ReadPublicData)#else#define _ReadPublicDataAddress 0#endif // CC_ReadPublic#if CC_ActivateCredential#include "ActivateCredential_fp.h"
typedef TPM_RC (ActivateCredential_Entry)(
ActivateCredential_In*in,
ActivateCredential_Out*out);typedef const struct {ActivateCredential_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} ActivateCredential_COMMAND_DESCRIPTOR_t;
ActivateCredential_COMMAND_DESCRIPTOR_t _ActivateCredentialData = {/* entry*/&TPM2_ActivateCredential,/* inSize*/(UINT16)(sizeof(ActivateCredential_In)),/* outSize*/(UINT16)(sizeof(ActivateCredential_Out)),/* offsetOfTypes */offsetof(ActivateCredential_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(ActivateCredential_In, keyHandle)),(UINT16)(offsetof(ActivateCredential_In,
credentialBlob)),(UINT16)(offsetof(ActivateCredential_In, secret))},Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 33
April 15, 2019

Trusted Platform Module Library
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694

/* types*/

Part 4: Supporting Routines{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_ID_OBJECT_P_UNMARSHAL,TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,END_OF_LIST}};#define _ActivateCredentialDataAddress (&_ActivateCredentialData)#else#define _ActivateCredentialDataAddress 0#endif // CC_ActivateCredential#if CC_MakeCredential#include "MakeCredential_fp.h"
typedef TPM_RC (MakeCredential_Entry)(
MakeCredential_In*in,
MakeCredential_Out*out);typedef const struct {MakeCredential_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} MakeCredential_COMMAND_DESCRIPTOR_t;
MakeCredential_COMMAND_DESCRIPTOR_t _MakeCredentialData = {/* entry*/&TPM2_MakeCredential,/* inSize*/(UINT16)(sizeof(MakeCredential_In)),/* outSize*/(UINT16)(sizeof(MakeCredential_Out)),/* offsetOfTypes */offsetof(MakeCredential_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(MakeCredential_In, credential)),(UINT16)(offsetof(MakeCredential_In, objectName)),(UINT16)(offsetof(MakeCredential_Out, secret))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,END_OF_LIST,
TPM2B_ID_OBJECT_P_MARSHAL,TPM2B_ENCRYPTED_SECRET_P_MARSHAL,END_OF_LIST}};#define _MakeCredentialDataAddress (&_MakeCredentialData)#else#define _MakeCredentialDataAddress 0#endif // CC_MakeCredential#if CC_Unseal#include "Unseal_fp.h"
typedef TPM_RC (Unseal_Entry)(
Unseal_In*in,
Unseal_Out*out);typedef const struct {Unseal_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} Unseal_COMMAND_DESCRIPTOR_t;
Unseal_COMMAND_DESCRIPTOR_t _UnsealData = {/* entry*/&TPM2_Unseal,/* inSize*/(UINT16)(sizeof(Unseal_In)),/* outSize*/(UINT16)(sizeof(Unseal_Out)),/* offsetOfTypes */offsetof(Unseal_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,

Page 34
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760

Trusted Platform Module Library
END_OF_LIST,
TPM2B_SENSITIVE_DATA_P_MARSHAL,END_OF_LIST}};#define _UnsealDataAddress (&_UnsealData)#else#define _UnsealDataAddress 0#endif // CC_Unseal#if CC_ObjectChangeAuth#include "ObjectChangeAuth_fp.h"
typedef TPM_RC (ObjectChangeAuth_Entry)(
ObjectChangeAuth_In*in,
ObjectChangeAuth_Out*out);typedef const struct {ObjectChangeAuth_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} ObjectChangeAuth_COMMAND_DESCRIPTOR_t;
ObjectChangeAuth_COMMAND_DESCRIPTOR_t _ObjectChangeAuthData = {/* entry*/&TPM2_ObjectChangeAuth,/* inSize*/(UINT16)(sizeof(ObjectChangeAuth_In)),/* outSize*/(UINT16)(sizeof(ObjectChangeAuth_Out)),/* offsetOfTypes */offsetof(ObjectChangeAuth_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ObjectChangeAuth_In, parentHandle)),(UINT16)(offsetof(ObjectChangeAuth_In, newAuth))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_AUTH_P_UNMARSHAL,END_OF_LIST,
TPM2B_PRIVATE_P_MARSHAL,END_OF_LIST}};#define _ObjectChangeAuthDataAddress (&_ObjectChangeAuthData)#else#define _ObjectChangeAuthDataAddress 0#endif // CC_ObjectChangeAuth#if CC_CreateLoaded#include "CreateLoaded_fp.h"
typedef TPM_RC (CreateLoaded_Entry)(
CreateLoaded_In*in,CreateLoaded_Out*out);typedef const struct {CreateLoaded_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} CreateLoaded_COMMAND_DESCRIPTOR_t;
CreateLoaded_COMMAND_DESCRIPTOR_t _CreateLoadedData = {/* entry*/&TPM2_CreateLoaded,/* inSize*/(UINT16)(sizeof(CreateLoaded_In)),/* outSize*/(UINT16)(sizeof(CreateLoaded_Out)),/* offsetOfTypes */offsetof(CreateLoaded_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(CreateLoaded_In, inSensitive)),(UINT16)(offsetof(CreateLoaded_In, inPublic)),(UINT16)(offsetof(CreateLoaded_Out, outPrivate)),(UINT16)(offsetof(CreateLoaded_Out, outPublic)),(UINT16)(offsetof(CreateLoaded_Out, name))},/* types*/{TPMI_DH_PARENT_H_UNMARSHAL + ADD_FLAG,TPM2B_SENSITIVE_CREATE_P_UNMARSHAL,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 35
April 15, 2019

Trusted Platform Module Library
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

Part 4: Supporting Routines
TPM2B_TEMPLATE_P_UNMARSHAL,END_OF_LIST,
TPM_HANDLE_H_MARSHAL,TPM2B_PRIVATE_P_MARSHAL,TPM2B_PUBLIC_P_MARSHAL,TPM2B_NAME_P_MARSHAL,END_OF_LIST}};#define _CreateLoadedDataAddress (&_CreateLoadedData)#else#define _CreateLoadedDataAddress 0#endif // CC_CreateLoaded#if CC_Duplicate#include "Duplicate_fp.h"
typedef TPM_RC (Duplicate_Entry)(
Duplicate_In*in,
Duplicate_Out*out);typedef const struct {Duplicate_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} Duplicate_COMMAND_DESCRIPTOR_t;
Duplicate_COMMAND_DESCRIPTOR_t _DuplicateData = {/* entry*/&TPM2_Duplicate,/* inSize*/(UINT16)(sizeof(Duplicate_In)),/* outSize*/(UINT16)(sizeof(Duplicate_Out)),/* offsetOfTypes */offsetof(Duplicate_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Duplicate_In, newParentHandle)),(UINT16)(offsetof(Duplicate_In, encryptionKeyIn)),(UINT16)(offsetof(Duplicate_In, symmetricAlg)),(UINT16)(offsetof(Duplicate_Out, duplicate)),(UINT16)(offsetof(Duplicate_Out, outSymSeed))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,
TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_DATA_P_MARSHAL,TPM2B_PRIVATE_P_MARSHAL,TPM2B_ENCRYPTED_SECRET_P_MARSHAL,END_OF_LIST}};#define _DuplicateDataAddress (&_DuplicateData)#else#define _DuplicateDataAddress 0#endif // CC_Duplicate#if CC_Rewrap#include "Rewrap_fp.h"
typedef TPM_RC (Rewrap_Entry)(
Rewrap_In*in,
Rewrap_Out*out);typedef const struct {Rewrap_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} Rewrap_COMMAND_DESCRIPTOR_t;
Rewrap_COMMAND_DESCRIPTOR_t _RewrapData = {/* entry*/&TPM2_Rewrap,

Page 36
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892

/* inSize*//* outSize*//* offsetOfTypes *//* offsets*//* types*/

Trusted Platform Module Library(UINT16)(sizeof(Rewrap_In)),(UINT16)(sizeof(Rewrap_Out)),
offsetof(Rewrap_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(Rewrap_In, newParent)),(UINT16)(offsetof(Rewrap_In, inDuplicate)),(UINT16)(offsetof(Rewrap_In, name)),(UINT16)(offsetof(Rewrap_In, inSymSeed)),(UINT16)(offsetof(Rewrap_Out, outSymSeed))},{TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_PRIVATE_P_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL,END_OF_LIST,
TPM2B_PRIVATE_P_MARSHAL,TPM2B_ENCRYPTED_SECRET_P_MARSHAL,END_OF_LIST}};#define _RewrapDataAddress (&_RewrapData)#else#define _RewrapDataAddress 0#endif // CC_Rewrap#if CC_Import#include "Import_fp.h"
typedef TPM_RC (Import_Entry)(
Import_In*in,
Import_Out*out);
typedef const struct {Import_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} Import_COMMAND_DESCRIPTOR_t;
Import_COMMAND_DESCRIPTOR_t _ImportData = {/* entry*/&TPM2_Import,/* inSize*/(UINT16)(sizeof(Import_In)),/* outSize*/(UINT16)(sizeof(Import_Out)),/* offsetOfTypes */offsetof(Import_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Import_In, encryptionKey)),(UINT16)(offsetof(Import_In, objectPublic)),(UINT16)(offsetof(Import_In, duplicate)),(UINT16)(offsetof(Import_In, inSymSeed)),(UINT16)(offsetof(Import_In, symmetricAlg))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_DATA_P_UNMARSHAL,TPM2B_PUBLIC_P_UNMARSHAL,TPM2B_PRIVATE_P_UNMARSHAL,TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL,
TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_PRIVATE_P_MARSHAL,END_OF_LIST}};#define _ImportDataAddress (&_ImportData)#else#define _ImportDataAddress 0#endif // CC_Import#if CC_RSA_Encrypt#include "RSA_Encrypt_fp.h"
typedef TPM_RC (RSA_Encrypt_Entry)(
RSA_Encrypt_In*in,
RSA_Encrypt_Out*out);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 37
April 15, 2019

Trusted Platform Module Library
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958

Part 4: Supporting Routines

typedef const struct {RSA_Encrypt_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} RSA_Encrypt_COMMAND_DESCRIPTOR_t;
RSA_Encrypt_COMMAND_DESCRIPTOR_t _RSA_EncryptData = {/* entry*/&TPM2_RSA_Encrypt,/* inSize*/(UINT16)(sizeof(RSA_Encrypt_In)),/* outSize*/(UINT16)(sizeof(RSA_Encrypt_Out)),/* offsetOfTypes */offsetof(RSA_Encrypt_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(RSA_Encrypt_In, message)),(UINT16)(offsetof(RSA_Encrypt_In, inScheme)),(UINT16)(offsetof(RSA_Encrypt_In, label))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL,
TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,END_OF_LIST,
TPM2B_PUBLIC_KEY_RSA_P_MARSHAL,END_OF_LIST}};#define _RSA_EncryptDataAddress (&_RSA_EncryptData)#else#define _RSA_EncryptDataAddress 0#endif // CC_RSA_Encrypt#if CC_RSA_Decrypt#include "RSA_Decrypt_fp.h"
typedef TPM_RC (RSA_Decrypt_Entry)(
RSA_Decrypt_In*in,
RSA_Decrypt_Out*out);
typedef const struct {RSA_Decrypt_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} RSA_Decrypt_COMMAND_DESCRIPTOR_t;
RSA_Decrypt_COMMAND_DESCRIPTOR_t _RSA_DecryptData = {/* entry*/&TPM2_RSA_Decrypt,/* inSize*/(UINT16)(sizeof(RSA_Decrypt_In)),/* outSize*/(UINT16)(sizeof(RSA_Decrypt_Out)),/* offsetOfTypes */offsetof(RSA_Decrypt_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(RSA_Decrypt_In, cipherText)),(UINT16)(offsetof(RSA_Decrypt_In, inScheme)),(UINT16)(offsetof(RSA_Decrypt_In, label))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL,
TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,END_OF_LIST,
TPM2B_PUBLIC_KEY_RSA_P_MARSHAL,END_OF_LIST}};#define _RSA_DecryptDataAddress (&_RSA_DecryptData)#else#define _RSA_DecryptDataAddress 0#endif // CC_RSA_Decrypt#if CC_ECDH_KeyGen#include "ECDH_KeyGen_fp.h"
typedef TPM_RC (ECDH_KeyGen_Entry)(
ECDH_KeyGen_In*in,Page 38
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

Trusted Platform Module Library

ECDH_KeyGen_Out*out);typedef const struct {ECDH_KeyGen_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} ECDH_KeyGen_COMMAND_DESCRIPTOR_t;
ECDH_KeyGen_COMMAND_DESCRIPTOR_t _ECDH_KeyGenData = {/* entry*/&TPM2_ECDH_KeyGen,/* inSize*/(UINT16)(sizeof(ECDH_KeyGen_In)),/* outSize*/(UINT16)(sizeof(ECDH_KeyGen_Out)),/* offsetOfTypes */offsetof(ECDH_KeyGen_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ECDH_KeyGen_Out, pubPoint))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,END_OF_LIST,
TPM2B_ECC_POINT_P_MARSHAL,TPM2B_ECC_POINT_P_MARSHAL,END_OF_LIST}};#define _ECDH_KeyGenDataAddress (&_ECDH_KeyGenData)#else#define _ECDH_KeyGenDataAddress 0#endif // CC_ECDH_KeyGen#if CC_ECDH_ZGen#include "ECDH_ZGen_fp.h"
typedef TPM_RC (ECDH_ZGen_Entry)(
ECDH_ZGen_In*in,
ECDH_ZGen_Out*out);typedef const struct {ECDH_ZGen_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} ECDH_ZGen_COMMAND_DESCRIPTOR_t;
ECDH_ZGen_COMMAND_DESCRIPTOR_t _ECDH_ZGenData = {/* entry*/&TPM2_ECDH_ZGen,/* inSize*/(UINT16)(sizeof(ECDH_ZGen_In)),/* outSize*/(UINT16)(sizeof(ECDH_ZGen_Out)),/* offsetOfTypes */offsetof(ECDH_ZGen_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ECDH_ZGen_In, inPoint))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_ECC_POINT_P_UNMARSHAL,END_OF_LIST,
TPM2B_ECC_POINT_P_MARSHAL,END_OF_LIST}};#define _ECDH_ZGenDataAddress (&_ECDH_ZGenData)#else#define _ECDH_ZGenDataAddress 0#endif // CC_ECDH_ZGen#if CC_ECC_Parameters#include "ECC_Parameters_fp.h"
typedef TPM_RC (ECC_Parameters_Entry)(
ECC_Parameters_In*in,
ECC_Parameters_Out*out);typedef const struct {ECC_Parameters_Entry*entry;UINT16
inSize;UINT16outSize;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 39
April 15, 2019

Trusted Platform Module Library
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090

Part 4: Supporting RoutinesUINT16
offsetOfTypes;
BYTE
types[4];} ECC_Parameters_COMMAND_DESCRIPTOR_t;
ECC_Parameters_COMMAND_DESCRIPTOR_t _ECC_ParametersData = {/* entry*/&TPM2_ECC_Parameters,/* inSize*/(UINT16)(sizeof(ECC_Parameters_In)),/* outSize*/(UINT16)(sizeof(ECC_Parameters_Out)),/* offsetOfTypes */offsetof(ECC_Parameters_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_ECC_CURVE_P_UNMARSHAL,END_OF_LIST,
TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL,END_OF_LIST}};#define _ECC_ParametersDataAddress (&_ECC_ParametersData)#else#define _ECC_ParametersDataAddress 0#endif // CC_ECC_Parameters#if CC_ZGen_2Phase#include "ZGen_2Phase_fp.h"
typedef TPM_RC (ZGen_2Phase_Entry)(
ZGen_2Phase_In*in,
ZGen_2Phase_Out*out);typedef const struct {ZGen_2Phase_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} ZGen_2Phase_COMMAND_DESCRIPTOR_t;
ZGen_2Phase_COMMAND_DESCRIPTOR_t _ZGen_2PhaseData = {/* entry*/&TPM2_ZGen_2Phase,/* inSize*/(UINT16)(sizeof(ZGen_2Phase_In)),/* outSize*/(UINT16)(sizeof(ZGen_2Phase_Out)),/* offsetOfTypes */offsetof(ZGen_2Phase_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ZGen_2Phase_In, inQsB)),(UINT16)(offsetof(ZGen_2Phase_In, inQeB)),(UINT16)(offsetof(ZGen_2Phase_In, inScheme)),(UINT16)(offsetof(ZGen_2Phase_In, counter)),(UINT16)(offsetof(ZGen_2Phase_Out, outZ2))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_ECC_POINT_P_UNMARSHAL,TPM2B_ECC_POINT_P_UNMARSHAL,
TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL,UINT16_P_UNMARSHAL,END_OF_LIST,
TPM2B_ECC_POINT_P_MARSHAL,TPM2B_ECC_POINT_P_MARSHAL,END_OF_LIST}};#define _ZGen_2PhaseDataAddress (&_ZGen_2PhaseData)#else#define _ZGen_2PhaseDataAddress 0#endif // CC_ZGen_2Phase#if CC_EncryptDecrypt#include "EncryptDecrypt_fp.h"
typedef TPM_RC (EncryptDecrypt_Entry)(
EncryptDecrypt_In*in,
EncryptDecrypt_Out*out);
typedef const struct {EncryptDecrypt_Entry*entry;UINT16
inSize;UINT16outSize;

Page 40
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

Trusted Platform Module Library

UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} EncryptDecrypt_COMMAND_DESCRIPTOR_t;
EncryptDecrypt_COMMAND_DESCRIPTOR_t _EncryptDecryptData = {/* entry*/&TPM2_EncryptDecrypt,/* inSize*/(UINT16)(sizeof(EncryptDecrypt_In)),/* outSize*/(UINT16)(sizeof(EncryptDecrypt_Out)),/* offsetOfTypes */offsetof(EncryptDecrypt_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(EncryptDecrypt_In, decrypt)),(UINT16)(offsetof(EncryptDecrypt_In, mode)),(UINT16)(offsetof(EncryptDecrypt_In, ivIn)),(UINT16)(offsetof(EncryptDecrypt_In, inData)),(UINT16)(offsetof(EncryptDecrypt_Out, ivOut))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,
TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG,TPM2B_IV_P_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,TPM2B_IV_P_MARSHAL,END_OF_LIST}};#define _EncryptDecryptDataAddress (&_EncryptDecryptData)#else#define _EncryptDecryptDataAddress 0#endif // CC_EncryptDecrypt#if CC_EncryptDecrypt2#include "EncryptDecrypt2_fp.h"
typedef TPM_RC (EncryptDecrypt2_Entry)(
EncryptDecrypt2_In*in,
EncryptDecrypt2_Out*out);typedef const struct {EncryptDecrypt2_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} EncryptDecrypt2_COMMAND_DESCRIPTOR_t;
EncryptDecrypt2_COMMAND_DESCRIPTOR_t _EncryptDecrypt2Data = {/* entry*/&TPM2_EncryptDecrypt2,/* inSize*/(UINT16)(sizeof(EncryptDecrypt2_In)),/* outSize*/(UINT16)(sizeof(EncryptDecrypt2_Out)),/* offsetOfTypes */offsetof(EncryptDecrypt2_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(EncryptDecrypt2_In, inData)),(UINT16)(offsetof(EncryptDecrypt2_In, decrypt)),(UINT16)(offsetof(EncryptDecrypt2_In, mode)),(UINT16)(offsetof(EncryptDecrypt2_In, ivIn)),(UINT16)(offsetof(EncryptDecrypt2_Out, ivOut))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,
TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG,TPM2B_IV_P_UNMARSHAL,END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,TPM2B_IV_P_MARSHAL,END_OF_LIST}};#define _EncryptDecrypt2DataAddress (&_EncryptDecrypt2Data)#else#define _EncryptDecrypt2DataAddress 0#endif // CC_EncryptDecrypt2

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 41
April 15, 2019

Trusted Platform Module Library
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222

Part 4: Supporting Routines#if CC_Hash#include "Hash_fp.h"
typedef TPM_RC (Hash_Entry)(
Hash_In*in,
Hash_Out*out);
typedef const struct {Hash_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} Hash_COMMAND_DESCRIPTOR_t;
Hash_COMMAND_DESCRIPTOR_t _HashData = {/* entry*/&TPM2_Hash,/* inSize*/(UINT16)(sizeof(Hash_In)),/* outSize*/(UINT16)(sizeof(Hash_Out)),/* offsetOfTypes */offsetof(Hash_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Hash_In, hashAlg)),(UINT16)(offsetof(Hash_In, hierarchy)),(UINT16)(offsetof(Hash_Out, validation))},/* types*/{TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL,
TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,
TPMT_TK_HASHCHECK_P_MARSHAL,END_OF_LIST}};#define _HashDataAddress (&_HashData)#else#define _HashDataAddress 0#endif // CC_Hash#if CC_HMAC#include "HMAC_fp.h"
typedef TPM_RC (HMAC_Entry)(
HMAC_In*in,
HMAC_Out*out);
typedef const struct {HMAC_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} HMAC_COMMAND_DESCRIPTOR_t;
HMAC_COMMAND_DESCRIPTOR_t _HMACData = {/* entry*/&TPM2_HMAC,/* inSize*/(UINT16)(sizeof(HMAC_In)),/* outSize*/(UINT16)(sizeof(HMAC_Out)),/* offsetOfTypes */offsetof(HMAC_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(HMAC_In, buffer)),(UINT16)(offsetof(HMAC_In, hashAlg))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,END_OF_LIST}};#define _HMACDataAddress (&_HMACData)#else#define _HMACDataAddress 0#endif // CC_HMAC

Page 42
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

Trusted Platform Module Library#if CC_MAC#include "MAC_fp.h"
typedef TPM_RC (MAC_Entry)(
MAC_In*in,
MAC_Out*out);
typedef const struct {MAC_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} MAC_COMMAND_DESCRIPTOR_t;
MAC_COMMAND_DESCRIPTOR_t _MACData = {/* entry*/&TPM2_MAC,/* inSize*/(UINT16)(sizeof(MAC_In)),/* outSize*/(UINT16)(sizeof(MAC_Out)),/* offsetOfTypes */offsetof(MAC_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(MAC_In, buffer)),(UINT16)(offsetof(MAC_In, inScheme))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,END_OF_LIST}};#define _MACDataAddress (&_MACData)#else#define _MACDataAddress 0#endif // CC_MAC#if CC_GetRandom#include "GetRandom_fp.h"
typedef TPM_RC (GetRandom_Entry)(
GetRandom_In*in,
GetRandom_Out*out);typedef const struct {GetRandom_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} GetRandom_COMMAND_DESCRIPTOR_t;
GetRandom_COMMAND_DESCRIPTOR_t _GetRandomData = {/* entry*/&TPM2_GetRandom,/* inSize*/(UINT16)(sizeof(GetRandom_In)),/* outSize*/(UINT16)(sizeof(GetRandom_Out)),/* offsetOfTypes */offsetof(GetRandom_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{UINT16_P_UNMARSHAL,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,END_OF_LIST}};#define _GetRandomDataAddress (&_GetRandomData)#else#define _GetRandomDataAddress 0#endif // CC_GetRandom#if CC_StirRandom#include "StirRandom_fp.h"
typedef TPM_RC (StirRandom_Entry)(
StirRandom_In*in);typedef const struct {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 43
April 15, 2019

Trusted Platform Module Library
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354

Part 4: Supporting Routines

StirRandom_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} StirRandom_COMMAND_DESCRIPTOR_t;
StirRandom_COMMAND_DESCRIPTOR_t _StirRandomData = {/* entry*/&TPM2_StirRandom,/* inSize*/(UINT16)(sizeof(StirRandom_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(StirRandom_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPM2B_SENSITIVE_DATA_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _StirRandomDataAddress (&_StirRandomData)#else#define _StirRandomDataAddress 0#endif // CC_StirRandom#if CC_HMAC_Start#include "HMAC_Start_fp.h"
typedef TPM_RC (HMAC_Start_Entry)(
HMAC_Start_In*in,
HMAC_Start_Out*out);
typedef const struct {HMAC_Start_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} HMAC_Start_COMMAND_DESCRIPTOR_t;
HMAC_Start_COMMAND_DESCRIPTOR_t _HMAC_StartData = {/* entry*/&TPM2_HMAC_Start,/* inSize*/(UINT16)(sizeof(HMAC_Start_In)),/* outSize*/(UINT16)(sizeof(HMAC_Start_Out)),/* offsetOfTypes */offsetof(HMAC_Start_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(HMAC_Start_In, auth)),(UINT16)(offsetof(HMAC_Start_In, hashAlg))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_AUTH_P_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPMI_DH_OBJECT_H_MARSHAL,END_OF_LIST}};#define _HMAC_StartDataAddress (&_HMAC_StartData)#else#define _HMAC_StartDataAddress 0#endif // CC_HMAC_Start#if CC_MAC_Start#include "MAC_Start_fp.h"
typedef TPM_RC (MAC_Start_Entry)(
MAC_Start_In*in,
MAC_Start_Out*out);
typedef const struct {MAC_Start_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} MAC_Start_COMMAND_DESCRIPTOR_t;

Page 44
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419

Trusted Platform Module Library

MAC_Start_COMMAND_DESCRIPTOR_t _MAC_StartData = {/* entry*/&TPM2_MAC_Start,/* inSize*/(UINT16)(sizeof(MAC_Start_In)),/* outSize*/(UINT16)(sizeof(MAC_Start_Out)),/* offsetOfTypes */offsetof(MAC_Start_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(MAC_Start_In, auth)),(UINT16)(offsetof(MAC_Start_In, inScheme))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_AUTH_P_UNMARSHAL,
TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPMI_DH_OBJECT_H_MARSHAL,END_OF_LIST}};#define _MAC_StartDataAddress (&_MAC_StartData)#else#define _MAC_StartDataAddress 0#endif // CC_MAC_Start#if CC_HashSequenceStart#include "HashSequenceStart_fp.h"
typedef TPM_RC (HashSequenceStart_Entry)(
HashSequenceStart_In*in,
HashSequenceStart_Out*out);
typedef const struct {HashSequenceStart_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} HashSequenceStart_COMMAND_DESCRIPTOR_t;
HashSequenceStart_COMMAND_DESCRIPTOR_t _HashSequenceStartData = {/* entry*/&TPM2_HashSequenceStart,/* inSize*/(UINT16)(sizeof(HashSequenceStart_In)),/* outSize*/(UINT16)(sizeof(HashSequenceStart_Out)),/* offsetOfTypes */offsetof(HashSequenceStart_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(HashSequenceStart_In, hashAlg))},/* types*/{TPM2B_AUTH_P_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPMI_DH_OBJECT_H_MARSHAL,END_OF_LIST}};#define _HashSequenceStartDataAddress (&_HashSequenceStartData)#else#define _HashSequenceStartDataAddress 0#endif // CC_HashSequenceStart#if CC_SequenceUpdate#include "SequenceUpdate_fp.h"
typedef TPM_RC (SequenceUpdate_Entry)(
SequenceUpdate_In*in);typedef const struct {SequenceUpdate_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} SequenceUpdate_COMMAND_DESCRIPTOR_t;
SequenceUpdate_COMMAND_DESCRIPTOR_t _SequenceUpdateData = {/* entry*/&TPM2_SequenceUpdate,/* inSize*/(UINT16)(sizeof(SequenceUpdate_In)),/* outSize*/
0,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 45
April 15, 2019

Trusted Platform Module Library
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483

/* offsetOfTypes *//* offsets*//* types*/

Part 4: Supporting Routines
offsetof(SequenceUpdate_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(SequenceUpdate_In, buffer))},{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _SequenceUpdateDataAddress (&_SequenceUpdateData)#else#define _SequenceUpdateDataAddress 0#endif // CC_SequenceUpdate#if CC_SequenceComplete#include "SequenceComplete_fp.h"
typedef TPM_RC (SequenceComplete_Entry)(
SequenceComplete_In*in,
SequenceComplete_Out*out);typedef const struct {SequenceComplete_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} SequenceComplete_COMMAND_DESCRIPTOR_t;
SequenceComplete_COMMAND_DESCRIPTOR_t _SequenceCompleteData = {/* entry*/&TPM2_SequenceComplete,/* inSize*/(UINT16)(sizeof(SequenceComplete_In)),/* outSize*/(UINT16)(sizeof(SequenceComplete_Out)),/* offsetOfTypes */offsetof(SequenceComplete_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(SequenceComplete_In, buffer)),(UINT16)(offsetof(SequenceComplete_In, hierarchy)),(UINT16)(offsetof(SequenceComplete_Out, validation))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,
TPMT_TK_HASHCHECK_P_MARSHAL,END_OF_LIST}};#define _SequenceCompleteDataAddress (&_SequenceCompleteData)#else#define _SequenceCompleteDataAddress 0#endif // CC_SequenceComplete#if CC_EventSequenceComplete#include "EventSequenceComplete_fp.h"
typedef TPM_RC (EventSequenceComplete_Entry)(
EventSequenceComplete_In*in,
EventSequenceComplete_Out*out);typedef const struct {EventSequenceComplete_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} EventSequenceComplete_COMMAND_DESCRIPTOR_t;
EventSequenceComplete_COMMAND_DESCRIPTOR_t _EventSequenceCompleteData = {/* entry*/&TPM2_EventSequenceComplete,/* inSize*/(UINT16)(sizeof(EventSequenceComplete_In)),/* outSize*/(UINT16)(sizeof(EventSequenceComplete_Out)),/* offsetOfTypes */offsetof(EventSequenceComplete_COMMAND_DESCRIPTOR_t, types),

Page 46
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines1484/* offsets
sequenceHandle)),

*/

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547

Trusted Platform Module Library{(UINT16)(offsetof(EventSequenceComplete_In,(UINT16)(offsetof(EventSequenceComplete_In,buffer))},/* types*/{TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG,
TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPML_DIGEST_VALUES_P_MARSHAL,END_OF_LIST}};#define _EventSequenceCompleteDataAddress (&_EventSequenceCompleteData)#else#define _EventSequenceCompleteDataAddress 0#endif // CC_EventSequenceComplete#if CC_Certify#include "Certify_fp.h"
typedef TPM_RC (Certify_Entry)(
Certify_In*in,Certify_Out*out);typedef const struct {Certify_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} Certify_COMMAND_DESCRIPTOR_t;
Certify_COMMAND_DESCRIPTOR_t _CertifyData = {/* entry*/&TPM2_Certify,/* inSize*/(UINT16)(sizeof(Certify_In)),/* outSize*/(UINT16)(sizeof(Certify_Out)),/* offsetOfTypes */offsetof(Certify_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Certify_In, signHandle)),(UINT16)(offsetof(Certify_In, qualifyingData)),(UINT16)(offsetof(Certify_In, inScheme)),(UINT16)(offsetof(Certify_Out, signature))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _CertifyDataAddress (&_CertifyData)#else#define _CertifyDataAddress 0#endif // CC_Certify#if CC_CertifyCreation#include "CertifyCreation_fp.h"
typedef TPM_RC (CertifyCreation_Entry)(
CertifyCreation_In*in,
CertifyCreation_Out*out);typedef const struct {CertifyCreation_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[6];BYTE
types[10];} CertifyCreation_COMMAND_DESCRIPTOR_t;
CertifyCreation_COMMAND_DESCRIPTOR_t _CertifyCreationData = {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 47
April 15, 2019

Trusted Platform Module Library
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613

/* entry*//* inSize*//* outSize*//* offsetOfTypes *//* offsets*//* types*/

Part 4: Supporting Routines&TPM2_CertifyCreation,(UINT16)(sizeof(CertifyCreation_In)),(UINT16)(sizeof(CertifyCreation_Out)),
offsetof(CertifyCreation_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(CertifyCreation_In, objectHandle)),(UINT16)(offsetof(CertifyCreation_In, qualifyingData)),(UINT16)(offsetof(CertifyCreation_In, creationHash)),(UINT16)(offsetof(CertifyCreation_In, inScheme)),(UINT16)(offsetof(CertifyCreation_In, creationTicket)),(UINT16)(offsetof(CertifyCreation_Out, signature))},{TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,
TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_DATA_P_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,
TPMT_TK_CREATION_P_UNMARSHAL,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _CertifyCreationDataAddress (&_CertifyCreationData)#else#define _CertifyCreationDataAddress 0#endif // CC_CertifyCreation#if CC_Quote#include "Quote_fp.h"
typedef TPM_RC (Quote_Entry)(
Quote_In*in,
Quote_Out*out);
typedef const struct {Quote_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} Quote_COMMAND_DESCRIPTOR_t;
Quote_COMMAND_DESCRIPTOR_t _QuoteData = {/* entry*/&TPM2_Quote,/* inSize*/(UINT16)(sizeof(Quote_In)),/* outSize*/(UINT16)(sizeof(Quote_Out)),/* offsetOfTypes */offsetof(Quote_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Quote_In, qualifyingData)),(UINT16)(offsetof(Quote_In, inScheme)),(UINT16)(offsetof(Quote_In, PCRselect)),(UINT16)(offsetof(Quote_Out, signature))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,
TPML_PCR_SELECTION_P_UNMARSHAL,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _QuoteDataAddress (&_QuoteData)#else#define _QuoteDataAddress 0#endif // CC_Quote#if CC_GetSessionAuditDigest#include "GetSessionAuditDigest_fp.h"
typedef TPM_RC (GetSessionAuditDigest_Entry)(
GetSessionAuditDigest_In*in,
GetSessionAuditDigest_Out*out

Page 48
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668

Trusted Platform Module Library);
typedef const struct {GetSessionAuditDigest_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[9];} GetSessionAuditDigest_COMMAND_DESCRIPTOR_t;
GetSessionAuditDigest_COMMAND_DESCRIPTOR_t _GetSessionAuditDigestData = {/* entry*/&TPM2_GetSessionAuditDigest,/* inSize*/(UINT16)(sizeof(GetSessionAuditDigest_In)),/* outSize*/(UINT16)(sizeof(GetSessionAuditDigest_Out)),/* offsetOfTypes */offsetof(GetSessionAuditDigest_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(GetSessionAuditDigest_In,
signHandle)),(UINT16)(offsetof(GetSessionAuditDigest_In,
sessionHandle)),(UINT16)(offsetof(GetSessionAuditDigest_In,
qualifyingData)),(UINT16)(offsetof(GetSessionAuditDigest_In,
inScheme)),(UINT16)(offsetof(GetSessionAuditDigest_Out,
signature))},/* types*/{TPMI_RH_ENDORSEMENT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,
TPMI_SH_HMAC_H_UNMARSHAL,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _GetSessionAuditDigestDataAddress (&_GetSessionAuditDigestData)#else#define _GetSessionAuditDigestDataAddress 0#endif // CC_GetSessionAuditDigest#if CC_GetCommandAuditDigest#include "GetCommandAuditDigest_fp.h"
typedef TPM_RC (GetCommandAuditDigest_Entry)(
GetCommandAuditDigest_In*in,
GetCommandAuditDigest_Out*out);
typedef const struct {GetCommandAuditDigest_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} GetCommandAuditDigest_COMMAND_DESCRIPTOR_t;
GetCommandAuditDigest_COMMAND_DESCRIPTOR_t _GetCommandAuditDigestData = {/* entry*/&TPM2_GetCommandAuditDigest,/* inSize*/(UINT16)(sizeof(GetCommandAuditDigest_In)),/* outSize*/(UINT16)(sizeof(GetCommandAuditDigest_Out)),/* offsetOfTypes */offsetof(GetCommandAuditDigest_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(GetCommandAuditDigest_In,
signHandle)),(UINT16)(offsetof(GetCommandAuditDigest_In,
qualifyingData)),(UINT16)(offsetof(GetCommandAuditDigest_In,
inScheme)),Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 49
April 15, 2019

Trusted Platform Module Library
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733

Part 4: Supporting Routines(UINT16)(offsetof(GetCommandAuditDigest_Out,

signature))},/* types*/{TPMI_RH_ENDORSEMENT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _GetCommandAuditDigestDataAddress (&_GetCommandAuditDigestData)#else#define _GetCommandAuditDigestDataAddress 0#endif // CC_GetCommandAuditDigest#if CC_GetTime#include "GetTime_fp.h"
typedef TPM_RC (GetTime_Entry)(
GetTime_In*in,
GetTime_Out*out);typedef const struct {GetTime_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} GetTime_COMMAND_DESCRIPTOR_t;
GetTime_COMMAND_DESCRIPTOR_t _GetTimeData = {/* entry*/&TPM2_GetTime,/* inSize*/(UINT16)(sizeof(GetTime_In)),/* outSize*/(UINT16)(sizeof(GetTime_Out)),/* offsetOfTypes */offsetof(GetTime_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(GetTime_In, signHandle)),(UINT16)(offsetof(GetTime_In, qualifyingData)),(UINT16)(offsetof(GetTime_In, inScheme)),(UINT16)(offsetof(GetTime_Out, signature))},/* types*/{TPMI_RH_ENDORSEMENT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _GetTimeDataAddress (&_GetTimeData)#else#define _GetTimeDataAddress 0#endif // CC_GetTime#if CC_CertifyX509#include "CertifyX509_fp.h"
typedef TPM_RC (CertifyX509_Entry)(
CertifyX509_In*in,
CertifyX509_Out*out);typedef const struct {CertifyX509_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[6];BYTE
types[10];} CertifyX509_COMMAND_DESCRIPTOR_t;
CertifyX509_COMMAND_DESCRIPTOR_t _CertifyX509Data = {Page 50
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799

/* entry*//* inSize*//* outSize*//* offsetOfTypes *//* offsets*//* types*/

Trusted Platform Module Library&TPM2_CertifyX509,(UINT16)(sizeof(CertifyX509_In)),(UINT16)(sizeof(CertifyX509_Out)),
offsetof(CertifyX509_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(CertifyX509_In, signHandle)),(UINT16)(offsetof(CertifyX509_In, qualifyingData)),(UINT16)(offsetof(CertifyX509_In, inScheme)),(UINT16)(offsetof(CertifyX509_In, partialCertificate)),(UINT16)(offsetof(CertifyX509_Out, tbsDigest)),(UINT16)(offsetof(CertifyX509_Out, signature))},{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,TPM2B_DIGEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _CertifyX509DataAddress (&_CertifyX509Data)#else#define _CertifyX509DataAddress 0#endif // CC_CertifyX509#if CC_Commit#include "Commit_fp.h"
typedef TPM_RC (Commit_Entry)(
Commit_In*in,
Commit_Out*out);
typedef const struct {Commit_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[6];BYTE
types[10];} Commit_COMMAND_DESCRIPTOR_t;
Commit_COMMAND_DESCRIPTOR_t _CommitData = {/* entry*/&TPM2_Commit,/* inSize*/(UINT16)(sizeof(Commit_In)),/* outSize*/(UINT16)(sizeof(Commit_Out)),/* offsetOfTypes */offsetof(Commit_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Commit_In, P1)),(UINT16)(offsetof(Commit_In, s2)),(UINT16)(offsetof(Commit_In, y2)),(UINT16)(offsetof(Commit_Out, L)),(UINT16)(offsetof(Commit_Out, E)),(UINT16)(offsetof(Commit_Out, counter))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_ECC_POINT_P_UNMARSHAL,TPM2B_SENSITIVE_DATA_P_UNMARSHAL,TPM2B_ECC_PARAMETER_P_UNMARSHAL,END_OF_LIST,
TPM2B_ECC_POINT_P_MARSHAL,TPM2B_ECC_POINT_P_MARSHAL,TPM2B_ECC_POINT_P_MARSHAL,UINT16_P_MARSHAL,END_OF_LIST}};#define _CommitDataAddress (&_CommitData)#else#define _CommitDataAddress 0#endif // CC_Commit#if CC_EC_Ephemeral

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 51
April 15, 2019

Trusted Platform Module Library
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865

Part 4: Supporting Routines#include "EC_Ephemeral_fp.h"
typedef TPM_RC (EC_Ephemeral_Entry)(
EC_Ephemeral_In*in,
EC_Ephemeral_Out*out);typedef const struct {EC_Ephemeral_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} EC_Ephemeral_COMMAND_DESCRIPTOR_t;
EC_Ephemeral_COMMAND_DESCRIPTOR_t _EC_EphemeralData = {/* entry*/&TPM2_EC_Ephemeral,/* inSize*/(UINT16)(sizeof(EC_Ephemeral_In)),/* outSize*/(UINT16)(sizeof(EC_Ephemeral_Out)),/* offsetOfTypes */offsetof(EC_Ephemeral_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(EC_Ephemeral_Out, counter))},/* types*/{TPMI_ECC_CURVE_P_UNMARSHAL,END_OF_LIST,
TPM2B_ECC_POINT_P_MARSHAL,UINT16_P_MARSHAL,END_OF_LIST}};#define _EC_EphemeralDataAddress (&_EC_EphemeralData)#else#define _EC_EphemeralDataAddress 0#endif // CC_EC_Ephemeral#if CC_VerifySignature#include "VerifySignature_fp.h"
typedef TPM_RC (VerifySignature_Entry)(
VerifySignature_In*in,
VerifySignature_Out*out);typedef const struct {VerifySignature_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} VerifySignature_COMMAND_DESCRIPTOR_t;
VerifySignature_COMMAND_DESCRIPTOR_t _VerifySignatureData = {/* entry*/&TPM2_VerifySignature,/* inSize*/(UINT16)(sizeof(VerifySignature_In)),/* outSize*/(UINT16)(sizeof(VerifySignature_Out)),/* offsetOfTypes */offsetof(VerifySignature_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(VerifySignature_In, digest)),(UINT16)(offsetof(VerifySignature_In, signature))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMT_SIGNATURE_P_UNMARSHAL,END_OF_LIST,
TPMT_TK_VERIFIED_P_MARSHAL,END_OF_LIST}};#define _VerifySignatureDataAddress (&_VerifySignatureData)#else#define _VerifySignatureDataAddress 0#endif // CC_VerifySignature#if CC_Sign#include "Sign_fp.h"
typedef TPM_RC (Sign_Entry)(
Sign_In*in,
Sign_Out*out

Page 52
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913

Trusted Platform Module Library);
typedef const struct {Sign_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} Sign_COMMAND_DESCRIPTOR_t;
Sign_COMMAND_DESCRIPTOR_t _SignData = {/* entry*/&TPM2_Sign,/* inSize*/(UINT16)(sizeof(Sign_In)),/* outSize*/(UINT16)(sizeof(Sign_Out)),/* offsetOfTypes */offsetof(Sign_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(Sign_In, digest)),(UINT16)(offsetof(Sign_In, inScheme)),(UINT16)(offsetof(Sign_In, validation))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,
TPMT_TK_HASHCHECK_P_UNMARSHAL,END_OF_LIST,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _SignDataAddress (&_SignData)#else#define _SignDataAddress 0#endif // CC_Sign#if CC_SetCommandCodeAuditStatus#include "SetCommandCodeAuditStatus_fp.h"
typedef TPM_RC (SetCommandCodeAuditStatus_Entry)(
SetCommandCodeAuditStatus_In*in);typedef const struct {SetCommandCodeAuditStatus_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t;
SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t _SetCommandCodeAuditStatusData = {/* entry*/&TPM2_SetCommandCodeAuditStatus,/* inSize*/(UINT16)(sizeof(SetCommandCodeAuditStatus_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(SetCommandCodeAuditStatus_In, auditAlg)),

1914(UINT16)(offsetof(SetCommandCodeAuditStatus_In, setList)),
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

(UINT16)(offsetof(SetCommandCodeAuditStatus_In, clearList))},/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG,
TPML_CC_P_UNMARSHAL,
TPML_CC_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _SetCommandCodeAuditStatusDataAddress (&_SetCommandCodeAuditStatusData)#else#define _SetCommandCodeAuditStatusDataAddress 0#endif // CC_SetCommandCodeAuditStatus

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 53
April 15, 2019

Trusted Platform Module Library
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992

Part 4: Supporting Routines#if CC_PCR_Extend#include "PCR_Extend_fp.h"
typedef TPM_RC (PCR_Extend_Entry)(
PCR_Extend_In*in);typedef const struct {PCR_Extend_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PCR_Extend_COMMAND_DESCRIPTOR_t;
PCR_Extend_COMMAND_DESCRIPTOR_t _PCR_ExtendData = {/* entry*/&TPM2_PCR_Extend,/* inSize*/(UINT16)(sizeof(PCR_Extend_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PCR_Extend_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PCR_Extend_In, digests))},/* types*/{TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG,
TPML_DIGEST_VALUES_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PCR_ExtendDataAddress (&_PCR_ExtendData)#else#define _PCR_ExtendDataAddress 0#endif // CC_PCR_Extend#if CC_PCR_Event#include "PCR_Event_fp.h"
typedef TPM_RC (PCR_Event_Entry)(
PCR_Event_In*in,
PCR_Event_Out*out);
typedef const struct {PCR_Event_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} PCR_Event_COMMAND_DESCRIPTOR_t;
PCR_Event_COMMAND_DESCRIPTOR_t _PCR_EventData = {/* entry*/&TPM2_PCR_Event,/* inSize*/(UINT16)(sizeof(PCR_Event_In)),/* outSize*/(UINT16)(sizeof(PCR_Event_Out)),/* offsetOfTypes */offsetof(PCR_Event_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PCR_Event_In, eventData))},/* types*/{TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG,TPM2B_EVENT_P_UNMARSHAL,END_OF_LIST,
TPML_DIGEST_VALUES_P_MARSHAL,END_OF_LIST}};#define _PCR_EventDataAddress (&_PCR_EventData)#else#define _PCR_EventDataAddress 0#endif // CC_PCR_Event#if CC_PCR_Read#include "PCR_Read_fp.h"
typedef TPM_RC (PCR_Read_Entry)(
PCR_Read_In*in,
PCR_Read_Out*out);typedef const struct {PCR_Read_Entry*entry;Page 54
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058

Trusted Platform Module Library

UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} PCR_Read_COMMAND_DESCRIPTOR_t;
PCR_Read_COMMAND_DESCRIPTOR_t _PCR_ReadData = {/* entry*/&TPM2_PCR_Read,/* inSize*/(UINT16)(sizeof(PCR_Read_In)),/* outSize*/(UINT16)(sizeof(PCR_Read_Out)),/* offsetOfTypes */offsetof(PCR_Read_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PCR_Read_Out, pcrSelectionOut)),(UINT16)(offsetof(PCR_Read_Out, pcrValues))},/* types*/{TPML_PCR_SELECTION_P_UNMARSHAL,END_OF_LIST,UINT32_P_MARSHAL,
TPML_PCR_SELECTION_P_MARSHAL,
TPML_DIGEST_P_MARSHAL,END_OF_LIST}};#define _PCR_ReadDataAddress (&_PCR_ReadData)#else#define _PCR_ReadDataAddress 0#endif // CC_PCR_Read#if CC_PCR_Allocate#include "PCR_Allocate_fp.h"
typedef TPM_RC (PCR_Allocate_Entry)(
PCR_Allocate_In*in,
PCR_Allocate_Out*out);typedef const struct {PCR_Allocate_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} PCR_Allocate_COMMAND_DESCRIPTOR_t;
PCR_Allocate_COMMAND_DESCRIPTOR_t _PCR_AllocateData = {/* entry*/&TPM2_PCR_Allocate,/* inSize*/(UINT16)(sizeof(PCR_Allocate_In)),/* outSize*/(UINT16)(sizeof(PCR_Allocate_Out)),/* offsetOfTypes */offsetof(PCR_Allocate_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PCR_Allocate_In, pcrAllocation)),(UINT16)(offsetof(PCR_Allocate_Out, maxPCR)),(UINT16)(offsetof(PCR_Allocate_Out, sizeNeeded)),(UINT16)(offsetof(PCR_Allocate_Out, sizeAvailable))},/* types*/{TPMI_RH_PLATFORM_H_UNMARSHAL,
TPML_PCR_SELECTION_P_UNMARSHAL,END_OF_LIST,
TPMI_YES_NO_P_MARSHAL,UINT32_P_MARSHAL,UINT32_P_MARSHAL,UINT32_P_MARSHAL,END_OF_LIST}};#define _PCR_AllocateDataAddress (&_PCR_AllocateData)#else#define _PCR_AllocateDataAddress 0#endif // CC_PCR_Allocate#if CC_PCR_SetAuthPolicy#include "PCR_SetAuthPolicy_fp.h"
typedef TPM_RC (PCR_SetAuthPolicy_Entry)(
PCR_SetAuthPolicy_In*in);typedef const struct {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 55
April 15, 2019

Trusted Platform Module Library
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123

Part 4: Supporting Routines

PCR_SetAuthPolicy_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t;
PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t _PCR_SetAuthPolicyData = {/* entry*/&TPM2_PCR_SetAuthPolicy,/* inSize*/(UINT16)(sizeof(PCR_SetAuthPolicy_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(PCR_SetAuthPolicy_In, authPolicy)),(UINT16)(offsetof(PCR_SetAuthPolicy_In, hashAlg)),(UINT16)(offsetof(PCR_SetAuthPolicy_In, pcrNum))},/* types*/{TPMI_RH_PLATFORM_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG,
TPMI_DH_PCR_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PCR_SetAuthPolicyDataAddress (&_PCR_SetAuthPolicyData)#else#define _PCR_SetAuthPolicyDataAddress 0#endif // CC_PCR_SetAuthPolicy#if CC_PCR_SetAuthValue#include "PCR_SetAuthValue_fp.h"
typedef TPM_RC (PCR_SetAuthValue_Entry)(
PCR_SetAuthValue_In*in);typedef const struct {PCR_SetAuthValue_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PCR_SetAuthValue_COMMAND_DESCRIPTOR_t;
PCR_SetAuthValue_COMMAND_DESCRIPTOR_t _PCR_SetAuthValueData = {/* entry*/&TPM2_PCR_SetAuthValue,/* inSize*/(UINT16)(sizeof(PCR_SetAuthValue_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PCR_SetAuthValue_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PCR_SetAuthValue_In, auth))},/* types*/{TPMI_DH_PCR_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PCR_SetAuthValueDataAddress (&_PCR_SetAuthValueData)#else#define _PCR_SetAuthValueDataAddress 0#endif // CC_PCR_SetAuthValue#if CC_PCR_Reset#include "PCR_Reset_fp.h"
typedef TPM_RC (PCR_Reset_Entry)(
PCR_Reset_In*in);typedef const struct {PCR_Reset_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];Page 56
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189

Trusted Platform Module Library} PCR_Reset_COMMAND_DESCRIPTOR_t;
PCR_Reset_COMMAND_DESCRIPTOR_t _PCR_ResetData = {/* entry*/&TPM2_PCR_Reset,/* inSize*/(UINT16)(sizeof(PCR_Reset_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PCR_Reset_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_DH_PCR_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PCR_ResetDataAddress (&_PCR_ResetData)#else#define _PCR_ResetDataAddress 0#endif // CC_PCR_Reset#if CC_PolicySigned#include "PolicySigned_fp.h"
typedef TPM_RC (PolicySigned_Entry)(
PolicySigned_In*in,PolicySigned_Out*out);typedef const struct {PolicySigned_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[7];BYTE
types[11];} PolicySigned_COMMAND_DESCRIPTOR_t;
PolicySigned_COMMAND_DESCRIPTOR_t _PolicySignedData = {/* entry*/&TPM2_PolicySigned,/* inSize*/(UINT16)(sizeof(PolicySigned_In)),/* outSize*/(UINT16)(sizeof(PolicySigned_Out)),/* offsetOfTypes */offsetof(PolicySigned_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicySigned_In, policySession)),(UINT16)(offsetof(PolicySigned_In, nonceTPM)),(UINT16)(offsetof(PolicySigned_In, cpHashA)),(UINT16)(offsetof(PolicySigned_In, policyRef)),(UINT16)(offsetof(PolicySigned_In, expiration)),(UINT16)(offsetof(PolicySigned_In, auth)),(UINT16)(offsetof(PolicySigned_Out, policyTicket))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,
INT32_P_UNMARSHAL,
TPMT_SIGNATURE_P_UNMARSHAL,END_OF_LIST,
TPM2B_TIMEOUT_P_MARSHAL,
TPMT_TK_AUTH_P_MARSHAL,END_OF_LIST}};#define _PolicySignedDataAddress (&_PolicySignedData)#else#define _PolicySignedDataAddress 0#endif // CC_PolicySigned#if CC_PolicySecret#include "PolicySecret_fp.h"
typedef TPM_RC (PolicySecret_Entry)(
PolicySecret_In*in,
PolicySecret_Out*out);
typedef const struct {PolicySecret_Entry*entry;UINT16
inSize;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 57
April 15, 2019

Trusted Platform Module Library
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255

Part 4: Supporting RoutinesUINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[6];BYTE
types[10];} PolicySecret_COMMAND_DESCRIPTOR_t;
PolicySecret_COMMAND_DESCRIPTOR_t _PolicySecretData = {/* entry*/&TPM2_PolicySecret,/* inSize*/(UINT16)(sizeof(PolicySecret_In)),/* outSize*/(UINT16)(sizeof(PolicySecret_Out)),/* offsetOfTypes */offsetof(PolicySecret_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicySecret_In, policySession)),(UINT16)(offsetof(PolicySecret_In, nonceTPM)),(UINT16)(offsetof(PolicySecret_In, cpHashA)),(UINT16)(offsetof(PolicySecret_In, policyRef)),(UINT16)(offsetof(PolicySecret_In, expiration)),(UINT16)(offsetof(PolicySecret_Out, policyTicket))},/* types*/{TPMI_DH_ENTITY_H_UNMARSHAL,
TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,
INT32_P_UNMARSHAL,END_OF_LIST,
TPM2B_TIMEOUT_P_MARSHAL,
TPMT_TK_AUTH_P_MARSHAL,END_OF_LIST}};#define _PolicySecretDataAddress (&_PolicySecretData)#else#define _PolicySecretDataAddress 0#endif // CC_PolicySecret#if CC_PolicyTicket#include "PolicyTicket_fp.h"
typedef TPM_RC (PolicyTicket_Entry)(
PolicyTicket_In*in);typedef const struct {PolicyTicket_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[8];} PolicyTicket_COMMAND_DESCRIPTOR_t;
PolicyTicket_COMMAND_DESCRIPTOR_t _PolicyTicketData = {/* entry*/&TPM2_PolicyTicket,/* inSize*/(UINT16)(sizeof(PolicyTicket_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyTicket_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyTicket_In, timeout)),(UINT16)(offsetof(PolicyTicket_In, cpHashA)),(UINT16)(offsetof(PolicyTicket_In, policyRef)),(UINT16)(offsetof(PolicyTicket_In, authName)),(UINT16)(offsetof(PolicyTicket_In, ticket))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_TIMEOUT_P_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,
TPMT_TK_AUTH_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyTicketDataAddress (&_PolicyTicketData)#else#define _PolicyTicketDataAddress 0

Page 58
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321

Trusted Platform Module Library#endif // CC_PolicyTicket#if CC_PolicyOR#include "PolicyOR_fp.h"
typedef TPM_RC (PolicyOR_Entry)(
PolicyOR_In*in);typedef const struct {PolicyOR_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyOR_COMMAND_DESCRIPTOR_t;
PolicyOR_COMMAND_DESCRIPTOR_t _PolicyORData = {/* entry*/&TPM2_PolicyOR,/* inSize*/(UINT16)(sizeof(PolicyOR_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyOR_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyOR_In, pHashList))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,
TPML_DIGEST_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyORDataAddress (&_PolicyORData)#else#define _PolicyORDataAddress 0#endif // CC_PolicyOR#if CC_PolicyPCR#include "PolicyPCR_fp.h"
typedef TPM_RC (PolicyPCR_Entry)(
PolicyPCR_In*in);typedef const struct {PolicyPCR_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} PolicyPCR_COMMAND_DESCRIPTOR_t;
PolicyPCR_COMMAND_DESCRIPTOR_t _PolicyPCRData = {/* entry*/&TPM2_PolicyPCR,/* inSize*/(UINT16)(sizeof(PolicyPCR_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyPCR_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyPCR_In, pcrDigest)),(UINT16)(offsetof(PolicyPCR_In, pcrs))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPML_PCR_SELECTION_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyPCRDataAddress (&_PolicyPCRData)#else#define _PolicyPCRDataAddress 0#endif // CC_PolicyPCR#if CC_PolicyLocality#include "PolicyLocality_fp.h"
typedef TPM_RC (PolicyLocality_Entry)(
PolicyLocality_In*in);typedef const struct {PolicyLocality_Entry*entry;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 59
April 15, 2019

Trusted Platform Module Library
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387

Part 4: Supporting RoutinesUINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyLocality_COMMAND_DESCRIPTOR_t;
PolicyLocality_COMMAND_DESCRIPTOR_t _PolicyLocalityData = {/* entry*/&TPM2_PolicyLocality,/* inSize*/(UINT16)(sizeof(PolicyLocality_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyLocality_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyLocality_In, locality))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,
TPMA_LOCALITY_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyLocalityDataAddress (&_PolicyLocalityData)#else#define _PolicyLocalityDataAddress 0#endif // CC_PolicyLocality#if CC_PolicyNV#include "PolicyNV_fp.h"
typedef TPM_RC (PolicyNV_Entry)(
PolicyNV_In*in);typedef const struct {PolicyNV_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[5];BYTE
types[8];} PolicyNV_COMMAND_DESCRIPTOR_t;
PolicyNV_COMMAND_DESCRIPTOR_t _PolicyNVData = {/* entry*/&TPM2_PolicyNV,/* inSize*/(UINT16)(sizeof(PolicyNV_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyNV_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyNV_In, nvIndex)),(UINT16)(offsetof(PolicyNV_In, policySession)),(UINT16)(offsetof(PolicyNV_In, operandB)),(UINT16)(offsetof(PolicyNV_In, offset)),(UINT16)(offsetof(PolicyNV_In, operation))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,
TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_OPERAND_P_UNMARSHAL,UINT16_P_UNMARSHAL,
TPM_EO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyNVDataAddress (&_PolicyNVData)#else#define _PolicyNVDataAddress 0#endif // CC_PolicyNV#if CC_PolicyCounterTimer#include "PolicyCounterTimer_fp.h"
typedef TPM_RC (PolicyCounterTimer_Entry)(
PolicyCounterTimer_In*in);typedef const struct {PolicyCounterTimer_Entry*entry;UINT16
inSize;UINT16outSize;

Page 60
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450

Trusted Platform Module Library

UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} PolicyCounterTimer_COMMAND_DESCRIPTOR_t;
PolicyCounterTimer_COMMAND_DESCRIPTOR_t _PolicyCounterTimerData = {/* entry*/&TPM2_PolicyCounterTimer,/* inSize*/(UINT16)(sizeof(PolicyCounterTimer_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyCounterTimer_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(PolicyCounterTimer_In, operandB)),(UINT16)(offsetof(PolicyCounterTimer_In, offset)),(UINT16)(offsetof(PolicyCounterTimer_In,
operation))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_OPERAND_P_UNMARSHAL,UINT16_P_UNMARSHAL,
TPM_EO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyCounterTimerDataAddress (&_PolicyCounterTimerData)#else#define _PolicyCounterTimerDataAddress 0#endif // CC_PolicyCounterTimer#if CC_PolicyCommandCode#include "PolicyCommandCode_fp.h"
typedef TPM_RC (PolicyCommandCode_Entry)(
PolicyCommandCode_In*in);typedef const struct {PolicyCommandCode_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyCommandCode_COMMAND_DESCRIPTOR_t;
PolicyCommandCode_COMMAND_DESCRIPTOR_t _PolicyCommandCodeData = {/* entry*/&TPM2_PolicyCommandCode,/* inSize*/(UINT16)(sizeof(PolicyCommandCode_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyCommandCode_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(PolicyCommandCode_In, code))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,
TPM_CC_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyCommandCodeDataAddress (&_PolicyCommandCodeData)#else#define _PolicyCommandCodeDataAddress 0#endif // CC_PolicyCommandCode#if CC_PolicyPhysicalPresence#include "PolicyPhysicalPresence_fp.h"
typedef TPM_RC (PolicyPhysicalPresence_Entry)(
PolicyPhysicalPresence_In*in);typedef const struct {PolicyPhysicalPresence_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 61
April 15, 2019

Trusted Platform Module Library
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515

Part 4: Supporting Routines

PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t _PolicyPhysicalPresenceData = {/* entry*/&TPM2_PolicyPhysicalPresence,/* inSize*/(UINT16)(sizeof(PolicyPhysicalPresence_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyPhysicalPresenceDataAddress (&_PolicyPhysicalPresenceData)#else#define _PolicyPhysicalPresenceDataAddress 0#endif // CC_PolicyPhysicalPresence#if CC_PolicyCpHash#include "PolicyCpHash_fp.h"
typedef TPM_RC (PolicyCpHash_Entry)(
PolicyCpHash_In*in);typedef const struct {PolicyCpHash_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyCpHash_COMMAND_DESCRIPTOR_t;
PolicyCpHash_COMMAND_DESCRIPTOR_t _PolicyCpHashData = {/* entry*/&TPM2_PolicyCpHash,/* inSize*/(UINT16)(sizeof(PolicyCpHash_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyCpHash_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyCpHash_In, cpHashA))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyCpHashDataAddress (&_PolicyCpHashData)#else#define _PolicyCpHashDataAddress 0#endif // CC_PolicyCpHash#if CC_PolicyNameHash#include "PolicyNameHash_fp.h"
typedef TPM_RC (PolicyNameHash_Entry)(
PolicyNameHash_In*in);typedef const struct {PolicyNameHash_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyNameHash_COMMAND_DESCRIPTOR_t;
PolicyNameHash_COMMAND_DESCRIPTOR_t _PolicyNameHashData = {/* entry*/&TPM2_PolicyNameHash,/* inSize*/(UINT16)(sizeof(PolicyNameHash_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyNameHash_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyNameHash_In, nameHash))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}

Page 62
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577

Trusted Platform Module Library};#define _PolicyNameHashDataAddress (&_PolicyNameHashData)#else#define _PolicyNameHashDataAddress 0#endif // CC_PolicyNameHash#if CC_PolicyDuplicationSelect#include "PolicyDuplicationSelect_fp.h"
typedef TPM_RC (PolicyDuplicationSelect_Entry)(
PolicyDuplicationSelect_In*in);typedef const struct {PolicyDuplicationSelect_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t;
PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t _PolicyDuplicationSelectData = {/* entry*/&TPM2_PolicyDuplicationSelect,/* inSize*/(UINT16)(sizeof(PolicyDuplicationSelect_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyDuplicationSelect_In,
objectName)),(UINT16)(offsetof(PolicyDuplicationSelect_In,
newParentName)),(UINT16)(offsetof(PolicyDuplicationSelect_In,
includeObject))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyDuplicationSelectDataAddress (&_PolicyDuplicationSelectData)#else#define _PolicyDuplicationSelectDataAddress 0#endif // CC_PolicyDuplicationSelect#if CC_PolicyAuthorize#include "PolicyAuthorize_fp.h"
typedef TPM_RC (PolicyAuthorize_Entry)(
PolicyAuthorize_In*in);typedef const struct {PolicyAuthorize_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[7];} PolicyAuthorize_COMMAND_DESCRIPTOR_t;
PolicyAuthorize_COMMAND_DESCRIPTOR_t _PolicyAuthorizeData = {/* entry*/&TPM2_PolicyAuthorize,/* inSize*/(UINT16)(sizeof(PolicyAuthorize_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyAuthorize_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyAuthorize_In, approvedPolicy)),(UINT16)(offsetof(PolicyAuthorize_In, policyRef)),(UINT16)(offsetof(PolicyAuthorize_In, keySign)),(UINT16)(offsetof(PolicyAuthorize_In, checkTicket))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 63
April 15, 2019

Trusted Platform Module Library
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643

Part 4: Supporting Routines
TPM2B_NAME_P_UNMARSHAL,
TPMT_TK_VERIFIED_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyAuthorizeDataAddress (&_PolicyAuthorizeData)#else#define _PolicyAuthorizeDataAddress 0#endif // CC_PolicyAuthorize#if CC_PolicyAuthValue#include "PolicyAuthValue_fp.h"
typedef TPM_RC (PolicyAuthValue_Entry)(
PolicyAuthValue_In*in);typedef const struct {PolicyAuthValue_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} PolicyAuthValue_COMMAND_DESCRIPTOR_t;
PolicyAuthValue_COMMAND_DESCRIPTOR_t _PolicyAuthValueData = {/* entry*/&TPM2_PolicyAuthValue,/* inSize*/(UINT16)(sizeof(PolicyAuthValue_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyAuthValue_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyAuthValueDataAddress (&_PolicyAuthValueData)#else#define _PolicyAuthValueDataAddress 0#endif // CC_PolicyAuthValue#if CC_PolicyPassword#include "PolicyPassword_fp.h"
typedef TPM_RC (PolicyPassword_Entry)(
PolicyPassword_In*in);typedef const struct {PolicyPassword_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} PolicyPassword_COMMAND_DESCRIPTOR_t;
PolicyPassword_COMMAND_DESCRIPTOR_t _PolicyPasswordData = {/* entry*/&TPM2_PolicyPassword,/* inSize*/(UINT16)(sizeof(PolicyPassword_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyPassword_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyPasswordDataAddress (&_PolicyPasswordData)#else#define _PolicyPasswordDataAddress 0#endif // CC_PolicyPassword#if CC_PolicyGetDigest#include "PolicyGetDigest_fp.h"
typedef TPM_RC (PolicyGetDigest_Entry)(
PolicyGetDigest_In*in,
PolicyGetDigest_Out*out

Page 64
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709

Trusted Platform Module Library);
typedef const struct {PolicyGetDigest_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} PolicyGetDigest_COMMAND_DESCRIPTOR_t;
PolicyGetDigest_COMMAND_DESCRIPTOR_t _PolicyGetDigestData = {/* entry*/&TPM2_PolicyGetDigest,/* inSize*/(UINT16)(sizeof(PolicyGetDigest_In)),/* outSize*/(UINT16)(sizeof(PolicyGetDigest_Out)),/* offsetOfTypes */offsetof(PolicyGetDigest_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,END_OF_LIST,
TPM2B_DIGEST_P_MARSHAL,END_OF_LIST}};#define _PolicyGetDigestDataAddress (&_PolicyGetDigestData)#else#define _PolicyGetDigestDataAddress 0#endif // CC_PolicyGetDigest#if CC_PolicyNvWritten#include "PolicyNvWritten_fp.h"
typedef TPM_RC (PolicyNvWritten_Entry)(
PolicyNvWritten_In*in);typedef const struct {PolicyNvWritten_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyNvWritten_COMMAND_DESCRIPTOR_t;
PolicyNvWritten_COMMAND_DESCRIPTOR_t _PolicyNvWrittenData = {/* entry*/&TPM2_PolicyNvWritten,/* inSize*/(UINT16)(sizeof(PolicyNvWritten_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyNvWritten_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyNvWritten_In, writtenSet))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyNvWrittenDataAddress (&_PolicyNvWrittenData)#else#define _PolicyNvWrittenDataAddress 0#endif // CC_PolicyNvWritten#if CC_PolicyTemplate#include "PolicyTemplate_fp.h"
typedef TPM_RC (PolicyTemplate_Entry)(
PolicyTemplate_In*in);typedef const struct {PolicyTemplate_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} PolicyTemplate_COMMAND_DESCRIPTOR_t;
PolicyTemplate_COMMAND_DESCRIPTOR_t _PolicyTemplateData = {/* entry*/&TPM2_PolicyTemplate,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 65
April 15, 2019

Trusted Platform Module Library
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773

/* inSize*//* outSize*//* offsetOfTypes *//* offsets*//* types*/

Part 4: Supporting Routines(UINT16)(sizeof(PolicyTemplate_In)),0,
offsetof(PolicyTemplate_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(PolicyTemplate_In, templateHash))},{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyTemplateDataAddress (&_PolicyTemplateData)#else#define _PolicyTemplateDataAddress 0#endif // CC_PolicyTemplate#if CC_PolicyAuthorizeNV#include "PolicyAuthorizeNV_fp.h"
typedef TPM_RC (PolicyAuthorizeNV_Entry)(
PolicyAuthorizeNV_In*in);typedef const struct {PolicyAuthorizeNV_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t;
PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t _PolicyAuthorizeNVData = {/* entry*/&TPM2_PolicyAuthorizeNV,/* inSize*/(UINT16)(sizeof(PolicyAuthorizeNV_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(PolicyAuthorizeNV_In, nvIndex)),(UINT16)(offsetof(PolicyAuthorizeNV_In,
policySession))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,
TPMI_SH_POLICY_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PolicyAuthorizeNVDataAddress (&_PolicyAuthorizeNVData)#else#define _PolicyAuthorizeNVDataAddress 0#endif // CC_PolicyAuthorizeNV#if CC_CreatePrimary#include "CreatePrimary_fp.h"
typedef TPM_RC (CreatePrimary_Entry)(
CreatePrimary_In*in,CreatePrimary_Out*out);typedef const struct {CreatePrimary_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[9];BYTE
types[13];} CreatePrimary_COMMAND_DESCRIPTOR_t;
CreatePrimary_COMMAND_DESCRIPTOR_t _CreatePrimaryData = {/* entry*/&TPM2_CreatePrimary,/* inSize*/(UINT16)(sizeof(CreatePrimary_In)),/* outSize*/(UINT16)(sizeof(CreatePrimary_Out)),/* offsetOfTypes */offsetof(CreatePrimary_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(CreatePrimary_In, inSensitive)),(UINT16)(offsetof(CreatePrimary_In, inPublic)),

Page 66
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839

/* types*/

Trusted Platform Module Library(UINT16)(offsetof(CreatePrimary_In, outsideInfo)),(UINT16)(offsetof(CreatePrimary_In, creationPCR)),(UINT16)(offsetof(CreatePrimary_Out, outPublic)),(UINT16)(offsetof(CreatePrimary_Out, creationData)),(UINT16)(offsetof(CreatePrimary_Out, creationHash)),(UINT16)(offsetof(CreatePrimary_Out, creationTicket)),(UINT16)(offsetof(CreatePrimary_Out, name))},{TPMI_RH_HIERARCHY_H_UNMARSHAL + ADD_FLAG,TPM2B_SENSITIVE_CREATE_P_UNMARSHAL,TPM2B_PUBLIC_P_UNMARSHAL,TPM2B_DATA_P_UNMARSHAL,
TPML_PCR_SELECTION_P_UNMARSHAL,END_OF_LIST,
TPM_HANDLE_H_MARSHAL,TPM2B_PUBLIC_P_MARSHAL,TPM2B_CREATION_DATA_P_MARSHAL,TPM2B_DIGEST_P_MARSHAL,
TPMT_TK_CREATION_P_MARSHAL,TPM2B_NAME_P_MARSHAL,END_OF_LIST}};#define _CreatePrimaryDataAddress (&_CreatePrimaryData)#else#define _CreatePrimaryDataAddress 0#endif // CC_CreatePrimary#if CC_HierarchyControl#include "HierarchyControl_fp.h"
typedef TPM_RC (HierarchyControl_Entry)(
HierarchyControl_In*in);typedef const struct {HierarchyControl_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} HierarchyControl_COMMAND_DESCRIPTOR_t;
HierarchyControl_COMMAND_DESCRIPTOR_t _HierarchyControlData = {/* entry*/&TPM2_HierarchyControl,/* inSize*/(UINT16)(sizeof(HierarchyControl_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(HierarchyControl_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(HierarchyControl_In, enable)),(UINT16)(offsetof(HierarchyControl_In, state))},/* types*/{TPMI_RH_HIERARCHY_H_UNMARSHAL,
TPMI_RH_ENABLES_P_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _HierarchyControlDataAddress (&_HierarchyControlData)#else#define _HierarchyControlDataAddress 0#endif // CC_HierarchyControl#if CC_SetPrimaryPolicy#include "SetPrimaryPolicy_fp.h"
typedef TPM_RC (SetPrimaryPolicy_Entry)(
SetPrimaryPolicy_In*in);typedef const struct {SetPrimaryPolicy_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 67
April 15, 2019

Trusted Platform Module Library
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905

Part 4: Supporting Routines

BYTE
types[5];} SetPrimaryPolicy_COMMAND_DESCRIPTOR_t;
SetPrimaryPolicy_COMMAND_DESCRIPTOR_t _SetPrimaryPolicyData = {/* entry*/&TPM2_SetPrimaryPolicy,/* inSize*/(UINT16)(sizeof(SetPrimaryPolicy_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(SetPrimaryPolicy_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(SetPrimaryPolicy_In, authPolicy)),(UINT16)(offsetof(SetPrimaryPolicy_In, hashAlg))},/* types*/{TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,END_OF_LIST}};#define _SetPrimaryPolicyDataAddress (&_SetPrimaryPolicyData)#else#define _SetPrimaryPolicyDataAddress 0#endif // CC_SetPrimaryPolicy#if CC_ChangePPS#include "ChangePPS_fp.h"
typedef TPM_RC (ChangePPS_Entry)(
ChangePPS_In*in);typedef const struct {ChangePPS_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} ChangePPS_COMMAND_DESCRIPTOR_t;
ChangePPS_COMMAND_DESCRIPTOR_t _ChangePPSData = {/* entry*/&TPM2_ChangePPS,/* inSize*/(UINT16)(sizeof(ChangePPS_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(ChangePPS_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_RH_PLATFORM_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ChangePPSDataAddress (&_ChangePPSData)#else#define _ChangePPSDataAddress 0#endif // CC_ChangePPS#if CC_ChangeEPS#include "ChangeEPS_fp.h"
typedef TPM_RC (ChangeEPS_Entry)(
ChangeEPS_In*in);typedef const struct {ChangeEPS_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} ChangeEPS_COMMAND_DESCRIPTOR_t;
ChangeEPS_COMMAND_DESCRIPTOR_t _ChangeEPSData = {/* entry*/&TPM2_ChangeEPS,/* inSize*/(UINT16)(sizeof(ChangeEPS_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(ChangeEPS_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_RH_PLATFORM_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}

Page 68
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

Trusted Platform Module Library};#define _ChangeEPSDataAddress (&_ChangeEPSData)#else#define _ChangeEPSDataAddress 0#endif // CC_ChangeEPS#if CC_Clear#include "Clear_fp.h"
typedef TPM_RC (Clear_Entry)(
Clear_In*in);typedef const struct {Clear_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} Clear_COMMAND_DESCRIPTOR_t;
Clear_COMMAND_DESCRIPTOR_t _ClearData = {/* entry*/&TPM2_Clear,/* inSize*/(UINT16)(sizeof(Clear_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(Clear_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_RH_CLEAR_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ClearDataAddress (&_ClearData)#else#define _ClearDataAddress 0#endif // CC_Clear#if CC_ClearControl#include "ClearControl_fp.h"
typedef TPM_RC (ClearControl_Entry)(
ClearControl_In*in);typedef const struct {ClearControl_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} ClearControl_COMMAND_DESCRIPTOR_t;
ClearControl_COMMAND_DESCRIPTOR_t _ClearControlData = {/* entry*/&TPM2_ClearControl,/* inSize*/(UINT16)(sizeof(ClearControl_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(ClearControl_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ClearControl_In, disable))},/* types*/{TPMI_RH_CLEAR_H_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ClearControlDataAddress (&_ClearControlData)#else#define _ClearControlDataAddress 0#endif // CC_ClearControl#if CC_HierarchyChangeAuth#include "HierarchyChangeAuth_fp.h"
typedef TPM_RC (HierarchyChangeAuth_Entry)(
HierarchyChangeAuth_In*in);typedef const struct {HierarchyChangeAuth_Entry*entry;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 69
April 15, 2019

Trusted Platform Module Library
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033

Part 4: Supporting RoutinesUINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} HierarchyChangeAuth_COMMAND_DESCRIPTOR_t;
HierarchyChangeAuth_COMMAND_DESCRIPTOR_t _HierarchyChangeAuthData = {/* entry*/&TPM2_HierarchyChangeAuth,/* inSize*/(UINT16)(sizeof(HierarchyChangeAuth_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(HierarchyChangeAuth_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(HierarchyChangeAuth_In, newAuth))},/* types*/{TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL,TPM2B_AUTH_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _HierarchyChangeAuthDataAddress (&_HierarchyChangeAuthData)#else#define _HierarchyChangeAuthDataAddress 0#endif // CC_HierarchyChangeAuth#if CC_DictionaryAttackLockReset#include "DictionaryAttackLockReset_fp.h"
typedef TPM_RC (DictionaryAttackLockReset_Entry)(
DictionaryAttackLockReset_In*in);typedef const struct {DictionaryAttackLockReset_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t;
DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t _DictionaryAttackLockResetData = {/* entry*/&TPM2_DictionaryAttackLockReset,/* inSize*/(UINT16)(sizeof(DictionaryAttackLockReset_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_RH_LOCKOUT_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _DictionaryAttackLockResetDataAddress (&_DictionaryAttackLockResetData)#else#define _DictionaryAttackLockResetDataAddress 0#endif // CC_DictionaryAttackLockReset#if CC_DictionaryAttackParameters#include "DictionaryAttackParameters_fp.h"
typedef TPM_RC (DictionaryAttackParameters_Entry)(
DictionaryAttackParameters_In*in);typedef const struct {DictionaryAttackParameters_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} DictionaryAttackParameters_COMMAND_DESCRIPTOR_t;
DictionaryAttackParameters_COMMAND_DESCRIPTOR_t _DictionaryAttackParametersData = {/* entry*/&TPM2_DictionaryAttackParameters,

Page 70
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3034
3035
3036
3037

Trusted Platform Module Library/* inSize*/(UINT16)(sizeof(DictionaryAttackParameters_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(DictionaryAttackParameters_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(DictionaryAttackParameters_In, newMaxTries)),

3038(UINT16)(offsetof(DictionaryAttackParameters_In, newRecoveryTime)),
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094

(UINT16)(offsetof(DictionaryAttackParameters_In, lockoutRecovery))},/* types*/{TPMI_RH_LOCKOUT_H_UNMARSHAL,UINT32_P_UNMARSHAL,UINT32_P_UNMARSHAL,UINT32_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _DictionaryAttackParametersDataAddress (&_DictionaryAttackParametersData)#else#define _DictionaryAttackParametersDataAddress 0#endif // CC_DictionaryAttackParameters#if CC_PP_Commands#include "PP_Commands_fp.h"
typedef TPM_RC (PP_Commands_Entry)(
PP_Commands_In*in);typedef const struct {PP_Commands_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} PP_Commands_COMMAND_DESCRIPTOR_t;
PP_Commands_COMMAND_DESCRIPTOR_t _PP_CommandsData = {/* entry*/&TPM2_PP_Commands,/* inSize*/(UINT16)(sizeof(PP_Commands_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PP_Commands_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PP_Commands_In, setList)),(UINT16)(offsetof(PP_Commands_In, clearList))},/* types*/{TPMI_RH_PLATFORM_H_UNMARSHAL,
TPML_CC_P_UNMARSHAL,
TPML_CC_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _PP_CommandsDataAddress (&_PP_CommandsData)#else#define _PP_CommandsDataAddress 0#endif // CC_PP_Commands#if CC_SetAlgorithmSet#include "SetAlgorithmSet_fp.h"
typedef TPM_RC (SetAlgorithmSet_Entry)(
SetAlgorithmSet_In*in);typedef const struct {SetAlgorithmSet_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} SetAlgorithmSet_COMMAND_DESCRIPTOR_t;
SetAlgorithmSet_COMMAND_DESCRIPTOR_t _SetAlgorithmSetData = {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 71
April 15, 2019

Trusted Platform Module Library
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158

/* entry*//* inSize*//* outSize*//* offsetOfTypes *//* offsets*//* types*/

Part 4: Supporting Routines&TPM2_SetAlgorithmSet,(UINT16)(sizeof(SetAlgorithmSet_In)),0,
offsetof(SetAlgorithmSet_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(SetAlgorithmSet_In, algorithmSet))},{TPMI_RH_PLATFORM_H_UNMARSHAL,UINT32_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _SetAlgorithmSetDataAddress (&_SetAlgorithmSetData)#else#define _SetAlgorithmSetDataAddress 0#endif // CC_SetAlgorithmSet#if CC_FieldUpgradeStart#include "FieldUpgradeStart_fp.h"
typedef TPM_RC (FieldUpgradeStart_Entry)(
FieldUpgradeStart_In*in);typedef const struct {FieldUpgradeStart_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} FieldUpgradeStart_COMMAND_DESCRIPTOR_t;
FieldUpgradeStart_COMMAND_DESCRIPTOR_t _FieldUpgradeStartData = {/* entry*/&TPM2_FieldUpgradeStart,/* inSize*/(UINT16)(sizeof(FieldUpgradeStart_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(FieldUpgradeStart_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(FieldUpgradeStart_In, keyHandle)),(UINT16)(offsetof(FieldUpgradeStart_In, fuDigest)),(UINT16)(offsetof(FieldUpgradeStart_In,
manifestSignature))},/* types*/{TPMI_RH_PLATFORM_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMT_SIGNATURE_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _FieldUpgradeStartDataAddress (&_FieldUpgradeStartData)#else#define _FieldUpgradeStartDataAddress 0#endif // CC_FieldUpgradeStart#if CC_FieldUpgradeData#include "FieldUpgradeData_fp.h"
typedef TPM_RC (FieldUpgradeData_Entry)(
FieldUpgradeData_In*in,
FieldUpgradeData_Out*out);typedef const struct {FieldUpgradeData_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} FieldUpgradeData_COMMAND_DESCRIPTOR_t;
FieldUpgradeData_COMMAND_DESCRIPTOR_t _FieldUpgradeDataData = {/* entry*/&TPM2_FieldUpgradeData,/* inSize*/(UINT16)(sizeof(FieldUpgradeData_In)),/* outSize*/(UINT16)(sizeof(FieldUpgradeData_Out)),

Page 72
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224

/* offsetOfTypes *//* offsets*//* types*/

Trusted Platform Module Libraryoffsetof(FieldUpgradeData_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(FieldUpgradeData_Out, firstDigest))},{TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPMT_HA_P_MARSHAL,
TPMT_HA_P_MARSHAL,END_OF_LIST}};#define _FieldUpgradeDataDataAddress (&_FieldUpgradeDataData)#else#define _FieldUpgradeDataDataAddress 0#endif // CC_FieldUpgradeData#if CC_FirmwareRead#include "FirmwareRead_fp.h"
typedef TPM_RC (FirmwareRead_Entry)(
FirmwareRead_In*in,
FirmwareRead_Out*out);typedef const struct {FirmwareRead_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} FirmwareRead_COMMAND_DESCRIPTOR_t;
FirmwareRead_COMMAND_DESCRIPTOR_t _FirmwareReadData = {/* entry*/&TPM2_FirmwareRead,/* inSize*/(UINT16)(sizeof(FirmwareRead_In)),/* outSize*/(UINT16)(sizeof(FirmwareRead_Out)),/* offsetOfTypes */offsetof(FirmwareRead_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{UINT32_P_UNMARSHAL,END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,END_OF_LIST}};#define _FirmwareReadDataAddress (&_FirmwareReadData)#else#define _FirmwareReadDataAddress 0#endif // CC_FirmwareRead#if CC_ContextSave#include "ContextSave_fp.h"
typedef TPM_RC (ContextSave_Entry)(
ContextSave_In*in,ContextSave_Out*out);typedef const struct {ContextSave_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} ContextSave_COMMAND_DESCRIPTOR_t;
ContextSave_COMMAND_DESCRIPTOR_t _ContextSaveData = {/* entry*/&TPM2_ContextSave,/* inSize*/(UINT16)(sizeof(ContextSave_In)),/* outSize*/(UINT16)(sizeof(ContextSave_Out)),/* offsetOfTypes */offsetof(ContextSave_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_DH_CONTEXT_H_UNMARSHAL,END_OF_LIST,
TPMS_CONTEXT_P_MARSHAL,END_OF_LIST}};#define _ContextSaveDataAddress (&_ContextSaveData)#else

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 73
April 15, 2019

Trusted Platform Module Library
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290

Part 4: Supporting Routines#define _ContextSaveDataAddress 0#endif // CC_ContextSave#if CC_ContextLoad#include "ContextLoad_fp.h"
typedef TPM_RC (ContextLoad_Entry)(
ContextLoad_In*in,
ContextLoad_Out*out);typedef const struct {ContextLoad_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} ContextLoad_COMMAND_DESCRIPTOR_t;
ContextLoad_COMMAND_DESCRIPTOR_t _ContextLoadData = {/* entry*/&TPM2_ContextLoad,/* inSize*/(UINT16)(sizeof(ContextLoad_In)),/* outSize*/(UINT16)(sizeof(ContextLoad_Out)),/* offsetOfTypes */offsetof(ContextLoad_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMS_CONTEXT_P_UNMARSHAL,END_OF_LIST,
TPMI_DH_CONTEXT_H_MARSHAL,END_OF_LIST}};#define _ContextLoadDataAddress (&_ContextLoadData)#else#define _ContextLoadDataAddress 0#endif // CC_ContextLoad#if CC_FlushContext#include "FlushContext_fp.h"
typedef TPM_RC (FlushContext_Entry)(
FlushContext_In*in);typedef const struct {FlushContext_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} FlushContext_COMMAND_DESCRIPTOR_t;
FlushContext_COMMAND_DESCRIPTOR_t _FlushContextData = {/* entry*/&TPM2_FlushContext,/* inSize*/(UINT16)(sizeof(FlushContext_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(FlushContext_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMI_DH_CONTEXT_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _FlushContextDataAddress (&_FlushContextData)#else#define _FlushContextDataAddress 0#endif // CC_FlushContext#if CC_EvictControl#include "EvictControl_fp.h"
typedef TPM_RC (EvictControl_Entry)(
EvictControl_In*in);typedef const struct {EvictControl_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;

Page 74
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356

Trusted Platform Module Library

UINT16paramOffsets[2];BYTE
types[5];} EvictControl_COMMAND_DESCRIPTOR_t;
EvictControl_COMMAND_DESCRIPTOR_t _EvictControlData = {/* entry*/&TPM2_EvictControl,/* inSize*/(UINT16)(sizeof(EvictControl_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(EvictControl_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(EvictControl_In, objectHandle)),(UINT16)(offsetof(EvictControl_In, persistentHandle))},/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,
TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_DH_PERSISTENT_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _EvictControlDataAddress (&_EvictControlData)#else#define _EvictControlDataAddress 0#endif // CC_EvictControl#if CC_ReadClock#include "ReadClock_fp.h"
typedef TPM_RC (ReadClock_Entry)(
ReadClock_Out*out);typedef const struct {ReadClock_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} ReadClock_COMMAND_DESCRIPTOR_t;
ReadClock_COMMAND_DESCRIPTOR_t _ReadClockData = {/* entry*/&TPM2_ReadClock,/* inSize*/0,/* outSize*/(UINT16)(sizeof(ReadClock_Out)),/* offsetOfTypes */offsetof(ReadClock_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{END_OF_LIST,
TPMS_TIME_INFO_P_MARSHAL,END_OF_LIST}};#define _ReadClockDataAddress (&_ReadClockData)#else#define _ReadClockDataAddress 0#endif // CC_ReadClock#if CC_ClockSet#include "ClockSet_fp.h"
typedef TPM_RC (ClockSet_Entry)(
ClockSet_In*in);typedef const struct {ClockSet_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} ClockSet_COMMAND_DESCRIPTOR_t;
ClockSet_COMMAND_DESCRIPTOR_t _ClockSetData = {/* entry*/&TPM2_ClockSet,/* inSize*/(UINT16)(sizeof(ClockSet_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(ClockSet_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ClockSet_In, newTime))},/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 75
April 15, 2019

Trusted Platform Module Library
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422

Part 4: Supporting RoutinesUINT64_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ClockSetDataAddress (&_ClockSetData)#else#define _ClockSetDataAddress 0#endif // CC_ClockSet#if CC_ClockRateAdjust#include "ClockRateAdjust_fp.h"
typedef TPM_RC (ClockRateAdjust_Entry)(
ClockRateAdjust_In*in);typedef const struct {ClockRateAdjust_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} ClockRateAdjust_COMMAND_DESCRIPTOR_t;
ClockRateAdjust_COMMAND_DESCRIPTOR_t _ClockRateAdjustData = {/* entry*/&TPM2_ClockRateAdjust,/* inSize*/(UINT16)(sizeof(ClockRateAdjust_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(ClockRateAdjust_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ClockRateAdjust_In, rateAdjust))},/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,
TPM_CLOCK_ADJUST_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ClockRateAdjustDataAddress (&_ClockRateAdjustData)#else#define _ClockRateAdjustDataAddress 0#endif // CC_ClockRateAdjust#if CC_GetCapability#include "GetCapability_fp.h"
typedef TPM_RC (GetCapability_Entry)(
GetCapability_In*in,
GetCapability_Out*out);typedef const struct {GetCapability_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} GetCapability_COMMAND_DESCRIPTOR_t;
GetCapability_COMMAND_DESCRIPTOR_t _GetCapabilityData = {/* entry*/&TPM2_GetCapability,/* inSize*/(UINT16)(sizeof(GetCapability_In)),/* outSize*/(UINT16)(sizeof(GetCapability_Out)),/* offsetOfTypes */offsetof(GetCapability_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(GetCapability_In, property)),(UINT16)(offsetof(GetCapability_In, propertyCount)),(UINT16)(offsetof(GetCapability_Out, capabilityData))},/* types*/{TPM_CAP_P_UNMARSHAL,UINT32_P_UNMARSHAL,UINT32_P_UNMARSHAL,END_OF_LIST,
TPMI_YES_NO_P_MARSHAL,
TPMS_CAPABILITY_DATA_P_MARSHAL,END_OF_LIST}};

Page 76
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488

Trusted Platform Module Library#define _GetCapabilityDataAddress (&_GetCapabilityData)#else#define _GetCapabilityDataAddress 0#endif // CC_GetCapability#if CC_TestParms#include "TestParms_fp.h"
typedef TPM_RC (TestParms_Entry)(
TestParms_In*in);typedef const struct {TestParms_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} TestParms_COMMAND_DESCRIPTOR_t;
TestParms_COMMAND_DESCRIPTOR_t _TestParmsData = {/* entry*/&TPM2_TestParms,/* inSize*/(UINT16)(sizeof(TestParms_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(TestParms_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPMT_PUBLIC_PARMS_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _TestParmsDataAddress (&_TestParmsData)#else#define _TestParmsDataAddress 0#endif // CC_TestParms#if CC_NV_DefineSpace#include "NV_DefineSpace_fp.h"
typedef TPM_RC (NV_DefineSpace_Entry)(
NV_DefineSpace_In*in);typedef const struct {NV_DefineSpace_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} NV_DefineSpace_COMMAND_DESCRIPTOR_t;
NV_DefineSpace_COMMAND_DESCRIPTOR_t _NV_DefineSpaceData = {/* entry*/&TPM2_NV_DefineSpace,/* inSize*/(UINT16)(sizeof(NV_DefineSpace_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_DefineSpace_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_DefineSpace_In, auth)),(UINT16)(offsetof(NV_DefineSpace_In, publicInfo))},/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,TPM2B_AUTH_P_UNMARSHAL,TPM2B_NV_PUBLIC_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_DefineSpaceDataAddress (&_NV_DefineSpaceData)#else#define _NV_DefineSpaceDataAddress 0#endif // CC_NV_DefineSpace#if CC_NV_UndefineSpace#include "NV_UndefineSpace_fp.h"
typedef TPM_RC (NV_UndefineSpace_Entry)(
NV_UndefineSpace_In*in);typedef const struct {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 77
April 15, 2019

Trusted Platform Module Library
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552

Part 4: Supporting Routines

NV_UndefineSpace_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} NV_UndefineSpace_COMMAND_DESCRIPTOR_t;
NV_UndefineSpace_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceData = {/* entry*/&TPM2_NV_UndefineSpace,/* inSize*/(UINT16)(sizeof(NV_UndefineSpace_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_UndefineSpace_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_UndefineSpace_In, nvIndex))},/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_UndefineSpaceDataAddress (&_NV_UndefineSpaceData)#else#define _NV_UndefineSpaceDataAddress 0#endif // CC_NV_UndefineSpace#if CC_NV_UndefineSpaceSpecial#include "NV_UndefineSpaceSpecial_fp.h"
typedef TPM_RC (NV_UndefineSpaceSpecial_Entry)(
NV_UndefineSpaceSpecial_In*in);typedef const struct {NV_UndefineSpaceSpecial_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t;
NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceSpecialData = {/* entry*/&TPM2_NV_UndefineSpaceSpecial,/* inSize*/(UINT16)(sizeof(NV_UndefineSpaceSpecial_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_UndefineSpaceSpecial_In,
platform))},/* types*/{TPMI_RH_NV_INDEX_H_UNMARSHAL,
TPMI_RH_PLATFORM_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_UndefineSpaceSpecialDataAddress (&_NV_UndefineSpaceSpecialData)#else#define _NV_UndefineSpaceSpecialDataAddress 0#endif // CC_NV_UndefineSpaceSpecial#if CC_NV_ReadPublic#include "NV_ReadPublic_fp.h"
typedef TPM_RC (NV_ReadPublic_Entry)(
NV_ReadPublic_In*in,
NV_ReadPublic_Out*out);typedef const struct {NV_ReadPublic_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} NV_ReadPublic_COMMAND_DESCRIPTOR_t;

Page 78
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618

Trusted Platform Module Library

NV_ReadPublic_COMMAND_DESCRIPTOR_t _NV_ReadPublicData = {/* entry*/&TPM2_NV_ReadPublic,/* inSize*/(UINT16)(sizeof(NV_ReadPublic_In)),/* outSize*/(UINT16)(sizeof(NV_ReadPublic_Out)),/* offsetOfTypes */offsetof(NV_ReadPublic_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_ReadPublic_Out, nvName))},/* types*/{TPMI_RH_NV_INDEX_H_UNMARSHAL,END_OF_LIST,
TPM2B_NV_PUBLIC_P_MARSHAL,TPM2B_NAME_P_MARSHAL,END_OF_LIST}};#define _NV_ReadPublicDataAddress (&_NV_ReadPublicData)#else#define _NV_ReadPublicDataAddress 0#endif // CC_NV_ReadPublic#if CC_NV_Write#include "NV_Write_fp.h"
typedef TPM_RC (NV_Write_Entry)(
NV_Write_In*in);typedef const struct {NV_Write_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[6];} NV_Write_COMMAND_DESCRIPTOR_t;
NV_Write_COMMAND_DESCRIPTOR_t _NV_WriteData = {/* entry*/&TPM2_NV_Write,/* inSize*/(UINT16)(sizeof(NV_Write_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_Write_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_Write_In, nvIndex)),(UINT16)(offsetof(NV_Write_In, data)),(UINT16)(offsetof(NV_Write_In, offset))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,TPM2B_MAX_NV_BUFFER_P_UNMARSHAL,UINT16_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_WriteDataAddress (&_NV_WriteData)#else#define _NV_WriteDataAddress 0#endif // CC_NV_Write#if CC_NV_Increment#include "NV_Increment_fp.h"
typedef TPM_RC (NV_Increment_Entry)(
NV_Increment_In*in);typedef const struct {NV_Increment_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} NV_Increment_COMMAND_DESCRIPTOR_t;
NV_Increment_COMMAND_DESCRIPTOR_t _NV_IncrementData = {/* entry*/&TPM2_NV_Increment,/* inSize*/(UINT16)(sizeof(NV_Increment_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_Increment_COMMAND_DESCRIPTOR_t, types),

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 79
April 15, 2019

Trusted Platform Module Library
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684

/* offsets/* types*/*/

Part 4: Supporting Routines{(UINT16)(offsetof(NV_Increment_In, nvIndex))},{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_IncrementDataAddress (&_NV_IncrementData)#else#define _NV_IncrementDataAddress 0#endif // CC_NV_Increment#if CC_NV_Extend#include "NV_Extend_fp.h"
typedef TPM_RC (NV_Extend_Entry)(
NV_Extend_In*in);typedef const struct {NV_Extend_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} NV_Extend_COMMAND_DESCRIPTOR_t;
NV_Extend_COMMAND_DESCRIPTOR_t _NV_ExtendData = {/* entry*/&TPM2_NV_Extend,/* inSize*/(UINT16)(sizeof(NV_Extend_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_Extend_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_Extend_In, nvIndex)),(UINT16)(offsetof(NV_Extend_In, data))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,TPM2B_MAX_NV_BUFFER_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_ExtendDataAddress (&_NV_ExtendData)#else#define _NV_ExtendDataAddress 0#endif // CC_NV_Extend#if CC_NV_SetBits#include "NV_SetBits_fp.h"
typedef TPM_RC (NV_SetBits_Entry)(
NV_SetBits_In*in);typedef const struct {NV_SetBits_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[5];} NV_SetBits_COMMAND_DESCRIPTOR_t;
NV_SetBits_COMMAND_DESCRIPTOR_t _NV_SetBitsData = {/* entry*/&TPM2_NV_SetBits,/* inSize*/(UINT16)(sizeof(NV_SetBits_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_SetBits_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_SetBits_In, nvIndex)),(UINT16)(offsetof(NV_SetBits_In, bits))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,UINT64_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};

Page 80
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749

Trusted Platform Module Library#define _NV_SetBitsDataAddress (&_NV_SetBitsData)#else#define _NV_SetBitsDataAddress 0#endif // CC_NV_SetBits#if CC_NV_WriteLock#include "NV_WriteLock_fp.h"
typedef TPM_RC (NV_WriteLock_Entry)(
NV_WriteLock_In*in);typedef const struct {NV_WriteLock_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} NV_WriteLock_COMMAND_DESCRIPTOR_t;
NV_WriteLock_COMMAND_DESCRIPTOR_t _NV_WriteLockData = {/* entry*/&TPM2_NV_WriteLock,/* inSize*/(UINT16)(sizeof(NV_WriteLock_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_WriteLock_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_WriteLock_In, nvIndex))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_WriteLockDataAddress (&_NV_WriteLockData)#else#define _NV_WriteLockDataAddress 0#endif // CC_NV_WriteLock#if CC_NV_GlobalWriteLock#include "NV_GlobalWriteLock_fp.h"
typedef TPM_RC (NV_GlobalWriteLock_Entry)(
NV_GlobalWriteLock_In*in);typedef const struct {NV_GlobalWriteLock_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[3];} NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t;
NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t _NV_GlobalWriteLockData = {/* entry*/&TPM2_NV_GlobalWriteLock,/* inSize*/(UINT16)(sizeof(NV_GlobalWriteLock_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t,
types),/* offsets*/// No parameter offsets;/* types*/{TPMI_RH_PROVISION_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_GlobalWriteLockDataAddress (&_NV_GlobalWriteLockData)#else#define _NV_GlobalWriteLockDataAddress 0#endif // CC_NV_GlobalWriteLock#if CC_NV_Read#include "NV_Read_fp.h"
typedef TPM_RC (NV_Read_Entry)(
NV_Read_In*in,
NV_Read_Out*out);typedef const struct {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 81
April 15, 2019

Trusted Platform Module Library
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815

Part 4: Supporting Routines

NV_Read_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} NV_Read_COMMAND_DESCRIPTOR_t;
NV_Read_COMMAND_DESCRIPTOR_t _NV_ReadData = {/* entry*/&TPM2_NV_Read,/* inSize*/(UINT16)(sizeof(NV_Read_In)),/* outSize*/(UINT16)(sizeof(NV_Read_Out)),/* offsetOfTypes */offsetof(NV_Read_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_Read_In, nvIndex)),(UINT16)(offsetof(NV_Read_In, size)),(UINT16)(offsetof(NV_Read_In, offset))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,UINT16_P_UNMARSHAL,UINT16_P_UNMARSHAL,END_OF_LIST,
TPM2B_MAX_NV_BUFFER_P_MARSHAL,END_OF_LIST}};#define _NV_ReadDataAddress (&_NV_ReadData)#else#define _NV_ReadDataAddress 0#endif // CC_NV_Read#if CC_NV_ReadLock#include "NV_ReadLock_fp.h"
typedef TPM_RC (NV_ReadLock_Entry)(
NV_ReadLock_In*in);typedef const struct {NV_ReadLock_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} NV_ReadLock_COMMAND_DESCRIPTOR_t;
NV_ReadLock_COMMAND_DESCRIPTOR_t _NV_ReadLockData = {/* entry*/&TPM2_NV_ReadLock,/* inSize*/(UINT16)(sizeof(NV_ReadLock_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_ReadLock_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_ReadLock_In, nvIndex))},/* types*/{TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_ReadLockDataAddress (&_NV_ReadLockData)#else#define _NV_ReadLockDataAddress 0#endif // CC_NV_ReadLock#if CC_NV_ChangeAuth#include "NV_ChangeAuth_fp.h"
typedef TPM_RC (NV_ChangeAuth_Entry)(
NV_ChangeAuth_In*in);typedef const struct {NV_ChangeAuth_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];Page 82
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881

Trusted Platform Module Library

BYTE
types[4];} NV_ChangeAuth_COMMAND_DESCRIPTOR_t;
NV_ChangeAuth_COMMAND_DESCRIPTOR_t _NV_ChangeAuthData = {/* entry*/&TPM2_NV_ChangeAuth,/* inSize*/(UINT16)(sizeof(NV_ChangeAuth_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(NV_ChangeAuth_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_ChangeAuth_In, newAuth))},/* types*/{TPMI_RH_NV_INDEX_H_UNMARSHAL,TPM2B_AUTH_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _NV_ChangeAuthDataAddress (&_NV_ChangeAuthData)#else#define _NV_ChangeAuthDataAddress 0#endif // CC_NV_ChangeAuth#if CC_NV_Certify#include "NV_Certify_fp.h"
typedef TPM_RC (NV_Certify_Entry)(
NV_Certify_In*in,
NV_Certify_Out*out);typedef const struct {NV_Certify_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[7];BYTE
types[11];} NV_Certify_COMMAND_DESCRIPTOR_t;
NV_Certify_COMMAND_DESCRIPTOR_t _NV_CertifyData = {/* entry*/&TPM2_NV_Certify,/* inSize*/(UINT16)(sizeof(NV_Certify_In)),/* outSize*/(UINT16)(sizeof(NV_Certify_Out)),/* offsetOfTypes */offsetof(NV_Certify_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(NV_Certify_In, authHandle)),(UINT16)(offsetof(NV_Certify_In, nvIndex)),(UINT16)(offsetof(NV_Certify_In, qualifyingData)),(UINT16)(offsetof(NV_Certify_In, inScheme)),(UINT16)(offsetof(NV_Certify_In, size)),(UINT16)(offsetof(NV_Certify_In, offset)),(UINT16)(offsetof(NV_Certify_Out, signature))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG,
TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_NV_INDEX_H_UNMARSHAL,TPM2B_DATA_P_UNMARSHAL,
TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG,UINT16_P_UNMARSHAL,UINT16_P_UNMARSHAL,END_OF_LIST,
TPM2B_ATTEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,END_OF_LIST}};#define _NV_CertifyDataAddress (&_NV_CertifyData)#else#define _NV_CertifyDataAddress 0#endif // CC_NV_Certify#if CC_AC_GetCapability#include "AC_GetCapability_fp.h"
typedef TPM_RC (AC_GetCapability_Entry)(
AC_GetCapability_In*in,
AC_GetCapability_Out*out);typedef const struct {Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 83
April 15, 2019

Trusted Platform Module Library
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946

Part 4: Supporting Routines

AC_GetCapability_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} AC_GetCapability_COMMAND_DESCRIPTOR_t;
AC_GetCapability_COMMAND_DESCRIPTOR_t _AC_GetCapabilityData = {/* entry*/&TPM2_AC_GetCapability,/* inSize*/(UINT16)(sizeof(AC_GetCapability_In)),/* outSize*/(UINT16)(sizeof(AC_GetCapability_Out)),/* offsetOfTypes */offsetof(AC_GetCapability_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(AC_GetCapability_In, capability)),(UINT16)(offsetof(AC_GetCapability_In, count)),(UINT16)(offsetof(AC_GetCapability_Out,
capabilitiesData))},/* types*/{TPMI_RH_AC_H_UNMARSHAL,
TPM_AT_P_UNMARSHAL,UINT32_P_UNMARSHAL,END_OF_LIST,
TPMI_YES_NO_P_MARSHAL,
TPML_AC_CAPABILITIES_P_MARSHAL,END_OF_LIST}};#define _AC_GetCapabilityDataAddress (&_AC_GetCapabilityData)#else#define _AC_GetCapabilityDataAddress 0#endif // CC_AC_GetCapability#if CC_AC_Send#include "AC_Send_fp.h"
typedef TPM_RC (AC_Send_Entry)(
AC_Send_In*in,
AC_Send_Out*out);typedef const struct {AC_Send_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[3];BYTE
types[7];} AC_Send_COMMAND_DESCRIPTOR_t;
AC_Send_COMMAND_DESCRIPTOR_t _AC_SendData = {/* entry*/&TPM2_AC_Send,/* inSize*/(UINT16)(sizeof(AC_Send_In)),/* outSize*/(UINT16)(sizeof(AC_Send_Out)),/* offsetOfTypes */offsetof(AC_Send_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(AC_Send_In, authHandle)),(UINT16)(offsetof(AC_Send_In, ac)),(UINT16)(offsetof(AC_Send_In, acDataIn))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,
TPMI_RH_NV_AUTH_H_UNMARSHAL,
TPMI_RH_AC_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPMS_AC_OUTPUT_P_MARSHAL,END_OF_LIST}};#define _AC_SendDataAddress (&_AC_SendData)#else#define _AC_SendDataAddress 0#endif // CC_AC_Send#if CC_Policy_AC_SendSelect#include "Policy_AC_SendSelect_fp.h"
typedef TPM_RC (Policy_AC_SendSelect_Entry)(
Policy_AC_SendSelect_In*inPage 84
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008

Trusted Platform Module Library);
typedef const struct {Policy_AC_SendSelect_Entry *entry;
UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[7];} Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t;
Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t _Policy_AC_SendSelectData = {/* entry*/&TPM2_Policy_AC_SendSelect,/* inSize*/(UINT16)(sizeof(Policy_AC_SendSelect_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t,
types),/* offsets*/{(UINT16)(offsetof(Policy_AC_SendSelect_In,
objectName)),(UINT16)(offsetof(Policy_AC_SendSelect_In,
authHandleName)),(UINT16)(offsetof(Policy_AC_SendSelect_In, acName)),(UINT16)(offsetof(Policy_AC_SendSelect_In,
includeObject))},/* types*/{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,TPM2B_NAME_P_UNMARSHAL,
TPMI_YES_NO_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _Policy_AC_SendSelectDataAddress (&_Policy_AC_SendSelectData)#else#define _Policy_AC_SendSelectDataAddress 0#endif // CC_Policy_AC_SendSelect#if CC_Vendor_TCG_Test#include "Vendor_TCG_Test_fp.h"
typedef TPM_RC (Vendor_TCG_Test_Entry)(
Vendor_TCG_Test_In*in,
Vendor_TCG_Test_Out*out);
typedef const struct {Vendor_TCG_Test_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
BYTE
types[4];} Vendor_TCG_Test_COMMAND_DESCRIPTOR_t;
Vendor_TCG_Test_COMMAND_DESCRIPTOR_t _Vendor_TCG_TestData = {/* entry*/&TPM2_Vendor_TCG_Test,/* inSize*/(UINT16)(sizeof(Vendor_TCG_Test_In)),/* outSize*/(UINT16)(sizeof(Vendor_TCG_Test_Out)),/* offsetOfTypes */offsetof(Vendor_TCG_Test_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{TPM2B_DATA_P_UNMARSHAL,END_OF_LIST,
TPM2B_DATA_P_MARSHAL,END_OF_LIST}};#define _Vendor_TCG_TestDataAddress (&_Vendor_TCG_TestData)#else#define _Vendor_TCG_TestDataAddress 0#endif // CC_Vendor_TCG_Test
COMMAND_DESCRIPTOR_t *s_CommandDataArray[] = {#if (PAD_LIST || CC_NV_UndefineSpaceSpecial)(COMMAND_DESCRIPTOR_t *)_NV_UndefineSpaceSpecialDataAddress,#endif // CC_NV_UndefineSpaceSpecial

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 85
April 15, 2019

Trusted Platform Module Library
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074

Part 4: Supporting Routines#if (PAD_LIST || CC_EvictControl)(COMMAND_DESCRIPTOR_t *)_EvictControlDataAddress,#endif // CC_EvictControl#if (PAD_LIST || CC_HierarchyControl)(COMMAND_DESCRIPTOR_t *)_HierarchyControlDataAddress,#endif // CC_HierarchyControl#if (PAD_LIST || CC_NV_UndefineSpace)(COMMAND_DESCRIPTOR_t *)_NV_UndefineSpaceDataAddress,#endif // CC_NV_UndefineSpace#if (PAD_LIST)(COMMAND_DESCRIPTOR_t *)0,
#endif //#if (PAD_LIST || CC_ChangeEPS)(COMMAND_DESCRIPTOR_t *)_ChangeEPSDataAddress,#endif // CC_ChangeEPS#if (PAD_LIST || CC_ChangePPS)(COMMAND_DESCRIPTOR_t *)_ChangePPSDataAddress,#endif // CC_ChangePPS#if (PAD_LIST || CC_Clear)(COMMAND_DESCRIPTOR_t *)_ClearDataAddress,#endif // CC_Clear#if (PAD_LIST || CC_ClearControl)(COMMAND_DESCRIPTOR_t *)_ClearControlDataAddress,#endif // CC_ClearControl#if (PAD_LIST || CC_ClockSet)(COMMAND_DESCRIPTOR_t *)_ClockSetDataAddress,#endif // CC_ClockSet#if (PAD_LIST || CC_HierarchyChangeAuth)(COMMAND_DESCRIPTOR_t *)_HierarchyChangeAuthDataAddress,#endif // CC_HierarchyChangeAuth#if (PAD_LIST || CC_NV_DefineSpace)(COMMAND_DESCRIPTOR_t *)_NV_DefineSpaceDataAddress,#endif // CC_NV_DefineSpace#if (PAD_LIST || CC_PCR_Allocate)(COMMAND_DESCRIPTOR_t *)_PCR_AllocateDataAddress,#endif // CC_PCR_Allocate#if (PAD_LIST || CC_PCR_SetAuthPolicy)(COMMAND_DESCRIPTOR_t *)_PCR_SetAuthPolicyDataAddress,#endif // CC_PCR_SetAuthPolicy#if (PAD_LIST || CC_PP_Commands)(COMMAND_DESCRIPTOR_t *)_PP_CommandsDataAddress,#endif // CC_PP_Commands#if (PAD_LIST || CC_SetPrimaryPolicy)(COMMAND_DESCRIPTOR_t *)_SetPrimaryPolicyDataAddress,#endif // CC_SetPrimaryPolicy#if (PAD_LIST || CC_FieldUpgradeStart)(COMMAND_DESCRIPTOR_t *)_FieldUpgradeStartDataAddress,#endif // CC_FieldUpgradeStart#if (PAD_LIST || CC_ClockRateAdjust)(COMMAND_DESCRIPTOR_t *)_ClockRateAdjustDataAddress,#endif // CC_ClockRateAdjust#if (PAD_LIST || CC_CreatePrimary)(COMMAND_DESCRIPTOR_t *)_CreatePrimaryDataAddress,#endif // CC_CreatePrimary#if (PAD_LIST || CC_NV_GlobalWriteLock)(COMMAND_DESCRIPTOR_t *)_NV_GlobalWriteLockDataAddress,#endif // CC_NV_GlobalWriteLock#if (PAD_LIST || CC_GetCommandAuditDigest)(COMMAND_DESCRIPTOR_t *)_GetCommandAuditDigestDataAddress,#endif // CC_GetCommandAuditDigest#if (PAD_LIST || CC_NV_Increment)(COMMAND_DESCRIPTOR_t *)_NV_IncrementDataAddress,#endif // CC_NV_Increment#if (PAD_LIST || CC_NV_SetBits)(COMMAND_DESCRIPTOR_t *)_NV_SetBitsDataAddress,#endif // CC_NV_SetBits

Page 86
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140

Trusted Platform Module Library#if (PAD_LIST || CC_NV_Extend)(COMMAND_DESCRIPTOR_t *)_NV_ExtendDataAddress,#endif // CC_NV_Extend#if (PAD_LIST || CC_NV_Write)(COMMAND_DESCRIPTOR_t *)_NV_WriteDataAddress,#endif // CC_NV_Write#if (PAD_LIST || CC_NV_WriteLock)(COMMAND_DESCRIPTOR_t *)_NV_WriteLockDataAddress,#endif // CC_NV_WriteLock#if (PAD_LIST || CC_DictionaryAttackLockReset)(COMMAND_DESCRIPTOR_t *)_DictionaryAttackLockResetDataAddress,#endif // CC_DictionaryAttackLockReset#if (PAD_LIST || CC_DictionaryAttackParameters)(COMMAND_DESCRIPTOR_t *)_DictionaryAttackParametersDataAddress,#endif // CC_DictionaryAttackParameters#if (PAD_LIST || CC_NV_ChangeAuth)(COMMAND_DESCRIPTOR_t *)_NV_ChangeAuthDataAddress,#endif // CC_NV_ChangeAuth#if (PAD_LIST || CC_PCR_Event)(COMMAND_DESCRIPTOR_t *)_PCR_EventDataAddress,#endif // CC_PCR_Event#if (PAD_LIST || CC_PCR_Reset)(COMMAND_DESCRIPTOR_t *)_PCR_ResetDataAddress,#endif // CC_PCR_Reset#if (PAD_LIST || CC_SequenceComplete)(COMMAND_DESCRIPTOR_t *)_SequenceCompleteDataAddress,#endif // CC_SequenceComplete#if (PAD_LIST || CC_SetAlgorithmSet)(COMMAND_DESCRIPTOR_t *)_SetAlgorithmSetDataAddress,#endif // CC_SetAlgorithmSet#if (PAD_LIST || CC_SetCommandCodeAuditStatus)(COMMAND_DESCRIPTOR_t *)_SetCommandCodeAuditStatusDataAddress,#endif // CC_SetCommandCodeAuditStatus#if (PAD_LIST || CC_FieldUpgradeData)(COMMAND_DESCRIPTOR_t *)_FieldUpgradeDataDataAddress,#endif // CC_FieldUpgradeData#if (PAD_LIST || CC_IncrementalSelfTest)(COMMAND_DESCRIPTOR_t *)_IncrementalSelfTestDataAddress,#endif // CC_IncrementalSelfTest#if (PAD_LIST || CC_SelfTest)(COMMAND_DESCRIPTOR_t *)_SelfTestDataAddress,#endif // CC_SelfTest#if (PAD_LIST || CC_Startup)(COMMAND_DESCRIPTOR_t *)_StartupDataAddress,#endif // CC_Startup#if (PAD_LIST || CC_Shutdown)(COMMAND_DESCRIPTOR_t *)_ShutdownDataAddress,#endif // CC_Shutdown#if (PAD_LIST || CC_StirRandom)(COMMAND_DESCRIPTOR_t *)_StirRandomDataAddress,#endif // CC_StirRandom#if (PAD_LIST || CC_ActivateCredential)(COMMAND_DESCRIPTOR_t *)_ActivateCredentialDataAddress,#endif // CC_ActivateCredential#if (PAD_LIST || CC_Certify)(COMMAND_DESCRIPTOR_t *)_CertifyDataAddress,#endif // CC_Certify#if (PAD_LIST || CC_PolicyNV)(COMMAND_DESCRIPTOR_t *)_PolicyNVDataAddress,#endif // CC_PolicyNV#if (PAD_LIST || CC_CertifyCreation)(COMMAND_DESCRIPTOR_t *)_CertifyCreationDataAddress,#endif // CC_CertifyCreation#if (PAD_LIST || CC_Duplicate)(COMMAND_DESCRIPTOR_t *)_DuplicateDataAddress,#endif // CC_Duplicate

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 87
April 15, 2019

Trusted Platform Module Library
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206

Part 4: Supporting Routines#if (PAD_LIST || CC_GetTime)(COMMAND_DESCRIPTOR_t *)_GetTimeDataAddress,#endif // CC_GetTime#if (PAD_LIST || CC_GetSessionAuditDigest)(COMMAND_DESCRIPTOR_t *)_GetSessionAuditDigestDataAddress,#endif // CC_GetSessionAuditDigest#if (PAD_LIST || CC_NV_Read)(COMMAND_DESCRIPTOR_t *)_NV_ReadDataAddress,#endif // CC_NV_Read#if (PAD_LIST || CC_NV_ReadLock)(COMMAND_DESCRIPTOR_t *)_NV_ReadLockDataAddress,#endif // CC_NV_ReadLock#if (PAD_LIST || CC_ObjectChangeAuth)(COMMAND_DESCRIPTOR_t *)_ObjectChangeAuthDataAddress,#endif // CC_ObjectChangeAuth#if (PAD_LIST || CC_PolicySecret)(COMMAND_DESCRIPTOR_t *)_PolicySecretDataAddress,#endif // CC_PolicySecret#if (PAD_LIST || CC_Rewrap)(COMMAND_DESCRIPTOR_t *)_RewrapDataAddress,#endif // CC_Rewrap#if (PAD_LIST || CC_Create)(COMMAND_DESCRIPTOR_t *)_CreateDataAddress,#endif // CC_Create#if (PAD_LIST || CC_ECDH_ZGen)(COMMAND_DESCRIPTOR_t *)_ECDH_ZGenDataAddress,#endif // CC_ECDH_ZGen#if (PAD_LIST || (CC_HMAC || CC_MAC))#
if CC_HMAC(COMMAND_DESCRIPTOR_t *)_HMACDataAddress,
#
endif
#
if CC_MAC(COMMAND_DESCRIPTOR_t *)_MACDataAddress,
#
endif
#
if (CC_HMAC || CC_MAC) > 1#
error "More than one aliased command defined"#
endif#endif // CC_HMAC CC_MAC#if (PAD_LIST || CC_Import)(COMMAND_DESCRIPTOR_t *)_ImportDataAddress,#endif // CC_Import#if (PAD_LIST || CC_Load)(COMMAND_DESCRIPTOR_t *)_LoadDataAddress,#endif // CC_Load#if (PAD_LIST || CC_Quote)(COMMAND_DESCRIPTOR_t *)_QuoteDataAddress,#endif // CC_Quote#if (PAD_LIST || CC_RSA_Decrypt)(COMMAND_DESCRIPTOR_t *)_RSA_DecryptDataAddress,#endif // CC_RSA_Decrypt#if (PAD_LIST)(COMMAND_DESCRIPTOR_t *)0,
#endif //#if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start))#
if CC_HMAC_Start(COMMAND_DESCRIPTOR_t *)_HMAC_StartDataAddress,
#
endif
#
if CC_MAC_Start(COMMAND_DESCRIPTOR_t *)_MAC_StartDataAddress,
#
endif
#
if (CC_HMAC_Start || CC_MAC_Start) > 1#
error "More than one aliased command defined"#
endif#endif // CC_HMAC_Start CC_MAC_Start#if (PAD_LIST || CC_SequenceUpdate)(COMMAND_DESCRIPTOR_t *)_SequenceUpdateDataAddress,

Page 88
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272

Trusted Platform Module Library#endif // CC_SequenceUpdate#if (PAD_LIST || CC_Sign)(COMMAND_DESCRIPTOR_t *)_SignDataAddress,#endif // CC_Sign#if (PAD_LIST || CC_Unseal)(COMMAND_DESCRIPTOR_t *)_UnsealDataAddress,#endif // CC_Unseal#if (PAD_LIST)(COMMAND_DESCRIPTOR_t *)0,
#endif //#if (PAD_LIST || CC_PolicySigned)(COMMAND_DESCRIPTOR_t *)_PolicySignedDataAddress,#endif // CC_PolicySigned#if (PAD_LIST || CC_ContextLoad)(COMMAND_DESCRIPTOR_t *)_ContextLoadDataAddress,#endif // CC_ContextLoad#if (PAD_LIST || CC_ContextSave)(COMMAND_DESCRIPTOR_t *)_ContextSaveDataAddress,#endif // CC_ContextSave#if (PAD_LIST || CC_ECDH_KeyGen)(COMMAND_DESCRIPTOR_t *)_ECDH_KeyGenDataAddress,#endif // CC_ECDH_KeyGen#if (PAD_LIST || CC_EncryptDecrypt)(COMMAND_DESCRIPTOR_t *)_EncryptDecryptDataAddress,#endif // CC_EncryptDecrypt#if (PAD_LIST || CC_FlushContext)(COMMAND_DESCRIPTOR_t *)_FlushContextDataAddress,#endif // CC_FlushContext#if (PAD_LIST)(COMMAND_DESCRIPTOR_t *)0,
#endif //#if (PAD_LIST || CC_LoadExternal)(COMMAND_DESCRIPTOR_t *)_LoadExternalDataAddress,#endif // CC_LoadExternal#if (PAD_LIST || CC_MakeCredential)(COMMAND_DESCRIPTOR_t *)_MakeCredentialDataAddress,#endif // CC_MakeCredential#if (PAD_LIST || CC_NV_ReadPublic)(COMMAND_DESCRIPTOR_t *)_NV_ReadPublicDataAddress,#endif // CC_NV_ReadPublic#if (PAD_LIST || CC_PolicyAuthorize)(COMMAND_DESCRIPTOR_t *)_PolicyAuthorizeDataAddress,#endif // CC_PolicyAuthorize#if (PAD_LIST || CC_PolicyAuthValue)(COMMAND_DESCRIPTOR_t *)_PolicyAuthValueDataAddress,#endif // CC_PolicyAuthValue#if (PAD_LIST || CC_PolicyCommandCode)(COMMAND_DESCRIPTOR_t *)_PolicyCommandCodeDataAddress,#endif // CC_PolicyCommandCode#if (PAD_LIST || CC_PolicyCounterTimer)(COMMAND_DESCRIPTOR_t *)_PolicyCounterTimerDataAddress,#endif // CC_PolicyCounterTimer#if (PAD_LIST || CC_PolicyCpHash)(COMMAND_DESCRIPTOR_t *)_PolicyCpHashDataAddress,#endif // CC_PolicyCpHash#if (PAD_LIST || CC_PolicyLocality)(COMMAND_DESCRIPTOR_t *)_PolicyLocalityDataAddress,#endif // CC_PolicyLocality#if (PAD_LIST || CC_PolicyNameHash)(COMMAND_DESCRIPTOR_t *)_PolicyNameHashDataAddress,#endif // CC_PolicyNameHash#if (PAD_LIST || CC_PolicyOR)(COMMAND_DESCRIPTOR_t *)_PolicyORDataAddress,#endif // CC_PolicyOR#if (PAD_LIST || CC_PolicyTicket)(COMMAND_DESCRIPTOR_t *)_PolicyTicketDataAddress,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 89
April 15, 2019

Trusted Platform Module Library
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338

Part 4: Supporting Routines#endif // CC_PolicyTicket#if (PAD_LIST || CC_ReadPublic)(COMMAND_DESCRIPTOR_t *)_ReadPublicDataAddress,#endif // CC_ReadPublic#if (PAD_LIST || CC_RSA_Encrypt)(COMMAND_DESCRIPTOR_t *)_RSA_EncryptDataAddress,#endif // CC_RSA_Encrypt#if (PAD_LIST)(COMMAND_DESCRIPTOR_t *)0,
#endif //#if (PAD_LIST || CC_StartAuthSession)(COMMAND_DESCRIPTOR_t *)_StartAuthSessionDataAddress,#endif // CC_StartAuthSession#if (PAD_LIST || CC_VerifySignature)(COMMAND_DESCRIPTOR_t *)_VerifySignatureDataAddress,#endif // CC_VerifySignature#if (PAD_LIST || CC_ECC_Parameters)(COMMAND_DESCRIPTOR_t *)_ECC_ParametersDataAddress,#endif // CC_ECC_Parameters#if (PAD_LIST || CC_FirmwareRead)(COMMAND_DESCRIPTOR_t *)_FirmwareReadDataAddress,#endif // CC_FirmwareRead#if (PAD_LIST || CC_GetCapability)(COMMAND_DESCRIPTOR_t *)_GetCapabilityDataAddress,#endif // CC_GetCapability#if (PAD_LIST || CC_GetRandom)(COMMAND_DESCRIPTOR_t *)_GetRandomDataAddress,#endif // CC_GetRandom#if (PAD_LIST || CC_GetTestResult)(COMMAND_DESCRIPTOR_t *)_GetTestResultDataAddress,#endif // CC_GetTestResult#if (PAD_LIST || CC_Hash)(COMMAND_DESCRIPTOR_t *)_HashDataAddress,#endif // CC_Hash#if (PAD_LIST || CC_PCR_Read)(COMMAND_DESCRIPTOR_t *)_PCR_ReadDataAddress,#endif // CC_PCR_Read#if (PAD_LIST || CC_PolicyPCR)(COMMAND_DESCRIPTOR_t *)_PolicyPCRDataAddress,#endif // CC_PolicyPCR#if (PAD_LIST || CC_PolicyRestart)(COMMAND_DESCRIPTOR_t *)_PolicyRestartDataAddress,#endif // CC_PolicyRestart#if (PAD_LIST || CC_ReadClock)(COMMAND_DESCRIPTOR_t *)_ReadClockDataAddress,#endif // CC_ReadClock#if (PAD_LIST || CC_PCR_Extend)(COMMAND_DESCRIPTOR_t *)_PCR_ExtendDataAddress,#endif // CC_PCR_Extend#if (PAD_LIST || CC_PCR_SetAuthValue)(COMMAND_DESCRIPTOR_t *)_PCR_SetAuthValueDataAddress,#endif // CC_PCR_SetAuthValue#if (PAD_LIST || CC_NV_Certify)(COMMAND_DESCRIPTOR_t *)_NV_CertifyDataAddress,#endif // CC_NV_Certify#if (PAD_LIST || CC_EventSequenceComplete)(COMMAND_DESCRIPTOR_t *)_EventSequenceCompleteDataAddress,#endif // CC_EventSequenceComplete#if (PAD_LIST || CC_HashSequenceStart)(COMMAND_DESCRIPTOR_t *)_HashSequenceStartDataAddress,#endif // CC_HashSequenceStart#if (PAD_LIST || CC_PolicyPhysicalPresence)(COMMAND_DESCRIPTOR_t *)_PolicyPhysicalPresenceDataAddress,#endif // CC_PolicyPhysicalPresence#if (PAD_LIST || CC_PolicyDuplicationSelect)(COMMAND_DESCRIPTOR_t *)_PolicyDuplicationSelectDataAddress,

Page 90
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390

Trusted Platform Module Library#endif // CC_PolicyDuplicationSelect#if (PAD_LIST || CC_PolicyGetDigest)(COMMAND_DESCRIPTOR_t *)_PolicyGetDigestDataAddress,#endif // CC_PolicyGetDigest#if (PAD_LIST || CC_TestParms)(COMMAND_DESCRIPTOR_t *)_TestParmsDataAddress,#endif // CC_TestParms#if (PAD_LIST || CC_Commit)(COMMAND_DESCRIPTOR_t *)_CommitDataAddress,#endif // CC_Commit#if (PAD_LIST || CC_PolicyPassword)(COMMAND_DESCRIPTOR_t *)_PolicyPasswordDataAddress,#endif // CC_PolicyPassword#if (PAD_LIST || CC_ZGen_2Phase)(COMMAND_DESCRIPTOR_t *)_ZGen_2PhaseDataAddress,#endif // CC_ZGen_2Phase#if (PAD_LIST || CC_EC_Ephemeral)(COMMAND_DESCRIPTOR_t *)_EC_EphemeralDataAddress,#endif // CC_EC_Ephemeral#if (PAD_LIST || CC_PolicyNvWritten)(COMMAND_DESCRIPTOR_t *)_PolicyNvWrittenDataAddress,#endif // CC_PolicyNvWritten#if (PAD_LIST || CC_PolicyTemplate)(COMMAND_DESCRIPTOR_t *)_PolicyTemplateDataAddress,#endif // CC_PolicyTemplate#if (PAD_LIST || CC_CreateLoaded)(COMMAND_DESCRIPTOR_t *)_CreateLoadedDataAddress,#endif // CC_CreateLoaded#if (PAD_LIST || CC_PolicyAuthorizeNV)(COMMAND_DESCRIPTOR_t *)_PolicyAuthorizeNVDataAddress,#endif // CC_PolicyAuthorizeNV#if (PAD_LIST || CC_EncryptDecrypt2)(COMMAND_DESCRIPTOR_t *)_EncryptDecrypt2DataAddress,#endif // CC_EncryptDecrypt2#if (PAD_LIST || CC_AC_GetCapability)(COMMAND_DESCRIPTOR_t *)_AC_GetCapabilityDataAddress,#endif // CC_AC_GetCapability#if (PAD_LIST || CC_AC_Send)(COMMAND_DESCRIPTOR_t *)_AC_SendDataAddress,#endif // CC_AC_Send#if (PAD_LIST || CC_Policy_AC_SendSelect)(COMMAND_DESCRIPTOR_t *)_Policy_AC_SendSelectDataAddress,#endif // CC_Policy_AC_SendSelect#if (PAD_LIST || CC_CertifyX509)(COMMAND_DESCRIPTOR_t *)_CertifyX509DataAddress,#endif // CC_CertifyX509#if (PAD_LIST || CC_Vendor_TCG_Test)(COMMAND_DESCRIPTOR_t *)_Vendor_TCG_TestDataAddress,#endif // CC_Vendor_TCG_Test0};#endif // _COMMAND_TABLE_DISPATCH_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 91
April 15, 2019

Trusted Platform Module Library

5.7
1
2

Part 4: Supporting Routines

Commands.h#ifndef _COMMANDS_H_#define _COMMANDS_H_

Start-up
3
4
5
6
7
8

#ifdef TPM_CC_Startup#include "Startup_fp.h"#endif#ifdef TPM_CC_Shutdown#include "Shutdown_fp.h"#endifTesting
9
10
11
12
13
14
15
16
17

#ifdef TPM_CC_SelfTest#include "SelfTest_fp.h"#endif#ifdef TPM_CC_IncrementalSelfTest#include "IncrementalSelfTest_fp.h"#endif#ifdef TPM_CC_GetTestResult#include "GetTestResult_fp.h"#endifSession Commands
18
19
20
21
22
23

#ifdef TPM_CC_StartAuthSession#include "StartAuthSession_fp.h"#endif#ifdef TPM_CC_PolicyRestart#include "PolicyRestart_fp.h"#endifObject Commands
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

#ifdef TPM_CC_Create#include "Create_fp.h"#endif#ifdef TPM_CC_Load#include "Load_fp.h"#endif#ifdef TPM_CC_LoadExternal#include "LoadExternal_fp.h"#endif#ifdef TPM_CC_ReadPublic#include "ReadPublic_fp.h"#endif#ifdef TPM_CC_ActivateCredential#include "ActivateCredential_fp.h"#endif#ifdef TPM_CC_MakeCredential#include "MakeCredential_fp.h"#endif#ifdef TPM_CC_Unseal#include "Unseal_fp.h"#endif#ifdef TPM_CC_ObjectChangeAuth#include "ObjectChangeAuth_fp.h"#endif#ifdef TPM_CC_CreateLoaded#include "CreateLoaded_fp.h"

Page 92
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
50

Trusted Platform Module Library#endifDuplication Commands
51
52
53
54
55
56
57
58
59

#ifdef TPM_CC_Duplicate#include "Duplicate_fp.h"#endif#ifdef TPM_CC_Rewrap#include "Rewrap_fp.h"#endif#ifdef TPM_CC_Import#include "Import_fp.h"#endifAsymmetric Primitives
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

#ifdef TPM_CC_RSA_Encrypt#include "RSA_Encrypt_fp.h"#endif#ifdef TPM_CC_RSA_Decrypt#include "RSA_Decrypt_fp.h"#endif#ifdef TPM_CC_ECDH_KeyGen#include "ECDH_KeyGen_fp.h"#endif#ifdef TPM_CC_ECDH_ZGen#include "ECDH_ZGen_fp.h"#endif#ifdef TPM_CC_ECC_Parameters#include "ECC_Parameters_fp.h"#endif#ifdef TPM_CC_ZGen_2Phase#include "ZGen_2Phase_fp.h"#endifSymmetric Primitives
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

#ifdef TPM_CC_EncryptDecrypt#include "EncryptDecrypt_fp.h"#endif#ifdef TPM_CC_EncryptDecrypt2#include "EncryptDecrypt2_fp.h"#endif#ifdef TPM_CC_Hash#include "Hash_fp.h"#endif#ifdef TPM_CC_HMAC#include "HMAC_fp.h"#endif#ifdef TPM_CC_MAC#include "MAC_fp.h"#endifRandom Number Generator
93
94
95
96
97
98

#ifdef TPM_CC_GetRandom#include "GetRandom_fp.h"#endif#ifdef TPM_CC_StirRandom#include "StirRandom_fp.h"#endifHash/HMAC/Event Sequences
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 93
April 15, 2019

Trusted Platform Module Library
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

Part 4: Supporting Routines#ifdef TPM_CC_HMAC_Start#include "HMAC_Start_fp.h"#endif#ifdef TPM_CC_MAC_Start#include "MAC_Start_fp.h"#endif#ifdef TPM_CC_HashSequenceStart#include "HashSequenceStart_fp.h"#endif#ifdef TPM_CC_SequenceUpdate#include "SequenceUpdate_fp.h"#endif#ifdef TPM_CC_SequenceComplete#include "SequenceComplete_fp.h"#endif#ifdef TPM_CC_EventSequenceComplete#include "EventSequenceComplete_fp.h"#endif

Attestation Commands
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

#ifdef TPM_CC_Certify#include "Certify_fp.h"#endif#ifdef TPM_CC_CertifyCreation#include "CertifyCreation_fp.h"#endif#ifdef TPM_CC_Quote#include "Quote_fp.h"#endif#ifdef TPM_CC_GetSessionAuditDigest#include "GetSessionAuditDigest_fp.h"#endif#ifdef TPM_CC_GetCommandAuditDigest#include "GetCommandAuditDigest_fp.h"#endif#ifdef TPM_CC_GetTime#include "GetTime_fp.h"#endif#ifdef TPM_CC_CertifyX509#include "CertifyX509_fp.h"#endifEphemeral EC Keys
138
139
140
141
142
143

#ifdef TPM_CC_Commit#include "Commit_fp.h"#endif#ifdef TPM_CC_EC_Ephemeral#include "EC_Ephemeral_fp.h"#endifSigning and Signature Verification
144
145
146
147
148
149

#ifdef TPM_CC_VerifySignature#include "VerifySignature_fp.h"#endif#ifdef TPM_CC_Sign#include "Sign_fp.h"#endifCommand Audit
150#ifdef TPM_CC_SetCommandCodeAuditStatus

Page 94
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
151
152

Trusted Platform Module Library#include "SetCommandCodeAuditStatus_fp.h"#endifIntegrity Collection (PCR)
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

#ifdef TPM_CC_PCR_Extend#include "PCR_Extend_fp.h"#endif#ifdef TPM_CC_PCR_Event#include "PCR_Event_fp.h"#endif#ifdef TPM_CC_PCR_Read#include "PCR_Read_fp.h"#endif#ifdef TPM_CC_PCR_Allocate#include "PCR_Allocate_fp.h"#endif#ifdef TPM_CC_PCR_SetAuthPolicy#include "PCR_SetAuthPolicy_fp.h"#endif#ifdef TPM_CC_PCR_SetAuthValue#include "PCR_SetAuthValue_fp.h"#endif#ifdef TPM_CC_PCR_Reset#include "PCR_Reset_fp.h"#endifEnhanced Authorization (EA) Commands
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

#ifdef TPM_CC_PolicySigned#include "PolicySigned_fp.h"#endif#ifdef TPM_CC_PolicySecret#include "PolicySecret_fp.h"#endif#ifdef TPM_CC_PolicyTicket#include "PolicyTicket_fp.h"#endif#ifdef TPM_CC_PolicyOR#include "PolicyOR_fp.h"#endif#ifdef TPM_CC_PolicyPCR#include "PolicyPCR_fp.h"#endif#ifdef TPM_CC_PolicyLocality#include "PolicyLocality_fp.h"#endif#ifdef TPM_CC_PolicyNV#include "PolicyNV_fp.h"#endif#ifdef TPM_CC_PolicyCounterTimer#include "PolicyCounterTimer_fp.h"#endif#ifdef TPM_CC_PolicyCommandCode#include "PolicyCommandCode_fp.h"#endif#ifdef TPM_CC_PolicyPhysicalPresence#include "PolicyPhysicalPresence_fp.h"#endif#ifdef TPM_CC_PolicyCpHash#include "PolicyCpHash_fp.h"#endif#ifdef TPM_CC_PolicyNameHash#include "PolicyNameHash_fp.h"#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 95
April 15, 2019

Trusted Platform Module Library
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

Part 4: Supporting Routines#ifdef TPM_CC_PolicyDuplicationSelect#include "PolicyDuplicationSelect_fp.h"#endif#ifdef TPM_CC_PolicyAuthorize#include "PolicyAuthorize_fp.h"#endif#ifdef TPM_CC_PolicyAuthValue#include "PolicyAuthValue_fp.h"#endif#ifdef TPM_CC_PolicyPassword#include "PolicyPassword_fp.h"#endif#ifdef TPM_CC_PolicyGetDigest#include "PolicyGetDigest_fp.h"#endif#ifdef TPM_CC_PolicyNvWritten#include "PolicyNvWritten_fp.h"#endif#ifdef TPM_CC_PolicyTemplate#include "PolicyTemplate_fp.h"#endif#ifdef TPM_CC_PolicyAuthorizeNV#include "PolicyAuthorizeNV_fp.h"#endif

Hierarchy Commands
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

#ifdef TPM_CC_CreatePrimary#include "CreatePrimary_fp.h"#endif#ifdef TPM_CC_HierarchyControl#include "HierarchyControl_fp.h"#endif#ifdef TPM_CC_SetPrimaryPolicy#include "SetPrimaryPolicy_fp.h"#endif#ifdef TPM_CC_ChangePPS#include "ChangePPS_fp.h"#endif#ifdef TPM_CC_ChangeEPS#include "ChangeEPS_fp.h"#endif#ifdef TPM_CC_Clear#include "Clear_fp.h"#endif#ifdef TPM_CC_ClearControl#include "ClearControl_fp.h"#endif#ifdef TPM_CC_HierarchyChangeAuth#include "HierarchyChangeAuth_fp.h"#endifDictionary Attack Functions
258
259
260
261
262
263

#ifdef TPM_CC_DictionaryAttackLockReset#include "DictionaryAttackLockReset_fp.h"#endif#ifdef TPM_CC_DictionaryAttackParameters#include "DictionaryAttackParameters_fp.h"#endifMiscellaneous Management Functions
264#ifdef TPM_CC_PP_Commands

Page 96
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
265
266
267
268
269

Trusted Platform Module Library#include "PP_Commands_fp.h"#endif#ifdef TPM_CC_SetAlgorithmSet#include "SetAlgorithmSet_fp.h"#endifField Upgrade
270
271
272
273
274
275
276
277
278

#ifdef TPM_CC_FieldUpgradeStart#include "FieldUpgradeStart_fp.h"#endif#ifdef TPM_CC_FieldUpgradeData#include "FieldUpgradeData_fp.h"#endif#ifdef TPM_CC_FirmwareRead#include "FirmwareRead_fp.h"#endifContext Management
279
280
281
282
283
284
285
286
287
288
289
290

#ifdef TPM_CC_ContextSave#include "ContextSave_fp.h"#endif#ifdef TPM_CC_ContextLoad#include "ContextLoad_fp.h"#endif#ifdef TPM_CC_FlushContext#include "FlushContext_fp.h"#endif#ifdef TPM_CC_EvictControl#include "EvictControl_fp.h"#endifClocks and Timers
291
292
293
294
295
296
297
298
299

#ifdef TPM_CC_ReadClock#include "ReadClock_fp.h"#endif#ifdef TPM_CC_ClockSet#include "ClockSet_fp.h"#endif#ifdef TPM_CC_ClockRateAdjust#include "ClockRateAdjust_fp.h"#endifCapability Commands
300
301
302
303
304
305

#ifdef TPM_CC_GetCapability#include "GetCapability_fp.h"#endif#ifdef TPM_CC_TestParms#include "TestParms_fp.h"#endifNon-volatile Storage
306
307
308
309
310
311
312

#ifdef TPM_CC_NV_DefineSpace#include "NV_DefineSpace_fp.h"#endif#ifdef TPM_CC_NV_UndefineSpace#include "NV_UndefineSpace_fp.h"#endif#ifdef TPM_CC_NV_UndefineSpaceSpecial

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 97
April 15, 2019

Trusted Platform Module Library
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347

Part 4: Supporting Routines#include "NV_UndefineSpaceSpecial_fp.h"#endif#ifdef TPM_CC_NV_ReadPublic#include "NV_ReadPublic_fp.h"#endif#ifdef TPM_CC_NV_Write#include "NV_Write_fp.h"#endif#ifdef TPM_CC_NV_Increment#include "NV_Increment_fp.h"#endif#ifdef TPM_CC_NV_Extend#include "NV_Extend_fp.h"#endif#ifdef TPM_CC_NV_SetBits#include "NV_SetBits_fp.h"#endif#ifdef TPM_CC_NV_WriteLock#include "NV_WriteLock_fp.h"#endif#ifdef TPM_CC_NV_GlobalWriteLock#include "NV_GlobalWriteLock_fp.h"#endif#ifdef TPM_CC_NV_Read#include "NV_Read_fp.h"#endif#ifdef TPM_CC_NV_ReadLock#include "NV_ReadLock_fp.h"#endif#ifdef TPM_CC_NV_ChangeAuth#include "NV_ChangeAuth_fp.h"#endif#ifdef TPM_CC_NV_Certify#include "NV_Certify_fp.h"#endifAttached Components
348
349
350
351
352
353
354
355
356

#ifdef TPM_CC_AC_GetCapability#include "AC_GetCapability_fp.h"#endif#ifdef TPM_CC_AC_Send#include "AC_Send_fp.h"#endif#ifdef TPM_CC_Policy_AC_SendSelect#include "Policy_AC_SendSelect_fp.h"#endifVendor Specific
357
358
359
360

#ifdef TPM_CC_Vendor_TCG_Test#include "Vendor_TCG_Test_fp.h"#endif#endifPage 98
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.8

Trusted Platform Module LibraryCompilerDependencies.h

This file contains the build switches. This contains switches for multiple versions of the crypto-library sosome may not apply to your environment.
1
2
3
4
5
6
7

#ifndef _COMPILER_DEPENDENCIES_H_#define _COMPILER_DEPENDENCIES_H_#ifdef GCC#
undef _MSC_VER#
undef WIN32#endif#ifdef _MSC_VER

These definitions are for the Microsoft compiler Endian conversion for aligned structures
8
9
10

#
#
#

define REVERSE_ENDIAN_16(_Number) _byteswap_ushort(_Number)define REVERSE_ENDIAN_32(_Number) _byteswap_ulong(_Number)define REVERSE_ENDIAN_64(_Number) _byteswap_uint64(_Number)

Avoid compiler warning for in line of stdio (or not)11//#define _NO_CRT_STDIO_INLINE

This macro is used to handle LIB_EXPORT of function and variable names in lieu of a .def file. Visual
Studio requires that functions be explicitly exported and imported.
12
13

#
#

define LIB_EXPORT __declspec(dllexport) // VS compatible version
define LIB_IMPORT __declspec(dllimport)

This is defined to indicate a function that does not return. Microsoft compilers do not support the_Noretrun function parameter.
14
15
16
17
18
19
20
21
22
23

#
define NORETURN __declspec(noreturn)#
if _MSC_VER >= 1400// SAL processing when needed#
include <sal.h>
#
endif
#
ifdef _WIN64#
define _INTPTR 2#
else#
define _INTPTR 1#
endif#define NOT_REFERENCED(x)(x)

Lower the compiler error warning for system include files. They tend not to be that clean and there is no
reason to sort through all the spurious errors that they generate when the normal error level is set to /Wall
24
25#
define _REDUCE_WARNING_LEVEL_(n)__pragma(warning(push, n))\

Restore the compiler warning level
26
27
28
29
30
31
32
33
34
35

#
define _NORMAL_WARNING_LEVEL_\__pragma(warning(pop))#
include <stdint.h>#endif#ifndef _MSC_VER#ifndef WINAPI#
define WINAPI#endif#define __pragma(x)#define REVERSE_ENDIAN_16(_Number) __builtin_bswap16(_Number)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 99
April 15, 2019

Trusted Platform Module Library
36
37
38
39
40
41
42

Part 4: Supporting Routines#
define REVERSE_ENDIAN_32(_Number) __builtin_bswap32(_Number)#define REVERSE_ENDIAN_64(_Number) __builtin_bswap64(_Number)#endif#if defined(__GNUC__)#
define NORETURN__attribute__((noreturn))#
include <stdint.h>#endifThings that are not defined should be defined as NULL
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#ifndef NORETURN#
define NORETURN#endif#ifndef LIB_EXPORT#
define LIB_EXPORT#endif#ifndef LIB_IMPORT#
define LIB_IMPORT#endif#ifndef _REDUCE_WARNING_LEVEL_#
define _REDUCE_WARNING_LEVEL_(n)#endif#ifndef _NORMAL_WARNING_LEVEL_#
define _NORMAL_WARNING_LEVEL_#endif#ifndef NOT_REFERENCED#
define NOT_REFERENCED(x) (x = x)
#endif#ifdef _POSIX_
typedef int SOCKET;#endif#endif // _COMPILER_DEPENDENCIES_H_

Page 100
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.9
5.9.1

Trusted Platform Module Library

Global.hDescription

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 thesubsystem 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 thecode. 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.
1
2
3#if !defined _TPM_H_#error "Should only be instanced in TPM.h"#endif

5.9.2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

Includes#ifndef
GLOBAL_H#define
GLOBAL_H#ifdef GLOBAL_C#define EXTERN#define INITIALIZER(_value_)#else#define EXTERN extern#define INITIALIZER(_name_)#endif_REDUCE_WARNING_LEVEL_(2)#include <string.h>#include <stddef.h>= _value__NORMAL_WARNING_LEVEL_#if SIMULATION#undef CONTEXT_SLOT# define CONTEXT_SLOT
UINT8#endif#include "Capabilities.h"#include "TpmTypes.h"#include "CommandAttributes.h"#include "CryptTest.h"#include "BnValues.h"#include "CryptHash.h"#include "CryptSym.h"#include "CryptRand.h"#include "CryptEcc.h"#include "CryptRsa.h"#include "CryptTest.h"#include "TpmError.h"#include "NV.h"//** Defines and Types//*** Size Types// These types are used to differentiate the two different size values used.
//// NUMBYTES is used when a size is a number of bytes (usually a TPM2B)

typedef UINT16

NUMBYTES;//*** Other Types// An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 101
April 15, 2019

Trusted Platform Module Library46

typedef BYTEPart 4: Supporting Routines

AUTH_VALUE[sizeof(TPMU_HA)];A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO
47

typedef BYTE

TIME_INFO[sizeof(TPMS_TIME_INFO)];A NAME is a BYTE array that can contain a TPMU_NAME
48

typedef BYTE

NAME[sizeof(TPMU_NAME)];

Definition for a PROOF value49

TPM2B_TYPE(PROOF, PROOF_SIZE);Definition for a Primary Seed value50

TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE);A CLOCK_NONCE is used to tag the time value in the authorization session and in the ticket computation
so that the ticket expires when there is a time discontinuity. When the clock stops during normal
operation, the nonce is 64-bit value kept in RAM but it is a 32-bit counter when the clock only stops during
power events.
51
52
53
54
55

#if CLOCK_STOPS
typedef UINT64#else
typedef UINT32#endif

5.9.3

CLOCK_NONCE;
CLOCK_NONCE;

Loaded Object Structures

5.9.3.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 ahash, HMAC, or event.
5.9.3.2

OBJECT_ATTRIBUTESAn 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.
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

typedef struct{unsignedpublicOnly : 1;

unsigned

epsHierarchy : 1;

unsigned

ppsHierarchy : 1;

unsigned

spsHierarchy : 1;

unsigned

evict : 1;

Page 102
April 15, 2019//0) SET if only the public portion of//an object is loaded//1) SET if the object belongs to EPS//
Hierarchy//2) SET if the object belongs to PPS//
Hierarchy//3) SET f the object belongs to SPS//
Hierarchy//4) SET if the object is a platform or//owner evict object. Platform//
evict object belongs to PPS//
hierarchy, owner-evict object//
belongs to SPS or EPS hierarchy.

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

//
//

Trusted Platform Module Library

unsigned
unsigned
unsigned
unsignedprimary : 1;
temporary : 1;
stClear : 1;
hmacSeq : 1;

unsigned
unsigned
unsigned

hashSeq : 1;
eventSeq : 1;
ticketSafe : 1;

unsignedfirstBlock : 1;

unsigned

isParent : 1;

unsigned

privateExp : 1;

unsigned
unsigned
unsigned

not_used_14 : 1;
occupied : 1;
derivation : 1;

unsigned

external : 1;//
This bit is also used to mark a//completed sequence object so it//
will be flush when the//
SequenceComplete command succeeds.
//5) SET for a primary object//6) SET for a temporary object//7) SET for an stClear object//8) SET for an HMAC or MAC sequence//object//9) SET for a hash sequence object//10) SET for an event sequence object//11) SET if a ticket is safe to create//
for hash sequence object//12) SET if the first block of hash//data has been received. It//
works with ticketSafe bit//13) SET if the key has the proper//
attributes to be a parent key//14) SET when the private exponent//of an RSA key has been validated.
//15) SET when the slot is occupied.
//16) SET when the key is a derivation//
parent//17) SET when the object is loaded with//
TPM2_LoadExternal();} OBJECT_ATTRIBUTES;#if ALG_RSA

There is an overload of the sensitive.rsa.t.size field of a TPMT_SENSITIVE when an RSA key is loaded.
When the sensitive->sensitive contains an RSA key with all of the CRT values, then the MSB of the size
field will be set to indicate that the buffer contains all 5 of the CRT private key values.
99
100#define#endif

RSA_prime_flag

5.9.3.3

OBJECT Structure

0x8000An 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 forclarity of the reference implementation. Other implementations may choose to overlap portions of thestructure that are not used simultaneously. These changes would necessitate changes to the source code
but those changes would be compatible with the reference implementation.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

typedef struct OBJECT{// The attributes field is required to be first followed by the publicArea.
// This allows the overlay of the object structure and a sequence structure
OBJECT_ATTRIBUTES
attributes;// object attributes
TPMT_PUBLIC
publicArea;// public area of an object
TPMT_SENSITIVE
sensitive;// sensitive area of an object
TPM2B_NAME
qualifiedName;// object qualified name
TPMI_DH_OBJECT
evictHandle;// if the object is an evict object,// the original handle is kept here.
// The 'working' handle will be the// handle of an object slot.
TPM2B_NAME
name;// Name of the object name. Kept here// to avoid repeatedly computing it.
} OBJECT;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 103
April 15, 2019

Trusted Platform Module Library

5.9.3.4

Part 4: Supporting Routines

HASH_OBJECT StructureThis 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 arewhat they are supposed to be.
NOTE:

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

In a future version, this will probably be renamed as SEQUENCE_OBJECT

typedef struct HASH_OBJECT{OBJECT_ATTRIBUTES
attributes;
TPMI_ALG_PUBLIC
type;
TPMI_ALG_HASH
nameAlg;
TPMA_OBJECT
objectAttributes;// The attributes of the HASH object// algorithm// name algorithm// object attributes// The data below is unique to a sequence object
TPM2B_AUTHauth;// authorization for use of sequence
union{
HASH_STATE
hashState[HASH_COUNT];HMAC_STATE
hmacState;}state;} HASH_OBJECT;
typedef BYTE HASH_OBJECT_BUFFER[sizeof(HASH_OBJECT)];

5.9.3.5

ANY_OBJECTThis is the union for holding either a sequence object or a regular object. for ContextSave() andContextLoad()
132
133
134
135
136
137

typedef union ANY_OBJECT{OBJECT
entity;
HASH_OBJECT
hash;} ANY_OBJECT;
typedef BYTE
ANY_OBJECT_BUFFER[sizeof(ANY_OBJECT)];

5.9.4

AUTH_DUP Types

These values are used in the authorization processing.
138
139
140
141
142

typedef UINT32#define AUTH_NONE#define AUTH_USER#define AUTH_ADMIN#define AUTH_DUP

5.9.5

AUTH_ROLE;((AUTH_ROLE)(0))((AUTH_ROLE)(1))((AUTH_ROLE)(2))((AUTH_ROLE)(3))

Active Session Context

5.9.5.1

Description

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

Page 104
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.9.5.2

Trusted Platform Module Library

SESSION_ATTRIBUTESThe 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.
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

typedef struct SESSION_ATTRIBUTES{
unsigned
isPolicy : 1;
unsigned
unsigned

isAudit : 1;
isBound : 1;

unsigned

isCpHashDefined : 1;

unsigned

isAuthValueNeeded : 1;

unsigned

isPasswordNeeded : 1;

unsigned

isPPRequired : 1;

unsigned

isTrialPolicy : 1;

unsigned

isDaBound : 1;

unsigned

isLockoutBound : 1;

unsigned

includeAuth : 1;

unsigned

checkNvWritten : 1;

unsigned

nvWrittenState : 1;

unsigned

isTemplateSet : 1;//1) SET if the session may only be used//
for policy//2) SET if the session is used for audit//3) SET if the session is bound to with an//entity. This attribute will be CLEAR//
if either isPolicy or isAudit is SET.
//3) SET if the cpHash has been defined//This attribute is not SET unless//'isPolicy' is SET.
//5) SET if the authValue is required for//computing the session HMAC. This//
attribute is not SET unless 'isPolicy'//
is SET.
//6) SET if a password authValue is required//
for authorization This attribute is not//
SET unless 'isPolicy' is SET.
//7) SET if physical presence is required to//
be asserted when the authorization is//checked. This attribute is not SET//
unless 'isPolicy' is SET.
//8) SET if the policy session is created//
for trial of the policy's policyHash//
generation. This attribute is not SET//
unless 'isPolicy' is SET.
//9) SET if the bind entity had noDA CLEAR.
//
If this is SET, then an authorization//
failure using this session will count//against lockout even if the object//
being authorized is exempt from DA.
//10) SET if the session is bound to//lockoutAuth.
//11) This attribute is SET when the//authValue of an object is to be//
included in the computation of the//
HMAC key for the command and response//computations. (was 'requestWasBound')//12) SET if the TPMA_NV_WRITTEN attribute//needs to be checked when the policy is//used for authorization for NV access.
//If this is SET for any other type, the//policy will fail.
//13) SET if TPMA_NV_WRITTEN is required to//
be SET. Used when 'checkNvWritten' is//
SET//14) SET if the templateHash needs to be//checked for Create, CreatePrimary, or//CreateLoaded.

} SESSION_ATTRIBUTES;

5.9.5.3

SESSION Structure

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

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 105
April 15, 2019

Trusted Platform Module Library

NOTE:

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

Part 4: Supporting Routines

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

typedef struct SESSION{SESSION_ATTRIBUTESUINT32attributes;
pcrCounter;// session attributes// PCR counter value when PCR is// included (policy session)// If no PCR is included, this// value is 0.
// The value in g_time when the session// was started (policy session)// The timeout relative to g_time// There is no timeout if this value// is 0.
// The g_clockEpoch value when the// session was started. If g_clockEpoch// does not match this value when the// timeout is used, then// then the command will fail.
// command code (policy session)// session hash algorithm// command locality (policy session)// session symmetric algorithm (if any)// session secret value used for// this session// last TPM-generated nonce for// generating HMAC and encryption keys

UINT64startTime;UINT64

timeout;

CLOCK_NONCE

epoch;

TPM_CCTPM_ALG_ID
TPMA_LOCALITY
TPMT_SYM_DEF
TPM2B_AUTH

commandCode;authHashAlg;
commandLocality;
symmetric;
sessionKey;

TPM2B_NONCE

nonceTPM;

union{
TPM2B_NAME

boundEntity;// value used to track the entity to// which the session is boundcpHash;// the required cpHash value for the// command being authorized// the required nameHash// the required template for creation

TPM2B_DIGESTTPM2B_DIGESTTPM2B_DIGEST
} u1;
union
{
TPM2B_DIGESTTPM2B_DIGEST} u2;

nameHash;templateHash;auditDigest;policyDigest;// audit session digest// policyHash// audit log and policyHash may// share space to save memory} SESSION;#define
EXPIRES_ON_RESET
INT32_MIN#define
TIMEOUT_ON_RESETUINT64_MAX#define
EXPIRES_ON_RESTART (INT32_MIN + 1)
#define
TIMEOUT_ON_RESTART (UINT64_MAX - 1)
typedef BYTESESSION_BUF[sizeof(SESSION)];

5.9.6

PCR

5.9.6.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.
241
242
243

typedef struct PCR_SAVE{#if
ALG_SHA1

Page 106
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

BYTE
#endif#if
ALG_SHA256
BYTE#endif#if
ALG_SHA384
BYTE#endif#if
ALG_SHA512
BYTE#endif#if
ALG_SM3_256
BYTE#endifsha1[NUM_STATIC_PCR][SHA1_DIGEST_SIZE];
sha256[NUM_STATIC_PCR][SHA256_DIGEST_SIZE];
sha384[NUM_STATIC_PCR][SHA384_DIGEST_SIZE];
sha512[NUM_STATIC_PCR][SHA512_DIGEST_SIZE];
sm3_256[NUM_STATIC_PCR][SM3_256_DIGEST_SIZE];// This counter increments whenever the PCR are updated.
// NOTE: A platform-specific specification may designate//
certain PCR changes as not causing this counter//to increment.
UINT32
pcrCounter;} PCR_SAVE;

5.9.6.2
265

Trusted Platform Module Library

PCR_POLICY#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0

This structure holds the PCR policies, one for each group of PCR controlled by policy.
266
267
268
269
270
271
272

typedef struct PCR_POLICY{TPMI_ALG_HASH
hashAlg[NUM_POLICY_PCR_GROUP];
TPM2B_DIGESTa;
TPM2B_DIGEST
policy[NUM_POLICY_PCR_GROUP];} PCR_POLICY;#endif

5.9.6.3

PCR_AUTHVALUEThis structure holds the PCR policies, one for each group of PCR controlled by policy.
273
274
275
276

typedef struct PCR_AUTH_VALUE{
TPM2B_DIGEST
auth[NUM_AUTHVALUE_PCR_GROUP];} PCR_AUTHVALUE;

5.9.7

STARTUP_TYPE

This enumeration is the possible startup types. The type is determined by the combination of
TPM2_ShutDown() and TPM2_Startup().
277
278
279
280
281
282

typedef enum{
SU_RESET,
SU_RESTART,
SU_RESUME} STARTUP_TYPE;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 107
April 15, 2019

Trusted Platform Module Library

5.9.8

Part 4: Supporting Routines

NV

5.9.8.1

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.
283
284
285
286
287

typedef struct NV_INDEX{TPMS_NV_PUBLIC
publicArea;
TPM2B_AUTH
authValue;} NV_INDEX;

5.9.8.2

NV_REFAn NV_REF is an opaque value returned by the NV subsystem. It is used to reference and NV Index in a
relatively efficient way. Rather than having to continually search for an Index, its reference value may be
used. In this implementation, an NV_REF is a byte pointer that points to the copy of the NV memory thatis kept in RAM.
288
289

typedef UINT32
typedef BYTE

5.9.8.3

NV_REF;*NV_RAM_REF;

NV_PIN

This structure deals with the possible endianess differences between the canonical form of the
TPMS_NV_PIN_COUNTER_PARAMETERS structure and the internal value. The structures allow thedata in a PIN index to be read as an 8-octet value using NvReadUINT64Data(). That function will byte
swap all the values on a little endian system. This will put the bytes with the 4-octet values in the correct
order but will swap the pinLimit and pinCount values. When written, the PIN index is simply handled as anormal index with the octets in canonical order.
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

#if BIG_ENDIAN_TPM
typedef struct{
UINT32
pinCount;
UINT32pinLimit;} PIN_DATA;#else
typedef struct{
UINT32pinLimit;
UINT32
pinCount;} PIN_DATA;#endiftypedef union{
UINT64
intVal;PIN_DATApin;} NV_PIN;

5.9.9

COMMIT_INDEX_MASKThis 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.
308

#if

ALG_ECC

Page 108
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
309
310

Trusted Platform Module Library#define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1))#endif

5.9.105.9.10.1

RAM Global Values
Description

The values in this section are only extant in RAM or ROM as constant values.
5.9.10.2
311
312

Crypto Self-Test Values

EXTERN ALGORITHM_VECTOR
EXTERN ALGORITHM_VECTOR

5.9.10.3

g_implementedAlgorithms;
g_toTest;

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 achievedby using a macro.
313
314
315
316
317

#define g_rcIndexInitializer {EXTERN const UINT16

5.9.10.4

TPM_RC_1, TPM_RC_2, TPM_RC_3, TPM_RC_4,
TPM_RC_5, TPM_RC_6, TPM_RC_7, TPM_RC_8,
TPM_RC_9, TPM_RC_A, TPM_RC_B, TPM_RC_C,
TPM_RC_D, TPM_RC_E, TPM_RC_F }g_rcIndex[15] INITIALIZER(g_rcIndexInitializer);\\\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.
318

EXTERN TPM_HANDLE

5.9.10.5

g_exclusiveAuditSession;g_timeThis is the value in which we keep the current command time. This is initialized at the start of eachcommand. The time is the accumulated time since the last time that the TPM's timer was last powered up.
Clock is the accumulated time since the last time that the TPM was cleared. g_time is in mS.
319

EXTERN

5.9.10.6

UINT64g_time;g_timeEpoch

This value contains the current clock Epoch. It changes when there is a clock discontinuity. It may benecessary to place this in NV should the timer be able to run across a power down of the TPM but not inall cases (e.g. dead battery). If the nonce is placed in NV, it should go in gp because it should bechanging slowly.
320
321
322
323
324

#if CLOCK_STOPSEXTERN CLOCK_NONCE#else#define g_timeEpoch#endifFamily “2.0”Level 00 Revision 01.55

g_timeEpoch;
gp.timeEpochTCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 109
April 15, 2019

Trusted Platform Module Library

5.9.10.7

Part 4: Supporting Routinesg_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.
325

EXTERN BOOL

5.9.10.8

g_phEnable;

g_pcrReConfig

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).
326

EXTERN BOOL

5.9.10.9

g_pcrReConfig;

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().
327

EXTERN TPMI_DH_OBJECT

g_DRTMHandle;

5.9.10.10 g_DrtmPreStartup
This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The definefor 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.
328

EXTERNBOOL

g_DrtmPreStartup;

5.9.10.11 g_StartupLocality3
This value indicates that a TPM2_Startup() occurred 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.
329

EXTERN

BOOL

g_StartupLocality3;

5.9.10.12 TPM_SU_NONEPart 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() andTPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was received.
NOTE:

330
331

This is a reserved value.

#define SU_NONE_VALUE#define TPM_SU_NONE(0xFFFF)(TPM_SU)(SU_NONE_VALUE)

5.9.10.13 TPM_SU_DA_USEDAs with TPM_SU_NONE, this value is added to allow indication that the shutdown was not orderly andthat a DA=protected object was reference during the previous cycle.
332
333#define SU_DA_USED_VALUE#define TPM_SU_DA_USEDPage 110
April 15, 2019

(SU_NONE_VALUE - 1)
(TPM_SU)(SU_DA_USED_VALUE)TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

5.9.10.14 Startup Flags
These flags are included in gp.orderlyState. These are hacks and are being used to avoid having tochange the layout of gp. The PRE_STARTUP_FLAG indicates that a _TPM_Hash_Start()/_Data/_Endsequence was received after _TPM_Init() but before TPM2_StartUp(). STARTUP_LOCALITY_3 indicatesthat the last TPM2_Startup() was received at locality 3. These flags are only relevant if after a
TPM2_Shutdown(STATE).
334
335
336

#define PRE_STARTUP_FLAG#define STARTUP_LOCALITY_3#if USE_DA_USED

0x80000x40005.9.10.15 g_daUsed
This location indicates if a DA-protected value is accessed during a boot cycle. If none has, then there isno need to increment failedTries on the next non-orderly startup. This bit is merged with gp.orderlyState
when that gp.orderly is set to SU_NONE_VALUE
337
338

EXTERN#endifBOOL

g_daUsed;

5.9.10.16 g_updateNV
This flag indicates if NV should be updated at the end of a command. This flag is set to UT_NONE at the
beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand() after thedetailed actions of a command complete. If the command execution was successful and this flag is not
UT_NONE, any pending NV writes will be committed to NV. UT_ORDERLY causes any RAM data to be
written to the orderly space for staging the write to NV.
339
340
341
342
343

typedef BYTE
#define UT_NONE#define UT_NV#define UT_ORDERLY
EXTERN UPDATE_TYPE

UPDATE_TYPE;(UPDATE_TYPE)0(UPDATE_TYPE)1(UPDATE_TYPE)(UT_NV + 2)
g_updateNV;

5.9.10.17 g_powerWasLost
This flag is used to indicate if the power was lost. It is SET in _TPM__Init(). This flag is cleared by
TPM2_Startup() after all power-lost activities are completed.
NOTE:

344

When power is applied, this value can come up as anything. However, _plat__WasPowerLost() will provide theproper indication in that case. So, when power is actually lost, we get the correct answer. When power was not
lost, but the power-lost processing has not been completed before the next _TPM_Init(), then the TPM still does
the correct thing.

EXTERN BOOL

g_powerWasLost;

5.9.10.18 g_clearOrderlyThis 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 SU_NONE_VALUE, then the orderly state in
NV memory will be changed to SU_NONE_VALUE or SU_DA_USED_VALUE.
345

EXTERN BOOL

Family “2.0”Level 00 Revision 01.55

g_clearOrderly;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 111
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

5.9.10.19 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.
346

EXTERN TPM_SU

g_prevOrderlyState;

5.9.10.20 g_nvOk
This value indicates if the NV integrity check was successful or not. If not and the failure was severe, thenthe 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.
347

EXTERN BOOL

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

EXTERN TPM_RC

g_NvStatus;

5.9.10.21 g_platformUniqueThis 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 bederived 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.
349
350

EXTERN TPM2B_AUTH
EXTERN TPM2B_AUTH

5.9.11g_platformUniqueAuthorities; // Reserved for RNG
g_platformUniqueDetails;// referenced by VENDOR_PERMANENT

Persistent Global Values

5.9.11.1

Description

The values in this section are global values that are persistent across power events. The lifetime of thevalues determines the structure in which the value is placed.
5.9.11.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().
351
352
353
354
355
356
357
358
359

typedef struct{//*********************************************************************************//
Hierarchy//*********************************************************************************// The values in this section are related to the hierarchies.
BOOL

Page 112
April 15, 2019disableClear;// TRUE if TPM2_Clear() using// lockoutAuth is disabled

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

Trusted Platform Module Library// Hierarchy authPolicies
TPMI_ALG_HASH
ownerAlg;
TPMI_ALG_HASH
endorsementAlg;
TPMI_ALG_HASH
lockoutAlg;
TPM2B_DIGEST
ownerPolicy;
TPM2B_DIGEST
endorsementPolicy;
TPM2B_DIGEST
lockoutPolicy;// Hierarchy authValues
TPM2B_AUTH
ownerAuth;
TPM2B_AUTH
endorsementAuth;
TPM2B_AUTH
lockoutAuth;// Primary Seeds
TPM2B_SEEDEPSeed;TPM2B_SEEDSPSeed;TPM2B_SEED
PPSeed;// Note there is a nullSeed in the state_reset memory.
// Hierarchy proofs
TPM2B_PROOF
phProof;
TPM2B_PROOF
shProof;
TPM2B_PROOF
ehProof;// Note there is a nullProof in the state_reset memory.
//*********************************************************************************//
Reset Events//*********************************************************************************// A count that increments at each TPM reset and never get reset during the life// time of TPM. The value of this counter is initialized to 1 during TPM// manufacture process. It is used to invalidate all saved contexts after a TPM// Reset.
UINT64
totalResetCount;// This counter increments on each TPM Reset. The counter is reset by// TPM2_Clear().
UINT32
resetCount;//*********************************************************************************//
PCR//*********************************************************************************// This structure hold the policies for those PCR that have an update policy.
// This implementation only supports a single group of PCR controlled by// policy. If more are required, then this structure would be changed to// an array.
#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0
PCR_POLICY
pcrPolicies;#endif// This structure indicates the allocation of PCR. The structure contains a// list of PCR allocations for each implemented algorithm. If no PCR are// allocated for an algorithm, a list entry still exists but the bit map// will contain no SET bits.
TPML_PCR_SELECTION pcrAllocated;//*********************************************************************************//
Physical Presence//*********************************************************************************// The PP_LIST type contains a bit map of the commands that require physical// to be asserted when the authorization is evaluated. Physical presence will be// checked if the corresponding bit in the array is SET and if the authorization// handle is TPM_RH_PLATFORM.
//// These bits may be changed with TPM2_PP_Commands().
BYTE
ppList[(COMMAND_COUNT + 7) / 8];

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 113
April 15, 2019

Trusted Platform Module Library
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

Part 4: Supporting Routines//*********************************************************************************//
Dictionary attack values//*********************************************************************************// These values are used for dictionary attack tracking and control.
UINT32failedTries;// the current count of unexpired// authorization failures
UINT32

maxTries;// number of unexpired authorization// failures before the TPM is in// lockout

UINT32

recoveryTime;// time between authorization failures// before failedTries is decremented

UINT32

lockoutRecovery;// time that must expire between// authorization failures associated// with lockoutAuth

BOOL

lockOutAuthEnabled; // TRUE if use of lockoutAuth is// allowed//*****************************************************************************//
Orderly State//*****************************************************************************// The orderly state for current cycle
TPM_SUorderlyState;//*****************************************************************************//
Command audit values.
//*****************************************************************************
BYTE
auditCommands[((COMMAND_COUNT + 1) + 7) / 8];
TPMI_ALG_HASH
auditHashAlg;
UINT64auditCounter;//*****************************************************************************//
Algorithm selection//*****************************************************************************//// The 'algorithmSet' value indicates the collection of algorithms that are// currently in used on the TPM. The interpretation of value is vendor dependent.
UINT32algorithmSet;//*****************************************************************************//
Firmware version//*****************************************************************************// The firmwareV1 and firmwareV2 values are instanced in TimeStamp.c. This is// a scheme used in development to allow determination of the linker build time// of the TPM. An actual implementation would implement these values in a way that// is consistent with vendor needs. The values are maintained in RAM for simplified// access with a master version in NV. These values are modified in a// vendor-specific way.
// g_firmwareV1 contains the more significant 32-bits of the vendor version number.
// In the reference implementation, if this value is printed as a hex// value, it will have the format of YYYYMMDDUINT32
firmwareV1;// g_firmwareV1 contains the less significant 32-bits of the vendor version number.
// In the reference implementation, if this value is printed as a hex// value, it will have the format of 00 HH MM SS
UINT32
firmwareV2;//*****************************************************************************//
Timer Epoch//*****************************************************************************// timeEpoch contains a nonce that has a vendor=specific size (should not be

Page 114
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
492
493
494
495
496
497
498
499

Trusted Platform Module Library// less than 8 bytes. This nonce changes when the clock epoch changes. The clock// epoch changes when there is a discontinuity in the timing of the TPM.
#if !CLOCK_STOPSCLOCK_NONCE
timeEpoch;#endif} PERSISTENT_DATA;EXTERN PERSISTENT_DATA

5.9.11.3

gp;

ORDERLY_DATA

The data in this structure is saved to NV on each TPM2_Shutdown().
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

typedef struct orderly_data{//*****************************************************************************//
TIME//*****************************************************************************// Clock has two parts. One is the state save part and one is the NV part. The// state save version is updated on each command. When the clock rolls over, the// NV version is updated. When the TPM starts up, if the TPM was shutdown in and// orderly way, then the sClock value is used to initialize the clock. If the// TPM shutdown was not orderly, then the persistent value is used and the safe// attribute is clear.
UINT64
TPMI_YES_NO

clock;
clockSafe;// The orderly version of clock// Indicates if the clock value is// safe.

// In many implementations, the quality of the entropy available is not that// high. To compensate, the current value of the drbgState can be saved and// restored on each power cycle. This prevents the internal state from reverting// to the initial state on each power cycle and starting with a limited amount// of entropy. By keeping the old state and adding entropy, the entropy will// accumulate.
DRBG_STATE
drbgState;// These values allow the accumulation of self-healing time across orderly shutdown// of the TPM.
#if ACCUMULATE_SELF_HEAL_TIMERUINT64
selfHealTimer; // current value of s_selfHealTimerUINT64lockoutTimer;// current value of s_lockoutTimerUINT64time;// current value of g_time at shutdown#endif // ACCUMULATE_SELF_HEAL_TIMER} ORDERLY_DATA;#if ACCUMULATE_SELF_HEAL_TIMER#defines_selfHealTimergo.selfHealTimer#defines_lockoutTimergo.lockoutTimer#endif // ACCUMULATE_SELF_HEAL_TIMER# define drbgDefault go.drbgState
EXTERN ORDERLY_DATAgo;

5.9.11.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 eachStartup(CLEAR).
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 115
April 15, 2019

Trusted Platform Module Library
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565

Part 4: Supporting Routines

typedef struct state_clear_data{//*****************************************************************************//
Hierarchy Control//*****************************************************************************
BOOL
shEnable;// default reset is SET
BOOL
ehEnable;// default reset is SET
BOOL
phEnableNV;// default reset is SET
TPMI_ALG_HASH
platformAlg;// default reset is TPM_ALG_NULL
TPM2B_DIGEST
platformPolicy;// default reset is an Empty Buffer
TPM2B_AUTH
platformAuth;// default reset is an Empty Buffer//*****************************************************************************//
PCR//*****************************************************************************// The set of PCR to be saved on Shutdown(STATE)
PCR_SAVE
pcrSave;// default reset is 0...0// This structure hold the authorization values for those PCR that have an// update authorization.
// This implementation only supports a single group of PCR controlled by// authorization. If more are required, then this structure would be changed to// an array.
PCR_AUTHVALUE
pcrAuthValues;} STATE_CLEAR_DATA;EXTERN STATE_CLEAR_DATA gc;

5.9.11.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.
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596

typedef struct state_reset_data{//*****************************************************************************//
Hierarchy Control//*****************************************************************************TPM2B_PROOF
nullProof;// The proof value associated with// the TPM_RH_NULL hierarchy. The// default reset value is from the RNG.
TPM2B_SEED

nullSeed;// The seed value for the TPM_RN_NULL// hierarchy. The default reset value// is from the RNG.

//*****************************************************************************//
Context//*****************************************************************************// The 'clearCount' counter is incremented each time the TPM successfully executes// a TPM Resume. The counter is included in each saved context that has 'stClear'// SET (including descendants of keys that have 'stClear' SET). This prevents these// objects from being loaded after a TPM Resume.
// If 'clearCount' is at its maximum value when the TPM receives a Shutdown(STATE),// the TPM will return TPM_RC_RANGE and the TPM will only accept Shutdown(CLEAR).
UINT32
clearCount;// The default reset value is 0.
UINT64#ifndef NDEBUG#undef CONTEXT_SLOT#define CONTEXT_SLOT#endifPage 116
April 15, 2019

objectContextID;// This is the context ID for a saved// object context. The default reset// value is 0.

BYTE

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

Trusted Platform Module Library

CONTEXT_SLOT

contextArray[MAX_ACTIVE_SESSIONS];// This array contains// contains the values used to track// the version numbers of saved// contexts (see// Session.c in for details). The// default reset value is {0}.

CONTEXT_COUNTER

contextCounter;// This is the value from which the// 'contextID' is derived. The// default reset value is {0}.

//*****************************************************************************//
Command Audit//*****************************************************************************// When an audited command completes, ExecuteCommand() checks the return// value. If it is TPM_RC_SUCCESS, and the command is an audited command, the// TPM will extend the cpHash and rpHash for the command to this value. If this// digest was the Zero Digest before the cpHash was extended, the audit counter// is incremented.
TPM2B_DIGEST

commandAuditDigest; // This value is set to an Empty Digest// by TPM2_GetCommandAuditDigest() or a// TPM Reset.

//*****************************************************************************//
Boot counter//*****************************************************************************UINT32

restartCount;// This counter counts TPM Restarts.
// The default reset value is 0.

//*********************************************************************************//
PCR//*********************************************************************************// This counter increments whenever the PCR are updated. This counter is preserved// across TPM Resume even though the PCR are not preserved. This is because// sessions remain active across TPM Restart and the count value in the session// is compared to this counter so this counter must have values that are unique// as long as the sessions are active.
// NOTE: A platform-specific specification may designate that certain PCR changes//
do not increment this counter to increment.
UINT32
pcrCounter;// The default reset value is 0.
#if

ALG_ECC//*****************************************************************************//
ECDAA//*****************************************************************************UINT64
commitCounter;// This counter increments each time// TPM2_Commit() returns// TPM_RC_SUCCESS. The default reset// value is 0.
TPM2B_NONCE

commitNonce;// This random value is used to compute// the commit values. The default reset// value is from the RNG.

// This implementation relies on the number of bits in g_commitArray being a// power of 2 (8, 16, 32, 64, etc.) and no greater than 64K.
BYTE
commitArray[16];// The default reset value is {0}.
#endif // ALG_ECC} STATE_RESET_DATA;EXTERN STATE_RESET_DATA gr;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 117
April 15, 2019

Trusted Platform Module Library

5.9.12

Part 4: Supporting Routines

NV Layout

The NV data organization isa PERSISTENT_DATA structure
a STATE_RESET_DATA structure
a STATE_CLEAR_DATA structure
an ORDERLY_DATA structure
the user defined NV index space
662
663
664
665
666
667
668

#define NV_PERSISTENT_DATA (0)#define NV_STATE_RESET_DATA (NV_PERSISTENT_DATA + sizeof(PERSISTENT_DATA))#define NV_STATE_CLEAR_DATA (NV_STATE_RESET_DATA + sizeof(STATE_RESET_DATA))#define NV_ORDERLY_DATA(NV_STATE_CLEAR_DATA + sizeof(STATE_CLEAR_DATA))#define NV_INDEX_RAM_DATA(NV_ORDERLY_DATA + sizeof(ORDERLY_DATA))#define NV_USER_DYNAMIC(NV_INDEX_RAM_DATA + sizeof(s_indexOrderlyRam))#define NV_USER_DYNAMIC_END
NV_MEMORY_SIZE

5.9.13Global Macro Definitions

The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members of
the PERSISTENT_DATA structure in NV.
669
670
671
672
673
674
675

#define NV_READ_PERSISTENT(to, from)\
NvRead(&to, offsetof(PERSISTENT_DATA, from), sizeof(to))#define NV_WRITE_PERSISTENT(to, from)\
NvWrite(offsetof(PERSISTENT_DATA, to), sizeof(gp.to), &from)#define CLEAR_PERSISTENT(item)\
NvClearPersistent(offsetof(PERSISTENT_DATA, item), sizeof(gp.item))#define NV_SYNC_PERSISTENT(item) NV_WRITE_PERSISTENT(item, gp.item)

At the start of command processing, the index of the command is determined. This index value is used toaccess the various data tables that contain per-command information. There are multiple options for how
the per-command tables can be implemented. This is resolved in GetClosestCommandIndex().
676
677
678
679
680
681
682
683
684

typedef UINT16
COMMAND_INDEX;#define UNIMPLEMENTED_COMMAND_INDEX((COMMAND_INDEX)(~0))
typedef struct _COMMAND_FLAGS_{
unsignedtrialPolicy : 1;//1) If SET, one of the handles references a//trial policy and authorization may be//skipped. This is only allowed for a policy//
command.
} COMMAND_FLAGS;This structure is used to avoid having to manage a large number of parameters being passed throughvarious levels of the command input processing.
685
686
687
688
689
690
691
692
693
694
695

typedef struct _COMMAND_{
TPM_STtag;
TPM_CC
code;
COMMAND_INDEX
index;UINT32handleNum;
TPM_HANDLEUINT32
INT32

Page 118
April 15, 2019// the parsed command tag// the parsed command code// the computed command index// the number of entity handles in the//handle area of the command
handles[MAX_HANDLE_NUM]; // the parsed handle values
sessionNum;// the number of sessions foundparameterSize;// starts out with the parsed command size// and is reduced and values are

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727

INT32

Trusted Platform Module Library

authSize;

BYTE*parameterBuffer;
BYTE*responseBuffer;#if ALG_SHA1
TPM2B_SHA1_DIGEST
sha1CpHash;
TPM2B_SHA1_DIGEST
sha1RpHash;#endif#if ALG_SHA256
TPM2B_SHA256_DIGEST sha256CpHash;
TPM2B_SHA256_DIGEST sha256RpHash;#endif#if ALG_SHA384
TPM2B_SHA384_DIGEST sha384CpHash;
TPM2B_SHA384_DIGEST sha384RpHash;#endif#if ALG_SHA512
TPM2B_SHA512_DIGEST sha512CpHash;
TPM2B_SHA512_DIGEST sha512RpHash;#endif#if ALG_SM3_256
TPM2B_SM3_256_DIGEST sm3_256CpHash;
TPM2B_SM3_256_DIGEST sm3_256RpHash;#endif} COMMAND;// unmarshaled. Just before calling the// command actions, this should be zero.
// After the command actions, this number// should grow as values are marshaled// in to the response buffer.
// this is initialized with the parsed size// of authorizationSize field and should// be zero when the authorizations are// parsed.
// input to ExecuteCommand// input to ExecuteCommand

Global sting constants for consistency in KDF function calls. These string constants are shared acrossfunctions to make sure that they are all using consistent sting values.
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753

#define STRING_INITIALIZER(value){{sizeof(value), {value}}}#define TPM2B_STRING(name, value)
typedef union name##_ {struct {UINT16 size;
BYTE
buffer[sizeof(value)];
} t;
TPM2B
b;
} TPM2B_##name##_;EXTERN const TPM2B_##name##_name##_ INITIALIZER(STRING_INITIALIZER(value));
EXTERN const TPM2B*name INITIALIZER(&name##_.b)
TPM2B_STRING(PRIMARY_OBJECT_CREATION, "Primary Object Creation");
TPM2B_STRING(CFB_KEY, "CFB");TPM2B_STRING(CONTEXT_KEY, "CONTEXT");TPM2B_STRING(INTEGRITY_KEY, "INTEGRITY");
TPM2B_STRING(SECRET_KEY, "SECRET");TPM2B_STRING(SESSION_KEY, "ATH");TPM2B_STRING(STORAGE_KEY, "STORAGE");TPM2B_STRING(XOR_KEY, "XOR");TPM2B_STRING(COMMIT_STRING, "ECDAA Commit");
TPM2B_STRING(DUPLICATE_STRING, "DUPLICATE");TPM2B_STRING(IDENTITY_STRING, "IDENTITY");
TPM2B_STRING(OBFUSCATE_STRING, "OBFUSCATE");#if SELF_TEST
TPM2B_STRING(OAEP_TEST_STRING, "OAEP Test Value");#endif // SELF_TEST

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\
\
\

Page 119
April 15, 2019

Trusted Platform Module Library

5.9.14

Part 4: Supporting Routines

From CryptTest.c

This structure contains the self-test state values for the cryptographic modules.
754

EXTERN CRYPTO_SELF_TEST_STATE

5.9.15755

g_cryptoSelfTestState;

From Manufacture.c

EXTERN BOOL

g_manufactured INITIALIZER(FALSE);

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.
756

EXTERN BOOL

5.9.16

Private data

5.9.16.1757

g_initialized;

From SessionProcess.c#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_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 areindexed by the session index in accordance with the order of sessions in the session area of thecommand.
Array of the authorization session handles
758

EXTERN TPM_HANDLEs_sessionHandles[MAX_SESSION_NUM];

Array of authorization session attributes
759

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
760

EXTERN TPM_HANDLEs_associatedHandles[MAX_SESSION_NUM];

Array of nonces provided by the caller for the corresponding sessions
761

EXTERN TPM2B_NONCE

s_nonceCaller[MAX_SESSION_NUM];

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

EXTERN TPM2B_AUTH

s_inputAuthValues[MAX_SESSION_NUM];

Array of pointers to the SESSION structures for the sessions in a command
763

EXTERN SESSION*s_usedSessions[MAX_SESSION_NUM];

Special value to indicate an undefined session index764#defineUNDEFINED_INDEX(0xFFFF)

Index of the session used for encryption of a response parameter
Page 120
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
765

EXTERN UINT32

Trusted Platform Module Librarys_encryptSessionIndex;

Index of the session used for decryption of a command parameter
766

EXTERN UINT32

s_decryptSessionIndex;

Index of a session used for audit
767

EXTERN UINT32

s_auditSessionIndex;

The cpHash for command audit
768
769
770

#ifdef TPM_CC_GetCommandAuditDigest
EXTERN TPM2B_DIGEST
s_cpHashForCommandAudit;#endifFlag indicating if NV update is pending for the lockOutAuthEnabled or failedTries DA parameter
771
772

EXTERN BOOL
s_DAPendingOnNV;#endif // SESSION_PROCESS_C

5.9.16.2
773

From DA.c#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C

This variable holds the accumulated time since the last time that failedTries was decremented. This value
is in millisecond.
774
775#if !ACCUMULATE_SELF_HEAL_TIMER
EXTERN UINT64
s_selfHealTimer;This variable holds the accumulated time that the lockoutAuth has been blocked.
776
777
778

EXTERN UINT64
s_lockoutTimer;#endif // ACCUMULATE_SELF_HEAL_TIMER#endif // DA_C

5.9.16.3
779

From NV.c#if defined NV_C || defined GLOBAL_C

This marks the end of the NV area. This is a run-time variable as it might not be compile-time constant.
780

EXTERN NV_REF

s_evictNvEnd;

This space is used to hold the index data for an orderly Index. It also contains the attributes for the index.
781

EXTERN BYTE

s_indexOrderlyRam[RAM_INDEX_SPACE];// The orderly NV Index data

This value contains the current max counter value. It is written to the end of allocatable NV space eachtime an index is deleted or added. This value is initialized on Startup. The indices are searched and the
maximum of all the current counter indices and this value is the initial value for this.
782

EXTERN UINT64

s_maxCounter;

This is space used for the NV Index cache. As with a persistent object, the contents of a referenced index
are copied into the cache so that the NV Index memory scanning and data copying can be reduced. Only
code that operates on NV Index data should use this cache directly. When that action code runs,
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 121
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routiness_lastNvIndex will contain the index header information. It will have been loaded when the handles wereverified.
NOTE:

783
784
785

EXTERNEXTERNEXTERNAn NV index handle can appear in many commands that do not operate on the NV data (e.g.
TPM2_StartAuthSession()). However, only one NV Index at a time is ever directly referenced by any command.
If that changes, then the NV Index caching needs to be changed to accommodate that. Currently, the code willverify that only one NV Index is referenced by the handles of the command.

NV_INDEX
NV_REF
BYTE

s_cachedNvIndex;
s_cachedNvRef;*s_cachedNvRamRef;

Initial NV Index/evict object iterator value
786
787

788

#define#endif

NV_REF_INIT

5.9.16.4

From Object.c(NV_REF)0xFFFFFFFF#if defined OBJECT_C || defined GLOBAL_C

This type is the container for an object.
789
790

EXTERN OBJECT#endif // OBJECT_C

5.9.16.5
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824

s_objects[MAX_LOADED_OBJECTS];

From PCR.c#if defined PCR_C || defined GLOBAL_C
typedef struct{#if
ALG_SHA1// SHA1 PCR
BYTE
sha1Pcr[SHA1_DIGEST_SIZE];#endif#if
ALG_SHA256// SHA256 PCR
BYTE
sha256Pcr[SHA256_DIGEST_SIZE];#endif#if
ALG_SHA384// SHA384 PCR
BYTE
sha384Pcr[SHA384_DIGEST_SIZE];#endif#if
ALG_SHA512// SHA512 PCR
BYTE
sha512Pcr[SHA512_DIGEST_SIZE];#endif#if
ALG_SM3_256// SHA256 PCR
BYTE
sm3_256Pcr[SM3_256_DIGEST_SIZE];#endif} PCR;
typedef struct{unsigned int
stateSave : 1;
unsigned int

resetLocality : 5;

unsigned int

extendLocality : 5;

} PCR_Attributes;
EXTERN PCR

Page 122
April 15, 2019// if the PCR value should be// saved in state save// The locality that the PCR// can be reset// The locality that the PCR// can be extend

s_pcrs[IMPLEMENTATION_PCR];

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
825#endif // PCR_C

5.9.16.6
826

Trusted Platform Module Library

From Session.c#if defined SESSION_C || defined GLOBAL_C

Container for HMAC or policy session tracking information
827
828
829
830
831
832

typedef struct{
BOOL
SESSION} SESSION_SLOT;EXTERN SESSION_SLOT

occupied;session;// session structures_sessions[MAX_LOADED_SESSIONS];

The index in contextArray 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.
833

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)
834
835

EXTERN int#endif // SESSION_C

5.9.16.7836

s_freeSessionSlots;

From IoBuffers.c#if defined IO_BUFFER_C || defined GLOBAL_C

Each command function is allowed a structure for the inputs to the function and a structure for the
outputs. The command dispatch code unmarshals the input butter to the command action input structure
starting at the first byte of s_actionIoBuffer. The value of s_actionIoAllocation is the number of UINT64
values allocated. It is used to set the pointer for the response structure. The command dispatch code will
marshal the response values into the final output buffer.
837
838
839
840

EXTERN UINT64
EXTERN UINT32

s_actionIoBuffer[768];s_actionIoAllocation;// action I/O buffer// number of UIN64 allocated for the// action input structure#endif // IO_BUFFER_C

5.9.16.8

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 filethe failure occurred.
841
842
843
844
845
846
847
848
849
850
851

EXTERN BOOL
g_inFailureMode;// Indicates that the TPM is in failure mode
#if SIMULATIONEXTERN BOOL
g_forceFailureMode;// flag to force failure mode during test
#endiftypedef void(FailFunction)(const char *function, int line, int code);#if defined TPM_FAIL_C || defined GLOBAL_C
EXTERN UINT32
s_failFunction;
EXTERN UINT32
s_failLine;// the line in the file at which// the error was signaled
EXTERN UINT32
s_failCode;// the error code used
EXTERN FailFunction*LibFailCallback;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 123
April 15, 2019

Trusted Platform Module Library
852

Part 4: Supporting Routines#endif // TPM_FAIL_C

5.9.16.9

From CommandCodeAttributes.c

This array is instanced in CommandCodeAttributes.c when it includes CommandCodeAttributes.h. Don'tchange the extern to EXTERN.
853
854
855

extern const TPMA_CC
extern const COMMAND_ATTRIBUTES#endif // GLOBAL_H

Page 124
April 15, 2019s_ccAttr[];s_commandAttributes[];

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.10

Trusted Platform Module Library

GpMacros.h

5.10.1Introduction

This file is a collection of miscellaneous macros.
1
2
3
4
5
6
7

#ifndef GP_MACROS_H#define GP_MACROS_H#ifndef NULL
#define NULL 0#endif#include "swap.h"#include "VendorString.h"

5.10.2For Self-test

These macros are used in CryptUtil() to invoke the incremental self test.
8
9#if SELF_TEST#
defineTEST(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 withthat value, don't do it.
10
11
12
13
14
15
16
17

#

define

\
\
\

#else
#
define TEST(alg)#define TEST_HASH(alg)#endif // SELF_TEST

5.10.3
18
19
20
21
22
23
24
25
26
27
28
29

TEST_HASH(alg)if(TEST_BIT(alg, g_toTest)&& (alg != ALG_NULL_VALUE))
CryptTestAlgorithm(alg, NULL)For Failures#if defined _POSIX_#
define FUNCTION_NAME
0
#else
#
define FUNCTION_NAME__FUNCTION__#endif#if !FAIL_TRACE#
define FAIL(errorCode) (TpmFail(errorCode))#
define LOG_FAILURE(errorCode) (TpmLogFailure(errorCode))#else#
define FAIL(errorCode)TpmFail(FUNCTION_NAME, __LINE__, errorCode)#define LOG_FAILURE(errorCode) TpmLogFailure(FUNCTION_NAME, __LINE__, errorCode)#endifIf implementation is using longjmp, then the call to TpmFail() does not return and the compiler willcomplain about unreachable code that comes after. To allow for not having longjmp, TpmFail() will returnand the subsequent code will be executed. This macro accounts for the difference.
30
31
32
33
34
35
36

#ifndef NO_LONGJMP#
define FAIL_RETURN(returnCode)#define TPM_FAIL_RETURNNORETURN void#else#
define FAIL_RETURN(returnCode) return (returnCode)#define TPM_FAIL_RETURN
void#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 125
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

This macro tests that a condition is TRUE and puts the TPM into failure mode if it is not. If longjmp is
being used, then the FAIL(FATAL_ERROR_) macro makes a call from which there is no return.
Otherwise, it returns and the function will exit with the appropriate return code.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#define REQUIRE(condition, errorCode, returnCode){if(!!(condition)){
FAIL(FATAL_ERROR_errorCode);
FAIL_RETURN(returnCode);}}#define PARAMETER_CHECK(condition, returnCode)REQUIRE((condition), PARAMETER, returnCode)#if (defined EMPTY_ASSERT) && (EMPTY_ASSERT != NO)#
define pAssert(a) ((void)0)#else#
define pAssert(a) {if(!(a)) FAIL(FATAL_ERROR_PARAMETER);}#endif

5.10.4

\
\
\
\
\
\
\
\

Derived from Vendor-specific values

Values derived from vendor specific settings in Implementation.h
52
53
54
55
56
57
58

#define PCR_SELECT_MIN((PLATFORM_PCR+7)/8)#define PCR_SELECT_MAX((IMPLEMENTATION_PCR+7)/8)#define MAX_ORDERLY_COUNT((1 << ORDERLY_BITS) - 1)
#ifndef PRIVATE_VENDOR_SPECIFIC_BYTES#
define PRIVATE_VENDOR_SPECIFIC_BYTES((MAX_RSA_KEY_BYTES/2) * (3 + CRT_FORMAT_RSA * 2))#endif

5.10.5\Compile-time Checks

In some cases, the relationship between two values may be dependent on things that change based on
various selections like the chosen cryptographic libraries. It is possible that these selections will result inincompatible settings. These are often detectable by the compiler but it isn't always possible to do thecheck in the preprocessor code. For example, when the check requires use of sizeof then the
preprocessor can't do the comparison. For these cases, we include a special macro that, depending on
the compiler will generate a warning to indicate if the check always passes or always fails because it
involves fixed constants. To run these checks, define COMPILER_CHECKS in TpmBuildSwitches.h
59
60
61
62
63

#if COMPILER_CHECKS#
define cAssert
pAssert#else#
define cAssert(value)#endifThis is used commonly in the Crypt code as a way to keep listings from getting too long. This is not tosave paper but to allow one to see more useful stuff on the screen at any given time.
64
65
66
67
68
69
70
71
72
73

#define{ERROR_RETURN(returnCode)retVal = returnCode;goto Exit;

\
\
\
\

}
#ifndef MAX# define MAX(a, b) ((a) > (b) ? (a) : (b))#endif#ifndef MIN# define MIN(a, b) ((a) < (b) ? (a) : (b))

Page 126
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
74
75
76
77
78
79
80

Trusted Platform Module Library#endif#ifndef IsOdd# define IsOdd(a)(((a) & 1) != 0)#endif#ifndef BITS_TO_BYTES# define BITS_TO_BYTES(bits) (((bits) + 7) >> 3)#endif

These are defined for use when the size of the vector being checked is known at compile time.
81
82
83

#define TEST_BIT(bit, vector)
TestBit((bit), (BYTE *)&(vector), sizeof(vector))#define SET_BIT(bit, vector)
SetBit((bit), (BYTE *)&(vector), sizeof(vector))#define CLEAR_BIT(bit, vector) ClearBit((bit), (BYTE *)&(vector), sizeof(vector))

The following definitions are used if they have not already been defined. The defaults for these settings
are compatible with ISO/IEC 9899:2011 (E)
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

#ifndef LIB_EXPORT#
define LIB_EXPORT#
define LIB_IMPORT#endif#ifndef NORETURN#
define NORETURN _Noreturn#endif#ifndef NOT_REFERENCED#
define NOT_REFERENCED(x = x)((void) (x))#endif#define STD_RESPONSE_HEADER (sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC))#define JOIN(x, y) x##y
#define JOIN3(x, y, z) x##y##z#define CONCAT(x, y) JOIN(x, y)#define CONCAT3(x, y, z) JOIN3(x,y,z)

If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style table. Otherwise,pick the strongest implemented hash algorithm as the context hash.
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

#ifndef CONTEXT_HASH_ALGORITHM#
if defined ALG_SHA512 && ALG_SHA512 == YES#
define CONTEXT_HASH_ALGORITHM
SHA512#elif defined ALG_SHA384 && ALG_SHA384 == YES#
define CONTEXT_HASH_ALGORITHM
SHA384#elif defined ALG_SHA256 && ALG_SHA256 == YES#
define CONTEXT_HASH_ALGORITHM
SHA256#
elif defined ALG_SM3_256 && ALG_SM3_256 == YES#
define CONTEXT_HASH_ALGORITHM
SM3_256#
elif defined ALG_SHA1 && ALG_SHA1 == YES#
define CONTEXT_HASH_ALGORITHM SHA1
#
endif
#
define CONTEXT_INTEGRITY_HASH_ALG CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM)#endif#ifndef CONTEXT_INTEGRITY_HASH_SIZE#define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE)#endif#if
ALG_RSA#define
RSA_SECURITY_STRENGTH (MAX_RSA_KEY_BITS >= 15360 ? 256 :(MAX_RSA_KEY_BITS >= 7680 ? 192 :(MAX_RSA_KEY_BITS >= 3072 ? 128 :(MAX_RSA_KEY_BITS >= 2048 ? 112 :(MAX_RSA_KEY_BITS >= 1024 ? 80 : 0)))))#else#define
RSA_SECURITY_STRENGTH
0#endif // ALG_RSA#if
ALG_ECC#define
ECC_SECURITY_STRENGTH (MAX_ECC_KEY_BITS >= 521 ? 256 :Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\

\

Page 127
April 15, 2019

Trusted Platform Module Library
127
128
129
130
131
132
133
134

Part 4: Supporting Routines(MAX_ECC_KEY_BITS >= 384 ? 192 :(MAX_ECC_KEY_BITS >= 256 ? 128 : 0)))

\

#else
#define
ECC_SECURITY_STRENGTH
0#endif // ALG_ECC#define
MAX_ASYM_SECURITY_STRENGTH
MAX(RSA_SECURITY_STRENGTH, ECC_SECURITY_STRENGTH)#define
MAX_HASH_SECURITY_STRENGTH ((CONTEXT_INTEGRITY_HASH_SIZE * 8) / 2)\

Unless some algorithm is broken...
135
136
137
138
139

#defineMAX_SYM_SECURITY_STRENGTH
MAX_SYM_KEY_BITS#define MAX_SECURITY_STRENGTH_BITS
MAX(MAX_ASYM_SECURITY_STRENGTH,
MAX(MAX_SYM_SECURITY_STRENGTH,
MAX_HASH_SECURITY_STRENGTH))\\\

This is the size that was used before the 1.38 errata requiring that P1.14.4 be followed140#define PROOF_SIZECONTEXT_INTEGRITY_HASH_SIZE

As required by P1.14.4
141
142#define COMPLIANT_PROOF_SIZE(MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES)))\As required by P1.14.3.1
143
144#define COMPLIANT_PRIMARY_SEED_SIZE
BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2)\This is the pre-errata version
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

#ifndef PRIMARY_SEED_SIZE#
define PRIMARY_SEED_SIZEPROOF_SIZE#endif#if USE_SPEC_COMPLIANT_PROOFS#
undef PROOF_SIZE#
define PROOF_SIZECOMPLIANT_PROOF_SIZE#
undef PRIMARY_SEED_SIZE#
define PRIMARY_SEED_SIZECOMPLIANT_PRIMARY_SEED_SIZE#endif // USE_SPEC_COMPLIANT_PROOFS#if !SKIP_PROOF_ERRORS#
if PROOF_SIZE < COMPLIANT_PROOF_SIZE#
error "PROOF_SIZE is not compliant with TPM specification"
#
endif
#
if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE#
error "Implementation.h specifies a non-compliant PRIMARY_SEED_SIZE"#
endif#endif // !SKIP_PROOF_ERRORS

If CONTEXT_ENCRYPT_ALG is defined, then the vendor is using the old style table
162
163
164
165
166
167
168
169
170
171

#if defined CONTEXT_ENCRYPT_ALG#
undef CONTEXT_ENCRYPT_ALGORITHM#
if CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE#
define CONTEXT_ENCRYPT_ALGORITHM AES#
elif CONTEXT_ENCRYPT_ALG == ALG_SM4_VALUE#
define CONTEXT_ENCRYPT_ALGORITHM SM4#
elif CONTEXT_ENCRYPT_ALG == ALG_CAMELLIA_VALUE#
define CONTEXT_ENCRYPT_ALGORITHM CAMELLIA#
elif CONTEXT_ENCRYPT_ALG == ALG_TDES_VALUE#
error Are you kidding?

Page 128
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
172
173
174
175
176
177
178
179
180
181

Trusted Platform Module Library

#
else
#
error Unknown value for CONTEXT_ENCRYPT_ALG#
endif // CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE#else#
define CONTEXT_ENCRYPT_ALG
CONCAT3(ALG_, CONTEXT_ENCRYPT_ALGORITHM, _VALUE)#endif // CONTEXT_ENCRYPT_ALG#define CONTEXT_ENCRYPT_KEY_BITS
CONCAT(CONTEXT_ENCRYPT_ALGORITHM, _MAX_KEY_SIZE_BITS)#define CONTEXT_ENCRYPT_KEY_BYTES((CONTEXT_ENCRYPT_KEY_BITS+7)/8)\\

This is updated to follow the requirement of P2 that the label not be larger than 32 bytes.
182
183
184

#ifndef LABEL_MAX_BUFFER#define LABEL_MAX_BUFFER MIN(32, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE))#endifThis bit is used to indicate that an authorization ticket expires on TPM Reset and TPM Restart. It is added
to the timeout value returned by TPM2_PoliySigned() and TPM2_PolicySecret() and used by
TPM2_PolicyTicket(). The timeout value is relative to Time (g_time). Time is reset whenever the TPM
loses power and cannot be moved forward by the user (as can Clock). g_time is a 64-bit value expressing
time in ms. Sealing the MSb for a flag means that the TPM needs to be reset at least once every
292,471,208 years rather than once every 584,942,417 years.
185#define EXPIRATION_BIT ((UINT64)1 << 63)

Check for consistency of the bit ordering of bit fields
186
187
188

#if BIG_ENDIAN_TPM && MOST_SIGNIFICANT_BIT_0 && USE_BIT_FIELD_STRUCTURES#
error "Settings not consistent"#endif

These macros are used to handle the variation in handling of bit fields. If
189
190
191
192
193
194
195
196
197
198
199
200
201
202

#if USE_BIT_FIELD_STRUCTURES // The default, old version, with bit fields#
define IS_ATTRIBUTE(a, type, b)((a.b != 0))#
define SET_ATTRIBUTE(a, type, b)(a.b = SET)#
define CLEAR_ATTRIBUTE(a, type, b)(a.b = CLEAR)#
define GET_ATTRIBUTE(a, type, b)
(a.b)
#else
#
define IS_ATTRIBUTE(a, type, b)((a & type##_##b) != 0)#
define SET_ATTRIBUTE(a, type, b)(a |= type##_##b)#
define CLEAR_ATTRIBUTE(a, type, b)(a &= ~type##_##b)#
define GET_ATTRIBUTE(a, type, b)\(type)((a & type##_##b) >> type##_##b##_SHIFT)#endif#define VERIFY(_X) if(!(_X)) goto Error#endif // GP_MACROS_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 129
April 15, 2019

Trusted Platform Module Library

5.11
1
2
3
4
5

Part 4: Supporting Routines

InternalRoutines.h#ifndef
INTERNAL_ROUTINES_H#define
INTERNAL_ROUTINES_H#if !defined _LIB_SUPPORT_H_ && !defined _TPM_H_#error "Should not be called"#endif

DRTM functions
6
7
8#include "_TPM_Hash_Start_fp.h"#include "_TPM_Hash_Data_fp.h"#include "_TPM_Hash_End_fp.h"

Internal subsystem functions
9
10
11
12
13
14
15
16
17
18
19
20
21

#include "Object_fp.h"#include "Context_spt_fp.h"#include "Object_spt_fp.h"#include "Entity_fp.h"#include "Session_fp.h"#include "Hierarchy_fp.h"#include "NvReserved_fp.h"#include "NvDynamic_fp.h"#include "NV_spt_fp.h"#include "PCR_fp.h"#include "DA_fp.h"#include "TpmFail_fp.h"#include "SessionProcess_fp.h"

Internal support functions
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#include "CommandCodeAttributes_fp.h"#include "Marshal_fp.h"#include "Time_fp.h"#include "Locality_fp.h"#include "PP_fp.h"#include "CommandAudit_fp.h"#include "Manufacture_fp.h"#include "Handle_fp.h"#include "Power_fp.h"#include "Response_fp.h"#include "CommandDispatcher_fp.h"#ifdef CC_AC_Send#
include "AC_spt_fp.h"#endif // CC_AC_Send

Miscellaneous
36
37
38
39
40
41

#include "Bits_fp.h"#include "AlgorithmCap_fp.h"#include "PropertyCap_fp.h"#include "IoBuffers_fp.h"#include "Memory_fp.h"#include "ResponseCodeProcessing_fp.h"

Internal cryptographic functions
42
43
44
45

#include "BnConvert_fp.h"#include "BnMath_fp.h"#include "BnMemory_fp.h"#include "Ticket_fp.h"

Page 130
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

Trusted Platform Module Library#include "CryptUtil_fp.h"#include "CryptHash_fp.h"#include "CryptSym_fp.h"#include "CryptDes_fp.h"#include "CryptPrime_fp.h"#include "CryptRand_fp.h"#include "CryptSelfTest_fp.h"#include "MathOnByteBuffers_fp.h"#include "CryptSym_fp.h"#include "AlgorithmTests_fp.h"#if ALG_RSA#include "CryptRsa_fp.h"#include "CryptPrimeSieve_fp.h"#endif#if ALG_ECC#include "CryptEccMain_fp.h"#include "CryptEccSignature_fp.h"#include "CryptEccKeyExchange_fp.h"#endif#if CC_MAC || CC_MAC_Start#
include "CryptSmac_fp.h"#
if ALG_CMAC#
include "CryptCmac_fp.h"#
endif#endif

Support library71#include "SupportLibraryFunctionPrototypes_fp.h"

Linkage to platform functions
72
73#include "Platform_fp.h"#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 131
April 15, 2019

Trusted Platform Module Library

5.12

Part 4: Supporting Routines

LibSupport.h

This header file is used to select the library code that gets included in the TPM built
1
2
3
4
5
6
7
8
9

#ifndef _LIB_SUPPORT_H_#define _LIB_SUPPORT_H_#ifndef RADIX_BITS#
if defined(__x86_64__) || defined(_WIN64) || defined(_M_X64) || defined(_M_ARM64)#
define RADIX_BITS
64
#
else
#
define RADIX_BITS
32
#
endif
#endif // RADIX_BITS

These macros use the selected libraries to the proper include files.
10
11
12
13
14
15
16
17

#define LIB_JOIN(x,y) x##y
#define LIB_CONCAT(x,y) LIB_JOIN(x, y)#define LIB_QUOTE(_STRING_) #_STRING_#define LIB_INCLUDE2(_LIB_, _TYPE_) LIB_QUOTE(##_LIB_##/TpmTo##_LIB_##_TYPE_.h)#define LIB_INCLUDE(_LIB_, _TYPE_) LIB_INCLUDE2(_LIB_, _TYPE_)#define SYM_LIBRARY LIB_CONCAT(SYM_LIB_, SYM_LIB)#define HASH_LIBRARY(_LIB_) LIB_CONCAT(HASH_LIB_, HASH_LIB)#define MATH_LIBRARY(_LIB_) LIB_CONCAT(MATH_LIB_, MATH_LIB)

Include the options for hashing and symmetric. Defer the load of the math package Until the bignum
parameters are defined.
18
19
20
21
22

#include LIB_INCLUDE(SYM_LIB, Sym)
#include LIB_INCLUDE(HASH_LIB, Hash)#undef MIN#undef MAX#endif // _LIB_SUPPORT_H_

Page 132
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.13

Trusted Platform Module LibraryNV.h5.13.1

Index Type Definitions

These definitions allow the same code to be used pre and post 1.21. The main action is to redefine theindex type values from the bit values. Use TPM_NT_ORDINARY to indicate if the TPM_NT type isdefined1
2
3#ifndef#define#ifdef_NV_H__NV_H_TPM_NT_ORDINARY

If TPM_NT_ORDINARY is defined, then the TPM_NT field is present in a TPMA_NV
45#define GET_TPM_NT(attributes) GET_ATTRIBUTE(attributes, TPMA_NV, TPM_NT)#else

If TPM_NT_ORDINARY is not defined, then need to synthesize it from the attributes
6
7
8
9
10
11
12
13
14
15

#

define GetNv_TPM_NV(attributes)(
IS_ATTRIBUTE(attributes, TPMA_NV, COUNTER)+(IS_ATTRIBUTE(attributes, TPMA_NV, BITS) << 1)+(IS_ATTRIBUTE(attributes, TPMA_NV, EXTEND) << 2))#define TPM_NT_ORDINARY (0)#define TPM_NT_COUNTER (1)#define TPM_NT_BITS(2)#
define TPM_NT_EXTEND(4)#endif

5.13.2\\\\Attribute Macros

These macros are used to isolate the differences in the way that the index type changed in version 1.21of the specification
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#

define IsNvOrdinaryIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_ORDINARY)#
define IsNvCounterIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_COUNTER)#
define IsNvBitsIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_BITS)#
define IsNvExtendIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_EXTEND)#ifdef TPM_NT_PIN_PASS#
define IsNvPinPassIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_PIN_PASS)#endif#ifdef TPM_NT_PIN_FAIL#
define IsNvPinFailIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_PIN_FAIL)#endiftypedef struct {UINT32size;
TPM_HANDLE handle;} NV_ENTRY_HEADER;#define NV_EVICT_OBJECT_SIZE\(sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(OBJECT))#define NV_INDEX_COUNTER_SIZE\(sizeof(UINT32) + sizeof(NV_INDEX) + sizeof(UINT64))#define NV_RAM_INDEX_COUNTER_SIZE\(sizeof(NV_RAM_HEADER) + sizeof(UINT64))

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\

\

Page 133
April 15, 2019

Trusted Platform Module Library
42
43
44
45
46

typedef struct {UINT32
TPM_HANDLE
TPMA_NV} NV_RAM_HEADER;

Part 4: Supporting Routines

size;
handle;attributes;

Defines the end-of-list marker for NV. The list terminator is a UINT32 of zero, followed by the current
value of s_maxCounter which is a 64-bit value. The structure is defined as an array of 3 UINT32 values
so that there is no padding between the UINT32 list end marker and the UIT64m maxCounter value.
47

typedef UINT32 NV_LIST_TERMINATOR[3];5.13.3

Orderly RAM Values

The following defines are for accessing orderly RAM values. This is the initialize for the RAM reference
iterator.
48#define

NV_RAM_REF_INIT

0This is the starting address of the RAM space used for orderly data
49
50

#define

RAM_ORDERLY_START(&s_indexOrderlyRam[0])\This is the offset within NV that is used to save the orderly data on an orderly shutdown.
51
52#define

NV_ORDERLY_START(NV_INDEX_RAM_DATA)\This is the end of the orderly RAM space. It is actually the first byte after the last byte of orderly RAM data
53
54

#define

RAM_ORDERLY_END\(RAM_ORDERLY_START + sizeof(s_indexOrderlyRam))

This is the end of the orderly space in NV memory. As with RAM_ORDERLY_END, it is actually the offsetof the first byte after the end of the NV orderly data.
55
56#define

NV_ORDERLY_END\(NV_ORDERLY_START + sizeof(s_indexOrderlyRam))

Macro to check that an orderly RAM address is with range.
57
58
59
60
61
62
63

#define ORDERLY_RAM_ADDRESS_OK(start, offset)\((start >= RAM_ORDERLY_START) && ((start + offset - 1) < RAM_ORDERLY_END))#define RETURN_IF_NV_IS_NOT_AVAILABLE\{\
if(g_NvStatus != TPM_RC_SUCCESS)\
return g_NvStatus;\}

Routinely have to clear the orderly flag and fail if the NV is not available so that it can be cleared.
64
65
66
67
68
69
70
71

#define RETURN_IF_ORDERLY\{\
if(NvClearOrderly() != TPM_RC_SUCCESS)\
return g_NvStatus;\}#define NV_IS_AVAILABLE(g_NvStatus == TPM_RC_SUCCESS)#define IS_ORDERLY(value)(value < SU_DA_USED_VALUE)#define NV_IS_ORDERLY(IS_ORDERLY(gp.orderlyState))

Page 134
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

Macro to set the NV UPDATE_TYPE. This deals with the fact that the update is possibly a combination of
UT_NV and UT_ORDERLY.
72
73#define SET_NV_UPDATE(type)#endif // _NV_H_

Family “2.0”Level 00 Revision 01.55

g_updateNV |= (type)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 135
April 15, 2019

Trusted Platform Module Library

5.14
1
2
3
4

Part 4: Supporting Routines

PRNG_TestVectors.h#ifndef_MSBN_DRBG_TEST_VECTORS_H#define_MSBN_DRBG_TEST_VECTORS_H//#if DRBG_ALGORITHM == TPM_ALG_AES && DRBG_KEY_BITS == 256#if DRBG_KEY_SIZE_BITS == 256

Entropy is the size of a the state. The state is the size of the key plus the IV. The IV is a block. If Key =256 and Block = 128 then State = 384
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#

define DRBG_TEST_INITIATE_ENTROPY\
0x0d, 0x15, 0xaa, 0x80, 0xb1, 0x6c, 0x3a, 0x10, \0x90, 0x6c, 0xfe, 0xdb, 0x79, 0x5d, 0xae, 0x0b, \0x5b, 0x81, 0x04, 0x1c, 0x5c, 0x5b, 0xfa, 0xcb, \0x37, 0x3d, 0x44, 0x40, 0xd9, 0x12, 0x0f, 0x7e, \0x3d, 0x6c, 0xf9, 0x09, 0x86, 0xcf, 0x52, 0xd8, \0x5d, 0x3e, 0x94, 0x7d, 0x8c, 0x06, 0x1f, 0x91#
define DRBG_TEST_RESEED_ENTROPY\
0x6e, 0xe7, 0x93, 0xa3, 0x39, 0x55, 0xd7, 0x2a, \0xd1, 0x2f, 0xd8, 0x0a, 0x8a, 0x3f, 0xcf, 0x95, \0xed, 0x3b, 0x4d, 0xac, 0x57, 0x95, 0xfe, 0x25, \0xcf, 0x86, 0x9f, 0x7c, 0x27, 0x57, 0x3b, 0xbc, \0x56, 0xf1, 0xac, 0xae, 0x13, 0xa6, 0x50, 0x42, \0xb3, 0x40, 0x09, 0x3c, 0x46, 0x4a, 0x7a, 0x22#
define DRBG_TEST_GENERATED_INTERM\
0x28, 0xe0, 0xeb, 0xb8, 0x21, 0x01, 0x66, 0x50, \0x8c, 0x8f, 0x65, 0xf2, 0x20, 0x7b, 0xd0, 0xa3#
define DRBG_TEST_GENERATED\
0x94, 0x6f, 0x51, 0x82, 0xd5, 0x45, 0x10, 0xb9, \0x46, 0x12, 0x48, 0xf5, 0x71, 0xca, 0x06, 0xc9
#elif DRBG_KEY_SIZE_BITS == 128#
define DRBG_TEST_INITIATE_ENTROPY\
0x8f, 0xc1, 0x1b, 0xdb, 0x5a, 0xab, 0xb7, 0xe0, \0x93, 0xb6, 0x14, 0x28, 0xe0, 0x90, 0x73, 0x03, \0xcb, 0x45, 0x9f, 0x3b, 0x60, 0x0d, 0xad, 0x87, \0x09, 0x55, 0xf2, 0x2d, 0xa8, 0x0a, 0x44, 0xf8#
define DRBG_TEST_RESEED_ENTROPY\
0x0c, 0xd5, 0x3c, 0xd5, 0xec, 0xcd, 0x5a, 0x10, \0xd7, 0xea, 0x26, 0x61, 0x11, 0x25, 0x9b, 0x05, \0x57, 0x4f, 0xc6, 0xdd, 0xd8, 0xbe, 0xd8, 0xbd, \0x72, 0x37, 0x8c, 0xf8, 0x2f, 0x1d, 0xba, 0x2a
#define DRBG_TEST_GENERATED_INTERM\
0xdc, 0x3c, 0xf6, 0xbf, 0x5b, 0xd3, 0x41, 0x13, \0x5f, 0x2c, 0x68, 0x11, 0xa1, 0x07, 0x1c, 0x87#
define DRBG_TEST_GENERATED\
0xb6, 0x18, 0x50, 0xde, 0xcf, 0xd7, 0x10, 0x6d, \0x44, 0x76, 0x9a, 0x8e, 0x6e, 0x8c, 0x1a, 0xd4
#endif#endif//_MSBN_DRBG_TEST_VECTORS_H

Page 136
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.15

Trusted Platform Module Library

SelfTest.h

5.15.1Introduction

This file contains the structure definitions for the self-test. It also contains macros for use when the selftest is implemented.
12#ifndef#define5.15.2_SELF_TEST_H__SELF_TEST_H_

DefinesWas typing this a lot
3#define SELF_TEST_FAILURE

FAIL(FATAL_ERROR_SELF_TEST)

Use the definition of key sizes to set algorithm values for key size.
4
5
6
7
8
9

#define AES_ENTRIES (AES_128 + AES_192 + AES_256)#define SM4_ENTRIES (SM4_128)#define CAMELLIA_ENTRIES (CAMELLIA_128 + CAMELLIA_192 + CAMELLIA_256)#define TDES_ENTRIES (TDES_128 + TDES_192)#define NUM_SYMS(AES_ENTRIES + SM4_ENTRIES + CAMELLIA_ENTRIES + TDES_ENTRIES)
typedef UINT32
SYM_INDEX;

These two defines deal with the fact that the TPM_ALG_ID table does not delimit the symmetric mode
values with a TPM_SYM_MODE_FIRST and TPM_SYM_MODE_LAST
10
11
12

#define TPM_SYM_MODE_FIRST
ALG_CTR_VALUE#define TPM_SYM_MODE_LAST
ALG_ECB_VALUE#define NUM_SYM_MODES(TPM_SYM_MODE_LAST - TPM_SYM_MODE_FIRST + 1)

Define a type to hold a bit vector for the modes.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#if NUM_SYM_MODES <= 0#error "No symmetric modes implemented"#elif NUM_SYM_MODES <= 8typedef BYTESYM_MODES;#elif NUM_SYM_MODES <= 16typedef UINT16 SYM_MODES;#elif NUM_SYM_MODES <= 32
typedef UINT32 SYM_MODES;#else#error "Too many symmetric modes"#endiftypedef struct SYMMETRIC_TEST_VECTOR {const TPM_ALG_IDalg;// the algorithm
const UINT16
keyBits;// bits in the key
const BYTE
*key;// The test key
const UINT32
ivSize;// block size of the algorithm
const UINT32
dataInOutSize;// size to encrypt/decrypt
const BYTE
*dataIn;// data to encrypt
const BYTE
*dataOut[NUM_SYM_MODES];// data to decrypt} SYMMETRIC_TEST_VECTOR;#if ALG_SHA512#
define DEFAULT_TEST_HASH
ALG_SHA512_VALUE#
define DEFAULT_TEST_DIGEST_SIZESHA512_DIGEST_SIZE#
define DEFAULT_TEST_HASH_BLOCK_SIZESHA512_BLOCK_SIZE#elif ALG_SHA384#
define DEFAULT_TEST_HASH
ALG_SHA384_VALUE

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 137
April 15, 2019

Trusted Platform Module Library
39
40
41
42
43
44
45
46
47
48
49
50

Part 4: Supporting Routines#
define DEFAULT_TEST_DIGEST_SIZE#
define DEFAULT_TEST_HASH_BLOCK_SIZE#elif ALG_SHA256#
define DEFAULT_TEST_HASH#
define DEFAULT_TEST_DIGEST_SIZE#
define DEFAULT_TEST_HASH_BLOCK_SIZE#elif ALG_SHA1#
define DEFAULT_TEST_HASH#
define DEFAULT_TEST_DIGEST_SIZE#
define DEFAULT_TEST_HASH_BLOCK_SIZE#endif#endif// _SELF_TEST_H_

Page 138
April 15, 2019

SHA384_DIGEST_SIZESHA384_BLOCK_SIZE
ALG_SHA256_VALUE
SHA256_DIGEST_SIZESHA256_BLOCK_SIZE
ALG_SHA1_VALUE
SHA1_DIGEST_SIZE
SHA1_BLOCK_SIZE

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.16

Trusted Platform Module Library

SupportLibraryFunctionPrototypes_fp.h

5.16.1Introduction

This file contains the function prototypes for the functions that need to be present in the selected match
library. For each function listed, there should be a small stub function. That stub provides the interface
between the TPM code and the support library. In most cases, the stub function will only need to do aformat conversion between the TPM big number and the support library big number. The TPM big
number format was chosen to make this relatively simple and fast.
Arithmetic operations return a BOOL to indicate if the operation completed successfully or not.
1
2

#ifndef SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H#define SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H

5.16.2

SupportLibInit()

This function is called by CryptInit() so that necessary initializations can be performed on thecryptographic library.
3
4

LIB_EXPORT
int SupportLibInit(void);

5.16.3

MathLibraryCompatibililtyCheck()

This function is only used during development to make sure that the library that is being referenced isusing the same size of data structures as the TPM.
5
6
7
8

void
MathLibraryCompatibilityCheck(void);

5.16.4

BnModMult()

Does op1 * op2 and divide by modulus returning the remainder of the divide.
910

LIB_EXPORT BOOL
BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus);

5.16.5

BnMult()Multiplies two numbers and returns the result
11
12

LIB_EXPORT BOOL
BnMult(bigNum result, bigConst multiplicand, bigConst multiplier);

5.16.6

BnDiv()

This function divides two bigNum values. The function returns FALSE if there is an error in the operation.
13
14
15

LIB_EXPORT BOOL
BnDiv(bigNum quotient, bigNum remainder,
bigConst dividend, bigConst divisor);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 139
April 15, 2019

Trusted Platform Module Library

5.16.7
16

BnMod()#define BnMod(a, b)

5.16.8

Part 4: Supporting Routines

BnDiv(NULL, (a), (a), (b))

BnGcd()

Get the greatest common divisor of two numbers. This function is only needed when the TPM implements
RSA.
17
18

LIB_EXPORT BOOL
BnGcd(bigNum gcd, bigConst number1, bigConst number2);

5.16.9

BnModExp()

Do modular exponentiation using bigNum values. This function is only needed when the TPM implements
RSA.
19
20
21

LIB_EXPORT BOOL
BnModExp(bigNum result, bigConst number,
bigConst exponent, bigConst modulus);

5.16.10 BnModInverse()
Modular multiplicative inverse. This function is only needed when the TPM implements RSA.
22
23

LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number,
bigConst modulus);

5.16.11 BnEccModMult()
This function does a point multiply of the form R = [d]S. A return of FALSE indicates that the result was
the point at infinity. This function is only needed if the TPM supports ECC.
2425

LIB_EXPORT BOOL
BnEccModMult(bigPoint R, pointConst S, bigConst d, bigCurve E);

5.16.12 BnEccModMult2()
This function does a point multiply of the form R = [d]S + [u]Q. A return of FALSE indicates that the result
was the point at infinity. This function is only needed if the TPM supports ECC.
26
27
28

LIB_EXPORT BOOL
BnEccModMult2(bigPoint R, pointConst S, bigConst d,
pointConst Q, bigConst u, bigCurve E);

5.16.13 BnEccAdd()
This function does a point add R = S + Q. A return of FALSE indicates that the result was the point at
infinity. This function is only needed if the TPM supports ECC.
2930

LIB_EXPORT BOOL
BnEccAdd(bigPoint R, pointConst S, pointConst Q, bigCurve E);

Page 140
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

5.16.14 BnCurveInitialize()This function is used to initialize the pointers of a bnCurve_t structure. The structure is a set of pointers to
bigNum values. The curve-dependent values are set by a different function. This function is only needed if
the TPM supports ECC.
3132

LIB_EXPORT bigCurve
BnCurveInitialize(bigCurve E, TPM_ECC_CURVE curveId);

5.16.14.1 BnCurveFree()This function will free the allocated components of the curve and end the frame in which the curve data
exists33
34
35

LIB_EXPORT void
BnCurveFree(bigCurve E);#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 141
April 15, 2019

Trusted Platform Module Library

5.17

Part 4: Supporting Routines

TPMB.hThis file contains extra TPM2B structures
1
2#ifndef _TPMB_H#define _TPMB_H

TPM2B Types
3
4
5
6
7

typedef struct {UINT16size;
BYTE
buffer[1];} TPM2B, *P2B;
typedef const TPM2B*PC2B;

This macro helps avoid having to type in the structure in order to create a new TPM2B type that is used ina function.
8
9
10
11
12
13
14
15

#define TPM2B_TYPE(name, bytes)
typedef union {struct {UINT16 size;
BYTE
buffer[(bytes)];
} t;
TPM2B
b;
} TPM2B_##name

\
\
\
\
\
\
\

This macro defines a TPM2B with a constant character value. This macro sets the size of the string to thesize minus the terminating zero byte. This lets the user of the label add their terminating 0. This method ischosen so that existing code that provides a label will continue to work correctly. Macro to instance andinitialize a TPM2B value
16
17
18
19

#define TPM2B_INIT(TYPE, name) \TPM2B_##TYPE
name = {sizeof(name.t.buffer), {0}}#define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes)#endifPage 142
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.18

Trusted Platform Module Library

Tpm.hRoot header file for building any TPM.lib code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#ifndef_TPM_H_#define_TPM_H_#include "TpmBuildSwitches.h"#include "BaseTypes.h"#include "TPMB.h"#include "MinMax.h"#include "TpmProfile.h"#include "TpmAlgorithmDefines.h"#include "LibSupport.h"// Types from the library. These need to come before// Global.h because some of the structures in// that file depend on the structures used by the// cryptographic libraries.
#include "GpMacros.h"// Define additional macros#include "Global.h"// Define other TPM types#include "InternalRoutines.h"// Function prototypes#endif // _TPM_H_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 143
April 15, 2019

Trusted Platform Module Library

5.19

Part 4: Supporting Routines

TpmBuildSwitches.hThis file contains the build switches. This contains switches for multiple versions of the crypto-library sosome may not apply to your environment.
The switches are guarded so that they can either be set on the command line or set here. If the switch islisted on the command line (-DSOME_SWITCH) with NO setting, then the switch will be set to YES. If theswitch setting is not on the command line or if the setting is other than YES or NO, then the switch will be
set to the default value. The default can either be YES or NO as indicated on each line where the default
is selected.
A caution. Do not try to test these macros by inserting #defines in this file. For some curious reason, avariable set on the command line with no setting will have a value of 1. An #if SOME_VARIABLE will work
if the variable is not defined or is defined on the command line with no initial setting. However, a "#define
SOME_VARIABLE" is a null string and when used in "#if SOME_VARIABLE" will not be a proper
expression If you want to test various switches, either use the command line or change the default.
1
2
3
4
5
6

#ifndef _TPM_BUILD_SWITCHES_H_#define _TPM_BUILD_SWITCHES_H_#undef YES#define YES 1#undef NO#define NO 0

Allow the command line to specify a profile file. E.g., PROFILE=/the/profile.h
7
8
9
10
11

#ifdef PROFILE#
define PROFILE_QUOTE(a) #a#
define PROFILE_INCLUDE(a) PROFILE_QUOTE(a)#include PROFILE_INCLUDE(PROFILE)#endifNeed an unambiguous definition for DEBUG. Don't change this
12
13
14
15
16
17
18
19
20
21
22

#ifndef DEBUG#
ifdef NDEBUG#
define DEBUG
NO
#
else
#
define DEBUG
YES
#
endif
#elif (DEBUG != NO) && (DEBUG != YES)
#
undef
DEBUG
#
define DEBUG
YES// Default: Either YES or NO#endif#include "CompilerDependencies.h"

This definition is required for the re-factored code
23
24
25
26
27

#if (!defined USE_BN_ECC_DATA)|| ((USE_BN_ECC_DATA != NO) && (USE_BN_ECC_DATA != YES))#
undef
USE_BN_ECC_DATA#
define USE_BN_ECC_DATA
YES// Default: Either YES or NO#endif\The SIMULATION switch allows certain other macros to be enabled. The things that can be enabled in asimulation include key caching, reproducible random sequences, instrumentation of the RSA key
generation process, and certain other debug code. SIMULATION Needs to be defined as either YES or
NO. This grouping of macros will make sure that it is set correctly. A simulated TPM would include a
Virtual TPM. The interfaces for a Virtual TPM should be modified from the standard ones in the Simulator
project.
Page 144
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

If SIMULATION is in the compile parameters without modifiers, make SIMULATION == YES
28
29
30
31

#if !(defined SIMULATION) || ((SIMULATION != NO) && (SIMULATION != YES))#
undef
SIMULATION#
define SIMULATIONYES// Default: Either YES or NO#endifDefine this to run the function that checks the compatibility between the chosen big number math libraryand the TPM code. Not all ports use this.
32
33
34
35
36
37
38
39
40
41

#if !(defined LIBRARY_COMPATABILITY_CHECK)\|| ((LIBRARY_COMPATABILITY_CHECK != NO)\&& (LIBRARY_COMPATABILITY_CHECK != YES))#
undef
LIBRARY_COMPATABILITY_CHECK#
define LIBRARY_COMPATABILITY_CHECKYES// Default: Either YES or NO#endif#if !(defined FIPS_COMPLIANT) || ((FIPS_COMPLIANT != NO) && (FIPS_COMPLIANT != YES))#
undef
FIPS_COMPLIANT#
define FIPS_COMPLIANT
YES// Default: Either YES or NO#endifDefinition to allow alternate behavior for non-orderly startup. If there is a chance that the TPM could not
update failedTries
42
43
44
45

#if !(defined USE_DA_USED) || ((USE_DA_USED != NO) && (USE_DA_USED != YES))#
undef
USE_DA_USED#
define USE_DA_USEDYES// Default: Either YES or NO#endifDefine TABLE_DRIVEN_DISPATCH to use tables rather than case statements for command dispatch
and handle unmarshaling
46
47
48
49
50

#if !(defined TABLE_DRIVEN_DISPATCH)|| ((TABLE_DRIVEN_DISPATCH != NO) && (TABLE_DRIVEN_DISPATCH != YES))#
undef
TABLE_DRIVEN_DISPATCH#
define TABLE_DRIVEN_DISPATCH
YES// Default: Either YES or NO#endif\This switch is used to enable the self-test capability in AlgorithmTests.c
51
52
53
54

#if !(defined SELF_TEST) || ((SELF_TEST != NO) && (SELF_TEST != YES))#
undef
SELF_TEST#
define SELF_TEST
YES// Default: Either YES or NO#endifEnable the generation of RSA primes using a sieve.
55
56
57
58

#if !(defined RSA_KEY_SIEVE) || ((RSA_KEY_SIEVE != NO) && (RSA_KEY_SIEVE != YES))#
undef
RSA_KEY_SIEVE#
define RSA_KEY_SIEVE
YES// Default: Either YES or NO#endifEnable the instrumentation of the sieve process. This is used to tune the sieve variables.
59
60
61
62
63
64
65

#if RSA_KEY_SIEVE && SIMULATION#
if !(defined RSA_INSTRUMENT)|| ((RSA_INSTRUMENT != NO) && (RSA_INSTRUMENT != YES))#
undef
RSA_INSTRUMENT#
define RSA_INSTRUMENTNO// Default: Either YES or NO#
endif#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019\

Page 145
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

This switch enables the RNG state save and restore
66
67
68
69
70

#if !(defined _DRBG_STATE_SAVE)|| ((_DRBG_STATE_SAVE != NO) && (_DRBG_STATE_SAVE != YES))#
undef_DRBG_STATE_SAVE#
define _DRBG_STATE_SAVE
YES// Default: Either YES or NO#endif\Switch added to support packed lists that leave out space associated with unimplemented commands.
Comment this out to use linear lists.
NOTE:

71
72
73
74
75

if vendor specific commands are present, the associated list is always in compressed form.

#if !(defined COMPRESSED_LISTS)|| ((COMPRESSED_LISTS != NO) && (COMPRESSED_LISTS != YES))#
undef
COMPRESSED_LISTS#
define COMPRESSED_LISTS
YES// Default: Either YES or NO#endif\This switch indicates where clock epoch value should be stored. If this value defined, then it is assumed
that the timer will change at any time so the nonce should be a random number kept in RAM. When it is
not defined, then the timer only stops during power outages.
76
77
78
79

#if !(defined CLOCK_STOPS) || ((CLOCK_STOPS != NO) && (CLOCK_STOPS != YES))#
undef
CLOCK_STOPS#
define CLOCK_STOPSNO// Default: Either YES or NO#endifThis switch allows use of #defines in place of pass-through marshaling or unmarshaling code. A passthrough function just calls another function to do the required function and does no parameter checking of
its own. The table-driven dispatcher calls directly to the lowest level marshaling/unmarshaling code andby-passes any pass-through functions.
80
81
82
83
84
85

#if (defined USE_MARSHALING_DEFINES) && (USE_MARSHALING_DEFINES != NO)#
undef
USE_MARSHALING_DEFINES#
define USE_MARSHALING_DEFINES YES#else#
define USE_MARSHALING_DEFINES
YES// Default: Either YES or NO#endif

The switches in this group can only be enabled when doing debug during simulation86#if SIMULATION && DEBUG

Enables use of the key cache. Default is YES
87
88
89
90
91

#
#
#
#

if !(defined USE_RSA_KEY_CACHE)|| ((USE_RSA_KEY_CACHE != NO) && (USE_RSA_KEY_CACHE != YES))
undef
USE_RSA_KEY_CACHE
define USE_RSA_KEY_CACHEYES// Default: Either YES or NO
endif

\

Enables use of a file to store the key cache values so that the TPM will start faster during debug. Default
for this is YES
92
93
94
95
96
97

#
#
#
#
#

if USE_RSA_KEY_CACHE
if !(defined USE_KEY_CACHE_FILE)|| ((USE_KEY_CACHE_FILE != NO) && (USE_KEY_CACHE_FILE != YES))
undef
USE_KEY_CACHE_FILE
define USE_KEY_CACHE_FILE YES// Default: Either YES or NO
endif

Page 146
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
98
99
100
101

#
#
#
#

Trusted Platform Module Library

else
undef
USE_KEY_CACHE_FILE
define USE_KEY_CACHE_FILE
endif// USE_RSA_KEY_CACHENOThis provides fixed seeding of the RNG when doing debug on a simulator. This should allow consistent
results on test runs as long as the input parameters to the functions remains the same. There is nodefault value.
102
103
104
105

#
#
#
#

if !(defined USE_DEBUG_RNG) || ((USE_DEBUG_RNG != NO) && (USE_DEBUG_RNG != YES))
undef
USE_DEBUG_RNG
define USE_DEBUG_RNG
YES// Default: Either YES or NO
endif

Don't change these. They are the settings needed when not doing a simulation and not doing debug.
Can't use the key cache except during debug. Otherwise, all of the key values end up being the same
106
107
108
109
110
111

#else
#
define USE_RSA_KEY_CACHE#
define USE_RSA_KEY_CACHE_FILE#
define USE_DEBUG_RNG#endif // DEBUG && SIMULATION#if DEBUG

NO
NO
NO

In some cases, the relationship between two values may be dependent on things that change based on
various selections like the chosen cryptographic libraries. It is possible that these selections will result inincompatible settings. These are often detectable by the compiler but it isn't always possible to do thecheck in the preprocessor code. For example, when the check requires use of 'sizeof()' then the
preprocessor can't do the comparison. For these cases, we include a special macro that, depending on
the compiler will generate a warning to indicate if the check always passes or always fails because it
involves fixed constants. To run these checks, define COMPILER_CHECKS.
112
113
114
115
116

#
#
#
#

if !(defined COMPILER_CHECKS)|| ((COMPILER_CHECKS != NO) && (COMPILER_CHECKS != YES))
undef
COMPILER_CHECKS
define COMPILER_CHECKSNO// Default: Either YES or NO
endif

\

Some of the values (such as sizes) are the result of different options set in Implementation.h. The
combination might not be consistent. A function is defined (TpmSizeChecks()) that is used to verify thesizes at run time. To enable the function, define this parameter.
117
118
119
120
121

#
#
#
#

if !(defined RUNTIME_SIZE_CHECKS)|| ((RUNTIME_SIZE_CHECKS != NO) && (RUNTIME_SIZE_CHECKS != YES))
undef RUNTIME_SIZE_CHECKS
define RUNTIME_SIZE_CHECKSNO// Default: Either YES or NO
endif

\

If doing debug, can set the DRBG to print out the intermediate test values. Before enabling this, makesure that the dbgDumpMemBlock() function has been added someplace (preferably, somewhere in
CryptRand.c)
122
123
124
125
126

#
#
#
#

if !(defined DRBG_DEBUG_PRINT)|| ((DRBG_DEBUG_PRINT != NO) && (DRBG_DEBUG_PRINT != YES))
undef
DRBG_DEBUG_PRINT
define DRBG_DEBUG_PRINTNO// Default: Either YES or NO
endif

\

If an assertion event it not going to produce any trace information (function and line number) then makeFAIL_TRACE == NOFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 147
April 15, 2019

Trusted Platform Module Library
127
128
129
130
131

Part 4: Supporting Routines#
if !(defined FAIL_TRACE) || ((FAIL_TRACE != NO) && (FAIL_TRACE != YES))#
undef
FAIL_TRACE#
define FAIL_TRACE
YES// Default: Either YES or NO#
endif#endif // DEBUG

Indicate if the implementation is going to give lockout time credit for time up to the last orderly shutdown.
132
133
134
135
136

#if !(defined ACCUMULATE_SELF_HEAL_TIMER)|| ((ACCUMULATE_SELF_HEAL_TIMER != NO) && (ACCUMULATE_SELF_HEAL_TIMER != YES))#
undef
ACCUMULATE_SELF_HEAL_TIMER#
define ACCUMULATE_SELF_HEAL_TIMER
YES// Default: Either YES or NO#endif\Indicates if the implementation is to compute the sizes of the proof and primary seed size values basedon the implemented algorithms.
137
138
139
140
141

#if !(defined USE_SPEC_COMPLIANT_PROOFS)|| ((USE_SPEC_COMPLIANT_PROOFS != NO) && (USE_SPEC_COMPLIANT_PROOFS != YES))#
undef
USE_SPEC_COMPLIANT_PROOFS#
define USE_SPEC_COMPLIANT_PROOFS
YES// Default: Either YES or NO#endif\Comment this out to allow compile to continue even though the chosen proof values do not match thecompliant values. This is written so that someone would have to proactively ignore errors.
142
143
144
145
146

#if !(defined SKIP_PROOF_ERRORS)|| ((SKIP_PROOF_ERRORS != NO) && (SKIP_PROOF_ERRORS != YES))#
undef
SKIP_PROOF_ERRORS#
define SKIP_PROOF_ERRORSNO// Default: Either YES or NO#endif\This define is used to eliminate the use of bit-fields. It can be enabled for big- or little-endian machines.
For big-endian architectures that numbers bits in registers from left to right (MSb0) this must be enabled.
Little-endian machines number from right to left with the least significant bit having assigned a bit numberof 0. These are LSb0 machines (they are also little-endian so they are also least-significant byte 0 (LSB0)
machines. Big-endian (MSB0) machines may number in either direction (MSb0 or LSb0). For an
MSB0+MSb0 machine this value is required to be NO
147
148
149
150
151

#if !(defined USE_BIT_FIELD_STRUCTURES)|| ((USE_BIT_FIELD_STRUCTURES != NO) && (USE_BIT_FIELD_STRUCTURES != YES))#
undef
USE_BIT_FIELD_STRUCTURES#
define USE_BIT_FIELD_STRUCTURES
DEBUG// Default: Either YES or NO#endif\This define is used to enable any runtime checks of the interface between the cryptographic library (e.g.,
OpenSSL) and the thunking layer.
152
153
154
155
156

#if !(defined LIBRARY_COMPATIBILITY_CHECK)\|| ((LIBRARY_COMPATIBILITY_CHECK != NO) && (LIBRARY_COMPATIBILITY_CHECK != YES))#
undef
LIBRARY_COMPATIBILITY_CHECK#
define LIBRARY_COMPATIBILITY_CHECKNO// Default: Either YES or NO#endifChange these definitions to turn all algorithms or commands ON or OFF. That is, to turn all algorithms on,
set ALG_NO to YES. This is mostly useful as a debug feature.
157
158
159
160

#define#define#define#definePage 148
April 15, 2019

ALG_YESALG_NO
CC_YES
CC_NO

YES
NO
YES
NO

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
161

Trusted Platform Module Library#endif // _TPM_BUILD_SWITCHES_H_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 149
April 15, 2019

Trusted Platform Module Library

5.20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Part 4: Supporting Routines

TpmError.h#ifndef _TPM_ERROR_H#define _TPM_ERROR_H#defineFATAL_ERROR_ALLOCATION#defineFATAL_ERROR_DIVIDE_ZERO#defineFATAL_ERROR_INTERNAL#defineFATAL_ERROR_PARAMETER#defineFATAL_ERROR_ENTROPY#defineFATAL_ERROR_SELF_TEST#defineFATAL_ERROR_CRYPTO#defineFATAL_ERROR_NV_UNRECOVERABLE#defineFATAL_ERROR_REMANUFACTURED#defineFATAL_ERROR_DRBG#defineFATAL_ERROR_MOVE_SIZE#defineFATAL_ERROR_COUNTER_OVERFLOW#defineFATAL_ERROR_SUBTRACT#defineFATAL_ERROR_MATHLIBRARY#defineFATAL_ERROR_FORCED#endif // _TPM_ERROR_H

Page 150
April 15, 2019

(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9) // indicates that the TPM has// been re-manufactured after an// unrecoverable NV error
(10)
(11)
(12)
(13)
(14)
(666)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.21
1
2

Trusted Platform Module Library

TpmTypes.h#ifndef _TPM_TYPES_H_#define _TPM_TYPES_H_

Table 1:2 - Definition of TPM_ALG_ID Constants
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

typedef UINT16#define TYPE_OF_TPM_ALG_ID#define
ALG_ERROR_VALUE#define TPM_ALG_ERROR#define
ALG_RSA_VALUE#define TPM_ALG_RSA#define
ALG_TDES_VALUE#define TPM_ALG_TDES#define
ALG_SHA_VALUE#define TPM_ALG_SHA#define
ALG_SHA1_VALUE#define TPM_ALG_SHA1#define
ALG_HMAC_VALUE#define TPM_ALG_HMAC#define
ALG_AES_VALUE#define TPM_ALG_AES#define
ALG_MGF1_VALUE#define TPM_ALG_MGF1#define
ALG_KEYEDHASH_VALUE#define TPM_ALG_KEYEDHASH#defineALG_XOR_VALUE#define TPM_ALG_XOR#define
ALG_SHA256_VALUE#define TPM_ALG_SHA256#define
ALG_SHA384_VALUE#define TPM_ALG_SHA384#define
ALG_SHA512_VALUE#define TPM_ALG_SHA512#define
ALG_NULL_VALUE#define TPM_ALG_NULL#define
ALG_SM3_256_VALUE#define TPM_ALG_SM3_256#define
ALG_SM4_VALUE#define TPM_ALG_SM4#define
ALG_RSASSA_VALUE#define TPM_ALG_RSASSA#define
ALG_RSAES_VALUE#define TPM_ALG_RSAES#define
ALG_RSAPSS_VALUE#define TPM_ALG_RSAPSS#define
ALG_OAEP_VALUE#define TPM_ALG_OAEP#define
ALG_ECDSA_VALUE#define TPM_ALG_ECDSA#define
ALG_ECDH_VALUE#define TPM_ALG_ECDH#define
ALG_ECDAA_VALUE#define TPM_ALG_ECDAA#define
ALG_SM2_VALUE#define TPM_ALG_SM2#define
ALG_ECSCHNORR_VALUE#define TPM_ALG_ECSCHNORR#define
ALG_ECMQV_VALUE#define TPM_ALG_ECMQV#define
ALG_KDF1_SP800_56A_VALUE#define TPM_ALG_KDF1_SP800_56A#define
ALG_KDF2_VALUE

Family “2.0”Level 00 Revision 01.55

TPM_ALG_ID;
UINT160x0000(TPM_ALG_ID)(ALG_ERROR_VALUE)
0x0001(TPM_ALG_ID)(ALG_RSA_VALUE)
0x0003(TPM_ALG_ID)(ALG_TDES_VALUE)
0x0004(TPM_ALG_ID)(ALG_SHA_VALUE)
0x0004(TPM_ALG_ID)(ALG_SHA1_VALUE)
0x0005(TPM_ALG_ID)(ALG_HMAC_VALUE)
0x0006(TPM_ALG_ID)(ALG_AES_VALUE)
0x0007(TPM_ALG_ID)(ALG_MGF1_VALUE)
0x0008(TPM_ALG_ID)(ALG_KEYEDHASH_VALUE)
0x000A(TPM_ALG_ID)(ALG_XOR_VALUE)
0x000B(TPM_ALG_ID)(ALG_SHA256_VALUE)
0x000C(TPM_ALG_ID)(ALG_SHA384_VALUE)
0x000D(TPM_ALG_ID)(ALG_SHA512_VALUE)
0x0010(TPM_ALG_ID)(ALG_NULL_VALUE)
0x0012(TPM_ALG_ID)(ALG_SM3_256_VALUE)
0x0013(TPM_ALG_ID)(ALG_SM4_VALUE)
0x0014(TPM_ALG_ID)(ALG_RSASSA_VALUE)
0x0015(TPM_ALG_ID)(ALG_RSAES_VALUE)
0x0016(TPM_ALG_ID)(ALG_RSAPSS_VALUE)
0x0017(TPM_ALG_ID)(ALG_OAEP_VALUE)
0x0018(TPM_ALG_ID)(ALG_ECDSA_VALUE)
0x0019(TPM_ALG_ID)(ALG_ECDH_VALUE)
0x001A(TPM_ALG_ID)(ALG_ECDAA_VALUE)
0x001B(TPM_ALG_ID)(ALG_SM2_VALUE)
0x001C(TPM_ALG_ID)(ALG_ECSCHNORR_VALUE)
0x001D(TPM_ALG_ID)(ALG_ECMQV_VALUE)
0x0020(TPM_ALG_ID)(ALG_KDF1_SP800_56A_VALUE)
0x0021

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 151
April 15, 2019

Trusted Platform Module Library
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

Part 4: Supporting Routines#define TPM_ALG_KDF2#define
ALG_KDF1_SP800_108_VALUE#define TPM_ALG_KDF1_SP800_108#define
ALG_ECC_VALUE#define TPM_ALG_ECC#define
ALG_SYMCIPHER_VALUE#define TPM_ALG_SYMCIPHER#define
ALG_CAMELLIA_VALUE#define TPM_ALG_CAMELLIA#define
ALG_SHA3_256_VALUE#define TPM_ALG_SHA3_256#define
ALG_SHA3_384_VALUE#define TPM_ALG_SHA3_384#define
ALG_SHA3_512_VALUE#define TPM_ALG_SHA3_512#define
ALG_CMAC_VALUE#define TPM_ALG_CMAC#define
ALG_CTR_VALUE#define TPM_ALG_CTR#define
ALG_OFB_VALUE#define TPM_ALG_OFB#define
ALG_CBC_VALUE#define TPM_ALG_CBC#define
ALG_CFB_VALUE#define TPM_ALG_CFB#define
ALG_ECB_VALUE#define TPM_ALG_ECB(TPM_ALG_ID)(ALG_KDF2_VALUE)
0x0022(TPM_ALG_ID)(ALG_KDF1_SP800_108_VALUE)
0x0023(TPM_ALG_ID)(ALG_ECC_VALUE)
0x0025(TPM_ALG_ID)(ALG_SYMCIPHER_VALUE)
0x0026(TPM_ALG_ID)(ALG_CAMELLIA_VALUE)
0x0027(TPM_ALG_ID)(ALG_SHA3_256_VALUE)
0x0028(TPM_ALG_ID)(ALG_SHA3_384_VALUE)
0x0029(TPM_ALG_ID)(ALG_SHA3_512_VALUE)
0x003F(TPM_ALG_ID)(ALG_CMAC_VALUE)
0x0040(TPM_ALG_ID)(ALG_CTR_VALUE)
0x0041(TPM_ALG_ID)(ALG_OFB_VALUE)
0x0042(TPM_ALG_ID)(ALG_CBC_VALUE)
0x0043(TPM_ALG_ID)(ALG_CFB_VALUE)
0x0044(TPM_ALG_ID)(ALG_ECB_VALUE)

Values derived from Table 1:2
87
88
89
90

#define
ALG_FIRST_VALUE#define TPM_ALG_FIRST#defineALG_LAST_VALUE#define TPM_ALG_LAST

0x0001(TPM_ALG_ID)(ALG_FIRST_VALUE)
0x0044(TPM_ALG_ID)(ALG_LAST_VALUE)

Table 1:3 - Definition of TPM_ECC_CURVE Constants
91
92
93
94
95
96
97
98
99
100
101

typedef UINT16
TPM_ECC_CURVE;#define TYPE_OF_TPM_ECC_CURVEUINT16#define TPM_ECC_NONE(TPM_ECC_CURVE)(0x0000)#define TPM_ECC_NIST_P192(TPM_ECC_CURVE)(0x0001)#define TPM_ECC_NIST_P224(TPM_ECC_CURVE)(0x0002)#define TPM_ECC_NIST_P256(TPM_ECC_CURVE)(0x0003)#define TPM_ECC_NIST_P384(TPM_ECC_CURVE)(0x0004)#define TPM_ECC_NIST_P521(TPM_ECC_CURVE)(0x0005)#define TPM_ECC_BN_P256(TPM_ECC_CURVE)(0x0010)#define TPM_ECC_BN_P638(TPM_ECC_CURVE)(0x0011)#define TPM_ECC_SM2_P256(TPM_ECC_CURVE)(0x0020)

Table 2:12 - Definition of TPM_CC Constants
102
103
104
105
106
107
108
109
110
111
112
113
114

typedef UINT32#define TYPE_OF_TPM_CC#define TPM_CC_NV_UndefineSpaceSpecial#define TPM_CC_EvictControl#define TPM_CC_HierarchyControl#define TPM_CC_NV_UndefineSpace#define TPM_CC_ChangeEPS#define TPM_CC_ChangePPS#define TPM_CC_Clear#define TPM_CC_ClearControl#define TPM_CC_ClockSet#define TPM_CC_HierarchyChangeAuth#define TPM_CC_NV_DefineSpace

Page 152
April 15, 2019

TPM_CC;UINT32(TPM_CC)(0x0000011F)(TPM_CC)(0x00000120)(TPM_CC)(0x00000121)(TPM_CC)(0x00000122)(TPM_CC)(0x00000124)(TPM_CC)(0x00000125)(TPM_CC)(0x00000126)(TPM_CC)(0x00000127)(TPM_CC)(0x00000128)(TPM_CC)(0x00000129)(TPM_CC)(0x0000012A)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

Trusted Platform Module Library#define TPM_CC_PCR_Allocate#define TPM_CC_PCR_SetAuthPolicy#define TPM_CC_PP_Commands#define TPM_CC_SetPrimaryPolicy#define TPM_CC_FieldUpgradeStart#define TPM_CC_ClockRateAdjust#define TPM_CC_CreatePrimary#define TPM_CC_NV_GlobalWriteLock#define TPM_CC_GetCommandAuditDigest#define TPM_CC_NV_Increment#define TPM_CC_NV_SetBits#define TPM_CC_NV_Extend#define TPM_CC_NV_Write#define TPM_CC_NV_WriteLock#define TPM_CC_DictionaryAttackLockReset#define TPM_CC_DictionaryAttackParameters#define TPM_CC_NV_ChangeAuth#define TPM_CC_PCR_Event#define TPM_CC_PCR_Reset#define TPM_CC_SequenceComplete#define TPM_CC_SetAlgorithmSet#define TPM_CC_SetCommandCodeAuditStatus#define TPM_CC_FieldUpgradeData#define TPM_CC_IncrementalSelfTest#define TPM_CC_SelfTest#define TPM_CC_Startup#define TPM_CC_Shutdown#define TPM_CC_StirRandom#define TPM_CC_ActivateCredential#define TPM_CC_Certify#define TPM_CC_PolicyNV#define TPM_CC_CertifyCreation#define TPM_CC_Duplicate#define TPM_CC_GetTime#define TPM_CC_GetSessionAuditDigest#define TPM_CC_NV_Read#define TPM_CC_NV_ReadLock#define TPM_CC_ObjectChangeAuth#define TPM_CC_PolicySecret#define TPM_CC_Rewrap#define TPM_CC_Create#define TPM_CC_ECDH_ZGen#define TPM_CC_HMAC#define TPM_CC_MAC#define TPM_CC_Import#define TPM_CC_Load#define TPM_CC_Quote#define TPM_CC_RSA_Decrypt#define TPM_CC_HMAC_Start#define TPM_CC_MAC_Start#define TPM_CC_SequenceUpdate#define TPM_CC_Sign#define TPM_CC_Unseal#define TPM_CC_PolicySigned#define TPM_CC_ContextLoad#define TPM_CC_ContextSave#define TPM_CC_ECDH_KeyGen#define TPM_CC_EncryptDecrypt#define TPM_CC_FlushContext#define TPM_CC_LoadExternal#define TPM_CC_MakeCredential#define TPM_CC_NV_ReadPublic#define TPM_CC_PolicyAuthorize#define TPM_CC_PolicyAuthValue#define TPM_CC_PolicyCommandCode#define TPM_CC_PolicyCounterTimer

Family “2.0”Level 00 Revision 01.55(TPM_CC)(0x0000012B)(TPM_CC)(0x0000012C)(TPM_CC)(0x0000012D)(TPM_CC)(0x0000012E)(TPM_CC)(0x0000012F)(TPM_CC)(0x00000130)(TPM_CC)(0x00000131)(TPM_CC)(0x00000132)(TPM_CC)(0x00000133)(TPM_CC)(0x00000134)(TPM_CC)(0x00000135)(TPM_CC)(0x00000136)(TPM_CC)(0x00000137)(TPM_CC)(0x00000138)(TPM_CC)(0x00000139)(TPM_CC)(0x0000013A)(TPM_CC)(0x0000013B)(TPM_CC)(0x0000013C)(TPM_CC)(0x0000013D)(TPM_CC)(0x0000013E)(TPM_CC)(0x0000013F)(TPM_CC)(0x00000140)(TPM_CC)(0x00000141)(TPM_CC)(0x00000142)(TPM_CC)(0x00000143)(TPM_CC)(0x00000144)(TPM_CC)(0x00000145)(TPM_CC)(0x00000146)(TPM_CC)(0x00000147)(TPM_CC)(0x00000148)(TPM_CC)(0x00000149)(TPM_CC)(0x0000014A)(TPM_CC)(0x0000014B)(TPM_CC)(0x0000014C)(TPM_CC)(0x0000014D)(TPM_CC)(0x0000014E)(TPM_CC)(0x0000014F)(TPM_CC)(0x00000150)(TPM_CC)(0x00000151)(TPM_CC)(0x00000152)(TPM_CC)(0x00000153)(TPM_CC)(0x00000154)(TPM_CC)(0x00000155)(TPM_CC)(0x00000155)(TPM_CC)(0x00000156)(TPM_CC)(0x00000157)(TPM_CC)(0x00000158)(TPM_CC)(0x00000159)(TPM_CC)(0x0000015B)(TPM_CC)(0x0000015B)(TPM_CC)(0x0000015C)(TPM_CC)(0x0000015D)(TPM_CC)(0x0000015E)(TPM_CC)(0x00000160)(TPM_CC)(0x00000161)(TPM_CC)(0x00000162)(TPM_CC)(0x00000163)(TPM_CC)(0x00000164)(TPM_CC)(0x00000165)(TPM_CC)(0x00000167)(TPM_CC)(0x00000168)(TPM_CC)(0x00000169)(TPM_CC)(0x0000016A)(TPM_CC)(0x0000016B)(TPM_CC)(0x0000016C)(TPM_CC)(0x0000016D)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 153
April 15, 2019

Trusted Platform Module Library
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

Part 4: Supporting Routines#define TPM_CC_PolicyCpHash#define TPM_CC_PolicyLocality#define TPM_CC_PolicyNameHash#define TPM_CC_PolicyOR#define TPM_CC_PolicyTicket#define TPM_CC_ReadPublic#define TPM_CC_RSA_Encrypt#define TPM_CC_StartAuthSession#define TPM_CC_VerifySignature#define TPM_CC_ECC_Parameters#define TPM_CC_FirmwareRead#define TPM_CC_GetCapability#define TPM_CC_GetRandom#define TPM_CC_GetTestResult#define TPM_CC_Hash#define TPM_CC_PCR_Read#define TPM_CC_PolicyPCR#define TPM_CC_PolicyRestart#define TPM_CC_ReadClock#define TPM_CC_PCR_Extend#define TPM_CC_PCR_SetAuthValue#define TPM_CC_NV_Certify#define TPM_CC_EventSequenceComplete#define TPM_CC_HashSequenceStart#define TPM_CC_PolicyPhysicalPresence#define TPM_CC_PolicyDuplicationSelect#define TPM_CC_PolicyGetDigest#define TPM_CC_TestParms#define TPM_CC_Commit#define TPM_CC_PolicyPassword#define TPM_CC_ZGen_2Phase#define TPM_CC_EC_Ephemeral#define TPM_CC_PolicyNvWritten#define TPM_CC_PolicyTemplate#define TPM_CC_CreateLoaded#define TPM_CC_PolicyAuthorizeNV#define TPM_CC_EncryptDecrypt2#define TPM_CC_AC_GetCapability#define TPM_CC_AC_Send#define TPM_CC_Policy_AC_SendSelect#define TPM_CC_CertifyX509#define CC_VEND#define TPM_CC_Vendor_TCG_Test(TPM_CC)(0x0000016E)(TPM_CC)(0x0000016F)(TPM_CC)(0x00000170)(TPM_CC)(0x00000171)(TPM_CC)(0x00000172)(TPM_CC)(0x00000173)(TPM_CC)(0x00000174)(TPM_CC)(0x00000176)(TPM_CC)(0x00000177)(TPM_CC)(0x00000178)(TPM_CC)(0x00000179)(TPM_CC)(0x0000017A)(TPM_CC)(0x0000017B)(TPM_CC)(0x0000017C)(TPM_CC)(0x0000017D)(TPM_CC)(0x0000017E)(TPM_CC)(0x0000017F)(TPM_CC)(0x00000180)(TPM_CC)(0x00000181)(TPM_CC)(0x00000182)(TPM_CC)(0x00000183)(TPM_CC)(0x00000184)(TPM_CC)(0x00000185)(TPM_CC)(0x00000186)(TPM_CC)(0x00000187)(TPM_CC)(0x00000188)(TPM_CC)(0x00000189)(TPM_CC)(0x0000018A)(TPM_CC)(0x0000018B)(TPM_CC)(0x0000018C)(TPM_CC)(0x0000018D)(TPM_CC)(0x0000018E)(TPM_CC)(0x0000018F)(TPM_CC)(0x00000190)(TPM_CC)(0x00000191)(TPM_CC)(0x00000192)(TPM_CC)(0x00000193)(TPM_CC)(0x00000194)(TPM_CC)(0x00000195)(TPM_CC)(0x00000196)(TPM_CC)(0x00000197)
0x20000000(TPM_CC)(0x20000000)

Table 2:5 - Definition of Types for Documentation Clarity
224
225
226
227
228
229
230
231
232
233
234
235

typedef UINT32
TPM_ALGORITHM_ID;#define TYPE_OF_TPM_ALGORITHM_ID
UINT32
typedef UINT32
TPM_MODIFIER_INDICATOR;#define TYPE_OF_TPM_MODIFIER_INDICATOR UINT32
typedef UINT32
TPM_AUTHORIZATION_SIZE;#define TYPE_OF_TPM_AUTHORIZATION_SIZE UINT32
typedef UINT32
TPM_PARAMETER_SIZE;#define TYPE_OF_TPM_PARAMETER_SIZE UINT32
typedef UINT16
TPM_KEY_SIZE;#define TYPE_OF_TPM_KEY_SIZEUINT16
typedef UINT16
TPM_KEY_BITS;#define TYPE_OF_TPM_KEY_BITS
UINT16

Table 2:6 - Definition of TPM_SPEC Constants
236
237
238
239

typedef UINT32#define TYPE_OF_TPM_SPEC#define SPEC_FAMILY#define TPM_SPEC_FAMILY

Page 154
April 15, 2019

TPM_SPEC;UINT320x322E3000(TPM_SPEC)(SPEC_FAMILY)TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
240
241
242
243
244
245
246
247

Trusted Platform Module Library#define SPEC_LEVEL#define TPM_SPEC_LEVEL#define SPEC_VERSION#define TPM_SPEC_VERSION#define SPEC_YEAR#define TPM_SPEC_YEAR#define SPEC_DAY_OF_YEAR#define TPM_SPEC_DAY_OF_YEAR

00(TPM_SPEC)(SPEC_LEVEL)
155(TPM_SPEC)(SPEC_VERSION)
2019(TPM_SPEC)(SPEC_YEAR)107(TPM_SPEC)(SPEC_DAY_OF_YEAR)

Table 2:7 - Definition of TPM_GENERATED Constants
248
249
250

typedef UINT32#define TYPE_OF_TPM_GENERATED#define TPM_GENERATED_VALUE

TPM_GENERATED;UINT32(TPM_GENERATED)(0xFF544347)

Table 2:16 - Definition of TPM_RC Constants
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

typedef UINT32#define TYPE_OF_TPM_RC#define TPM_RC_SUCCESS#define TPM_RC_BAD_TAG#define RC_VER1#define TPM_RC_INITIALIZE#define TPM_RC_FAILURE#define TPM_RC_SEQUENCE#define TPM_RC_PRIVATE#define TPM_RC_HMAC#define TPM_RC_DISABLED#define TPM_RC_EXCLUSIVE#define TPM_RC_AUTH_TYPE#define TPM_RC_AUTH_MISSING#define TPM_RC_POLICY#define TPM_RC_PCR#define TPM_RC_PCR_CHANGED#define TPM_RC_UPGRADE#define TPM_RC_TOO_MANY_CONTEXTS#define TPM_RC_AUTH_UNAVAILABLE#define TPM_RC_REBOOT#define TPM_RC_UNBALANCED#define TPM_RC_COMMAND_SIZE#define TPM_RC_COMMAND_CODE#define TPM_RC_AUTHSIZE#define TPM_RC_AUTH_CONTEXT#define TPM_RC_NV_RANGE#define TPM_RC_NV_SIZE#define TPM_RC_NV_LOCKED#define TPM_RC_NV_AUTHORIZATION#define TPM_RC_NV_UNINITIALIZED#define TPM_RC_NV_SPACE#define TPM_RC_NV_DEFINED#define TPM_RC_BAD_CONTEXT#define TPM_RC_CPHASH#define TPM_RC_PARENT#define TPM_RC_NEEDS_TEST#define TPM_RC_NO_RESULT#define TPM_RC_SENSITIVE#define RC_MAX_FM0#define RC_FMT1#define TPM_RC_ASYMMETRIC#define TPM_RCS_ASYMMETRIC#define TPM_RC_ATTRIBUTES#define TPM_RCS_ATTRIBUTES#define TPM_RC_HASH#define TPM_RCS_HASH#define TPM_RC_VALUE

Family “2.0”Level 00 Revision 01.55

TPM_RC;UINT32(TPM_RC)(0x000)(TPM_RC)(0x01E)(TPM_RC)(0x100)(TPM_RC)(RC_VER1+0x000)(TPM_RC)(RC_VER1+0x001)(TPM_RC)(RC_VER1+0x003)(TPM_RC)(RC_VER1+0x00B)(TPM_RC)(RC_VER1+0x019)(TPM_RC)(RC_VER1+0x020)(TPM_RC)(RC_VER1+0x021)(TPM_RC)(RC_VER1+0x024)(TPM_RC)(RC_VER1+0x025)(TPM_RC)(RC_VER1+0x026)(TPM_RC)(RC_VER1+0x027)(TPM_RC)(RC_VER1+0x028)(TPM_RC)(RC_VER1+0x02D)(TPM_RC)(RC_VER1+0x02E)(TPM_RC)(RC_VER1+0x02F)(TPM_RC)(RC_VER1+0x030)(TPM_RC)(RC_VER1+0x031)(TPM_RC)(RC_VER1+0x042)(TPM_RC)(RC_VER1+0x043)(TPM_RC)(RC_VER1+0x044)(TPM_RC)(RC_VER1+0x045)(TPM_RC)(RC_VER1+0x046)(TPM_RC)(RC_VER1+0x047)(TPM_RC)(RC_VER1+0x048)(TPM_RC)(RC_VER1+0x049)(TPM_RC)(RC_VER1+0x04A)(TPM_RC)(RC_VER1+0x04B)(TPM_RC)(RC_VER1+0x04C)(TPM_RC)(RC_VER1+0x050)(TPM_RC)(RC_VER1+0x051)(TPM_RC)(RC_VER1+0x052)(TPM_RC)(RC_VER1+0x053)(TPM_RC)(RC_VER1+0x054)(TPM_RC)(RC_VER1+0x055)(TPM_RC)(RC_VER1+0x07F)(TPM_RC)(0x080)(TPM_RC)(RC_FMT1+0x001)(TPM_RC)(RC_FMT1+0x001)(TPM_RC)(RC_FMT1+0x002)(TPM_RC)(RC_FMT1+0x002)(TPM_RC)(RC_FMT1+0x003)(TPM_RC)(RC_FMT1+0x003)(TPM_RC)(RC_FMT1+0x004)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 155
April 15, 2019

Trusted Platform Module Library
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

#define TPM_RCS_VALUE#define TPM_RC_HIERARCHY#define TPM_RCS_HIERARCHY#define TPM_RC_KEY_SIZE#define TPM_RCS_KEY_SIZE#define TPM_RC_MGF#define TPM_RCS_MGF#define TPM_RC_MODE#define TPM_RCS_MODE#define TPM_RC_TYPE#define TPM_RCS_TYPE#define TPM_RC_HANDLE#define TPM_RCS_HANDLE#define TPM_RC_KDF#define TPM_RCS_KDF#define TPM_RC_RANGE#define TPM_RCS_RANGE#define TPM_RC_AUTH_FAIL#define TPM_RCS_AUTH_FAIL#define TPM_RC_NONCE#define TPM_RCS_NONCE#define TPM_RC_PP#define TPM_RCS_PP#define TPM_RC_SCHEME#define TPM_RCS_SCHEME#define TPM_RC_SIZE#define TPM_RCS_SIZE#define TPM_RC_SYMMETRIC#define TPM_RCS_SYMMETRIC#define TPM_RC_TAG#define TPM_RCS_TAG#define TPM_RC_SELECTOR#define TPM_RCS_SELECTOR#define TPM_RC_INSUFFICIENT#define TPM_RCS_INSUFFICIENT#define TPM_RC_SIGNATURE#define TPM_RCS_SIGNATURE#define TPM_RC_KEY#define TPM_RCS_KEY#define TPM_RC_POLICY_FAIL#define TPM_RCS_POLICY_FAIL#define TPM_RC_INTEGRITY#define TPM_RCS_INTEGRITY#define TPM_RC_TICKET#define TPM_RCS_TICKET#define TPM_RC_RESERVED_BITS#define TPM_RCS_RESERVED_BITS#define TPM_RC_BAD_AUTH#define TPM_RCS_BAD_AUTH#define TPM_RC_EXPIRED#define TPM_RCS_EXPIRED#define TPM_RC_POLICY_CC#define TPM_RCS_POLICY_CC#define TPM_RC_BINDING#define TPM_RCS_BINDING#define TPM_RC_CURVE#define TPM_RCS_CURVE#define TPM_RC_ECC_POINT#define TPM_RCS_ECC_POINT#define RC_WARN#define TPM_RC_CONTEXT_GAP#define TPM_RC_OBJECT_MEMORY#define TPM_RC_SESSION_MEMORY#define TPM_RC_MEMORY#define TPM_RC_SESSION_HANDLES#define TPM_RC_OBJECT_HANDLES

Page 156
April 15, 2019

Part 4: Supporting Routines(TPM_RC)(RC_FMT1+0x004)(TPM_RC)(RC_FMT1+0x005)(TPM_RC)(RC_FMT1+0x005)(TPM_RC)(RC_FMT1+0x007)(TPM_RC)(RC_FMT1+0x007)(TPM_RC)(RC_FMT1+0x008)(TPM_RC)(RC_FMT1+0x008)(TPM_RC)(RC_FMT1+0x009)(TPM_RC)(RC_FMT1+0x009)(TPM_RC)(RC_FMT1+0x00A)(TPM_RC)(RC_FMT1+0x00A)(TPM_RC)(RC_FMT1+0x00B)(TPM_RC)(RC_FMT1+0x00B)(TPM_RC)(RC_FMT1+0x00C)(TPM_RC)(RC_FMT1+0x00C)(TPM_RC)(RC_FMT1+0x00D)(TPM_RC)(RC_FMT1+0x00D)(TPM_RC)(RC_FMT1+0x00E)(TPM_RC)(RC_FMT1+0x00E)(TPM_RC)(RC_FMT1+0x00F)(TPM_RC)(RC_FMT1+0x00F)(TPM_RC)(RC_FMT1+0x010)(TPM_RC)(RC_FMT1+0x010)(TPM_RC)(RC_FMT1+0x012)(TPM_RC)(RC_FMT1+0x012)(TPM_RC)(RC_FMT1+0x015)(TPM_RC)(RC_FMT1+0x015)(TPM_RC)(RC_FMT1+0x016)(TPM_RC)(RC_FMT1+0x016)(TPM_RC)(RC_FMT1+0x017)(TPM_RC)(RC_FMT1+0x017)(TPM_RC)(RC_FMT1+0x018)(TPM_RC)(RC_FMT1+0x018)(TPM_RC)(RC_FMT1+0x01A)(TPM_RC)(RC_FMT1+0x01A)(TPM_RC)(RC_FMT1+0x01B)(TPM_RC)(RC_FMT1+0x01B)(TPM_RC)(RC_FMT1+0x01C)(TPM_RC)(RC_FMT1+0x01C)(TPM_RC)(RC_FMT1+0x01D)(TPM_RC)(RC_FMT1+0x01D)(TPM_RC)(RC_FMT1+0x01F)(TPM_RC)(RC_FMT1+0x01F)(TPM_RC)(RC_FMT1+0x020)(TPM_RC)(RC_FMT1+0x020)(TPM_RC)(RC_FMT1+0x021)(TPM_RC)(RC_FMT1+0x021)(TPM_RC)(RC_FMT1+0x022)(TPM_RC)(RC_FMT1+0x022)(TPM_RC)(RC_FMT1+0x023)(TPM_RC)(RC_FMT1+0x023)(TPM_RC)(RC_FMT1+0x024)(TPM_RC)(RC_FMT1+0x024)(TPM_RC)(RC_FMT1+0x025)(TPM_RC)(RC_FMT1+0x025)(TPM_RC)(RC_FMT1+0x026)(TPM_RC)(RC_FMT1+0x026)(TPM_RC)(RC_FMT1+0x027)(TPM_RC)(RC_FMT1+0x027)(TPM_RC)(0x900)(TPM_RC)(RC_WARN+0x001)(TPM_RC)(RC_WARN+0x002)(TPM_RC)(RC_WARN+0x003)(TPM_RC)(RC_WARN+0x004)(TPM_RC)(RC_WARN+0x005)(TPM_RC)(RC_WARN+0x006)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

Trusted Platform Module Library#define TPM_RC_LOCALITY#define TPM_RC_YIELDED#define TPM_RC_CANCELED#define TPM_RC_TESTING#define TPM_RC_REFERENCE_H0#define TPM_RC_REFERENCE_H1#define TPM_RC_REFERENCE_H2#define TPM_RC_REFERENCE_H3#define TPM_RC_REFERENCE_H4#define TPM_RC_REFERENCE_H5#define TPM_RC_REFERENCE_H6#define TPM_RC_REFERENCE_S0#define TPM_RC_REFERENCE_S1#define TPM_RC_REFERENCE_S2#define TPM_RC_REFERENCE_S3#define TPM_RC_REFERENCE_S4#define TPM_RC_REFERENCE_S5#define TPM_RC_REFERENCE_S6#define TPM_RC_NV_RATE#define TPM_RC_LOCKOUT#define TPM_RC_RETRY#define TPM_RC_NV_UNAVAILABLE#define TPM_RC_NOT_USED#define TPM_RC_H#define TPM_RC_P#define TPM_RC_S#define TPM_RC_1#define TPM_RC_2#define TPM_RC_3#define TPM_RC_4#define TPM_RC_5#define TPM_RC_6#define TPM_RC_7#define TPM_RC_8#define TPM_RC_9#define TPM_RC_A#define TPM_RC_B#define TPM_RC_C#define TPM_RC_D#define TPM_RC_E#define TPM_RC_F#define TPM_RC_N_MASK(TPM_RC)(RC_WARN+0x007)(TPM_RC)(RC_WARN+0x008)(TPM_RC)(RC_WARN+0x009)(TPM_RC)(RC_WARN+0x00A)(TPM_RC)(RC_WARN+0x010)(TPM_RC)(RC_WARN+0x011)(TPM_RC)(RC_WARN+0x012)(TPM_RC)(RC_WARN+0x013)(TPM_RC)(RC_WARN+0x014)(TPM_RC)(RC_WARN+0x015)(TPM_RC)(RC_WARN+0x016)(TPM_RC)(RC_WARN+0x018)(TPM_RC)(RC_WARN+0x019)(TPM_RC)(RC_WARN+0x01A)(TPM_RC)(RC_WARN+0x01B)(TPM_RC)(RC_WARN+0x01C)(TPM_RC)(RC_WARN+0x01D)(TPM_RC)(RC_WARN+0x01E)(TPM_RC)(RC_WARN+0x020)(TPM_RC)(RC_WARN+0x021)(TPM_RC)(RC_WARN+0x022)(TPM_RC)(RC_WARN+0x023)(TPM_RC)(RC_WARN+0x7F)(TPM_RC)(0x000)(TPM_RC)(0x040)(TPM_RC)(0x800)(TPM_RC)(0x100)(TPM_RC)(0x200)(TPM_RC)(0x300)(TPM_RC)(0x400)(TPM_RC)(0x500)(TPM_RC)(0x600)(TPM_RC)(0x700)(TPM_RC)(0x800)(TPM_RC)(0x900)(TPM_RC)(0xA00)(TPM_RC)(0xB00)(TPM_RC)(0xC00)(TPM_RC)(0xD00)(TPM_RC)(0xE00)(TPM_RC)(0xF00)(TPM_RC)(0xF00)

Table 2:17 - Definition of TPM_CLOCK_ADJUST Constants
407
408
409
410
411
412
413
414
415

typedef INT8
#define TYPE_OF_TPM_CLOCK_ADJUST#define TPM_CLOCK_COARSE_SLOWER#define TPM_CLOCK_MEDIUM_SLOWER#define TPM_CLOCK_FINE_SLOWER#define TPM_CLOCK_NO_CHANGE#define TPM_CLOCK_FINE_FASTER#define TPM_CLOCK_MEDIUM_FASTER#define TPM_CLOCK_COARSE_FASTER

TPM_CLOCK_ADJUST;UINT8(TPM_CLOCK_ADJUST)(-3)(TPM_CLOCK_ADJUST)(-2)(TPM_CLOCK_ADJUST)(-1)(TPM_CLOCK_ADJUST)(0)(TPM_CLOCK_ADJUST)(1)(TPM_CLOCK_ADJUST)(2)(TPM_CLOCK_ADJUST)(3)

Table 2:18 - Definition of TPM_EO Constants
416
417
418
419
420
421
422
423

typedef UINT16#define TYPE_OF_TPM_EO#define TPM_EO_EQ#define TPM_EO_NEQ#define TPM_EO_SIGNED_GT#define TPM_EO_UNSIGNED_GT#define TPM_EO_SIGNED_LT#define TPM_EO_UNSIGNED_LT

Family “2.0”Level 00 Revision 01.55

TPM_EO;UINT16(TPM_EO)(0x0000)(TPM_EO)(0x0001)(TPM_EO)(0x0002)(TPM_EO)(0x0003)(TPM_EO)(0x0004)(TPM_EO)(0x0005)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 157
April 15, 2019

Trusted Platform Module Library
424
425
426
427
428
429

#define TPM_EO_SIGNED_GE#define TPM_EO_UNSIGNED_GE#define TPM_EO_SIGNED_LE#define TPM_EO_UNSIGNED_LE#define TPM_EO_BITSET#define TPM_EO_BITCLEAR

Part 4: Supporting Routines(TPM_EO)(0x0006)(TPM_EO)(0x0007)(TPM_EO)(0x0008)(TPM_EO)(0x0009)(TPM_EO)(0x000A)(TPM_EO)(0x000B)

Table 2:19 - Definition of TPM_ST Constants
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

typedef UINT16#define TYPE_OF_TPM_ST#define TPM_ST_RSP_COMMAND#define TPM_ST_NULL#define TPM_ST_NO_SESSIONS#define TPM_ST_SESSIONS#define TPM_ST_ATTEST_NV#define TPM_ST_ATTEST_COMMAND_AUDIT#define TPM_ST_ATTEST_SESSION_AUDIT#define TPM_ST_ATTEST_CERTIFY#define TPM_ST_ATTEST_QUOTE#define TPM_ST_ATTEST_TIME#define TPM_ST_ATTEST_CREATION#define TPM_ST_ATTEST_NV_DIGEST#define TPM_ST_CREATION#define TPM_ST_VERIFIED#define TPM_ST_AUTH_SECRET#define TPM_ST_HASHCHECK#define TPM_ST_AUTH_SIGNED#define TPM_ST_FU_MANIFEST

TPM_ST;UINT16(TPM_ST)(0x00C4)(TPM_ST)(0x8000)(TPM_ST)(0x8001)(TPM_ST)(0x8002)(TPM_ST)(0x8014)(TPM_ST)(0x8015)(TPM_ST)(0x8016)(TPM_ST)(0x8017)(TPM_ST)(0x8018)(TPM_ST)(0x8019)(TPM_ST)(0x801A)(TPM_ST)(0x801C)(TPM_ST)(0x8021)(TPM_ST)(0x8022)(TPM_ST)(0x8023)(TPM_ST)(0x8024)(TPM_ST)(0x8025)(TPM_ST)(0x8029)

Table 2:20 - Definition of TPM_SU Constants
450
451
452
453

typedef UINT16#define TYPE_OF_TPM_SU#define TPM_SU_CLEAR#define TPM_SU_STATETPM_SU;UINT16(TPM_SU)(0x0000)(TPM_SU)(0x0001)

Table 2:21 - Definition of TPM_SE Constants
454
455
456
457
458

typedef UINT8#define TYPE_OF_TPM_SE#define TPM_SE_HMAC#define TPM_SE_POLICY#define TPM_SE_TRIAL

TPM_SE;UINT8(TPM_SE)(0x00)(TPM_SE)(0x01)(TPM_SE)(0x03)

Table 2:22 - Definition of TPM_CAP Constants
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

typedef UINT32#define TYPE_OF_TPM_CAP#define TPM_CAP_FIRST#define TPM_CAP_ALGS#define TPM_CAP_HANDLES#define TPM_CAP_COMMANDS#define TPM_CAP_PP_COMMANDS#define TPM_CAP_AUDIT_COMMANDS#define TPM_CAP_PCRS#define TPM_CAP_TPM_PROPERTIES#define TPM_CAP_PCR_PROPERTIES#define TPM_CAP_ECC_CURVES#define TPM_CAP_AUTH_POLICIES#define TPM_CAP_LAST#define TPM_CAP_VENDOR_PROPERTY

Page 158
April 15, 2019

TPM_CAP;UINT32(TPM_CAP)(0x00000000)(TPM_CAP)(0x00000000)(TPM_CAP)(0x00000001)(TPM_CAP)(0x00000002)(TPM_CAP)(0x00000003)(TPM_CAP)(0x00000004)(TPM_CAP)(0x00000005)(TPM_CAP)(0x00000006)(TPM_CAP)(0x00000007)(TPM_CAP)(0x00000008)(TPM_CAP)(0x00000009)(TPM_CAP)(0x00000009)(TPM_CAP)(0x00000100)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

Table 2:23 - Definition of TPM_PT Constants
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537

typedef UINT32#define TYPE_OF_TPM_PT#define TPM_PT_NONE#define PT_GROUP#define PT_FIXED#define TPM_PT_FAMILY_INDICATOR#define TPM_PT_LEVEL#define TPM_PT_REVISION#define TPM_PT_DAY_OF_YEAR#define TPM_PT_YEAR#define TPM_PT_MANUFACTURER#define TPM_PT_VENDOR_STRING_1#define TPM_PT_VENDOR_STRING_2#define TPM_PT_VENDOR_STRING_3#define TPM_PT_VENDOR_STRING_4#define TPM_PT_VENDOR_TPM_TYPE#define TPM_PT_FIRMWARE_VERSION_1#define TPM_PT_FIRMWARE_VERSION_2#define TPM_PT_INPUT_BUFFER#define TPM_PT_HR_TRANSIENT_MIN#define TPM_PT_HR_PERSISTENT_MIN#define TPM_PT_HR_LOADED_MIN#define TPM_PT_ACTIVE_SESSIONS_MAX#define TPM_PT_PCR_COUNT#define TPM_PT_PCR_SELECT_MIN#define TPM_PT_CONTEXT_GAP_MAX#define TPM_PT_NV_COUNTERS_MAX#define TPM_PT_NV_INDEX_MAX#define TPM_PT_MEMORY#define TPM_PT_CLOCK_UPDATE#define TPM_PT_CONTEXT_HASH#define TPM_PT_CONTEXT_SYM#define TPM_PT_CONTEXT_SYM_SIZE#define TPM_PT_ORDERLY_COUNT#define TPM_PT_MAX_COMMAND_SIZE#define TPM_PT_MAX_RESPONSE_SIZE#define TPM_PT_MAX_DIGEST#define TPM_PT_MAX_OBJECT_CONTEXT#define TPM_PT_MAX_SESSION_CONTEXT#define TPM_PT_PS_FAMILY_INDICATOR#define TPM_PT_PS_LEVEL#define TPM_PT_PS_REVISION#define TPM_PT_PS_DAY_OF_YEAR#define TPM_PT_PS_YEAR#define TPM_PT_SPLIT_MAX#define TPM_PT_TOTAL_COMMANDS#define TPM_PT_LIBRARY_COMMANDS#define TPM_PT_VENDOR_COMMANDS#define TPM_PT_NV_BUFFER_MAX#define TPM_PT_MODES#define TPM_PT_MAX_CAP_BUFFER#define PT_VAR#define TPM_PT_PERMANENT#define TPM_PT_STARTUP_CLEAR#define TPM_PT_HR_NV_INDEX#define TPM_PT_HR_LOADED#define TPM_PT_HR_LOADED_AVAIL#define TPM_PT_HR_ACTIVE#define TPM_PT_HR_ACTIVE_AVAIL#define TPM_PT_HR_TRANSIENT_AVAIL#define TPM_PT_HR_PERSISTENT#define TPM_PT_HR_PERSISTENT_AVAIL#define TPM_PT_NV_COUNTERS#define TPM_PT_NV_COUNTERS_AVAILFamily “2.0”Level 00 Revision 01.55

TPM_PT;UINT32(TPM_PT)(0x00000000)(TPM_PT)(0x00000100)(TPM_PT)(PT_GROUP*1)(TPM_PT)(PT_FIXED+0)(TPM_PT)(PT_FIXED+1)(TPM_PT)(PT_FIXED+2)(TPM_PT)(PT_FIXED+3)(TPM_PT)(PT_FIXED+4)(TPM_PT)(PT_FIXED+5)(TPM_PT)(PT_FIXED+6)(TPM_PT)(PT_FIXED+7)(TPM_PT)(PT_FIXED+8)(TPM_PT)(PT_FIXED+9)(TPM_PT)(PT_FIXED+10)(TPM_PT)(PT_FIXED+11)(TPM_PT)(PT_FIXED+12)(TPM_PT)(PT_FIXED+13)(TPM_PT)(PT_FIXED+14)(TPM_PT)(PT_FIXED+15)(TPM_PT)(PT_FIXED+16)(TPM_PT)(PT_FIXED+17)(TPM_PT)(PT_FIXED+18)(TPM_PT)(PT_FIXED+19)(TPM_PT)(PT_FIXED+20)(TPM_PT)(PT_FIXED+22)(TPM_PT)(PT_FIXED+23)(TPM_PT)(PT_FIXED+24)(TPM_PT)(PT_FIXED+25)(TPM_PT)(PT_FIXED+26)(TPM_PT)(PT_FIXED+27)(TPM_PT)(PT_FIXED+28)(TPM_PT)(PT_FIXED+29)(TPM_PT)(PT_FIXED+30)(TPM_PT)(PT_FIXED+31)(TPM_PT)(PT_FIXED+32)(TPM_PT)(PT_FIXED+33)(TPM_PT)(PT_FIXED+34)(TPM_PT)(PT_FIXED+35)(TPM_PT)(PT_FIXED+36)(TPM_PT)(PT_FIXED+37)(TPM_PT)(PT_FIXED+38)(TPM_PT)(PT_FIXED+39)(TPM_PT)(PT_FIXED+40)(TPM_PT)(PT_FIXED+41)(TPM_PT)(PT_FIXED+42)(TPM_PT)(PT_FIXED+43)(TPM_PT)(PT_FIXED+44)(TPM_PT)(PT_FIXED+45)(TPM_PT)(PT_FIXED+46)(TPM_PT)(PT_GROUP*2)(TPM_PT)(PT_VAR+0)(TPM_PT)(PT_VAR+1)(TPM_PT)(PT_VAR+2)(TPM_PT)(PT_VAR+3)(TPM_PT)(PT_VAR+4)(TPM_PT)(PT_VAR+5)(TPM_PT)(PT_VAR+6)(TPM_PT)(PT_VAR+7)(TPM_PT)(PT_VAR+8)(TPM_PT)(PT_VAR+9)(TPM_PT)(PT_VAR+10)(TPM_PT)(PT_VAR+11)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 159
April 15, 2019

Trusted Platform Module Library
538
539
540
541
542
543
544
545
546

Part 4: Supporting Routines#define TPM_PT_ALGORITHM_SET#define TPM_PT_LOADED_CURVES#define TPM_PT_LOCKOUT_COUNTER#define TPM_PT_MAX_AUTH_FAIL#define TPM_PT_LOCKOUT_INTERVAL#define TPM_PT_LOCKOUT_RECOVERY#define TPM_PT_NV_WRITE_RECOVERY#define TPM_PT_AUDIT_COUNTER_0#define TPM_PT_AUDIT_COUNTER_1(TPM_PT)(PT_VAR+12)(TPM_PT)(PT_VAR+13)(TPM_PT)(PT_VAR+14)(TPM_PT)(PT_VAR+15)(TPM_PT)(PT_VAR+16)(TPM_PT)(PT_VAR+17)(TPM_PT)(PT_VAR+18)(TPM_PT)(PT_VAR+19)(TPM_PT)(PT_VAR+20)

Table 2:24 - Definition of TPM_PT_PCR Constants
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565

typedef UINT32#define TYPE_OF_TPM_PT_PCR#define TPM_PT_PCR_FIRST#define TPM_PT_PCR_SAVE#define TPM_PT_PCR_EXTEND_L0#define TPM_PT_PCR_RESET_L0#define TPM_PT_PCR_EXTEND_L1#define TPM_PT_PCR_RESET_L1#define TPM_PT_PCR_EXTEND_L2#define TPM_PT_PCR_RESET_L2#define TPM_PT_PCR_EXTEND_L3#define TPM_PT_PCR_RESET_L3#define TPM_PT_PCR_EXTEND_L4#define TPM_PT_PCR_RESET_L4#define TPM_PT_PCR_NO_INCREMENT#define TPM_PT_PCR_DRTM_RESET#define TPM_PT_PCR_POLICY#define TPM_PT_PCR_AUTH#define TPM_PT_PCR_LAST

TPM_PT_PCR;
UINT32(TPM_PT_PCR)(0x00000000)(TPM_PT_PCR)(0x00000000)(TPM_PT_PCR)(0x00000001)(TPM_PT_PCR)(0x00000002)(TPM_PT_PCR)(0x00000003)(TPM_PT_PCR)(0x00000004)(TPM_PT_PCR)(0x00000005)(TPM_PT_PCR)(0x00000006)(TPM_PT_PCR)(0x00000007)(TPM_PT_PCR)(0x00000008)(TPM_PT_PCR)(0x00000009)(TPM_PT_PCR)(0x0000000A)(TPM_PT_PCR)(0x00000011)(TPM_PT_PCR)(0x00000012)(TPM_PT_PCR)(0x00000013)(TPM_PT_PCR)(0x00000014)(TPM_PT_PCR)(0x00000014)

Table 2:25 - Definition of TPM_PS Constants
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

typedef UINT32#define TYPE_OF_TPM_PS#define TPM_PS_MAIN#define TPM_PS_PC#define TPM_PS_PDA#define TPM_PS_CELL_PHONE#define TPM_PS_SERVER#define TPM_PS_PERIPHERAL#define TPM_PS_TSS#define TPM_PS_STORAGE#define TPM_PS_AUTHENTICATION#define TPM_PS_EMBEDDED#define TPM_PS_HARDCOPY#define TPM_PS_INFRASTRUCTURE#define TPM_PS_VIRTUALIZATION#define TPM_PS_TNC#define TPM_PS_MULTI_TENANT#define TPM_PS_TC

TPM_PS;UINT32(TPM_PS)(0x00000000)(TPM_PS)(0x00000001)(TPM_PS)(0x00000002)(TPM_PS)(0x00000003)(TPM_PS)(0x00000004)(TPM_PS)(0x00000005)(TPM_PS)(0x00000006)(TPM_PS)(0x00000007)(TPM_PS)(0x00000008)(TPM_PS)(0x00000009)(TPM_PS)(0x0000000A)(TPM_PS)(0x0000000B)(TPM_PS)(0x0000000C)(TPM_PS)(0x0000000D)(TPM_PS)(0x0000000E)(TPM_PS)(0x0000000F)

Table 2:26 - Definition of Types for Handles
584
585

typedef UINT32#define TYPE_OF_TPM_HANDLE

TPM_HANDLE;UINT32

Table 2:27 - Definition of TPM_HT Constants
586
587
588
589

typedef UINT8#define TYPE_OF_TPM_HT#define TPM_HT_PCR#define TPM_HT_NV_INDEX

Page 160
April 15, 2019

TPM_HT;
UINT8(TPM_HT)(0x00)(TPM_HT)(0x01)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
590
591
592
593
594
595
596
597

Trusted Platform Module Library#define TPM_HT_HMAC_SESSION#define TPM_HT_LOADED_SESSION#define TPM_HT_POLICY_SESSION#define TPM_HT_SAVED_SESSION#define TPM_HT_PERMANENT#define TPM_HT_TRANSIENT#define TPM_HT_PERSISTENT#define TPM_HT_AC(TPM_HT)(0x02)(TPM_HT)(0x02)(TPM_HT)(0x03)(TPM_HT)(0x03)(TPM_HT)(0x40)(TPM_HT)(0x80)(TPM_HT)(0x81)(TPM_HT)(0x90)

Table 2:28 - Definition of TPM_RH Constants
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

typedef TPM_HANDLE#define TPM_RH_FIRST#define TPM_RH_SRK#define TPM_RH_OWNER#define TPM_RH_REVOKE#define TPM_RH_TRANSPORT#define TPM_RH_OPERATOR#define TPM_RH_ADMIN#define TPM_RH_EK#define TPM_RH_NULL#define TPM_RH_UNASSIGNED#define TPM_RS_PW#define TPM_RH_LOCKOUT#define TPM_RH_ENDORSEMENT#define TPM_RH_PLATFORM#define TPM_RH_PLATFORM_NV#define TPM_RH_AUTH_00#define TPM_RH_AUTH_FF#define TPM_RH_LAST

TPM_RH;(TPM_RH)(0x40000000)(TPM_RH)(0x40000000)(TPM_RH)(0x40000001)(TPM_RH)(0x40000002)(TPM_RH)(0x40000003)(TPM_RH)(0x40000004)(TPM_RH)(0x40000005)(TPM_RH)(0x40000006)(TPM_RH)(0x40000007)(TPM_RH)(0x40000008)(TPM_RH)(0x40000009)(TPM_RH)(0x4000000A)(TPM_RH)(0x4000000B)(TPM_RH)(0x4000000C)(TPM_RH)(0x4000000D)(TPM_RH)(0x40000010)(TPM_RH)(0x4000010F)(TPM_RH)(0x4000010F)

Table 2:29 - Definition of TPM_HC Constants
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

typedef TPM_HANDLE
TPM_HC;#define HR_HANDLE_MASK(TPM_HC)(0x00FFFFFF)#define HR_RANGE_MASK(TPM_HC)(0xFF000000)#define HR_SHIFT(TPM_HC)(24)#define HR_PCR(TPM_HC)((TPM_HT_PCR<<HR_SHIFT))#define HR_HMAC_SESSION(TPM_HC)((TPM_HT_HMAC_SESSION<<HR_SHIFT))#define HR_POLICY_SESSION(TPM_HC)((TPM_HT_POLICY_SESSION<<HR_SHIFT))#define HR_TRANSIENT(TPM_HC)((TPM_HT_TRANSIENT<<HR_SHIFT))#define HR_PERSISTENT(TPM_HC)((TPM_HT_PERSISTENT<<HR_SHIFT))#define HR_NV_INDEX(TPM_HC)((TPM_HT_NV_INDEX<<HR_SHIFT))#define HR_PERMANENT(TPM_HC)((TPM_HT_PERMANENT<<HR_SHIFT))#define PCR_FIRST(TPM_HC)((HR_PCR+0))#define PCR_LAST(TPM_HC)((PCR_FIRST+IMPLEMENTATION_PCR-1))#define HMAC_SESSION_FIRST(TPM_HC)((HR_HMAC_SESSION+0))#define HMAC_SESSION_LAST(TPM_HC)((HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1))#define LOADED_SESSION_FIRST(TPM_HC)(HMAC_SESSION_FIRST)#define LOADED_SESSION_LAST(TPM_HC)(HMAC_SESSION_LAST)#define POLICY_SESSION_FIRST(TPM_HC)((HR_POLICY_SESSION+0))#define POLICY_SESSION_LAST\(TPM_HC)((POLICY_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1))#define TRANSIENT_FIRST(TPM_HC)((HR_TRANSIENT+0))#define ACTIVE_SESSION_FIRST(TPM_HC)(POLICY_SESSION_FIRST)#define ACTIVE_SESSION_LAST(TPM_HC)(POLICY_SESSION_LAST)#define TRANSIENT_LAST(TPM_HC)((TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1))#define PERSISTENT_FIRST(TPM_HC)((HR_PERSISTENT+0))#define PERSISTENT_LAST(TPM_HC)((PERSISTENT_FIRST+0x00FFFFFF))#define PLATFORM_PERSISTENT(TPM_HC)((PERSISTENT_FIRST+0x00800000))#define NV_INDEX_FIRST(TPM_HC)((HR_NV_INDEX+0))#define NV_INDEX_LAST(TPM_HC)((NV_INDEX_FIRST+0x00FFFFFF))#define PERMANENT_FIRST(TPM_HC)(TPM_RH_FIRST)#define PERMANENT_LAST(TPM_HC)(TPM_RH_LAST)#define HR_NV_AC(TPM_HC)(((TPM_HT_NV_INDEX<<HR_SHIFT)+0xD00000))

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 161
April 15, 2019

Trusted Platform Module Library
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674

Part 4: Supporting Routines#define NV_AC_FIRST(TPM_HC)((HR_NV_AC+0))#define NV_AC_LAST(TPM_HC)((HR_NV_AC+0x0000FFFF))#define HR_AC(TPM_HC)((TPM_HT_AC<<HR_SHIFT))#define AC_FIRST(TPM_HC)((HR_AC+0))#define AC_LAST(TPM_HC)((HR_AC+0x0000FFFF))#define TYPE_OF_TPMA_ALGORITHM UINT32#define TPMA_ALGORITHM_TO_UINT32(a) (*((UINT32 *)&(a)))#define UINT32_TO_TPMA_ALGORITHM(a) (*((TPMA_ALGORITHM *)&(a)))#define TPMA_ALGORITHM_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_ALGORITHM_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_ALGORITHM(i, a){UINT32 x = BYTE_ARRAY_TO_UINT32(a);i = UINT32_TO_TPMA_ALGORITHM(x);}#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_ALGORITHM {// Table 2:30
unsigned
asymmetric: 1;
unsignedsymmetric: 1;
unsignedhash: 1;
unsigned
object: 1;
unsigned
Reserved_bits_at_4: 4;
unsignedsigning: 1;
unsigned
encrypting: 1;
unsigned
method: 1;
unsigned
Reserved_bits_at_11 : 21;} TPMA_ALGORITHM;/* Bits */

\
\
\
\

This is the initializer for a TPMA_ALGORITHM structure
675
676
677
678
679
680

#define TPMA_ALGORITHM_INITIALIZER(
asymmetric, symmetric, hash,signing,
encrypting, method,{asymmetric, symmetric, hash,signing,
encrypting, method,#else // USE_BIT_FIELD_STRUCTURES

\
\
\
\

object,bits_at_4,
bits_at_11)
object,bits_at_4,
bits_at_11}

This implements Table 2:30 TPMA_ALGORITHM using bit masking
681
682
683
684
685
686
687
688
689

typedef UINT32#define TYPE_OF_TPMA_ALGORITHM#define TPMA_ALGORITHM_asymmetric#define TPMA_ALGORITHM_symmetric#define TPMA_ALGORITHM_hash#define TPMA_ALGORITHM_object#define TPMA_ALGORITHM_signing#define TPMA_ALGORITHM_encrypting#define TPMA_ALGORITHM_method

TPMA_ALGORITHM;
UINT32((TPMA_ALGORITHM)1 << 0)((TPMA_ALGORITHM)1 << 1)((TPMA_ALGORITHM)1 << 2)((TPMA_ALGORITHM)1 << 3)((TPMA_ALGORITHM)1 << 8)((TPMA_ALGORITHM)1 << 9)((TPMA_ALGORITHM)1 << 10)This is the initializer for a TPMA_ALGORITHM bit array.
690
691
692
693
694
695
696
697
698
699
700
701
702
703

#define TPMA_ALGORITHM_INITIALIZER(
asymmetric, symmetric, hash,object,bits_at_4,
signing,
encrypting, method,
bits_at_11){(asymmetric << 0) + (symmetric << 1) + (hash << 2)+(object << 3)+ (signing << 8)+ (encrypting << 9) +(method << 10)}#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_OBJECT UINT32#define TPMA_OBJECT_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPMA_OBJECT(a)(*((TPMA_OBJECT *)&(a)))#define TPMA_OBJECT_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_OBJECT_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_OBJECT(i, a){ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_OBJECT(x); }Page 162
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\

\
\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

Trusted Platform Module Library#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_OBJECT {unsigned
Reserved_bit_at_0
unsigned
fixedTPM
unsigned
stClearunsigned
Reserved_bit_at_3
unsigned
fixedParent
unsignedsensitiveDataOrigin
unsigned
userWithAuth
unsigned
adminWithPolicy
unsigned
Reserved_bits_at_8
unsignednoDA
unsigned
encryptedDuplication
unsigned
Reserved_bits_at_12
unsigned
restrictedunsigned
decrypt
unsignedsign
unsignedx509sign
unsigned
Reserved_bits_at_20} TPMA_OBJECT;// Table 2:31
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 2;
: 1;
: 1;
: 4;
: 1;
: 1;
: 1;
: 1;
: 12;
/* Bits */This is the initializer for a TPMA_OBJECT structure
724
725
726
727
728
729
730
731
732
733
734
735
736
737

#define TPMA_OBJECT_INITIALIZER(
bit_at_0,
bit_at_3,
userwithauth,noda,
restricted,
x509sign,{bit_at_0,
bit_at_3,
userwithauth,noda,
restricted,
x509sign,#else // USE_BIT_FIELD_STRUCTURES

fixedtpm,
stclear,fixedparent,
sensitivedataorigin,adminwithpolicy,
bits_at_8,
encryptedduplication, bits_at_12,
decrypt,
sign,
bits_at_20)
fixedtpm,
stclear,fixedparent,
sensitivedataorigin,adminwithpolicy,
bits_at_8,
encryptedduplication, bits_at_12,
decrypt,
sign,
bits_at_20}

\
\
\
\
\
\
\
\
\
\
\
\

This implements Table 2:31 TPMA_OBJECT using bit masking
738
739
740
741
742
743
744
745
746
747
748
749
750
751

typedef UINT32#define TYPE_OF_TPMA_OBJECT#define TPMA_OBJECT_fixedTPM#define TPMA_OBJECT_stClear#define TPMA_OBJECT_fixedParent#define TPMA_OBJECT_sensitiveDataOrigin#define TPMA_OBJECT_userWithAuth#define TPMA_OBJECT_adminWithPolicy#define TPMA_OBJECT_noDA#define TPMA_OBJECT_encryptedDuplication#define TPMA_OBJECT_restricted#define TPMA_OBJECT_decrypt#define TPMA_OBJECT_sign#define TPMA_OBJECT_x509sign

TPMA_OBJECT;UINT32((TPMA_OBJECT)1 << 1)((TPMA_OBJECT)1 << 2)((TPMA_OBJECT)1 << 4)((TPMA_OBJECT)1 << 5)((TPMA_OBJECT)1 << 6)((TPMA_OBJECT)1 << 7)((TPMA_OBJECT)1 << 10)((TPMA_OBJECT)1 << 11)((TPMA_OBJECT)1 << 16)((TPMA_OBJECT)1 << 17)((TPMA_OBJECT)1 << 18)((TPMA_OBJECT)1 << 19)This is the initializer for a TPMA_OBJECT bit array.
752
753
754
755
756
757
758

#define TPMA_OBJECT_INITIALIZER(
bit_at_0,
bit_at_3,
userwithauth,noda,
restricted,
x509sign,

Family “2.0”Level 00 Revision 01.55

fixedtpm,
stclear,fixedparent,
sensitivedataorigin,adminwithpolicy,
bits_at_8,
encryptedduplication, bits_at_12,
decrypt,
sign,
bits_at_20)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\

Page 163
April 15, 2019

Trusted Platform Module Library
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

Part 4: Supporting Routines{(fixedtpm << 1)+ (stclear << 2)+(fixedparent << 4)+ (sensitivedataorigin << 5)+(userwithauth << 6)+ (adminwithpolicy << 7)+(noda << 10)+ (encryptedduplication << 11) +(restricted << 16)+ (decrypt << 17)+(sign << 18)+ (x509sign << 19)}
#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_SESSION
UINT8#define TPMA_SESSION_TO_UINT8(a)(*((UINT8 *)&(a)))#define UINT8_TO_TPMA_SESSION(a)(*((TPMA_SESSION *)&(a)))#define TPMA_SESSION_TO_BYTE_ARRAY(i, a)
UINT8_TO_BYTE_ARRAY((TPMA_SESSION_TO_UINT8(i)), (a))#define BYTE_ARRAY_TO_TPMA_SESSION(i, a){ UINT8 x = BYTE_ARRAY_TO_UINT8(a); i = UINT8_TO_TPMA_SESSION(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_SESSION {// Table 2:32
unsigned
continueSession: 1;
unsigned
auditExclusive: 1;
unsigned
auditReset: 1;
unsigned
Reserved_bits_at_3: 2;
unsigned
decrypt: 1;
unsigned
encrypt: 1;
unsignedaudit: 1;} TPMA_SESSION;/* Bits */

\
\
\
\
\

\
\

This is the initializer for a TPMA_SESSION structure
783
784
785
786
787
788

#define TPMA_SESSION_INITIALIZER(
continuesession, auditexclusive,
decrypt,
encrypt,{continuesession, auditexclusive,
decrypt,
encrypt,#else // USE_BIT_FIELD_STRUCTURES

auditreset,
audit)
auditreset,
audit}\\\\

bits_at_3,
bits_at_3,

This implements Table 2:32 TPMA_SESSION using bit masking
789
790
791
792
793
794
795
796

typedef UINT8#define TYPE_OF_TPMA_SESSION#define TPMA_SESSION_continueSession#define TPMA_SESSION_auditExclusive#define TPMA_SESSION_auditReset#define TPMA_SESSION_decrypt#define TPMA_SESSION_encrypt#define TPMA_SESSION_audit

TPMA_SESSION;UINT8((TPMA_SESSION)1 << 0)((TPMA_SESSION)1 << 1)((TPMA_SESSION)1 << 2)((TPMA_SESSION)1 << 5)((TPMA_SESSION)1 << 6)((TPMA_SESSION)1 << 7)This is the initializer for a TPMA_SESSION bit array.
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813

#define TPMA_SESSION_INITIALIZER(
continuesession, auditexclusive, auditreset,
bits_at_3,
decrypt,
encrypt,
audit){(continuesession << 0) + (auditexclusive << 1) +(auditreset << 2)+ (decrypt << 5)+(encrypt << 6)+ (audit << 7)}#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_LOCALITY
UINT8#define TPMA_LOCALITY_TO_UINT8(a)(*((UINT8 *)&(a)))#define UINT8_TO_TPMA_LOCALITY(a)(*((TPMA_LOCALITY *)&(a)))#define TPMA_LOCALITY_TO_BYTE_ARRAY(i, a)
UINT8_TO_BYTE_ARRAY((TPMA_LOCALITY_TO_UINT8(i)), (a))#define BYTE_ARRAY_TO_TPMA_LOCALITY(i, a){ UINT8 x = BYTE_ARRAY_TO_UINT8(a); i = UINT8_TO_TPMA_LOCALITY(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_LOCALITY {// Table 2:33
unsigned
TPM_LOC_ZERO: 1;

Page 164
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\

\
\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
814
815
816
817
818
819

Trusted Platform Module Library

unsigned
TPM_LOC_ONE
unsigned
TPM_LOC_TWO
unsigned
TPM_LOC_THREE
unsigned
TPM_LOC_FOUR
unsigned
Extended} TPMA_LOCALITY;

: 1;
: 1;
: 1;
: 1;
: 3;
/* Bits */This is the initializer for a TPMA_LOCALITY structure
820
821
822
823
824
825

#define TPMA_LOCALITY_INITIALIZER(
tpm_loc_zero, tpm_loc_one,
tpm_loc_four, extended){tpm_loc_zero, tpm_loc_one,
tpm_loc_four, extended}#else // USE_BIT_FIELD_STRUCTURES

tpm_loc_two,

tpm_loc_three,tpm_loc_two,

tpm_loc_three,

\
\
\
\

This implements Table 2:33 TPMA_LOCALITY using bit masking
826
827
828
829
830
831
832
833
834

typedef UINT8#define TYPE_OF_TPMA_LOCALITY#define TPMA_LOCALITY_TPM_LOC_ZERO#define TPMA_LOCALITY_TPM_LOC_ONE#define TPMA_LOCALITY_TPM_LOC_TWO#define TPMA_LOCALITY_TPM_LOC_THREE#define TPMA_LOCALITY_TPM_LOC_FOUR#define TPMA_LOCALITY_Extended_SHIFT#define TPMA_LOCALITY_Extended

TPMA_LOCALITY;UINT8((TPMA_LOCALITY)1 << 0)((TPMA_LOCALITY)1 << 1)((TPMA_LOCALITY)1 << 2)((TPMA_LOCALITY)1 << 3)((TPMA_LOCALITY)1 << 4)
5((TPMA_LOCALITY)0x7 << 5)This is the initializer for a TPMA_LOCALITY bit array.
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860

#define TPMA_LOCALITY_INITIALIZER(
tpm_loc_zero, tpm_loc_one,
tpm_loc_two,
tpm_loc_three,tpm_loc_four, extended){(tpm_loc_zero << 0) + (tpm_loc_one << 1)+ (tpm_loc_two << 2)(tpm_loc_three << 3) + (tpm_loc_four << 4) + (extended << 5)}#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_PERMANENT UINT32#define TPMA_PERMANENT_TO_UINT32(a) (*((UINT32 *)&(a)))#define UINT32_TO_TPMA_PERMANENT(a) (*((TPMA_PERMANENT *)&(a)))#define TPMA_PERMANENT_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_PERMANENT_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_PERMANENT(i, a){UINT32 x = BYTE_ARRAY_TO_UINT32(a);i = UINT32_TO_TPMA_PERMANENT(x);}#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_PERMANENT {// Table 2:34
unsignedownerAuthSet: 1;
unsignedendorsementAuthSet: 1;
unsigned
lockoutAuthSet: 1;
unsigned
Reserved_bits_at_3: 5;
unsigned
disableClear: 1;
unsigned
inLockout: 1;
unsigned
tpmGeneratedEPS: 1;
unsigned
Reserved_bits_at_11 : 21;} TPMA_PERMANENT;/* Bits */

+

\
\
\
\

\
\
\
\

This is the initializer for a TPMA_PERMANENT structure
861
862
863
864
865

#define TPMA_PERMANENT_INITIALIZER(
ownerauthset,
endorsementauthset, lockoutauthset,
bits_at_3,
disableclear,inlockout,
tpmgeneratedeps,
bits_at_11){ownerauthset,
endorsementauthset, lockoutauthset,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\

Page 165
April 15, 2019

Trusted Platform Module Library
866
867
868

Part 4: Supporting Routines

bits_at_3,
disableclear,tpmgeneratedeps,
bits_at_11}#else // USE_BIT_FIELD_STRUCTURES

inlockout,\

This implements Table 2:34 TPMA_PERMANENT using bit masking
869
870
871
872
873
874
875
876

typedef UINT32#define TYPE_OF_TPMA_PERMANENT#define TPMA_PERMANENT_ownerAuthSet#define TPMA_PERMANENT_endorsementAuthSet#define TPMA_PERMANENT_lockoutAuthSet#define TPMA_PERMANENT_disableClear#define TPMA_PERMANENT_inLockout#define TPMA_PERMANENT_tpmGeneratedEPS

TPMA_PERMANENT;UINT32((TPMA_PERMANENT)1 << 0)((TPMA_PERMANENT)1 << 1)((TPMA_PERMANENT)1 << 2)((TPMA_PERMANENT)1 << 8)((TPMA_PERMANENT)1 << 9)((TPMA_PERMANENT)1 << 10)This is the initializer for a TPMA_PERMANENT bit array.
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902

#define TPMA_PERMANENT_INITIALIZER(
ownerauthset,
endorsementauthset, lockoutauthset,
bits_at_3,
disableclear,inlockout,
tpmgeneratedeps,
bits_at_11){(ownerauthset << 0)+ (endorsementauthset << 1) +(lockoutauthset << 2)+ (disableclear << 8)+(inlockout << 9)+ (tpmgeneratedeps << 10)}#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_STARTUP_CLEAR UINT32#define TPMA_STARTUP_CLEAR_TO_UINT32(a) (*((UINT32 *)&(a)))#define UINT32_TO_TPMA_STARTUP_CLEAR(a) (*((TPMA_STARTUP_CLEAR *)&(a)))#define TPMA_STARTUP_CLEAR_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_STARTUP_CLEAR_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_STARTUP_CLEAR(i, a){UINT32 x = BYTE_ARRAY_TO_UINT32(a);i = UINT32_TO_TPMA_STARTUP_CLEAR(x);}#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_STARTUP_CLEAR {// Table 2:35
unsigned
phEnable: 1;
unsigned
shEnable: 1;
unsigned
ehEnable: 1;
unsigned
phEnableNV: 1;
unsigned
Reserved_bits_at_4: 27;
unsignedorderly: 1;} TPMA_STARTUP_CLEAR;/* Bits */

\
\
\
\
\
\

\
\
\
\

This is the initializer for a TPMA_STARTUP_CLEAR structure
903
904
905
906

#define TPMA_STARTUP_CLEAR_INITIALIZER(
phenable, shenable, ehenable, phenablenv, bits_at_4, orderly){phenable, shenable, ehenable, phenablenv, bits_at_4, orderly}#else // USE_BIT_FIELD_STRUCTURES\\

This implements Table 2:35 TPMA_STARTUP_CLEAR using bit masking
907
908
909
910
911
912
913

typedef UINT32#define TYPE_OF_TPMA_STARTUP_CLEAR#define TPMA_STARTUP_CLEAR_phEnable#define TPMA_STARTUP_CLEAR_shEnable#define TPMA_STARTUP_CLEAR_ehEnable#define TPMA_STARTUP_CLEAR_phEnableNV#define TPMA_STARTUP_CLEAR_orderly

TPMA_STARTUP_CLEAR;UINT32((TPMA_STARTUP_CLEAR)1 << 0)((TPMA_STARTUP_CLEAR)1 << 1)((TPMA_STARTUP_CLEAR)1 << 2)((TPMA_STARTUP_CLEAR)1 << 3)((TPMA_STARTUP_CLEAR)1 << 31)This is the initializer for a TPMA_STARTUP_CLEAR bit array.

Page 166
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932

Trusted Platform Module Library#define TPMA_STARTUP_CLEAR_INITIALIZER(
phenable, shenable, ehenable, phenablenv, bits_at_4, orderly){(phenable << 0)+ (shenable << 1)+ (ehenable << 2)+(phenablenv << 3) + (orderly << 31)}
#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_MEMORY UINT32#define TPMA_MEMORY_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPMA_MEMORY(a)(*((TPMA_MEMORY *)&(a)))#define TPMA_MEMORY_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_MEMORY_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_MEMORY(i, a){ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_MEMORY(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_MEMORY {// Table 2:36
unsignedsharedRAM: 1;
unsignedsharedNV: 1;
unsigned
objectCopiedToRam: 1;
unsigned
Reserved_bits_at_3: 29;} TPMA_MEMORY;/* Bits */

\
\
\

\
\

This is the initializer for a TPMA_MEMORY structure
933
934
935
936

#define TPMA_MEMORY_INITIALIZER(
sharedram, sharednv, objectcopiedtoram, bits_at_3){sharedram, sharednv, objectcopiedtoram, bits_at_3}#else // USE_BIT_FIELD_STRUCTURES\\

This implements Table 2:36 TPMA_MEMORY using bit masking
937
938
939
940
941

typedef UINT32#define TYPE_OF_TPMA_MEMORY#define TPMA_MEMORY_sharedRAM#define TPMA_MEMORY_sharedNV#define TPMA_MEMORY_objectCopiedToRam

TPMA_MEMORY;UINT32((TPMA_MEMORY)1 << 0)((TPMA_MEMORY)1 << 1)((TPMA_MEMORY)1 << 2)This is the initializer for a TPMA_MEMORY bit array.
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964

#define TPMA_MEMORY_INITIALIZER(
sharedram, sharednv, objectcopiedtoram, bits_at_3){(sharedram << 0) + (sharednv << 1) + (objectcopiedtoram << 2)}#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_CC
UINT32#define TPMA_CC_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPMA_CC(a)(*((TPMA_CC *)&(a)))#define TPMA_CC_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_CC_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_CC(i, a){ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_CC(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_CC {// Table 2:37
unsignedcommandIndex: 16;
unsigned
Reserved_bits_at_16 : 6;
unsignednv: 1;
unsigned
extensive: 1;
unsignedflushed: 1;
unsignedcHandles: 3;
unsignedrHandle: 1;
unsignedV: 1;
unsigned
Reserved_bits_at_30 : 2;
} TPMA_CC;/* Bits */

\
\

\
\

This is the initializer for a TPMA_CC structure965#define TPMA_CC_INITIALIZER(

Family “2.0”Level 00 Revision 01.55\

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 167
April 15, 2019

Trusted Platform Module Library
966
967
968
969
970

Part 4: Supporting Routinescommandindex, bits_at_16,
chandles,rhandle,{commandindex, bits_at_16,
chandles,rhandle,#else // USE_BIT_FIELD_STRUCTURES

nv,
v,
nv,
v,

extensive,
bits_at_30)
extensive,
bits_at_30}

flushed,flushed,\\\This implements Table 2:37 TPMA_CC using bit masking
971
972
973
974
975
976
977
978
979
980
981

typedef UINT32#define TYPE_OF_TPMA_CC#define TPMA_CC_commandIndex_SHIFT#define TPMA_CC_commandIndex#define TPMA_CC_nv#define TPMA_CC_extensive#define TPMA_CC_flushed#define TPMA_CC_cHandles_SHIFT#define TPMA_CC_cHandles#define TPMA_CC_rHandle#define TPMA_CC_V

TPMA_CC;UINT320((TPMA_CC)0xffff << 0)((TPMA_CC)1 << 22)((TPMA_CC)1 << 23)((TPMA_CC)1 << 24)
25((TPMA_CC)0x7 << 25)((TPMA_CC)1 << 28)((TPMA_CC)1 << 29)This is the initializer for a TPMA_CC bit array.
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

#define TPMA_CC_INITIALIZER(
commandindex, bits_at_16,
nv,
extensive,
flushed,chandles,rhandle,v,
bits_at_30){(commandindex << 0) + (nv << 22)+ (extensive << 23)+(flushed << 24)+ (chandles << 25)+ (rhandle << 28)+(v << 29)}
#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_MODES UINT32#define TPMA_MODES_TO_UINT32(a) (*((UINT32 *)&(a)))#define UINT32_TO_TPMA_MODES(a) (*((TPMA_MODES *)&(a)))#define TPMA_MODES_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_MODES_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_MODES(i, a){ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_MODES(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_MODES {// Table 2:38
unsigned
FIPS_140_2: 1;
unsigned
Reserved_bits_at_1: 31;} TPMA_MODES;/* Bits */

\
\
\
\
\

\
\

This is the initializer for a TPMA_MODES structure
1001
1002

#define TPMA_MODES_INITIALIZER(fips_140_2, bits_at_1) {fips_140_2, bits_at_1}#else // USE_BIT_FIELD_STRUCTURES

This implements Table 2:38 TPMA_MODES using bit masking
1003
1004
1005

typedef UINT32#define TYPE_OF_TPMA_MODES#define TPMA_MODES_FIPS_140_2

TPMA_MODES;UINT32((TPMA_MODES)1 << 0)This is the initializer for a TPMA_MODES bit array.
1006
1007
1008
1009
1010
1011
1012
1013

#define TPMA_MODES_INITIALIZER(fips_140_2, bits_at_1) {(fips_140_2 << 0)}#endif // USE_BIT_FIELD_STRUCTURES#define TYPE_OF_TPMA_X509_KEY_USAGE UINT32#define TPMA_X509_KEY_USAGE_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPMA_X509_KEY_USAGE(a)(*((TPMA_X509_KEY_USAGE *)&(a)))#define TPMA_X509_KEY_USAGE_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_X509_KEY_USAGE_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_X509_KEY_USAGE(i, a)Page 168
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019\\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029

Trusted Platform Module Library{UINT32 x = BYTE_ARRAY_TO_UINT32(a);i = UINT32_TO_TPMA_X509_KEY_USAGE(x);}#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_X509_KEY_USAGE {unsigned
digitalSignature: 1;
unsignednonrepudiation: 1;
unsigned
keyEncipherment: 1;
unsigned
dataEncipherment: 1;
unsigned
keyAgreement: 1;
unsigned
keyCertSign: 1;
unsigned
crlSign: 1;
unsigned
encipherOnly: 1;
unsigned
decipherOnly: 1;
unsigned
Reserved_bits_at_9: 23;} TPMA_X509_KEY_USAGE;\\// Table 2:39/* Bits */This is the initializer for a TPMA_X509_KEY_USAGE structure
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

#define TPMA_X509_KEY_USAGE_INITIALIZER(
digitalsignature, nonrepudiation,
dataencipherment, keyagreement,
crlsign,
encipheronly,
bits_at_9){digitalsignature, nonrepudiation,
dataencipherment, keyagreement,
crlsign,
encipheronly,
bits_at_9}#else // USE_BIT_FIELD_STRUCTURES

\
\
\
\
\
\
\
\

keyencipherment,
keycertsign,
decipheronly,
keyencipherment,
keycertsign,
decipheronly,This implements Table 2:39 TPMA_X509_KEY_USAGE using bit masking
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

typedef UINT32#define TYPE_OF_TPMA_X509_KEY_USAGE#define TPMA_X509_KEY_USAGE_digitalSignature#define TPMA_X509_KEY_USAGE_nonrepudiation#define TPMA_X509_KEY_USAGE_keyEncipherment#define TPMA_X509_KEY_USAGE_dataEncipherment#define TPMA_X509_KEY_USAGE_keyAgreement#define TPMA_X509_KEY_USAGE_keyCertSign#define TPMA_X509_KEY_USAGE_crlSign#define TPMA_X509_KEY_USAGE_encipherOnly#define TPMA_X509_KEY_USAGE_decipherOnly

TPMA_X509_KEY_USAGE;
UINT32((TPMA_X509_KEY_USAGE)1 << 0)((TPMA_X509_KEY_USAGE)1 << 1)((TPMA_X509_KEY_USAGE)1 << 2)((TPMA_X509_KEY_USAGE)1 << 3)((TPMA_X509_KEY_USAGE)1 << 4)((TPMA_X509_KEY_USAGE)1 << 5)((TPMA_X509_KEY_USAGE)1 << 6)((TPMA_X509_KEY_USAGE)1 << 7)((TPMA_X509_KEY_USAGE)1 << 8)This is the initializer for a TPMA_X509_KEY_USAGE bit array.
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068

#define TPMA_X509_KEY_USAGE_INITIALIZER(
digitalsignature, nonrepudiation,
keyencipherment,
dataencipherment, keyagreement,
keycertsign,
crlsign,
encipheronly,
decipheronly,
bits_at_9){(digitalsignature << 0) + (nonrepudiation << 1)+(keyencipherment << 2) + (dataencipherment << 3) +(keyagreement << 4)+ (keycertsign << 5)+(crlsign << 6)+ (encipheronly << 7)+(decipheronly << 8)}#endif // USE_BIT_FIELD_STRUCTURES
typedef BYTE
TPMI_YES_NO;// Table 2:40
typedef TPM_HANDLE
TPMI_DH_OBJECT;// Table 2:41
typedef TPM_HANDLE
TPMI_DH_PARENT;// Table 2:42
typedef TPM_HANDLE
TPMI_DH_PERSISTENT;// Table 2:43
typedef TPM_HANDLE
TPMI_DH_ENTITY;// Table 2:44
typedef TPM_HANDLE
TPMI_DH_PCR;// Table 2:45
typedef TPM_HANDLE
TPMI_SH_AUTH_SESSION;// Table 2:46

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\
\
\
/* Interface *//* Interface *//* Interface *//* Interface *//* Interface *//* Interface *//* Interface */Page 169
April 15, 2019

Trusted Platform Module Library
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134

Part 4: Supporting Routines

typedef TPM_HANDLE
TPMI_SH_HMAC;// Table 2:47 /* Interface */typedef TPM_HANDLE
TPMI_SH_POLICY;// Table 2:48 /* Interface */typedef TPM_HANDLE
TPMI_DH_CONTEXT;// Table 2:49 /* Interface */typedef TPM_HANDLE
TPMI_DH_SAVED;// Table 2:50 /* Interface */typedef TPM_HANDLE
TPMI_RH_HIERARCHY;// Table 2:51 /* Interface */typedef TPM_HANDLE
TPMI_RH_ENABLES;// Table 2:52 /* Interface */typedef TPM_HANDLE
TPMI_RH_HIERARCHY_AUTH; // Table 2:53 /* Interface */typedef TPM_HANDLE
TPMI_RH_PLATFORM;// Table 2:54 /* Interface */typedef TPM_HANDLE
TPMI_RH_OWNER;// Table 2:55 /* Interface */typedef TPM_HANDLE
TPMI_RH_ENDORSEMENT;// Table 2:56 /* Interface */typedef TPM_HANDLE
TPMI_RH_PROVISION;// Table 2:57 /* Interface */typedef TPM_HANDLE
TPMI_RH_CLEAR;// Table 2:58 /* Interface */typedef TPM_HANDLE
TPMI_RH_NV_AUTH;// Table 2:59 /* Interface */typedef TPM_HANDLE
TPMI_RH_LOCKOUT;// Table 2:60 /* Interface */typedef TPM_HANDLE
TPMI_RH_NV_INDEX;// Table 2:61 /* Interface */typedef TPM_HANDLE
TPMI_RH_AC;// Table 2:62 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_HASH;// Table 2:63 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_ASYM;// Table 2:64 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_SYM;// Table 2:65 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_SYM_OBJECT;// Table 2:66 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_SYM_MODE;// Table 2:67 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_KDF;// Table 2:68 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_SIG_SCHEME;// Table 2:69 /* Interface */typedef TPM_ALG_ID
TPMI_ECC_KEY_EXCHANGE; // Table 2:70 /* Interface */typedef TPM_ST
TPMI_ST_COMMAND_TAG;// Table 2:71 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_MAC_SCHEME;// Table 2:72 /* Interface */typedef TPM_ALG_ID
TPMI_ALG_CIPHER_MODE;// Table 2:73 /* Interface */typedef BYTE
TPMS_EMPTY;// Table 2:74
typedef struct {// Table 2:75
TPM_ALG_ID
alg;
TPMA_ALGORITHM
attributes;} TPMS_ALGORITHM_DESCRIPTION;/* Structure */typedef union {// Table 2:76
#if ALG_SHA1
BYTE
sha1[SHA1_DIGEST_SIZE];#endif // ALG_SHA1#if ALG_SHA256
BYTE
sha256[SHA256_DIGEST_SIZE];#endif // ALG_SHA256#if ALG_SHA384
BYTE
sha384[SHA384_DIGEST_SIZE];#endif // ALG_SHA384#if ALG_SHA512
BYTE
sha512[SHA512_DIGEST_SIZE];#endif // ALG_SHA512#if ALG_SM3_256
BYTE
sm3_256[SM3_256_DIGEST_SIZE];#endif // ALG_SM3_256#if ALG_SHA3_256
BYTE
sha3_256[SHA3_256_DIGEST_SIZE];#endif // ALG_SHA3_256#if ALG_SHA3_384
BYTE
sha3_384[SHA3_384_DIGEST_SIZE];#endif // ALG_SHA3_384#if ALG_SHA3_512
BYTE
sha3_512[SHA3_512_DIGEST_SIZE];#endif // ALG_SHA3_512} TPMU_HA;/* Structure */typedef struct {// Table 2:77
TPMI_ALG_HASH
hashAlg;
TPMU_HA
digest;} TPMT_HA;/* Structure */typedef union {// Table 2:78
struct {UINT16size;
BYTE
buffer[sizeof(TPMU_HA)];

Page 170
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

}
TPM2B
} TPM2B_DIGEST;
typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_DATA;

Trusted Platform Module Libraryt;b;/* Structure */// Table 2:79
size;
buffer[sizeof(TPMT_HA)];t;b;/* Structure */Table 2:80 - Definition of Types for TPM2B_NONCE
1145

typedef TPM2B_DIGESTTPM2B_NONCE;

Table 2:81 - Definition of Types for TPM2B_AUTH
1146

typedef TPM2B_DIGESTTPM2B_AUTH;

Table 2:82 - Definition of Types for TPM2B_OPERAND
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

typedef TPM2B_DIGEST
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_EVENT;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_MAX_BUFFER;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_MAX_NV_BUFFER;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_TIMEOUT;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_IV;
typedef union {TPMT_HA
TPM_HANDLE} TPMU_NAME;
typedef union {struct {UINT16

Family “2.0”Level 00 Revision 01.55

TPM2B_OPERAND;// Table 2:83
size;
buffer[1024];/* Structure */// Table 2:84
size;
buffer[MAX_DIGEST_BUFFER];/* Structure */// Table 2:85
size;
buffer[MAX_NV_BUFFER_SIZE];/* Structure */// Table 2:86
size;
buffer[sizeof(UINT64)];/* Structure */// Table 2:87
size;
buffer[MAX_SYM_BLOCK_SIZE];/* Structure */// Table 2:88
digest;handle;/* Structure */// Table 2:89
size;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 171
April 15, 2019

Trusted Platform Module Library
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255

BYTE
}
t;
TPM2B
b;
} TPM2B_NAME;
typedef struct {
UINT8
BYTE
} TPMS_PCR_SELECT;
typedef struct {TPMI_ALG_HASH
UINT8
BYTE
} TPMS_PCR_SELECTION;
typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_CREATION;
typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_VERIFIED;
typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_AUTH;
typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_HASHCHECK;
typedef struct {TPM_ALG_ID
TPMA_ALGORITHM} TPMS_ALG_PROPERTY;
typedef struct {TPM_PTUINT32} TPMS_TAGGED_PROPERTY;
typedef struct {TPM_PT_PCR
UINT8
BYTE
} TPMS_TAGGED_PCR_SELECT;
typedef struct {TPM_HANDLE
TPMT_HA} TPMS_TAGGED_POLICY;
typedef struct {UINT32
TPM_CC} TPML_CC;
typedef struct {UINT32
TPMA_CC} TPML_CCA;
typedef struct {UINT32
TPM_ALG_ID} TPML_ALG;
typedef struct {UINT32
TPM_HANDLE} TPML_HANDLE;

Page 172
April 15, 2019

Part 4: Supporting Routines
name[sizeof(TPMU_NAME)];/* Structure */// Table 2:90
sizeofSelect;
pcrSelect[PCR_SELECT_MAX];/* Structure */// Table 2:91
hash;sizeofSelect;
pcrSelect[PCR_SELECT_MAX];/* Structure */// Table 2:94
tag;hierarchy;
digest;/* Structure */// Table 2:95
tag;hierarchy;
digest;/* Structure */// Table 2:96
tag;hierarchy;
digest;/* Structure */// Table 2:97
tag;hierarchy;
digest;/* Structure */// Table 2:98
alg;
algProperties;/* Structure */// Table 2:99
property;
value;/* Structure */// Table 2:100
tag;sizeofSelect;
pcrSelect[PCR_SELECT_MAX];/* Structure */// Table 2:101
handle;policyHash;/* Structure */// Table 2:102
count;
commandCodes[MAX_CAP_CC];/* Structure */// Table 2:103
count;
commandAttributes[MAX_CAP_CC];/* Structure */// Table 2:104
count;
algorithms[MAX_ALG_LIST_SIZE];/* Structure */// Table 2:105
count;
handle[MAX_CAP_HANDLES];/* Structure */TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

Trusted Platform Module Library

typedef struct {// Table 2:106
UINT32
count;TPM2B_DIGEST
digests[8];} TPML_DIGEST;/* Structure */typedef struct {// Table 2:107
UINT32
count;
TPMT_HA
digests[HASH_COUNT];} TPML_DIGEST_VALUES;/* Structure */typedef struct {// Table 2:108
UINT32
count;
TPMS_PCR_SELECTION
pcrSelections[HASH_COUNT];} TPML_PCR_SELECTION;/* Structure */typedef struct {// Table 2:109
UINT32
count;
TPMS_ALG_PROPERTY
algProperties[MAX_CAP_ALGS];} TPML_ALG_PROPERTY;/* Structure */typedef struct {// Table 2:110
UINT32
count;
TPMS_TAGGED_PROPERTY
tpmProperty[MAX_TPM_PROPERTIES];} TPML_TAGGED_TPM_PROPERTY;/* Structure */typedef struct {// Table 2:111
UINT32
count;
TPMS_TAGGED_PCR_SELECT
pcrProperty[MAX_PCR_PROPERTIES];} TPML_TAGGED_PCR_PROPERTY;/* Structure */typedef struct {// Table 2:112
UINT32
count;TPM_ECC_CURVE
eccCurves[MAX_ECC_CURVES];} TPML_ECC_CURVE;/* Structure */typedef struct {// Table 2:113
UINT32
count;
TPMS_TAGGED_POLICY
policies[MAX_TAGGED_POLICIES];} TPML_TAGGED_POLICY;/* Structure */typedef union {// Table 2:114
TPML_ALG_PROPERTY
algorithms;
TPML_HANDLE
handles;
TPML_CCA
command;
TPML_CC
ppCommands;
TPML_CC
auditCommands;
TPML_PCR_SELECTION
assignedPCR;
TPML_TAGGED_TPM_PROPERTY
tpmProperties;
TPML_TAGGED_PCR_PROPERTY
pcrProperties;#if ALG_ECC
TPML_ECC_CURVE
eccCurves;#endif // ALG_ECC
TPML_TAGGED_POLICY
authPolicies;} TPMU_CAPABILITIES;/* Structure */typedef struct {// Table 2:115
TPM_CAPcapability;
TPMU_CAPABILITIES
data;} TPMS_CAPABILITY_DATA;/* Structure */typedef struct {// Table 2:116
UINT64clock;UINT32
resetCount;
UINT32
restartCount;
TPMI_YES_NO
safe;} TPMS_CLOCK_INFO;/* Structure */typedef struct {// Table 2:117
UINT64
time;
TPMS_CLOCK_INFO
clockInfo;} TPMS_TIME_INFO;/* Structure */typedef struct {// Table 2:118
TPMS_TIME_INFO
time;
UINT64
firmwareVersion;} TPMS_TIME_ATTEST_INFO;/* Structure */typedef struct {// Table 2:119
TPM2B_NAME
name;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 173
April 15, 2019

Trusted Platform Module Library
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387

Part 4: Supporting Routines

TPM2B_NAME
qualifiedName;} TPMS_CERTIFY_INFO;/* Structure */typedef struct {// Table 2:120
TPML_PCR_SELECTION
pcrSelect;
TPM2B_DIGEST
pcrDigest;} TPMS_QUOTE_INFO;/* Structure */typedef struct {// Table 2:121
UINT64auditCounter;
TPM_ALG_ID
digestAlg;
TPM2B_DIGEST
auditDigest;
TPM2B_DIGEST
commandDigest;} TPMS_COMMAND_AUDIT_INFO;/* Structure */typedef struct {// Table 2:122
TPMI_YES_NO
exclusiveSession;
TPM2B_DIGEST
sessionDigest;} TPMS_SESSION_AUDIT_INFO;/* Structure */typedef struct {// Table 2:123
TPM2B_NAME
objectName;TPM2B_DIGEST
creationHash;} TPMS_CREATION_INFO;/* Structure */typedef struct {// Table 2:124
TPM2B_NAME
indexName;UINT16
offset;TPM2B_MAX_NV_BUFFER
nvContents;} TPMS_NV_CERTIFY_INFO;/* Structure */typedef struct {// Table 2:125
TPM2B_NAME
indexName;TPM2B_DIGEST
nvDigest;} TPMS_NV_DIGEST_CERTIFY_INFO;/* Structure */typedef TPM_ST
TPMI_ST_ATTEST;// Table 2:126 /* Interface */typedef union {// Table 2:127
TPMS_CERTIFY_INFO
certify;
TPMS_CREATION_INFO
creation;
TPMS_QUOTE_INFO
quote;
TPMS_COMMAND_AUDIT_INFO
commandAudit;
TPMS_SESSION_AUDIT_INFO
sessionAudit;
TPMS_TIME_ATTEST_INFO
time;
TPMS_NV_CERTIFY_INFO
nv;
TPMS_NV_DIGEST_CERTIFY_INFO
nvDigest;} TPMU_ATTEST;/* Structure */typedef struct {// Table 2:128
TPM_GENERATED
magic;
TPMI_ST_ATTEST
type;
TPM2B_NAME
qualifiedSigner;
TPM2B_DATA
extraData;
TPMS_CLOCK_INFO
clockInfo;UINT64
firmwareVersion;
TPMU_ATTEST
attested;} TPMS_ATTEST;/* Structure */typedef union {// Table 2:129
struct {UINT16size;
BYTE
attestationData[sizeof(TPMS_ATTEST)];
}
t;
TPM2B
b;
} TPM2B_ATTEST;/* Structure */typedef struct {// Table 2:130
TPMI_SH_AUTH_SESSION
sessionHandle;
TPM2B_NONCE
nonce;
TPMA_SESSION
sessionAttributes;
TPM2B_AUTH
hmac;} TPMS_AUTH_COMMAND;/* Structure */typedef struct {// Table 2:131
TPM2B_NONCE
nonce;
TPMA_SESSION
sessionAttributes;
TPM2B_AUTH
hmac;

Page 174
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

} TPMS_AUTH_RESPONSE;
typedef TPM_KEY_BITS
typedef TPM_KEY_BITS
typedef TPM_KEY_BITS
typedef TPM_KEY_BITS
typedef union {#if ALG_TDES
TPMI_TDES_KEY_BITS#endif // ALG_TDES#if ALG_AES
TPMI_AES_KEY_BITS#endif // ALG_AES#if ALG_SM4
TPMI_SM4_KEY_BITS#endif // ALG_SM4#if ALG_CAMELLIA
TPMI_CAMELLIA_KEY_BITS#endif // ALG_CAMELLIA
TPM_KEY_BITS#if ALG_XOR
TPMI_ALG_HASH#endif // ALG_XOR} TPMU_SYM_KEY_BITS;
typedef union {#if ALG_TDES
TPMI_ALG_SYM_MODE#endif // ALG_TDES#if ALG_AES
TPMI_ALG_SYM_MODE#endif // ALG_AES#if ALG_SM4
TPMI_ALG_SYM_MODE#endif // ALG_SM4#if ALG_CAMELLIA
TPMI_ALG_SYM_MODE#endif // ALG_CAMELLIA
TPMI_ALG_SYM_MODE} TPMU_SYM_MODE;
typedef struct {TPMI_ALG_SYM
TPMU_SYM_KEY_BITS
TPMU_SYM_MODE} TPMT_SYM_DEF;
typedef struct {TPMI_ALG_SYM_OBJECT
TPMU_SYM_KEY_BITS
TPMU_SYM_MODE} TPMT_SYM_DEF_OBJECT;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_SYM_KEY;
typedef struct {TPMT_SYM_DEF_OBJECT} TPMS_SYMCIPHER_PARMS;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_LABEL;
typedef struct {Family “2.0”Level 00 Revision 01.55

Trusted Platform Module Library/* Structure */TPMI_TDES_KEY_BITS;// Table 2:132 /* Interface */TPMI_AES_KEY_BITS;// Table 2:132 /* Interface */TPMI_SM4_KEY_BITS;// Table 2:132 /* Interface */TPMI_CAMELLIA_KEY_BITS; // Table 2:132 /* Interface */// Table 2:133
tdes;
aes;
sm4;
camellia;
sym;
xor;/* Structure */// Table 2:134
tdes;
aes;
sm4;
camellia;sym;/* Structure */// Table 2:136
algorithm;
keyBits;mode;/* Structure */// Table 2:137
algorithm;
keyBits;mode;/* Structure */// Table 2:138
size;
buffer[MAX_SYM_KEY_BYTES];/* Structure */// Table 2:139
sym;/* Structure */// Table 2:140
size;
buffer[LABEL_MAX_BUFFER];/* Structure */// Table 2:141

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 175
April 15, 2019

Trusted Platform Module Library
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490

TPM2B_LABELTPM2B_LABEL} TPMS_DERIVE;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_DERIVE;
typedef union {BYTE
TPMS_DERIVE} TPMU_SENSITIVE_CREATE;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_SENSITIVE_DATA;
typedef struct {TPM2B_AUTH
TPM2B_SENSITIVE_DATA} TPMS_SENSITIVE_CREATE;
typedef struct {UINT16
TPMS_SENSITIVE_CREATE} TPM2B_SENSITIVE_CREATE;
typedef struct {TPMI_ALG_HASH} TPMS_SCHEME_HASH;
typedef struct {TPMI_ALG_HASHUINT16} TPMS_SCHEME_ECDAA;
typedef TPM_ALG_ID

Part 4: Supporting Routines
label;
context;/* Structure */// Table 2:142
size;
buffer[sizeof(TPMS_DERIVE)];/* Structure */// Table 2:143
create[MAX_SYM_DATA];
derive;/* Structure */// Table 2:144
size;
buffer[sizeof(TPMU_SENSITIVE_CREATE)];/* Structure */// Table 2:145
userAuth;data;/* Structure */// Table 2:146
size;
sensitive;/* Structure */// Table 2:147
hashAlg;/* Structure */// Table 2:148
hashAlg;
count;/* Structure */TPMI_ALG_KEYEDHASH_SCHEME;

Table 2:150 - Definition of Types for HMAC_SIG_SCHEME
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507

typedef TPMS_SCHEME_HASH
TPMS_SCHEME_HMAC;
typedef struct {TPMI_ALG_HASH
hashAlg;
TPMI_ALG_KDF
kdf;} TPMS_SCHEME_XOR;
typedef union {#if ALG_HMAC
TPMS_SCHEME_HMAC
hmac;#endif // ALG_HMAC#if ALG_XOR
TPMS_SCHEME_XOR
xor;#endif // ALG_XOR} TPMU_SCHEME_KEYEDHASH;
typedef struct {TPMI_ALG_KEYEDHASH_SCHEME
scheme;
TPMU_SCHEME_KEYEDHASH
details;} TPMT_KEYEDHASH_SCHEME;// Table 2:151/* Structure */// Table 2:152/* Structure */// Table 2:153/* Structure */Table 2:154 - Definition of Types for RSA Signature Schemes
1508
1509

typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH

TPMS_SIG_SCHEME_RSASSA;TPMS_SIG_SCHEME_RSAPSS;

Table 2:155 - Definition of Types for ECC Signature Schemes
Page 176
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

Trusted Platform Module Library

typedef TPMS_SCHEME_HASH
TPMS_SIG_SCHEME_ECDSA;
typedef TPMS_SCHEME_HASH
TPMS_SIG_SCHEME_SM2;
typedef TPMS_SCHEME_HASH
TPMS_SIG_SCHEME_ECSCHNORR;
typedef TPMS_SCHEME_ECDAA
TPMS_SIG_SCHEME_ECDAA;
typedef union {// Table 2:156#if ALG_ECC
TPMS_SIG_SCHEME_ECDAA
ecdaa;#endif // ALG_ECC#if ALG_RSASSA
TPMS_SIG_SCHEME_RSASSA
rsassa;#endif // ALG_RSASSA#if ALG_RSAPSSTPMS_SIG_SCHEME_RSAPSS
rsapss;#endif // ALG_RSAPSS#if ALG_ECDSATPMS_SIG_SCHEME_ECDSA
ecdsa;#endif // ALG_ECDSA#if ALG_SM2
TPMS_SIG_SCHEME_SM2
sm2;#endif // ALG_SM2#if ALG_ECSCHNORR
TPMS_SIG_SCHEME_ECSCHNORR
ecschnorr;#endif // ALG_ECSCHNORR#if ALG_HMAC
TPMS_SCHEME_HMAC
hmac;#endif // ALG_HMAC
TPMS_SCHEME_HASHany;} TPMU_SIG_SCHEME;/* Structure */typedef struct {// Table 2:157
TPMI_ALG_SIG_SCHEME
scheme;
TPMU_SIG_SCHEME
details;} TPMT_SIG_SCHEME;/* Structure */Table 2:158 - Definition of Types for Encryption Schemes
1542
1543

typedef TPMS_SCHEME_HASH
typedef TPMS_EMPTYTPMS_ENC_SCHEME_OAEP;TPMS_ENC_SCHEME_RSAES;

Table 2:159 - Definition of Types for ECC Key Exchange
1544
1545

typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH

TPMS_KEY_SCHEME_ECDH;
TPMS_KEY_SCHEME_ECMQV;

Table 2:160 - Definition of Types for KDF Schemes
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564

typedef TPMS_SCHEME_HASH
TPMS_SCHEME_MGF1;
typedef TPMS_SCHEME_HASH
TPMS_SCHEME_KDF1_SP800_56A;
typedef TPMS_SCHEME_HASH
TPMS_SCHEME_KDF2;
typedef TPMS_SCHEME_HASH
TPMS_SCHEME_KDF1_SP800_108;
typedef union {// Table 2:161#if ALG_MGF1
TPMS_SCHEME_MGF1
mgf1;#endif // ALG_MGF1#if ALG_KDF1_SP800_56A
TPMS_SCHEME_KDF1_SP800_56A
kdf1_sp800_56a;#endif // ALG_KDF1_SP800_56A#if ALG_KDF2
TPMS_SCHEME_KDF2
kdf2;#endif // ALG_KDF2#if ALG_KDF1_SP800_108
TPMS_SCHEME_KDF1_SP800_108
kdf1_sp800_108;#endif // ALG_KDF1_SP800_108} TPMU_KDF_SCHEME;/* Structure */typedef struct {// Table 2:162

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 177
April 15, 2019

Trusted Platform Module Library
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

Part 4: Supporting Routines

TPMI_ALG_KDF
scheme;
TPMU_KDF_SCHEME
details;} TPMT_KDF_SCHEME;/* Structure */typedef TPM_ALG_ID
TPMI_ALG_ASYM_SCHEME;// Table 2:163 /* Interface */typedef union {// Table 2:164#if ALG_ECDH
TPMS_KEY_SCHEME_ECDH
ecdh;#endif // ALG_ECDH#if ALG_ECMQV
TPMS_KEY_SCHEME_ECMQV
ecmqv;#endif // ALG_ECMQV#if ALG_ECC
TPMS_SIG_SCHEME_ECDAA
ecdaa;#endif // ALG_ECC#if ALG_RSASSA
TPMS_SIG_SCHEME_RSASSA
rsassa;#endif // ALG_RSASSA#if ALG_RSAPSSTPMS_SIG_SCHEME_RSAPSS
rsapss;#endif // ALG_RSAPSS#if ALG_ECDSATPMS_SIG_SCHEME_ECDSA
ecdsa;#endif // ALG_ECDSA#if ALG_SM2
TPMS_SIG_SCHEME_SM2
sm2;#endif // ALG_SM2#if ALG_ECSCHNORR
TPMS_SIG_SCHEME_ECSCHNORR
ecschnorr;#endif // ALG_ECSCHNORR#if ALG_RSAESTPMS_ENC_SCHEME_RSAES
rsaes;#endif // ALG_RSAES#if ALG_OAEP
TPMS_ENC_SCHEME_OAEP
oaep;#endif // ALG_OAEP
TPMS_SCHEME_HASH
anySig;} TPMU_ASYM_SCHEME;/* Structure */typedef struct {// Table 2:165
TPMI_ALG_ASYM_SCHEME
scheme;
TPMU_ASYM_SCHEME
details;} TPMT_ASYM_SCHEME;/* Structure */typedef TPM_ALG_ID
TPMI_ALG_RSA_SCHEME;// Table 2:166 /* Interface */typedef struct {// Table 2:167
TPMI_ALG_RSA_SCHEME
scheme;
TPMU_ASYM_SCHEME
details;} TPMT_RSA_SCHEME;/* Structure */typedef TPM_ALG_ID
TPMI_ALG_RSA_DECRYPT;// Table 2:168 /* Interface */typedef struct {// Table 2:169
TPMI_ALG_RSA_DECRYPT
scheme;
TPMU_ASYM_SCHEME
details;} TPMT_RSA_DECRYPT;/* Structure */typedef union {// Table 2:170
struct {UINT16size;
BYTE
buffer[MAX_RSA_KEY_BYTES];
}
t;
TPM2B
b;
} TPM2B_PUBLIC_KEY_RSA;/* Structure */typedef TPM_KEY_BITS
TPMI_RSA_KEY_BITS;// Table 2:171 /* Interface */typedef union {// Table 2:172
struct {UINT16size;
BYTE
buffer[RSA_PRIVATE_SIZE];
}
t;
TPM2B
b;
} TPM2B_PRIVATE_KEY_RSA;/* Structure */Page 178
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668

Trusted Platform Module Library

typedef union {// Table 2:173
struct {UINT16size;
BYTE
buffer[MAX_ECC_KEY_BYTES];
}
t;
TPM2B
b;
} TPM2B_ECC_PARAMETER;/* Structure */typedef struct {// Table 2:174
TPM2B_ECC_PARAMETERx;
TPM2B_ECC_PARAMETERy;} TPMS_ECC_POINT;/* Structure */typedef struct {// Table 2:175
UINT16size;
TPMS_ECC_POINT
point;} TPM2B_ECC_POINT;/* Structure */typedef TPM_ALG_ID
TPMI_ALG_ECC_SCHEME;// Table 2:176 /* Interface */typedef TPM_ECC_CURVE
TPMI_ECC_CURVE;// Table 2:177 /* Interface */typedef struct {// Table 2:178
TPMI_ALG_ECC_SCHEME
scheme;
TPMU_ASYM_SCHEME
details;} TPMT_ECC_SCHEME;/* Structure */typedef struct {// Table 2:179
TPM_ECC_CURVE
curveID;UINT16
keySize;
TPMT_KDF_SCHEME
kdf;
TPMT_ECC_SCHEME
sign;
TPM2B_ECC_PARAMETERp;
TPM2B_ECC_PARAMETERa;
TPM2B_ECC_PARAMETERb;
TPM2B_ECC_PARAMETERgX;
TPM2B_ECC_PARAMETER
gY;
TPM2B_ECC_PARAMETERn;
TPM2B_ECC_PARAMETERh;} TPMS_ALGORITHM_DETAIL_ECC;/* Structure */typedef struct {// Table 2:180
TPMI_ALG_HASHhash;
TPM2B_PUBLIC_KEY_RSA
sig;} TPMS_SIGNATURE_RSA;/* Structure */Table 2:181 - Definition of Types for Signature
1669
1670
1671
1672
1673
1674
1675

typedef TPMS_SIGNATURE_RSA
typedef TPMS_SIGNATURE_RSA
typedef struct {TPMI_ALG_HASH
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER} TPMS_SIGNATURE_ECC;

TPMS_SIGNATURE_RSASSA;TPMS_SIGNATURE_RSAPSS;// Table 2:182
hash;signatureR;
signatureS;/* Structure */Table 2:183 - Definition of Types for TPMS_SIGNATURE_ECC
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689

typedef TPMS_SIGNATURE_ECC
typedef TPMS_SIGNATURE_ECC
typedef TPMS_SIGNATURE_ECC
typedef TPMS_SIGNATURE_ECC
typedef union {#if ALG_ECC
TPMS_SIGNATURE_ECDAA#endif // ALG_ECC#if ALG_RSA
TPMS_SIGNATURE_RSASSA#endif // ALG_RSA#if ALG_RSA
TPMS_SIGNATURE_RSAPSS#endif // ALG_RSA

Family “2.0”Level 00 Revision 01.55

TPMS_SIGNATURE_ECDAA;
TPMS_SIGNATURE_ECDSA;TPMS_SIGNATURE_SM2;
TPMS_SIGNATURE_ECSCHNORR;// Table 2:184
ecdaa;
rsassa;rsapss;TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 179
April 15, 2019

Trusted Platform Module Library
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755

Part 4: Supporting Routines#if ALG_ECC
TPMS_SIGNATURE_ECDSA
ecdsa;#endif // ALG_ECC#if ALG_ECC
TPMS_SIGNATURE_SM2
sm2;#endif // ALG_ECC#if ALG_ECC
TPMS_SIGNATURE_ECSCHNORR
ecschnorr;#endif // ALG_ECC#if ALG_HMAC
TPMT_HA
hmac;#endif // ALG_HMAC
TPMS_SCHEME_HASHany;} TPMU_SIGNATURE;/* Structure */typedef struct {// Table 2:185
TPMI_ALG_SIG_SCHEME
sigAlg;
TPMU_SIGNATURE
signature;} TPMT_SIGNATURE;/* Structure */typedef union {// Table 2:186#if ALG_ECC
BYTE
ecc[sizeof(TPMS_ECC_POINT)];#endif // ALG_ECC#if ALG_RSA
BYTE
rsa[MAX_RSA_KEY_BYTES];#endif // ALG_RSA#if ALG_SYMCIPHER
BYTE
symmetric[sizeof(TPM2B_DIGEST)];#endif // ALG_SYMCIPHER#if ALG_KEYEDHASH
BYTE
keyedHash[sizeof(TPM2B_DIGEST)];#endif // ALG_KEYEDHASH} TPMU_ENCRYPTED_SECRET;/* Structure */typedef union {// Table 2:187
struct {UINT16size;
BYTE
secret[sizeof(TPMU_ENCRYPTED_SECRET)];
}
t;
TPM2B
b;
} TPM2B_ENCRYPTED_SECRET;/* Structure */typedef TPM_ALG_ID
TPMI_ALG_PUBLIC;// Table 2:188 /* Interface */typedef union {// Table 2:189#if ALG_KEYEDHASHTPM2B_DIGEST
keyedHash;#endif // ALG_KEYEDHASH#if ALG_SYMCIPHER
TPM2B_DIGEST
sym;#endif // ALG_SYMCIPHER#if ALG_RSA
TPM2B_PUBLIC_KEY_RSA
rsa;#endif // ALG_RSA#if ALG_ECC
TPMS_ECC_POINT
ecc;#endif // ALG_ECC
TPMS_DERIVE
derive;} TPMU_PUBLIC_ID;/* Structure */typedef struct {// Table 2:190
TPMT_KEYEDHASH_SCHEME
scheme;} TPMS_KEYEDHASH_PARMS;/* Structure */typedef struct {// Table 2:191
TPMT_SYM_DEF_OBJECT
symmetric;
TPMT_ASYM_SCHEME
scheme;} TPMS_ASYM_PARMS;/* Structure */typedef struct {// Table 2:192
TPMT_SYM_DEF_OBJECT
symmetric;
TPMT_RSA_SCHEME
scheme;
TPMI_RSA_KEY_BITS
keyBits;

Page 180
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821

Trusted Platform Module Library

UINT32
exponent;} TPMS_RSA_PARMS;/* Structure */typedef struct {// Table 2:193
TPMT_SYM_DEF_OBJECT
symmetric;
TPMT_ECC_SCHEME
scheme;
TPMI_ECC_CURVE
curveID;
TPMT_KDF_SCHEME
kdf;} TPMS_ECC_PARMS;/* Structure */typedef union {// Table 2:194#if ALG_KEYEDHASH
TPMS_KEYEDHASH_PARMS
keyedHashDetail;#endif // ALG_KEYEDHASH#if ALG_SYMCIPHER
TPMS_SYMCIPHER_PARMS
symDetail;#endif // ALG_SYMCIPHER#if ALG_RSA
TPMS_RSA_PARMS
rsaDetail;#endif // ALG_RSA#if ALG_ECC
TPMS_ECC_PARMS
eccDetail;#endif // ALG_ECC
TPMS_ASYM_PARMS
asymDetail;} TPMU_PUBLIC_PARMS;/* Structure */typedef struct {// Table 2:195
TPMI_ALG_PUBLIC
type;
TPMU_PUBLIC_PARMS
parameters;} TPMT_PUBLIC_PARMS;/* Structure */typedef struct {// Table 2:196
TPMI_ALG_PUBLIC
type;
TPMI_ALG_HASH
nameAlg;
TPMA_OBJECT
objectAttributes;
TPM2B_DIGEST
authPolicy;
TPMU_PUBLIC_PARMS
parameters;
TPMU_PUBLIC_ID
unique;} TPMT_PUBLIC;/* Structure */typedef struct {// Table 2:197
UINT16size;
TPMT_PUBLIC
publicArea;} TPM2B_PUBLIC;/* Structure */typedef union {// Table 2:198
struct {UINT16size;
BYTE
buffer[sizeof(TPMT_PUBLIC)];
}
t;
TPM2B
b;
} TPM2B_TEMPLATE;/* Structure */typedef union {// Table 2:199
struct {UINT16size;
BYTE
buffer[PRIVATE_VENDOR_SPECIFIC_BYTES];
}
t;
TPM2B
b;
} TPM2B_PRIVATE_VENDOR_SPECIFIC;/* Structure */typedef union {// Table 2:200#if ALG_RSA
TPM2B_PRIVATE_KEY_RSA
rsa;#endif // ALG_RSA#if ALG_ECC
TPM2B_ECC_PARAMETER
ecc;#endif // ALG_ECC#if ALG_KEYEDHASHTPM2B_SENSITIVE_DATA
bits;#endif // ALG_KEYEDHASH#if ALG_SYMCIPHER
TPM2B_SYM_KEY
sym;#endif // ALG_SYMCIPHER

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 181
April 15, 2019

Trusted Platform Module Library
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868

Part 4: Supporting Routines

TPM2B_PRIVATE_VENDOR_SPECIFIC
any;} TPMU_SENSITIVE_COMPOSITE;/* Structure */typedef struct {// Table 2:201
TPMI_ALG_PUBLIC
sensitiveType;TPM2B_AUTH
authValue;
TPM2B_DIGEST
seedValue;
TPMU_SENSITIVE_COMPOSITE
sensitive;} TPMT_SENSITIVE;/* Structure */typedef struct {// Table 2:202
UINT16size;
TPMT_SENSITIVE
sensitiveArea;} TPM2B_SENSITIVE;/* Structure */typedef struct {// Table 2:203
TPM2B_DIGEST
integrityOuter;
TPM2B_DIGEST
integrityInner;
TPM2B_SENSITIVE
sensitive;} _PRIVATE;/* Structure */typedef union {// Table 2:204
struct {UINT16size;
BYTE
buffer[sizeof(_PRIVATE)];
}
t;
TPM2B
b;
} TPM2B_PRIVATE;/* Structure */typedef struct {// Table 2:205
TPM2B_DIGEST
integrityHMAC;
TPM2B_DIGEST
encIdentity;} TPMS_ID_OBJECT;/* Structure */typedef union {// Table 2:206
struct {UINT16size;
BYTE
credential[sizeof(TPMS_ID_OBJECT)];
}
t;
TPM2B
b;
} TPM2B_ID_OBJECT;/* Structure */#define TYPE_OF_TPM_NV_INDEXUINT32#define TPM_NV_INDEX_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPM_NV_INDEX(a)(*((TPM_NV_INDEX *)&(a)))#define TPM_NV_INDEX_TO_BYTE_ARRAY(i, a)\
UINT32_TO_BYTE_ARRAY((TPM_NV_INDEX_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPM_NV_INDEX(i, a)\{ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPM_NV_INDEX(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPM_NV_INDEX {// Table 2:207
unsigned
index
: 24;
unsigned
RH_NV: 8;} TPM_NV_INDEX;/* Bits */This is the initializer for a TPM_NV_INDEX structure
1869
1870

#define TPM_NV_INDEX_INITIALIZER(index, rh_nv) {index, rh_nv}#else // USE_BIT_FIELD_STRUCTURES

This implements Table 2:207 TPM_NV_INDEX using bit masking
1871
1872
1873
1874
1875
1876

typedef UINT32#define TYPE_OF_TPM_NV_INDEX#define TPM_NV_INDEX_index_SHIFT#define TPM_NV_INDEX_index#define TPM_NV_INDEX_RH_NV_SHIFT#define TPM_NV_INDEX_RH_NV

TPM_NV_INDEX;UINT320((TPM_NV_INDEX)0xffffff << 0)24((TPM_NV_INDEX)0xff << 24)This is the initializer for a TPM_NV_INDEX bit array.

Page 182
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1877
1878

Trusted Platform Module Library#define TPM_NV_INDEX_INITIALIZER(index, rh_nv) {(index << 0) + (rh_nv << 24)}
#endif // USE_BIT_FIELD_STRUCTURES

Table 2:208 - Definition of TPM_NT Constants
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924

typedef UINT32
TPM_NT;#define TYPE_OF_TPM_NT
UINT32#define TPM_NT_ORDINARY(TPM_NT)(0x0)#define TPM_NT_COUNTER(TPM_NT)(0x1)#define TPM_NT_BITS(TPM_NT)(0x2)#define TPM_NT_EXTEND(TPM_NT)(0x4)#define TPM_NT_PIN_FAIL(TPM_NT)(0x8)#define TPM_NT_PIN_PASS(TPM_NT)(0x9)typedef struct {// Table 2:209
UINT32
pinCount;
UINT32pinLimit;} TPMS_NV_PIN_COUNTER_PARAMETERS;/* Structure */#define TYPE_OF_TPMA_NV
UINT32#define TPMA_NV_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPMA_NV(a)(*((TPMA_NV *)&(a)))#define TPMA_NV_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_NV_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_NV(i, a){ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_NV(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_NV {// Table 2:210
unsigned
PPWRITE: 1;
unsigned
OWNERWRITE: 1;
unsigned
AUTHWRITE: 1;
unsigned
POLICYWRITE: 1;
unsigned
TPM_NT: 4;
unsigned
Reserved_bits_at_8: 2;
unsigned
POLICY_DELETE: 1;
unsigned
WRITELOCKED: 1;
unsigned
WRITEALL: 1;
unsigned
WRITEDEFINE: 1;
unsigned
WRITE_STCLEAR: 1;
unsigned
GLOBALLOCK: 1;
unsigned
PPREAD: 1;
unsigned
OWNERREAD: 1;
unsigned
AUTHREAD: 1;
unsigned
POLICYREAD: 1;
unsigned
Reserved_bits_at_20 : 5;
unsigned
NO_DA: 1;
unsigned
ORDERLY: 1;
unsigned
CLEAR_STCLEAR: 1;
unsigned
READLOCKED: 1;
unsigned
WRITTEN: 1;
unsigned
PLATFORMCREATE: 1;
unsigned
READ_STCLEAR: 1;} TPMA_NV;/* Bits */\\This is the initializer for a TPMA_NV structure
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935

#define TPMA_NV_INITIALIZER(
ppwrite,ownerwrite,
tpm_nt,bits_at_8,
writeall,writedefine,ppread,ownerread,
bits_at_20,
no_da,
readlocked,
written,{ppwrite,ownerwrite,
tpm_nt,bits_at_8,
writeall,writedefine,ppread,ownerread,

Family “2.0”Level 00 Revision 01.55

authwrite,
policywrite,
policy_delete, writelocked,
write_stclear, globallock,authread,policyread,orderly,
clear_stclear,platformcreate, read_stclear)authwrite,
policywrite,
policy_delete, writelocked,
write_stclear, globallock,authread,policyread,

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\
\
\
\
\

Page 183
April 15, 2019

Trusted Platform Module Library
1936
1937
1938

Part 4: Supporting Routines

bits_at_20,
no_da,
readlocked,
written,#else // USE_BIT_FIELD_STRUCTURES

orderly,
clear_stclear,platformcreate, read_stclear}\

This implements Table 2:210 TPMA_NV using bit masking
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963

typedef UINT32#define TYPE_OF_TPMA_NV#define TPMA_NV_PPWRITE#define TPMA_NV_OWNERWRITE#define TPMA_NV_AUTHWRITE#define TPMA_NV_POLICYWRITE#define TPMA_NV_TPM_NT_SHIFT#define TPMA_NV_TPM_NT#define TPMA_NV_POLICY_DELETE#define TPMA_NV_WRITELOCKED#define TPMA_NV_WRITEALL#define TPMA_NV_WRITEDEFINE#define TPMA_NV_WRITE_STCLEAR#define TPMA_NV_GLOBALLOCK#define TPMA_NV_PPREAD#define TPMA_NV_OWNERREAD#define TPMA_NV_AUTHREAD#define TPMA_NV_POLICYREAD#define TPMA_NV_NO_DA#define TPMA_NV_ORDERLY#define TPMA_NV_CLEAR_STCLEAR#define TPMA_NV_READLOCKED#define TPMA_NV_WRITTEN#define TPMA_NV_PLATFORMCREATE#define TPMA_NV_READ_STCLEAR

TPMA_NV;UINT32((TPMA_NV)1 << 0)((TPMA_NV)1 << 1)((TPMA_NV)1 << 2)((TPMA_NV)1 << 3)
4((TPMA_NV)0xf << 4)((TPMA_NV)1 << 10)((TPMA_NV)1 << 11)((TPMA_NV)1 << 12)((TPMA_NV)1 << 13)((TPMA_NV)1 << 14)((TPMA_NV)1 << 15)((TPMA_NV)1 << 16)((TPMA_NV)1 << 17)((TPMA_NV)1 << 18)((TPMA_NV)1 << 19)((TPMA_NV)1 << 25)((TPMA_NV)1 << 26)((TPMA_NV)1 << 27)((TPMA_NV)1 << 28)((TPMA_NV)1 << 29)((TPMA_NV)1 << 30)((TPMA_NV)1 << 31)This is the initializer for a TPMA_NV bit array.
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994

#define TPMA_NV_INITIALIZER(
ppwrite,ownerwrite,
authwrite,
policywrite,
tpm_nt,bits_at_8,
policy_delete, writelocked,
writeall,writedefine,write_stclear, globallock,ppread,ownerread,authread,policyread,
bits_at_20,
no_da,
orderly,
clear_stclear,
readlocked,
written,platformcreate, read_stclear){(ppwrite << 0)+ (ownerwrite << 1)+(authwrite << 2)+ (policywrite << 3)+(tpm_nt << 4)+ (policy_delete << 10) +(writelocked << 11)+ (writeall << 12)+(writedefine << 13)+ (write_stclear << 14) +(globallock << 15)+ (ppread << 16)+(ownerread << 17)+ (authread << 18)+(policyread << 19)+ (no_da << 25)+(orderly << 26)+ (clear_stclear << 27) +(readlocked << 28)+ (written << 29)+(platformcreate << 30) + (read_stclear << 31)}
#endif // USE_BIT_FIELD_STRUCTURES
typedef struct {// Table 2:211
TPMI_RH_NV_INDEX
nvIndex;
TPMI_ALG_HASH
nameAlg;
TPMA_NV
attributes;
TPM2B_DIGEST
authPolicy;
UINT16
dataSize;} TPMS_NV_PUBLIC;/* Structure */typedef struct {// Table 2:212
UINT16size;
TPMS_NV_PUBLIC
nvPublic;} TPM2B_NV_PUBLIC;/* Structure */typedef union {// Table 2:213

Page 184
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030

Trusted Platform Module Librarystruct {UINT16size;
BYTE
buffer[MAX_CONTEXT_SIZE];
}
t;
TPM2B
b;
} TPM2B_CONTEXT_SENSITIVE;/* Structure */typedef struct {// Table 2:214
TPM2B_DIGEST
integrity;
TPM2B_CONTEXT_SENSITIVE
encrypted;} TPMS_CONTEXT_DATA;/* Structure */typedef union {// Table 2:215
struct {UINT16size;
BYTE
buffer[sizeof(TPMS_CONTEXT_DATA)];
}
t;
TPM2B
b;
} TPM2B_CONTEXT_DATA;/* Structure */typedef struct {// Table 2:216
UINT64
sequence;
TPMI_DH_SAVED
savedHandle;
TPMI_RH_HIERARCHY
hierarchy;
TPM2B_CONTEXT_DATA
contextBlob;} TPMS_CONTEXT;/* Structure */typedef struct {// Table 2:218
TPML_PCR_SELECTION
pcrSelect;
TPM2B_DIGEST
pcrDigest;
TPMA_LOCALITY
locality;
TPM_ALG_ID
parentNameAlg;
TPM2B_NAME
parentName;TPM2B_NAME
parentQualifiedName;TPM2B_DATA
outsideInfo;} TPMS_CREATION_DATA;/* Structure */typedef struct {// Table 2:219
UINT16size;
TPMS_CREATION_DATA
creationData;} TPM2B_CREATION_DATA;/* Structure */Table 2:220 - Definition of TPM_AT Constants
2031
2032
2033
2034
2035
2036

typedef UINT32#define TYPE_OF_TPM_AT#define TPM_AT_ANY#define TPM_AT_ERROR#define TPM_AT_PV1#define TPM_AT_VEND

TPM_AT;UINT32(TPM_AT)(0x00000000)(TPM_AT)(0x00000001)(TPM_AT)(0x00000002)(TPM_AT)(0x80000000)

Table 2:221 - Definition of TPM_AE Constants
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048

typedef UINT32#define TYPE_OF_TPM_AE#define TPM_AE_NONE
typedef struct {TPM_ATUINT32} TPMS_AC_OUTPUT;
typedef struct {UINT32
TPMS_AC_OUTPUT} TPML_AC_CAPABILITIES;#endif // _TPM_TYPES_H_

Family “2.0”Level 00 Revision 01.55

TPM_AE;UINT32(TPM_AE)(0x00000000)// Table 2:222
tag;
data;
/* Structure */// Table 2:223
count;
acCapabilities[MAX_AC_CAPABILITIES];/* Structure */TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 185
April 15, 2019

Trusted Platform Module Library

5.22
1
2

Part 4: Supporting Routines

VendorString.h#ifndef#define_VENDOR_STRING_H_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 avendor specific string should be provided here.
3#define

MANUFACTURER"MSFT"

The following #if macro may be deleted after a proper MANUFACTURER is provided.
4
5
6
7
8

#ifndef MANUFACTURER#error MANUFACTURER is not provided. \Please modify include\VendorString.h to provide a specific \manufacturer name.
#endifDefine 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 appropriate.
9
10
11
12

#define#define// #define// #define

VENDOR_STRING_1
VENDOR_STRING_2
VENDOR_STRING_3
VENDOR_STRING_4"xCG ""fTPM"

The following #if macro may be deleted after a proper VENDOR_STRING_1 is provided.
13
14
15
16
17

#ifndef VENDOR_STRING_1#error VENDOR_STRING_1 is not provided. \Please modify include\VendorString.h to provide a vednor-specific \string.
#endifthe 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#defineFIRMWARE_V1(0x20170619)

the less significant 32-bits of a vendor-specific value indicating the version of the firmware
19#defineFIRMWARE_V2(0x00163636)

The following #if macro may be deleted after a proper FIRMWARE_V1 is provided.
20
21
22
23
24
25

#ifndef FIRMWARE_V1#error FIRMWARE_V1 is not provided. \Please modify include\VendorString.h to provide a vendor specific firmware \version#endif#endifPage 186
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

5.23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Trusted Platform Module Libraryswap.h#ifndef _SWAP_H#define _SWAP_H#if LITTLE_ENDIAN_TPM#define TO_BIG_ENDIAN_UINT16(i)#define FROM_BIG_ENDIAN_UINT16(i)#define TO_BIG_ENDIAN_UINT32(i)#define FROM_BIG_ENDIAN_UINT32(i)#define TO_BIG_ENDIAN_UINT64(i)#define FROM_BIG_ENDIAN_UINT64(i)#else#define TO_BIG_ENDIAN_UINT16(i)#define FROM_BIG_ENDIAN_UINT16(i)#define TO_BIG_ENDIAN_UINT32(i)#define FROM_BIG_ENDIAN_UINT32(i)#define TO_BIG_ENDIAN_UINT64(i)#define FROM_BIG_ENDIAN_UINT64(i)#endif#if
AUTO_ALIGN == NO

REVERSE_ENDIAN_16(i)REVERSE_ENDIAN_16(i)REVERSE_ENDIAN_32(i)REVERSE_ENDIAN_32(i)REVERSE_ENDIAN_64(i)REVERSE_ENDIAN_64(i)
(i)
(i)
(i)
(i)
(i)
(i)

The aggregation macros for machines that do not allow unaligned access or for little-endian machines.
Aggregate bytes into an UINT
19
20
21
22
23
24
25
26
27
28

#define BYTE_ARRAY_TO_UINT8(b) (uint8_t)((b)[0])#define BYTE_ARRAY_TO_UINT16(b) ByteArrayToUint16((BYTE *)(b))#define BYTE_ARRAY_TO_UINT32(b) ByteArrayToUint32((BYTE *)(b))#define BYTE_ARRAY_TO_UINT64(b) ByteArrayToUint64((BYTE *)(b))#define UINT8_TO_BYTE_ARRAY(i, b) ((b)[0] = (uint8_t)(i))#define UINT16_TO_BYTE_ARRAY(i, b) Uint16ToByteArray((i), (BYTE *)(b))#define UINT32_TO_BYTE_ARRAY(i, b) Uint32ToByteArray((i), (BYTE *)(b))#define UINT64_TO_BYTE_ARRAY(i, b) Uint64ToByteArray((i), (BYTE *)(b))#else // AUTO_ALIGN#if BIG_ENDIAN_TPM

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

#define BYTE_ARRAY_TO_UINT8(b)#define BYTE_ARRAY_TO_UINT16(b)#define BYTE_ARRAY_TO_UINT32(b)#define BYTE_ARRAY_TO_UINT64(b)*((uint8_t *)(b))*((uint16_t *)(b))*((uint32_t *)(b))*((uint64_t *)(b))

Disaggregate a UINT into a byte array
33
34
35
36
37

#define UINT8_TO_BYTE_ARRAY(i, b)#define UINT16_TO_BYTE_ARRAY(i, b)#define UINT32_TO_BYTE_ARRAY(i, b)#define UINT64_TO_BYTE_ARRAY(i, b)#else{*((uint8_t *)(b)) = (i);}{*((uint16_t *)(b)) = (i);}{*((uint32_t *)(b)) = (i);}{*((uint64_t *)(b)) = (i);}the little endian macros for machines that allow unaligned memory access the big-endian macros formachines that allow unaligned memory access Aggregate a byte array into a UINT
38
39
40
41

#define BYTE_ARRAY_TO_UINT8(b)#define BYTE_ARRAY_TO_UINT16(b)#define BYTE_ARRAY_TO_UINT32(b)#define BYTE_ARRAY_TO_UINT64(b)*((uint8_t *)(b))
REVERSE_ENDIAN_16(*((uint16_t *)(b)))
REVERSE_ENDIAN_32(*((uint32_t *)(b)))
REVERSE_ENDIAN_64(*((uint64_t *)(b)))

Disaggregate a UINT into a byte array42#define UINT8_TO_BYTE_ARRAY(i, b)

Family “2.0”Level 00 Revision 01.55{*((uint8_t*)(b)) = (i);}TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 187
April 15, 2019

Trusted Platform Module Library
43
44
45
46
47
48

Part 4: Supporting Routines#define UINT16_TO_BYTE_ARRAY(i, b)#define UINT32_TO_BYTE_ARRAY(i, b)#define UINT64_TO_BYTE_ARRAY(i, b)#endif// BIG_ENDIAN_TPM#endif // AUTO_ALIGN == NO#endif // _SWAP_H

Page 188
April 15, 2019{*((uint16_t *)(b)) = REVERSE_ENDIAN_16(i);}{*((uint32_t *)(b)) = REVERSE_ENDIAN_32(i);}{*((uint64_t *)(b)) = REVERSE_ENDIAN_64(i);}TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

6

Trusted Platform Module Library

Main

6.1

Introduction

The files in this section are the main processing blocks for the TPM. ExecuteCommand.c contains theentry point into the TPM code and the parsing of the command header. SessionProcess.c handles theparsing of the session area and the authorization checks, and CommandDispatch.c does the parameter
unmarshaling and command dispatch.
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
1
2

Includes#include "Tpm.h"#include "ExecCommand_fp.h"

Uncomment this next #include if doing static command/response buffer sizing3// #include "CommandResponseSizes_fp.h"

6.2.3

ExecuteCommand()The function performs the following steps.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 189
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

Parses the command header from input buffer.
Calls ParseHandleBuffer() to parse the handle area of the command.
Validates that each of the handles references a loaded entity.
Calls ParseSessionBuffer() () to:1) unmarshal and parse the session area;2) check the authorizations; and
3) when necessary, decrypt a parameter.
Calls CommandDispatcher() to:1) unmarshal the command parameters from the command buffer;2) call the routine that performs the command actions; and3) marshal the responses into the response buffer.
If any error occurs in any of the steps above create the error response and return.
Calls BuildResponseSessions() to:1) when necessary, encrypt a parameter2) build the response authorization sessions
3) update the audit sessions and nonces
Calls BuildResponseHeader() to complete the construction of the response.
responseSize is set by the caller to the maximum number of bytes available in the output buffer.
ExecuteCommand() will adjust the value and return the number of bytes placed in the buffer.
response is also set by the caller to indicate the buffer into which ExecuteCommand() is to place theresponse.
request and response may point to the same buffer
NOTE:

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

As of February, 2016, the failure processing has been moved to the platform-specific code. When the TPM
code encounters an unrecoverable failure, it will SET g_inFailureMode and call _plat__Fail(). That function
should not return but may call ExecuteCommand().

LIB_EXPORT void
ExecuteCommand(
uint32_t
unsigned charuint32_t
unsigned char)requestSize,*request,*responseSize,**response// IN: command buffer size// IN: command buffer// IN/OUT: response buffer size// IN/OUT: response buffer{// Command local variables
UINT32
commandSize;
COMMAND
command;// Response local variables
UINT32
maxResponse = *responseSize;
TPM_RC
result;// return code for the command// This next function call is used in development to size the command and response// buffers. The values printed are the sizes of the internal structures and// not the sizes of the canonical forms of the command response structures. Also,// the sizes do not include the tag, command.code, requestSize, or the authorization// fields.
//CommandResponseSizes();// Set flags for NV access state. This should happen before any other// operation that may require a NV write. Note, that this needs to be done

Page 190
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

Trusted Platform Module Library// even when in failure mode. Otherwise, g_updateNV would stay SET while in// Failure mode and the NV would be written on each call.
g_updateNV = UT_NONE;
g_clearOrderly = FALSE;
if(g_inFailureMode){// Do failure mode processing
TpmFailureMode(requestSize, request, responseSize, response);
return;}// Query platform to get the NV state. The result state is saved internally// and will be reported by NvIsAvailable(). The reference code requires that// accessibility of NV does not change during the execution of a command.
// Specifically, if NV is available when the command execution starts and then// is not available later when it is necessary to write to NV, then the TPM// will go into failure mode.
NvCheckState();// Due to the limitations of the simulation, TPM clock must be explicitly// synchronized with the system clock whenever a command is received.
// This function call is not necessary in a hardware TPM. However, taking// a snapshot of the hardware timer at the beginning of the command allows// the time value to be consistent for the duration of the command execution.
TimeUpdateToCurrent();// Any command through this function will unceremoniously end the// _TPM_Hash_Data/_TPM_Hash_End sequence.
if(g_DRTMHandle != TPM_RH_UNASSIGNED)
ObjectTerminateEvent();// Get command buffer size and command buffer.
command.parameterBuffer = request;command.parameterSize = requestSize;// Parse command header: tag, commandSize and command.code.
// First parse the tag. The unmarshaling routine will validate// that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS.
result = TPMI_ST_COMMAND_TAG_Unmarshal(&command.tag,&command.parameterBuffer,&command.parameterSize);if(result != TPM_RC_SUCCESS)
goto Cleanup;// Unmarshal the commandSize indicator.
result = UINT32_Unmarshal(&commandSize,&command.parameterBuffer,&command.parameterSize);if(result != TPM_RC_SUCCESS)
goto Cleanup;// On a TPM that receives bytes on a port, the number of bytes that were// received on that port is requestSize it must be identical to commandSize.
// In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed// by the implementation. The check against MAX_COMMAND_SIZE may be redundant// as the input processing (the function that receives the command bytes and// places them in the input buffer) would likely have the input truncated when// it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize.
if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE){
result = TPM_RC_COMMAND_SIZE;
goto Cleanup;}// Unmarshal the command code.
result = TPM_CC_Unmarshal(&command.code, &command.parameterBuffer,&command.parameterSize);if(result != TPM_RC_SUCCESS)
goto Cleanup;// Check to see if the command is implemented.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 191
April 15, 2019

Trusted Platform Module Library
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Part 4: Supporting Routinescommand.index = CommandCodeToCommandIndex(command.code);if(UNIMPLEMENTED_COMMAND_INDEX == command.index){
result = TPM_RC_COMMAND_CODE;
goto Cleanup;}#if FIELD_UPGRADE_IMPLEMENTED == YES// If the TPM is in FUM, then the only allowed command is// TPM_CC_FieldUpgradeData.
if(IsFieldUgradeMode() && (command.code != TPM_CC_FieldUpgradeData)){
result = TPM_RC_UPGRADE;
goto Cleanup;}else#endif// Excepting FUM, the TPM only accepts TPM2_Startup() after// _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup()// is no longer allowed.
if((!TPMIsStarted() && command.code != TPM_CC_Startup)|| (TPMIsStarted() && command.code == TPM_CC_Startup)){
result = TPM_RC_INITIALIZE;
goto Cleanup;}// Start regular command process.
NvIndexCacheInit();// Parse Handle buffer.
result = ParseHandleBuffer(&command);if(result != TPM_RC_SUCCESS)
goto Cleanup;// All handles in the handle area are required to reference TPM-resident// entities.
result = EntityGetLoadStatus(&command);if(result != TPM_RC_SUCCESS)
goto Cleanup;// Authorization session handling for the command.
ClearCpRpHashes(&command);if(command.tag == TPM_ST_SESSIONS){// Find out session buffer size.
result = UINT32_Unmarshal((UINT32 *)&command.authSize,&command.parameterBuffer,&command.parameterSize);if(result != TPM_RC_SUCCESS)
goto Cleanup;// Perform sanity check on the unmarshaled value. If it is smaller than// the smallest possible session or larger than the remaining size of// the command, then it is an error. NOTE: This check could pass but the// session size could still be wrong. That will be determined after the// sessions are unmarshaled.
if(command.authSize < 9|| command.authSize > command.parameterSize){
result = TPM_RC_SIZE;
goto Cleanup;}command.parameterSize -= command.authSize;// The actions of ParseSessionBuffer() are described in the introduction.
// As the sessions are parsed command.parameterBuffer is advanced so, on a// successful return, command.parameterBuffer should be pointing at the// first byte of the parameters.
result = ParseSessionBuffer(&command);if(result != TPM_RC_SUCCESS)
goto Cleanup;

Page 192
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

Trusted Platform Module Library

}
else
{
command.authSize = 0;// The command has no authorization sessions.
// If the command requires authorizations, then CheckAuthNoSession() will// return an error.
result = CheckAuthNoSession(&command);if(result != TPM_RC_SUCCESS)
goto Cleanup;}// Set up the response buffer pointers. CommandDispatch will marshal the// response parameters starting at the address in command.responseBuffer.
//*response = MemoryGetResponseBuffer(command.index);// leave space for the command header
command.responseBuffer = *response + STD_RESPONSE_HEADER;// leave space for the parameter size field if needed
if(command.tag == TPM_ST_SESSIONS)
command.responseBuffer += sizeof(UINT32);
if(IsHandleInResponse(command.index))command.responseBuffer += sizeof(TPM_HANDLE);// CommandDispatcher returns a response handle buffer and a response parameter// buffer if it succeeds. It will also set the parameterSize field in the// buffer if the tag is TPM_RC_SESSIONS.
result = CommandDispatcher(&command);if(result != TPM_RC_SUCCESS)
goto Cleanup;// Build the session area at the end of the parameter area.
BuildResponseSession(&command);
Cleanup:if(g_clearOrderly == TRUE&& NV_IS_ORDERLY){#if USE_DA_USED
gp.orderlyState = g_daUsed ? SU_DA_USED_VALUE : SU_NONE_VALUE;#else
gp.orderlyState = SU_NONE_VALUE;#endif
NV_SYNC_PERSISTENT(orderlyState);}// This implementation loads an "evict" object to a transient object slot in// RAM whenever an "evict" object handle is used in a command so that the// access to any object is the same. These temporary objects need to be// cleared from RAM whether the command succeeds or fails.
ObjectCleanupEvict();// The parameters and sessions have been marshaled. Now tack on the header and// set the sizes
BuildResponseHeader(&command, *response, result);// Try to commit all the writes to NV if any NV write happened during this// command execution. This check should be made for both succeeded and failed// commands, because a failed one may trigger a NV write in DA logic as well.
// This is the only place in the command execution path that may call the NV// commit. If the NV commit fails, the TPM should be put in failure mode.
if((g_updateNV != UT_NONE) && !g_inFailureMode){if(g_updateNV == UT_ORDERLY)
NvUpdateIndexOrderlyData();if(!NvCommit())
FAIL(FATAL_ERROR_INTERNAL);
g_updateNV = UT_NONE;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 193
April 15, 2019

Trusted Platform Module Library
226
227
228
229
230
231
232
233
234
235
236

Part 4: Supporting Routines}
pAssert((UINT32)command.parameterSize <= maxResponse);// Clear unused bits in response buffer.
MemorySet(*response + *responseSize, 0, maxResponse - *responseSize);// as a final act, and not before, update the response size.
*responseSize = (UINT32)command.parameterSize;
return;}Page 194
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

6.3

Trusted Platform Module Library

CommandDispatcher.c

6.3.1

Introduction

CommandDispatcher() performs the following operations:•

unmarshals command parameters from the input buffer;

NOTE 1•

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.

NOTE 2The output buffer is the return from the MemoryGetResponseBuffer() function. It includes the header, handles,
response parameters, and authorization area. respParmSize is the response parameter size, and does notinclude the header, handles, or authorization area.

NOTE 3

The reference implementation is permitted to do compare operations over a union as a byte array. Therefore,
the command parameter in structure must be initialized (e.g., zeroed) before unmarshaling so that the compare
operation is valid in cases where some bytes are unused.

6.3.1.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Unlike other unmarshaling functions, parmBufferStart does not advance. parmBufferSize Is reduced.

Includes and Typedefs#include "Tpm.h"#if TABLE_DRIVEN_DISPATCH
typedef TPM_RC(NoFlagFunction)(void *target, BYTE **buffer, INT32 *size);
typedef TPM_RC(FlagFunction)(void *target, BYTE **buffer, INT32 *size, BOOL flag);typedef FlagFunction *UNMARSHAL_t;
typedef INT16(MarshalFunction)(void *source, BYTE **buffer, INT32 *size);
typedef MarshalFunction *MARSHAL_t;
typedef TPM_RC(COMMAND_NO_ARGS)(void);
typedef TPM_RC(COMMAND_IN_ARG)(void *in);typedef TPM_RC(COMMAND_OUT_ARG)(void *out);
typedef TPM_RC(COMMAND_INOUT_ARG)(void *in, void *out);
typedef union COMMAND_t{
COMMAND_NO_ARGS*noArgs;
COMMAND_IN_ARG*inArg;COMMAND_OUT_ARG*outArg;
COMMAND_INOUT_ARG*inOutArg;} COMMAND_t;

This structure is used by ParseHandleBuffer() and CommandDispatcher(). The parameters in thisstructure are unique for each command. The parameters are:Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 195
April 15, 2019

Trusted Platform Module Library

19
20
21
22
23
24
25
26

Part 4: Supporting Routinescommandholds the address of the command processing functionthat is called by Command Dispatcher.

inSizethis is the size of the command-dependent input structure. The input
structure holds the unmarshaled handles and command parameters.
If the command takes no arguments (handles or parameters) theninSize will have a value of 0.

outSize

this is the size of the command-dependent output structure. The
output structure holds the results of the command in an unmarshaledform. When command processing is completed, these values aremarshaled into the output buffer. It is always the case that theunmarshaled version of an output structure is larger then themarshaled version. This is because the marshaled version contains
the exact same number of significant bytes but with padding
removed.

typesOffsets

this parameter points to the list of data types that are to be marshaledor unmarshaled. The list of types follows the offsets array. The offsets
array is variable sized so the typesOffset filed is necessary for thehandle and command processing to be able to find the types that are
being handled. The offsets array may be empty. The types structureis described below.

offsets

this is an array of offsets of each of the parameters in the commandor response. When processing the command parameters (nothandles) the list contains the offset of the next parameter. For
example, if the first command parameter has a size of 4 and there isa second command parameter, then the offset would be 4, indicatingthat the second parameter starts at 4. If the second parameter has asize of 8, and there is a third parameter, then the second entry inoffsets is 12 (4 for the first parameter and 8 for the second). An offset
value of 0 in the list indicates the start of the response parameter list.
When CommandDispatcher() hits this value, it will stop unmarshaling
the parameters and call command. If a command has no response
parameters and only one command parameter, then offsets can be
an empty list.

typedef struct COMMAND_DESCRIPTOR_t{
COMMAND_t
command;// Address of the command
UINT16
inSize;// Maximum size of the input structure
UINT16outSize;// Maximum size of the output structure
UINT16
typesOffset;// address of the types field
UINT16
offsets[1];} COMMAND_DESCRIPTOR_t;

The types list is an encoded byte array. The byte value has two parts. The most significant bit is used
when a parameter takes a flag and indicates if the flag should be SET or not. The remaining 7 bits are anindex into an array of addresses of marshaling and unmarshaling functions. The array of functions isdivided into 6 sections with a value assigned to denote the start of that section (and the end of theprevious section). The defined offset values for each section are:Page 196
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library0

unmarshaling for handles that do not take flags

HANDLE_FIRST_FLAG_TYPE

unmarshaling for handles that take flags

PARAMETER_FIRST_TYPE

unmarshaling for parameters that do not take flags

PARAMETER_FIRST_FLAG_TYPE

unmarshaling for parameters that take flags

PARAMETER_LAST_TYPE + 1

marshaling for handles

RESPONSE_PARAMETER_FIRST_TYPE

marshaling for parameters

RESPONSE_PARAMETER_LAST_TYPE

is the last value in the list of marshaling and unmarshaling
functions.

The types list is constructed with a byte of 0xff at the end of the command parameters and with an 0xff at
the end of the response parameters.
27
28
29
30
31
32
33
34
35
36
37
38

#if COMPRESSED_LISTS#
define PAD_LIST 0#else#
define PAD_LIST 1#endif#define _COMMAND_TABLE_DISPATCH_#include "CommandDispatchData.h"#define TEST_COMMAND
TPM_CC_Startup#define NEW_CC#else#include "Commands.h"#endif

6.3.1.2

Marshal/Unmarshal Functions

6.3.1.2.1

ParseHandleBuffer()

This is the table-driven version of the handle buffer unmarshaling code
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

TPM_RC
ParseHandleBuffer(
COMMAND)*command{TPM_RC#if TABLE_DRIVEN_DISPATCH
COMMAND_DESCRIPTOR_t
BYTE
BYTE
BYTE

result;*desc;*types;type;
dtype;// Make sure that nothing strange has happened
pAssert(command->index< sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *));// Get the address of the descriptor for this commanddesc = s_CommandDataArray[command->index];
pAssert(desc != NULL);// Get the associated list of unmarshaling data types.
types = &((BYTE *)desc)[desc->typesOffset];////if(s_ccAttr[commandIndex].commandIndex == TEST_COMMAND)
commandIndex = commandIndex;// No handles yet
command->handleNum = 0;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 197
April 15, 2019

Trusted Platform Module Library
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

Part 4: Supporting Routines// Get the first type value
for(type = *types++;// check each byte to make sure that we have not hit the start// of the parameters(dtype = (type & 0x7F)) < PARAMETER_FIRST_TYPE;// get the next type
type = *types++){// See if unmarshaling of this handle type requires a flagif(dtype < HANDLE_FIRST_FLAG_TYPE){// Look up the function to do the unmarshaling
NoFlagFunction *f = (NoFlagFunction *)UnmarshalArray[dtype];// call it
result = f(&(command->handles[command->handleNum]),&command->parameterBuffer,&command->parameterSize);}else{// Look up the function
FlagFunction*f = UnmarshalArray[dtype];// Call it setting the flag to the appropriate value
result = f(&(command->handles[command->handleNum]),&command->parameterBuffer,&command->parameterSize, (type & 0x80) != 0);}// Got a handle// We do this first so that the match for the handle offset of the// response code works correctly.
command->handleNum += 1;
if(result != TPM_RC_SUCCESS)// if the unmarshaling failed, return the response code with the// handle indication set
return result + TPM_RC_H + (command->handleNum * TPM_RC_1);
}
#else
BYTE
**handleBufferStart = &command->parameterBuffer;
INT32*bufferRemainingSize = &command->parameterSize;
TPM_HANDLE*handles = &command->handles[0];UINT32*handleCount = &command->handleNum;*handleCount = 0;
switch(command->code){#include "HandleProcess.h"#undef handles
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}#endifreturn TPM_RC_SUCCESS;}

6.3.1.2.2

CommandDispatcher()

Function to unmarshal the command parameters, call the selected action code, and marshal the
response parameters.
120
121
122
123

TPM_RC
CommandDispatcher(
COMMAND)

Page 198
April 15, 2019*commandTCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

Trusted Platform Module Library{#if !TABLE_DRIVEN_DISPATCH
TPM_RC
result;BYTE**paramBuffer = &command->parameterBuffer;
INT32*paramBufferSize = &command->parameterSize;
BYTE**responseBuffer = &command->responseBuffer;
INT32*respParmSize = &command->parameterSize;
INT32
rSize;
TPM_HANDLE *handles = &command->handles[0];//command->handleNum = 0;// The command-specific code knows how// many handles there are. This is for// cataloging the number of response// handles
MemoryIoBufferAllocationReset();// Initialize so that allocation will// work properly
switch(GetCommandCode(command->index)){#include "CommandDispatcher.h"default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
Exit:
MemoryIoBufferZero();return result;#else
COMMAND_DESCRIPTOR_t*desc;
BYTE*types;BYTE
type;
UINT16*offsets;
UINT16
offset = 0;
UINT32
maxInSize;
BYTE*commandIn;
INT32
maxOutSize;
BYTE*commandOut;
COMMAND_t
cmd;
TPM_HANDLE*handles;UINT32
hasInParameters = 0;
BOOL
hasOutParameters = FALSE;UINT32
pNum = 0;
BYTE
dType;// dispatch type
TPM_RC
result;//// Get the address of the descriptor for this command
pAssert(command->index< sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *));
desc = s_CommandDataArray[command->index];// Get the list of parameter types for this command
pAssert(desc != NULL);
types = &((BYTE *)desc)[desc->typesOffset];// Get a pointer to the list of parameter offsets
offsets = &desc->offsets[0];// pointer to handles
handles = command->handles;// Get the size required to hold all the unmarshaled parameters for this command
maxInSize = desc->inSize;// and the size of the output parameter structure returned by this commandmaxOutSize = desc->outSize;
MemoryIoBufferAllocationReset();// Get a buffer for the input parameters

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 199
April 15, 2019

Trusted Platform Module Library
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

Part 4: Supporting RoutinescommandIn = MemoryGetInBuffer(maxInSize);// And the output parameters
commandOut = (BYTE *)MemoryGetOutBuffer((UINT32)maxOutSize);// Get the address of the action code dispatch
cmd = desc->command;//// Copy any handles into the input bufferfor(type = *types++; (type & 0x7F) < PARAMETER_FIRST_TYPE; type = *types++){// 'offset' was initialized to zero so the first unmarshaling will always// be to the start of the data structure*(TPM_HANDLE *)&(commandIn[offset]) = *handles++;// This check is used so that we don't have to add an additional offset// value to the offsets list to correspond to the stop value in the// command parameter list.
if(*types != 0xFF)
offset = *offsets++;
maxInSize -= sizeof(TPM_HANDLE);
hasInParameters++;}// Exit loop with type containing the last value read from types// maxInSize has the amount of space remaining in the command action input// buffer. Make sure that we don't have more data to unmarshal than is going to// fit.
// type contains the last value read from types so it is not necessary to// reload it, which is good because *types now points to the next value
for(; (dType = (type & 0x7F)) <= PARAMETER_LAST_TYPE; type = *types++){
pNum++;
if(dType < PARAMETER_FIRST_FLAG_TYPE){
NoFlagFunction*f = (NoFlagFunction *)UnmarshalArray[dType];
result = f(&commandIn[offset], &command->parameterBuffer,&command->parameterSize);}else{
FlagFunction*f = UnmarshalArray[dType];
result = f(&commandIn[offset], &command->parameterBuffer,&command->parameterSize,(type & 0x80) != 0);}if(result != TPM_RC_SUCCESS){
result += TPM_RC_P + (TPM_RC_1 * pNum);goto Exit;}// This check is used so that we don't have to add an additional offset// value to the offsets list to correspond to the stop value in the// command parameter list.
if(*types != 0xFF)
offset = *offsets++;
hasInParameters++;}// Should have used all the bytes in the input
if(command->parameterSize != 0){
result = TPM_RC_SIZE;
goto Exit;}// The command parameter unmarshaling stopped when it hit a value that was out// of range for unmarshaling values and left *types pointing to the first

Page 200
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Trusted Platform Module Library// marshaling type. If that type happens to be the STOP value, then there// are no response parameters. So, set the flag to indicate if there are// output parameters.
hasOutParameters = *types != 0xFF;// There are four cases for calling, with and without input parameters and with// and without output parameters.
if(hasInParameters > 0){if(hasOutParameters)
result = cmd.inOutArg(commandIn, commandOut);else
result = cmd.inArg(commandIn);}else{
if(hasOutParameters)
result = cmd.outArg(commandOut);else
result = cmd.noArgs();}
if(result != TPM_RC_SUCCESS)
goto Exit;// Offset in the marshaled output structure
offset = 0;// Process the return handles, if any
command->handleNum = 0;// Could make this a loop to process output handles but there is only ever// one handle in the outputs (for now).
type = *types++;if((dType = (type & 0x7F)) < RESPONSE_PARAMETER_FIRST_TYPE){// The out->handle value was referenced as TPM_HANDLE in the// action code so it has to be properly aligned.
command->handles[command->handleNum++] =*((TPM_HANDLE *)&(commandOut[offset]));maxOutSize -= sizeof(UINT32);
type = *types++;
offset = *offsets++;}// Use the size of the command action output buffer as the maximum for the// number of bytes that can get marshaled. Since the marshaling code has// no pointers to data, all of the data being returned has to be in the// command action output buffer. If we try to marshal more bytes than// could fit into the output buffer, we need to fail.
for(;(dType = (type & 0x7F)) <= RESPONSE_PARAMETER_LAST_TYPE&& !g_inFailureMode; type = *types++){const MARSHAL_t
f = MarshalArray[dType];command->parameterSize += f(&commandOut[offset], &command->responseBuffer,&maxOutSize);
offset = *offsets++;}
result = (maxOutSize < 0) ? TPM_RC_FAILURE : TPM_RC_SUCCESS;
Exit:
MemoryIoBufferZero();return result;#endif}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 201
April 15, 2019

Trusted Platform Module Library

6.4

SessionProcess.c

6.4.1

Introduction

Part 4: Supporting Routines

This file contains the subsystem that process the authorization sessions including implementation of theDictionary 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
1
2

Includes and Data Definitions#define SESSION_PROCESS_C#include "Tpm.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 isa primary seed handle,
an object with noDA bit SET,an NV Index with TPMA_NV_NO_DA bit SET, ora PCR handle.

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Return Value

Meaning

TRUE(1)

handle is exempted from DA logic

FALSE(0)handle is not exempted from DA logic

BOOL
IsDAExempted(
TPM_HANDLE)

handle// IN: entity handle{
BOOL

result = FALSE;//
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:// All permanent handles, other than TPM_RH_LOCKOUT, are exempt from// DA protection.
result = (handle != TPM_RH_LOCKOUT);
break;// When this function is called, a persistent object will have been loaded// into an object slot and assigned a transient handle.
case TPM_HT_TRANSIENT:{
TPMA_OBJECT
attributes = ObjectGetPublicAttributes(handle);
result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA);
break;}
case TPM_HT_NV_INDEX:{
NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);
result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA);
break;}

Page 202
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
31
32
33
34
35
36
37
38
39

Trusted Platform Module Librarycase TPM_HT_PCR:// PCRs are always exempted from DA.
result = TRUE;
break;
default:
break;}
return result;}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.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

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

static TPM_RC
IncrementLockout(
UINT32)

sessionIndex

TPM_HANDLE
TPM_HANDLESESSIONhandle = s_associatedHandles[sessionIndex];
sessionHandle = s_sessionHandles[sessionIndex];*session = NULL;{//// Don't increment lockout unless the handle associated with the session// is DA protected or the session is bound to a DA protected entity.
if(sessionHandle == TPM_RS_PW){
if(IsDAExempted(handle))
return TPM_RC_BAD_AUTH;}
else{
session = SessionGet(sessionHandle);// If the session is bound to lockout, then use that as the relevant// handle. This means that an authorization failure with a bound session// bound to lockoutAuth will take precedence over any other// lockout checkif(session->attributes.isLockoutBound == SET)
handle = TPM_RH_LOCKOUT;
if(session->attributes.isDaBound == CLEAR&& (IsDAExempted(handle) || session->attributes.includeAuth == CLEAR))// If the handle was changed to TPM_RH_LOCKOUT, this will not return// TPM_RC_BAD_AUTH
return TPM_RC_BAD_AUTH;}
if(handle == TPM_RH_LOCKOUT){
pAssert(gp.lockOutAuthEnabled == TRUE);// lockout is no longer enabled
gp.lockOutAuthEnabled = FALSE;// For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since// the lockout authorization will be reset at startup.
if(gp.lockoutRecovery != 0){

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 203
April 15, 2019

Trusted Platform Module Library
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

Part 4: Supporting Routines

if(NV_IS_AVAILABLE)// Update NV.
NV_SYNC_PERSISTENT(lockOutAuthEnabled);else// No NV access for now. Put the TPM in pending mode.
s_DAPendingOnNV = TRUE;
}
}
else
{
if(gp.recoveryTime != 0){
gp.failedTries++;if(NV_IS_AVAILABLE)// Record changes to NV. NvWrite will SET g_updateNV
NV_SYNC_PERSISTENT(failedTries);
else// No NV access for now. Put the TPM in pending mode.
s_DAPendingOnNV = TRUE;}}// Register a DA failure and reset the timers.
DARegisterFailure(handle);
return TPM_RC_AUTH_FAIL;}

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 acombination of the Name and the authValue of the entity.

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

Return Value

Meaning

TRUE(1)

handle points to the session start entity

FALSE(0)handle does not point to the session start entity

static BOOL
IsSessionBindEntity(
TPM_HANDLESESSION)

associatedHandle,*session// IN: handle to be authorized// IN: associated session

TPM2B_NAME

entity;// The bind value for the entity{//// If the session is not bound, return FALSE.
if(session->attributes.isBound){// Compute the bind value for the entity.
SessionComputeBoundEntity(associatedHandle, &entity);// Compare to the bind value in the session.
return MemoryEqual2B(&entity.b, &session->u1.boundEntity.b);}
return FALSE;}

Page 204
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

6.4.3.4

Trusted Platform Module Library

IsPolicySessionRequired()

Checks if a policy session is required for a command. If a command requires DUP or ADMIN roleauthorization, 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:
the command requires the DUP role,
the command requires the ADMIN role and the authorized entity is an object and its adminWithPolicy
bit is SET, or
the command requires the ADMIN role and the authorized entity is a permanent handle or an NV
Index.
The authorized entity is a PCR belonging to a policy group, and has its policy initialized

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

Return Value

Meaning

TRUE(1)

policy session is required

FALSE(0)policy session is not required

static BOOL
IsPolicySessionRequired(
COMMAND_INDEXUINT32)

commandIndex,
sessionIndex// IN: command index// IN: session index

AUTH_ROLE
TPM_HTrole = CommandAuthRole(commandIndex, sessionIndex);
type = HandleGetType(s_associatedHandles[sessionIndex]);{//if(role == AUTH_DUP)
return TRUE;
if(role == AUTH_ADMIN){// We allow an exception for ADMIN role in a transient object. If the object// allows ADMIN role actions with authorization, then policy is not// required. For all other cases, there is no way to override the command// requirement that a policy be used
if(type == TPM_HT_TRANSIENT){OBJECT*object = HandleToObject(s_associatedHandles[sessionIndex]);if(!IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
adminWithPolicy))
return FALSE;}
return TRUE;}
if(type == TPM_HT_PCR){
if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex])){
TPM2B_DIGEST
policy;TPMI_ALG_HASH
policyAlg;
policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex],&policy);if(policyAlg != TPM_ALG_NULL)
return TRUE;}}
return FALSE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 205
April 15, 2019

Trusted Platform Module Library

6.4.3.5

Part 4: Supporting Routines

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 authValueas IsAuthPolicyAvailable() does (a null authValue is a valid authorization, 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.

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

Return Value

Meaning

TRUE(1)authValue is available

FALSE(0)authValue is not available

static BOOL
IsAuthValueAvailable(
TPM_HANDLE
COMMAND_INDEXUINT32)handle,commandIndex,
sessionIndex

BOOL

result = FALSE;// IN: handle of entity// IN: command index// IN: session index{//
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:
switch(handle){// At this point hierarchy availability has already been// checked so primary seed handles are always available herecase TPM_RH_OWNER:
case TPM_RH_ENDORSEMENT:
case TPM_RH_PLATFORM:#ifdef VENDOR_PERMANENT// This vendor defined handle associated with the// manufacturer's shared secretcase VENDOR_PERMANENT:#endif// The DA checking has been performed on LockoutAuth but we// bypass the DA logic if we are using lockout policy. The// policy would allow execution to continue an lockoutAuth// could be used, even if direct use of lockoutAuth is disabledcase TPM_RH_LOCKOUT:// NullAuth is always available.
case TPM_RH_NULL:
result = TRUE;
break;
default:// Otherwise authValue is not available.
break;}
break;
case TPM_HT_TRANSIENT:// A persistent object has already been loaded and the internal// handle changed.
{
OBJECT*object;
TPMA_OBJECT
attributes;//
object = HandleToObject(handle);
attributes = object->publicArea.objectAttributes;

Page 206
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

Trusted Platform Module Library// authValue is always available for a sequence object.
// An alternative for this is to// SET_ATTRIBUTE(object->publicArea, TPMA_OBJECT, userWithAuth) when the// sequence is started.
if(ObjectIsSequence(object)){result = TRUE;
break;}// authValue is available for an object if it has its sensitive// portion loaded and// 1. userWithAuth bit is SET, or// 2. ADMIN role is required
if(object->attributes.publicOnly == CLEAR&& (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth)|| (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, adminWithPolicy))))result = TRUE;}
break;
case TPM_HT_NV_INDEX:// NV Index.
{
NV_REF
locator;
NV_INDEX*nvIndex = NvGetIndexInfo(handle, &locator);
TPMA_NV
nvAttributes;//
pAssert(nvIndex != 0);
nvAttributes = nvIndex->publicArea.attributes;
if(IsWriteOperation(commandIndex)){// AuthWrite can't be set for a PIN index
if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE))
result = TRUE;}
else{// A "read" operation// For a PIN Index, the authValue is available as long as the// Index has been written and the pinCount is less than pinLimit
if(IsNvPinFailIndex(nvAttributes)|| IsNvPinPassIndex(nvAttributes)){
NV_PINpin;
if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
break; // return false// get the index values
pin.intVal = NvGetUINT64Data(nvIndex, locator);
if(pin.pin.pinCount < pin.pin.pinLimit)
result = TRUE;}// For non-PIN Indexes, need to allow use of the authValueelse if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD))
result = TRUE;}}
break;
case TPM_HT_PCR:// PCR handle.
// authValue is always allowed for PCR
result = TRUE;
break;
default:// Otherwise, authValue is not available

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 207
April 15, 2019

Trusted Platform Module Library
283
284
285
286

Part 4: Supporting Routines

break;}
return result;}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.

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

Return Value

Meaning

TRUE(1)

authPolicy is available

FALSE(0)authPolicy is not available

static BOOL
IsAuthPolicyAvailable(
TPM_HANDLE
COMMAND_INDEXUINT32)handle,commandIndex,
sessionIndex

BOOL

result = FALSE;// IN: handle of entity// IN: command index// IN: session index{//
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:
switch(handle){// At this point hierarchy availability has already been checked.
case TPM_RH_OWNER:
if(gp.ownerPolicy.t.size != 0)
result = TRUE;
break;
case TPM_RH_ENDORSEMENT:
if(gp.endorsementPolicy.t.size != 0)
result = TRUE;
break;
case TPM_RH_PLATFORM:
if(gc.platformPolicy.t.size != 0)
result = TRUE;
break;
case TPM_RH_LOCKOUT:
if(gp.lockoutPolicy.t.size != 0)
result = TRUE;
break;
default:
break;}
break;
case TPM_HT_TRANSIENT:{// Object handle.
// An evict object would already have been loaded and given a// transient object handle by this point.
OBJECT *object = HandleToObject(handle);// Policy authorization is not available for an object with only// public portion loaded.
if(object->attributes.publicOnly == CLEAR){// Policy authorization is always available for an object but

Page 208
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

// is never available for a sequence.
if(!ObjectIsSequence(object))result = TRUE;}
break;}
case TPM_HT_NV_INDEX:// An NV Index.
{
NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);
TPMA_NV
nvAttributes = nvIndex->publicArea.attributes;//// If the policy size is not zero, check if policy can be used.
if(nvIndex->publicArea.authPolicy.t.size != 0){// If policy session is required for this handle, always// uses policy regardless of the attributes bit setting
if(IsPolicySessionRequired(commandIndex, sessionIndex))
result = TRUE;// Otherwise, the presence of the policy depends on the NV// attributes.
else if(IsWriteOperation(commandIndex)){if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE))
result = TRUE;}
else{
if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD))
result = TRUE;}}}
break;
case TPM_HT_PCR:// PCR handle.
if(PCRPolicyIsAvailable(handle))
result = TRUE;
break;
default:
break;}
return result;}

6.4.4
6.4.4.1
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

Trusted Platform Module Library

Session Parsing Functions
ClearCpRpHashes()

void
ClearCpRpHashes(
COMMAND)*command{#if ALG_SHA1
command->sha1CpHash.t.size = 0;command->sha1RpHash.t.size = 0;
#endif#if ALG_SHA256
command->sha256CpHash.t.size = 0;command->sha256RpHash.t.size = 0;
#endif#if ALG_SHA384
command->sha384CpHash.t.size = 0;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 209
April 15, 2019

Trusted Platform Module Library
392
393
394
395
396
397
398
399
400
401
402

Part 4: Supporting Routinescommand->sha384RpHash.t.size = 0;
#endif#if ALG_SHA512
command->sha512CpHash.t.size = 0;command->sha512RpHash.t.size = 0;
#endif#if ALG_SM3_256
command->sm3_256CpHash.t.size = 0;command->sm3_256RpHash.t.size = 0;
#endif}

6.4.4.2

GetCpHashPointer()

Function to get a pointer to the cpHash of the command
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443

static TPM2B_DIGEST *GetCpHashPointer(
COMMAND
TPMI_ALG_HASH)*command,hashAlg

TPM2B_DIGEST*retVal;{//switch(hashAlg){#if ALG_SHA1
case ALG_SHA1_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha1CpHash;
break;#endif#if ALG_SHA256
case ALG_SHA256_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha256CpHash;
break;#endif#if ALG_SHA384
case ALG_SHA384_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha384CpHash;
break;#endif#if ALG_SHA512
case ALG_SHA512_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha512CpHash;
break;#endif#if ALG_SM3_256
case ALG_SM3_256_VALUE:
retVal = (TPM2B_DIGEST *)&command->sm3_256CpHash;
break;#endifdefault:
retVal = NULL;
break;}
return retVal;}

6.4.4.3

GetRpHashPointer()

Function to get a pointer to the RpHash() of the command
444

static TPM2B_DIGEST *Page 210
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

Trusted Platform Module Library

GetRpHashPointer(
COMMAND
TPMI_ALG_HASH)*command,hashAlg

TPM2B_DIGEST*retVal;{//switch(hashAlg){#if ALG_SHA1
case ALG_SHA1_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha1RpHash;
break;#endif#if ALG_SHA256
case ALG_SHA256_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha256RpHash;
break;#endif#if ALG_SHA384
case ALG_SHA384_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha384RpHash;
break;#endif#if ALG_SHA512
case ALG_SHA512_VALUE:
retVal = (TPM2B_DIGEST *)&command->sha512RpHash;
break;#endif#if ALG_SM3_256
case ALG_SM3_256_VALUE:
retVal = (TPM2B_DIGEST *)&command->sm3_256RpHash;
break;#endifdefault:
retVal = NULL;
break;}
return retVal;}

6.4.4.4

ComputeCpHash()This function computes the cpHash as defined in Part 2 and described in Part 1.
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503

static TPM2B_DIGEST *ComputeCpHash(
COMMAND
TPMI_ALG_HASH)*command,hashAlg// IN: command parsing structure// IN: hash algorithm{
UINT32
HASH_STATETPM2B_NAME
TPM2B_DIGESTi;hashState;
name;*cpHash;//// cpHash = hash(commandCode [ || authName1//[ || authName2//[ || authName 3 ]]]//[ || parameters])// A cpHash can contain just a commandCode only if the lone session is// an audit session.
// Get pointer to the hash value
cpHash = GetCpHashPointer(command, hashAlg);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 211
April 15, 2019

Trusted Platform Module Library
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

Part 4: Supporting Routines

if(cpHash->t.size == 0){
cpHash->t.size = CryptHashStart(&hashState, hashAlg);// Add commandCode.
CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);// Add authNames for each of the handles.
for(i = 0; i < command->handleNum; i++)
CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],&name)->b);// Add the parameters.
CryptDigestUpdate(&hashState, command->parameterSize,
command->parameterBuffer);// Complete the hash.
CryptHashEnd2B(&hashState, &cpHash->b);}
return cpHash;}

6.4.4.5

GetCpHash()This function is used to access a precomputed cpHash.
521
522
523
524
525
526
527
528
529
530
531

static TPM2B_DIGEST *GetCpHash(
COMMAND
TPMI_ALG_HASH)*command,hashAlg{
TPM2B_DIGEST*cpHash = GetCpHashPointer(command, hashAlg);//
pAssert(cpHash->t.size != 0);
return cpHash;}

6.4.4.6

CompareTemplateHash()This function computes the template hash and compares it to the session templateHash. It is the hash of
the second parameter assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or
TPM2_CreateLoaded()

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

Return Value

Meaning

TRUE(1)

template hash equal to session->templateHash

FALSE(0)template hash not equal to session->templateHash

static BOOL
CompareTemplateHash(
COMMANDSESSION)*command,*session// IN: parsing structure// IN: session data

{
BYTE
INT32
TPM2B_DIGESTUINT16*pBuffer = command->parameterBuffer;
pSize = command->parameterSize;tHash;size;//// Only try this for the three commands for which it is intended
if(command->code != TPM_CC_Create&& command->code != TPM_CC_CreatePrimary#if CC_CreateLoaded&& command->code != TPM_CC_CreateLoaded#endifPage 212
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

Trusted Platform Module Library)
return FALSE;// Assume that the first parameter is a TPM2B and unmarshal the size field// Note: this will not affect the parameter buffer and size in the calling// function.
if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
return FALSE;// reduce the space in the buffer.
// NOTE: this could make pSize go negative if the parameters are not correct but// the unmarshaling code does not try to unmarshal if the remaining size is// negative.
pSize -= size;// Advance the pointerpBuffer += size;// Get the size of what should be the templateif(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
return FALSE;// See if this is reasonableif(size > pSize)
return FALSE;// Hash the template datatHash.t.size = CryptHashBlock(session->authHashAlg, size, pBuffer,sizeof(tHash.t.buffer), tHash.t.buffer);
return(MemoryEqual2B(&session->u1.templateHash.b, &tHash.b));}6.4.4.7

CompareNameHash()This function computes the name hash and compares it to the nameHash in the session data.
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

BOOL
CompareNameHash(
COMMANDSESSION)*command,*session// IN: main parsing structure// IN: session structure with nameHash{
HASH_STATETPM2B_DIGESTUINT32TPM2B_NAME

hashState;
nameHash;
i;
name;

//
nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg);// Add names.
for(i = 0; i < command->handleNum; i++)
CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],&name)->b);// Complete hash.
CryptHashEnd2B(&hashState, &nameHash.b);// and compare
return MemoryEqual(session->u1.nameHash.t.buffer, nameHash.t.buffer,
nameHash.t.size);}

6.4.4.8

CheckPWAuthSession()

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

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 213
April 15, 2019

Trusted Platform Module Library

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

Part 4: Supporting Routines

Error Returns

Meaning

TPM_RC_AUTH_FAIL

authorization fails and increments DA failure count

TPM_RC_BAD_AUTH

authorization fails but DA does not apply

static TPM_RC
CheckPWAuthSession(
UINT32)

sessionIndex// IN: index of session to be processed

TPM2B_AUTH
TPM_HANDLE

authValue;associatedHandle = s_associatedHandles[sessionIndex];{//// Strip trailing zeros from the password.
MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]);// Get the authValue with trailing zeros removed
EntityGetAuthValue(associatedHandle, &authValue);// Success if the values are identical.
if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b)){
return TPM_RC_SUCCESS;}else// if the digests are not identical{// Invoke DA protection if applicable.
return IncrementLockout(sessionIndex);}}

6.4.4.9

ComputeCommandHMAC()

This function computes the HMAC for an authorization session in a command.
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

static TPM2B_DIGEST *ComputeCommandHMAC(
COMMANDUINT32TPM2B_DIGEST)*command,sessionIndex,*hmac// IN: primary control structure// IN: index of session to be processed// OUT: authorization HMAC{
TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));TPM2B_KEY
key;
BYTE
marshalBuffer[sizeof(TPMA_SESSION)];
BYTE*buffer;
UINT32marshalSize;
HMAC_STATE
hmacState;
TPM2B_NONCE*nonceDecrypt;
TPM2B_NONCE*nonceEncrypt;
SESSION*session;//
nonceDecrypt = NULL;
nonceEncrypt = NULL;// Determine if extra nonceTPM values are going to be required.
// If this is the first session (sessionIndex = 0) and it is an authorization// session that uses an HMAC, then check if additional session nonces are to be// included.
if(sessionIndex == 0&& s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED){// If there is a decrypt session and if this is not the decrypt session,

Page 214
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716

Trusted Platform Module Library// then an extra nonce may be needed.
if(s_decryptSessionIndex != UNDEFINED_INDEX&& s_decryptSessionIndex != sessionIndex){// Will add the nonce for the decrypt session.
SESSION *decryptSession= SessionGet(s_sessionHandles[s_decryptSessionIndex]);nonceDecrypt = &decryptSession->nonceTPM;}// Now repeat for the encrypt session.
if(s_encryptSessionIndex != UNDEFINED_INDEX&& s_encryptSessionIndex != sessionIndex&& s_encryptSessionIndex != s_decryptSessionIndex){// Have to have the nonce for the encrypt session.
SESSION *encryptSession= SessionGet(s_sessionHandles[s_encryptSessionIndex]);nonceEncrypt = &encryptSession->nonceTPM;}}// Continue with the HMAC processing.
session = SessionGet(s_sessionHandles[sessionIndex]);// Generate HMAC key.
MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));// Check if the session has an associated handle and if the associated entity// is the one to which the session is bound. If not, add the authValue of// this entity to the HMAC key.
// If the session is bound to the object or the session is a policy session// with no authValue required, do not include the authValue in the HMAC key.
// Note: For a policy session, its isBound attribute is CLEARED.
//// Include the entity authValue if it is needed
if(session->attributes.includeAuth == SET){TPM2B_AUTH
authValue;// Get the entity authValue with trailing zeros removed
EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);// add the authValue to the HMAC key
MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));}// if the HMAC key size is 0, a NULL string HMAC is allowed
if(key.t.size == 0&& s_inputAuthValues[sessionIndex].t.size == 0){
hmac->t.size = 0;
return hmac;}// Start HMAC
hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);// Add cpHash
CryptDigestUpdate2B(&hmacState.hashState,&ComputeCpHash(command, session->authHashAlg)->b);// Add nonces as required
CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);
CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);if(nonceDecrypt != NULL)
CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b);if(nonceEncrypt != NULL)
CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b);// Add sessionAttributes
buffer = marshalBuffer;marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]),

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 215
April 15, 2019

Trusted Platform Module Library
717
718
719
720
721
722
723

Part 4: Supporting Routines&buffer, NULL);
CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);// Complete the HMAC computation
CryptHmacEnd2B(&hmacState, &hmac->b);
return hmac;}

6.4.4.10

CheckSessionHMAC()

This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute theexpected 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.

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744

Error Returns

Meaning

TPM_RC_AUTH_FAIL

authorization failure caused failureCount increment

TPM_RC_BAD_AUTH

authorization failure did not cause failureCount increment

static TPM_RC
CheckSessionHMAC(
COMMANDUINT32)*command,sessionIndex// IN: primary control structure// IN: index of session to be processed{
TPM2B_DIGEST

hmac;// authHMAC for comparing//// Compute authHMAC
ComputeCommandHMAC(command, sessionIndex, &hmac);// Compare the input HMAC with the authHMAC computed above.
if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b)){// If an HMAC session has a failure, invoke the anti-hammering// if it applies to the authorized entity or the session.
// Otherwise, just indicate that the authorization is bad.
return IncrementLockout(sessionIndex);}
return TPM_RC_SUCCESS;}

6.4.4.11

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:compare policyDigest in session with authPolicy associated with the entity to be authorized;
compare timeout if applicable;compare commandCode if applicable;compare cpHash if applicable; andsee if PCR values have changed since computed.
If all the above checks succeed, the handle is authorized. The order of these comparisons is notimportant because any failure will result in the same error code.

Page 216
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

Trusted Platform Module Library

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

static TPM_RC
CheckPolicyAuthSession(
COMMANDUINT32)*command,sessionIndex// IN: primary parsing structure// IN: index of session to be processed{
SESSIONTPM2B_DIGESTTPMI_ALG_HASH
UINT8*session;
authPolicy;
policyAlg;
locality;//// Initialize pointer to the authorization session.
session = SessionGet(s_sessionHandles[sessionIndex]);// If the command is TPM2_PolicySecret(), make sure that// either password or authValue is required
if(command->code == TPM_CC_PolicySecret&& session->attributes.isPasswordNeeded == CLEAR&& session->attributes.isAuthValueNeeded == CLEAR)
return TPM_RC_MODE;// See if the PCR counter for the session is still valid.
if(!SessionPCRValueIsCurrent(session))
return TPM_RC_PCR_CHANGED;// Get authPolicy.
policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex],&authPolicy);// Compare authPolicy.
if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b))
return TPM_RC_POLICY_FAIL;// Policy is OK so check if the other factors are correct// Compare policy hash algorithm.
if(policyAlg != session->authHashAlg)
return TPM_RC_POLICY_FAIL;// Compare timeout.
if(session->timeout != 0){// Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE// or TPM_RC_NV_RATE error may be returned here. This doesn't mean that// a new nonce will be created just that, because TPM time can't advance// we can't do time-based operations.
RETURN_IF_NV_IS_NOT_AVAILABLE;if((session->timeout < g_time)|| (session->epoch != g_timeEpoch))return TPM_RC_EXPIRED;}// If command code is provided it must match

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 217
April 15, 2019

Trusted Platform Module Library
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859

Part 4: Supporting Routines

if(session->commandCode != 0){
if(session->commandCode != command->code)
return TPM_RC_POLICY_CC;}
else{// If command requires a DUP or ADMIN authorization, the session must have// command code set.
AUTH_ROLE
role = CommandAuthRole(command->index, sessionIndex);
if(role == AUTH_ADMIN || role == AUTH_DUP)
return TPM_RC_POLICY_FAIL;}// Check command locality.
{
BYTE
sessionLocality[sizeof(TPMA_LOCALITY)];
BYTE*buffer = sessionLocality;// Get existing locality setting in canonical form
sessionLocality[0] = 0;
TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);// See if the locality has been set
if(sessionLocality[0] != 0){// If so, get the current locality
locality = _plat__LocalityGet();if(locality < 5){if(((sessionLocality[0] & (1 << locality)) == 0)|| sessionLocality[0] > 31)
return TPM_RC_LOCALITY;}
else if(locality > 31){
if(sessionLocality[0] != locality)
return TPM_RC_LOCALITY;}
else{// Could throw an assert here but a locality error is just// as good. It just means that, whatever the locality is, it isn't// the locality requested so...
return TPM_RC_LOCALITY;}}} // end of locality check// Check physical presence.
if(session->attributes.isPPRequired == SET&& !_plat__PhysicalPresenceAsserted())
return TPM_RC_PP;// Compare cpHash/nameHash if defined, or if the command requires an ADMIN or// DUP role for this handle.
if(session->u1.cpHash.b.size != 0)
{
BOOL
OK;
if(session->attributes.isCpHashDefined)// Compare cpHash.
OK = MemoryEqual2B(&session->u1.cpHash.b,&ComputeCpHash(command, session->authHashAlg)->b);else if(session->attributes.isTemplateSet)
OK = CompareTemplateHash(command, session);else
OK = CompareNameHash(command, session);if(!OK)
return TPM_RCS_POLICY_FAIL;

Page 218
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878

Trusted Platform Module Library}if(session->attributes.checkNvWritten){
NV_REF
locator;
NV_INDEX*nvIndex;//// If this is not an NV index, the policy makes no sense so fail it.
if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX)
return TPM_RC_POLICY_FAIL;// Get the index data
nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator);// Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired stateif((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))!= (session->attributes.nvWrittenState == SET))
return TPM_RC_POLICY_FAIL;}
return TPM_RC_SUCCESS;}

6.4.4.12

RetrieveSessionData()

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

879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910

Error Returns

Meaning

TPM_RC_SUCCSS

unmarshaled without error

TPM_RC_SIZE

the number of bytes unmarshaled is not the same as the value forauthorizationSize in the command

static TPM_RC
RetrieveSessionData(
COMMAND)*command// IN: main parsing structure for commandint
TPM_RCSESSION
TPMA_SESSION
TPM_HT
INT32
TPM_RCi;
result;*session;sessionAttributes;
sessionType;sessionIndex;
errorIndex;{//
s_decryptSessionIndex = UNDEFINED_INDEX;
s_encryptSessionIndex = UNDEFINED_INDEX;
s_auditSessionIndex = UNDEFINED_INDEX;
for(sessionIndex = 0; command->authSize > 0; sessionIndex++){errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];// If maximum allowed number of sessions has been parsed, return a size// error with a session number that is larger than the number of allowed// sessions
if(sessionIndex == MAX_SESSION_NUM)
return TPM_RCS_SIZE + errorIndex;// make sure that the associated handle for each session starts out// unassigned
s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;// First parameter: Session handle.
result = TPMI_SH_AUTH_SESSION_Unmarshal(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 219
April 15, 2019

Trusted Platform Module Library
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

Part 4: Supporting Routines&s_sessionHandles[sessionIndex],&command->parameterBuffer,&command->authSize, TRUE);
if(result != TPM_RC_SUCCESS)
return result + TPM_RC_S + g_rcIndex[sessionIndex];// Second parameter: Nonce.
result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex],&command->parameterBuffer,&command->authSize);if(result != TPM_RC_SUCCESS)
return result + TPM_RC_S + g_rcIndex[sessionIndex];// Third parameter: sessionAttributes.
result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex],&command->parameterBuffer,&command->authSize);if(result != TPM_RC_SUCCESS)
return result + TPM_RC_S + g_rcIndex[sessionIndex];// Fourth parameter: authValue (PW or HMAC).
result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex],&command->parameterBuffer,&command->authSize);if(result != TPM_RC_SUCCESS)
return result + errorIndex;
sessionAttributes = s_attributes[sessionIndex];
if(s_sessionHandles[sessionIndex] == TPM_RS_PW){// A PWAP session needs additional processing.
//
Can't have any attributes set other than continueSession bit
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)|| IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset))
return TPM_RCS_ATTRIBUTES + errorIndex;//
The nonce size must be zero.
if(s_nonceCaller[sessionIndex].t.size != 0)
return TPM_RCS_NONCE + errorIndex;
continue;}// For not password sessions...
// Find out if the session is loaded.
if(!SessionIsLoaded(s_sessionHandles[sessionIndex]))return TPM_RC_REFERENCE_S0 + sessionIndex;
sessionType = HandleGetType(s_sessionHandles[sessionIndex]);session = SessionGet(s_sessionHandles[sessionIndex]);// Check if the session is an HMAC/policy session.
if((session->attributes.isPolicy == SET&& sessionType == TPM_HT_HMAC_SESSION)|| (session->attributes.isPolicy == CLEAR&& sessionType == TPM_HT_POLICY_SESSION))
return TPM_RCS_HANDLE + errorIndex;// Check that this handle has not previously been used.
for(i = 0; i < sessionIndex; i++){if(s_sessionHandles[i] == s_sessionHandles[sessionIndex])
return TPM_RCS_HANDLE + errorIndex;}// If the session is used for parameter encryption or audit as well, set// the corresponding Indexes.
// First process decrypt.
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)){// Check if the commandCode allows command parameter encryption.

Page 220
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035

Trusted Platform Module Libraryif(DecryptSize(command->index) == 0)
return TPM_RCS_ATTRIBUTES + errorIndex;// Encrypt attribute can only appear in one session
if(s_decryptSessionIndex != UNDEFINED_INDEX)
return TPM_RCS_ATTRIBUTES + errorIndex;// Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL
if(session->symmetric.algorithm == TPM_ALG_NULL)
return TPM_RCS_SYMMETRIC + errorIndex;// All checks passed, so set the index for the session used to decrypt// a command parameter.
s_decryptSessionIndex = sessionIndex;}// Now process encrypt.
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)){// Check if the commandCode allows response parameter encryption.
if(EncryptSize(command->index) == 0)
return TPM_RCS_ATTRIBUTES + errorIndex;// Encrypt attribute can only appear in one session.
if(s_encryptSessionIndex != UNDEFINED_INDEX)
return TPM_RCS_ATTRIBUTES + errorIndex;// Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL
if(session->symmetric.algorithm == TPM_ALG_NULL)
return TPM_RCS_SYMMETRIC + errorIndex;// All checks passed, so set the index for the session used to encrypt// a response parameter.
s_encryptSessionIndex = sessionIndex;}// At last process audit.
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)){// Audit attribute can only appear in one session.
if(s_auditSessionIndex != UNDEFINED_INDEX)
return TPM_RCS_ATTRIBUTES + errorIndex;// An audit session can not be policy session.
if(HandleGetType(s_sessionHandles[sessionIndex])== TPM_HT_POLICY_SESSION)
return TPM_RCS_ATTRIBUTES + errorIndex;// If this is a reset of the audit session, or the first use// of the session as an audit session, it doesn't matter what// the exclusive state is. The session will become exclusive.
if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)&& session->attributes.isAudit == SET){// Not first use or reset. If auditExlusive is SET, then this// session must be the current exclusive session.
if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)&& g_exclusiveAuditSession != s_sessionHandles[sessionIndex])
return TPM_RC_EXCLUSIVE;}
s_auditSessionIndex = sessionIndex;}// Initialize associated handle as undefined. This will be changed when// the handles are processed.
s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;}
command->sessionNum = sessionIndex;
return TPM_RC_SUCCESS;}

6.4.4.13

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
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 221
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

pending. Otherwise the TPM is locked out if checking for lockoutAuth (lockoutAuthCheck == TRUE) anduse of lockoutAuth is disabled, or failedTries >= maxTries

1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

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

static TPM_RC
CheckLockedOut(
BOOL)

lockoutAuthCheck// IN: TRUE if checking is for lockoutAuth{// If NV is unavailable, and current cycle state recorded in NV is not// SU_NONE_VALUE, refuse to check any authorization because we would// not be able to handle a DA failure.
if(!NV_IS_AVAILABLE && NV_IS_ORDERLY)
return g_NvStatus;// Check if DA info needs to be updated in NV.
if(s_DAPendingOnNV){// If NV is accessible,
RETURN_IF_NV_IS_NOT_AVAILABLE;// ... write the pending DA data and proceed.
NV_SYNC_PERSISTENT(lockOutAuthEnabled);
NV_SYNC_PERSISTENT(failedTries);
s_DAPendingOnNV = FALSE;}// Lockout is in effect if checking for lockoutAuth and use of lockoutAuth// is disabled...
if(lockoutAuthCheck){if(gp.lockOutAuthEnabled == FALSE)
return TPM_RC_LOCKOUT;}
else{// ... or if the number of failed tries has been maxed out.
if(gp.failedTries >= gp.maxTries)
return TPM_RC_LOCKOUT;#if USE_DA_USED// If the daUsed flag is not SET, then no DA validation until the// daUsed state is written to NV
if(!g_daUsed){
RETURN_IF_NV_IS_NOT_AVAILABLE;
g_daUsed = TRUE;
gp.orderlyState = SU_DA_USED_VALUE;
NV_SYNC_PERSISTENT(orderlyState);
return TPM_RC_RETRY;}#endif}return TPM_RC_SUCCESS;}

6.4.4.14

CheckAuthSession()

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

Page 222
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

Trusted Platform Module Library

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 apolicy session)

TPM_RC_BAD_AUTH

HMAC or PW authorization failed without DA side-effects (can be apolicy 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

static TPM_RC
CheckAuthSession(
COMMANDUINT32)*command,sessionIndex// IN: primary parsing structure// IN: index of session to be processed

TPM_RCSESSIONTPM_HANDLE
TPM_HANDLE
TPM_HT

result = TPM_RC_SUCCESS;*session = NULL;
sessionHandle = s_sessionHandles[sessionIndex];
associatedHandle = s_associatedHandles[sessionIndex];
sessionHandleType = HandleGetType(sessionHandle);{//
pAssert(sessionHandle != TPM_RH_UNASSIGNED);// Take care of physical presenceif(associatedHandle == TPM_RH_PLATFORM){// If the physical presence is required for this command, check for PP// assertion. If it isn't asserted, no point going any further.
if(PhysicalPresenceIsRequired(command->index)&& !_plat__PhysicalPresenceAsserted())
return TPM_RC_PP;}
if(sessionHandle != TPM_RS_PW){
session = SessionGet(sessionHandle);// Set includeAuth to indicate if DA checking will be required and if the// authValue will be included in any HMAC.
if(sessionHandleType == TPM_HT_POLICY_SESSION){// For a policy session, will check the DA status of the entity if either// isAuthValueNeeded or isPasswordNeeded is SET.
session->attributes.includeAuth =session->attributes.isAuthValueNeeded|| session->attributes.isPasswordNeeded;}else{// For an HMAC session, need to check unless the session// is bound.
session->attributes.includeAuth =!IsSessionBindEntity(s_associatedHandles[sessionIndex], session);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 223
April 15, 2019

Trusted Platform Module Library
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

Part 4: Supporting Routines}// If the authorization session is going to use an authValue, then make sure// that access to that authValue isn't locked out.
// Note: session == NULL for a PW session.
if(session == NULL || session->attributes.includeAuth){// See if entity is subject to lockout.
if(!IsDAExempted(associatedHandle)){// See if in lockout
result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT);
if(result != TPM_RC_SUCCESS)
return result;}}// Policy or HMAC+PW?
if(sessionHandleType != TPM_HT_POLICY_SESSION){// for non-policy session make sure that a policy session is not required
if(IsPolicySessionRequired(command->index, sessionIndex))
return TPM_RC_AUTH_TYPE;// The authValue must be available.
// Note: The authValue is going to be "used" even if it is an EmptyAuth.
// and the session is bound.
if(!IsAuthValueAvailable(associatedHandle, command->index, sessionIndex))
return TPM_RC_AUTH_UNAVAILABLE;}
else{// ... see if the entity has a policy, ...
// Note: IsAuthPolicyAvalable will return FALSE if the sensitive area of the// object is not loaded
if(!IsAuthPolicyAvailable(associatedHandle, command->index, sessionIndex))
return TPM_RC_AUTH_UNAVAILABLE;// ... and check the policy session.
result = CheckPolicyAuthSession(command, sessionIndex);
if(result != TPM_RC_SUCCESS)
return result;}// Check authorization according to the typeif(session == NULL || session->attributes.isPasswordNeeded == SET)
result = CheckPWAuthSession(sessionIndex);else
result = CheckSessionHMAC(command, sessionIndex);// Do processing for PIN Indexes are only three possibilities for 'result' at// this point: TPM_RC_SUCCESS, TPM_RC_AUTH_FAIL, and TPM_RC_BAD_AUTH.
// For all these cases, we would have to process a PIN index if the// authValue of the index was used for authorization.
// See if we need to do anything to a PIN index
if(TPM_HT_NV_INDEX == HandleGetType(associatedHandle)){
NV_REF
locator;
NV_INDEX*nvIndex = NvGetIndexInfo(associatedHandle, &locator);
NV_PIN
pinData;
TPMA_NV
nvAttributes;//
pAssert(nvIndex != NULL);
nvAttributes = nvIndex->publicArea.attributes;// If this is a PIN FAIL index and the value has been written// then we can update the counter (increment or clear)if(IsNvPinFailIndex(nvAttributes)&& IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)){
pinData.intVal = NvGetUINT64Data(nvIndex, locator);
if(result != TPM_RC_SUCCESS)
pinData.pin.pinCount++;

Page 224
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215

Trusted Platform Module Libraryelse
pinData.pin.pinCount = 0;
NvWriteUINT64Data(nvIndex, pinData.intVal);}// If this is a PIN PASS Index, increment if we have used the// authorization value for anything other than NV_Read.
// NOTE: If the counter has already hit the limit, then we// would not get here because the authorization value would not// be available and the TPM would have returned before it gets here
else if(IsNvPinPassIndex(nvAttributes)&& IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)&& result == TPM_RC_SUCCESS){// If the access is valid, then increment the use counter
pinData.intVal = NvGetUINT64Data(nvIndex, locator);
pinData.pin.pinCount++;
NvWriteUINT64Data(nvIndex, pinData.intVal);}}
return result;}#ifdef

TPM_CC_GetCommandAuditDigest

6.4.4.15

CheckCommandAudit()

This function is called before the command is processed if audit is enabled for the command. It will checkto see if the audit can be performed and will ensure that the cpHash is available for the audit.

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234

Error Returns

Meaning

TPM_RC_NV_UNAVAILABLE

NV is not available for write

TPM_RC_NV_RATE

NV is rate limiting

static TPM_RC
CheckCommandAudit(
COMMAND)*command{// If the audit digest is clear and command audit is required, NV must be// available so that TPM2_GetCommandAuditDigest() is able to increment// audit counter. If NV is not available, the function bails out to prevent// the TPM from attempting an operation that would fail anyway.
if(gr.commandAuditDigest.t.size == 0|| GetCommandCode(command->index) == TPM_CC_GetCommandAuditDigest){
RETURN_IF_NV_IS_NOT_AVAILABLE;}// Make sure that the cpHash is computed for the algorithm
ComputeCpHash(command, gp.auditHashAlg);
return TPM_RC_SUCCESS;}#endif

6.4.4.16

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 andpasses the information of encryption sessions to parameter encryption module.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 225
April 15, 2019

Trusted Platform Module Library

1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295

Part 4: Supporting Routines

Error Returns

Meaningvariousparsing failure or authorization failure

TPM_RC
ParseSessionBuffer(
COMMAND)*command// IN: the structure that contains{
TPM_RCUINT32
INT32
TPM2B_AUTHUINT32
TPM_RCSESSION

result;i;size = 0;
extraKey;sessionIndex;
errorIndex;*session = NULL;//// Check if a command allows any session in its session area.
if(!IsSessionAllowed(command->index))
return TPM_RC_AUTH_CONTEXT;// Default-initialization.
command->sessionNum = 0;
result = RetrieveSessionData(command);if(result != TPM_RC_SUCCESS)
return result;// There is no command in the TPM spec that has more handles than// MAX_SESSION_NUM.
pAssert(command->handleNum <= MAX_SESSION_NUM);// Associate the session with an authorization handle.
for(i = 0; i < command->handleNum; i++){if(CommandAuthRole(command->index, i) != AUTH_NONE){// If the received session number is less than the number of handles// that requires authorization, an error should be returned.
// Note: for all the TPM 2.0 commands, handles requiring// authorization come first in a command input and there are only ever// two values requiring authorization
if(i > (command->sessionNum - 1))
return TPM_RC_AUTH_MISSING;// Record the handle associated with the authorization session
s_associatedHandles[i] = command->handles[i];}}// Consistency checks are done first to avoid authorization failure when the// command will not be executed anyway.
for(sessionIndex = 0; sessionIndex < command->sessionNum; sessionIndex++){errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];// PW session must be an authorization session
if(s_sessionHandles[sessionIndex] == TPM_RS_PW){
if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED)
return TPM_RCS_HANDLE + errorIndex;// a password session can't be audit, encrypt or decryptif(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)|| IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)|| IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
return TPM_RCS_ATTRIBUTES + errorIndex;
session = NULL;
}
else
{

Page 226
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361

Trusted Platform Module Librarysession = SessionGet(s_sessionHandles[sessionIndex]);// A trial session can not appear in session area, because it cannot// be used for authorization, audit or encrypt/decrypt.
if(session->attributes.isTrialPolicy == SET)
return TPM_RCS_ATTRIBUTES + errorIndex;// See if the session is bound to a DA protected entity// NOTE: Since a policy session is never bound, a policy is still// usable even if the object is DA protected and the TPM is in// lockout.
if(session->attributes.isDaBound == SET){
result = CheckLockedOut(session->attributes.isLockoutBound == SET);
if(result != TPM_RC_SUCCESS)
return result;}// If this session is for auditing, make sure the cpHash is computed.
if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit))
ComputeCpHash(command, session->authHashAlg);}// if the session has an associated handle, check the authorizationif(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED){
result = CheckAuthSession(command, sessionIndex);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, errorIndex);}else{// a session that is not for authorization must either be encrypt,// decrypt, or audit
if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)&& !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)&& !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
return TPM_RCS_ATTRIBUTES + errorIndex;// no authValue included in any of the HMAC computations
pAssert(session != NULL);
session->attributes.includeAuth = CLEAR;// check HMAC for encrypt/decrypt/audit only sessions
result = CheckSessionHMAC(command, sessionIndex);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, errorIndex);}}#ifdef TPM_CC_GetCommandAuditDigest// Check if the command should be audited. Need to do this before any parameter// encryption so that the cpHash for the audit is correctif(CommandAuditIsRequired(command->index)){
result = CheckCommandAudit(command);if(result != TPM_RC_SUCCESS)
return result;// No session number to reference}#endif// Decrypt the first parameter if applicable. This should be the last operation// in session processing.
// If the encrypt session is associated with a handle and the handle's// authValue is available, then authValue is concatenated with sessionKey to// generate encryption key, no matter if the handle is the session bound entity// or not.
if(s_decryptSessionIndex != UNDEFINED_INDEX){

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 227
April 15, 2019

Trusted Platform Module Library
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385

Part 4: Supporting Routines// If this is an authorization session, include the authValue in the// generation of the decryption key
if(s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED){
EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex],&extraKey);}else{
extraKey.b.size = 0;}
size = DecryptSize(command->index);
result = CryptParameterDecryption(s_sessionHandles[s_decryptSessionIndex],&s_nonceCaller[s_decryptSessionIndex].b,
command->parameterSize, (UINT16)size,&extraKey,
command->parameterBuffer);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result,
TPM_RC_S + g_rcIndex[s_decryptSessionIndex]);}return TPM_RC_SUCCESS;}

6.4.4.17

CheckAuthNoSession()

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

1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

Error Returns

Meaning

TPM_RC_AUTH_MISSING

failure - one or more handles require authorization

TPM_RC
CheckAuthNoSession(
COMMAND)*command// IN: command parsing structure{
UINT32 i;
TPM_RC

result = TPM_RC_SUCCESS;//// Check if the command requires authorization
for(i = 0; i < command->handleNum; i++){if(CommandAuthRole(command->index, i) != AUTH_NONE)
return TPM_RC_AUTH_MISSING;}#ifdef TPM_CC_GetCommandAuditDigest// Check if the command should be audited.
if(CommandAuditIsRequired(command->index)){
result = CheckCommandAudit(command);if(result != TPM_RC_SUCCESS)
return result;}#endif// Initialize number of sessions to be 0command->sessionNum = 0;
return TPM_RC_SUCCESS;}

Page 228
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

6.4.5
6.4.5.1

Trusted Platform Module Library

Response Session Processing
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.
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

static TPM2B_DIGEST *ComputeRpHash(
COMMAND
TPM_ALG_ID)*command,hashAlg// IN: command structure// IN: hash algorithm to compute rpHash

TPM2B_DIGEST
HASH_STATE*rpHash = GetRpHashPointer(command, hashAlg);
hashState;{//if(rpHash->t.size == 0){//
rpHash := hash(responseCode || commandCode || parameters)// Initiate hash creation.
rpHash->t.size = CryptHashStart(&hashState, hashAlg);// Add hash constituents.
CryptDigestUpdateInt(&hashState, sizeof(TPM_RC), TPM_RC_SUCCESS);
CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);
CryptDigestUpdate(&hashState, command->parameterSize,
command->parameterBuffer);// Complete hash computation.
CryptHashEnd2B(&hashState, &rpHash->b);}
return rpHash;}

6.4.5.3

InitAuditSession()

This function initializes the audit data in an audit session.
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458

static void
InitAuditSession(
SESSION)*session// session to be initialized{// Mark session as an audit session.
session->attributes.isAudit = SET;// Audit session can not be bound.
session->attributes.isBound = CLEAR;// Size of the audit log is the size of session hash algorithm digest.
session->u2.auditDigest.t.size = CryptHashGetDigestSize(session->authHashAlg);// Set the original digest value to be 0.
MemorySet(&session->u2.auditDigest.t.buffer,0,
session->u2.auditDigest.t.size);
return;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 229
April 15, 2019

Trusted Platform Module Library
1459

Part 4: Supporting Routines}

6.4.5.4

UpdateAuditDigest

Function to update an audit digest
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

static void
UpdateAuditDigest(
COMMAND
TPMI_ALG_HASH
TPM2B_DIGEST)*command,hashAlg,*digest

HASH_STATETPM2B_DIGESTTPM2B_DIGEST

hashState;*cpHash = GetCpHash(command, hashAlg);*rpHash = ComputeRpHash(command, hashAlg);{//
pAssert(cpHash != NULL);// digestNew := hash (digestOld || cpHash || rpHash)// Start hash computation.
digest->t.size = CryptHashStart(&hashState, hashAlg);// Add old digest.
CryptDigestUpdate2B(&hashState, &digest->b);// Add cpHash
CryptDigestUpdate2B(&hashState, &cpHash->b);// Add rpHash
CryptDigestUpdate2B(&hashState, &rpHash->b);// Finalize the hash.
CryptHashEnd2B(&hashState, &digest->b);}

6.4.5.5

Audit()

This function updates the audit digest in an audit session.
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

static void
Audit(COMMANDSESSION)*command,*auditSession// IN: primary control structure// IN: loaded audit session{
UpdateAuditDigest(command, auditSession->authHashAlg,&auditSession->u2.auditDigest);
return;}#ifdef

TPM_CC_GetCommandAuditDigest

6.4.5.6

CommandAudit()

This function updates the command audit digest.
1496
1497
1498
1499
1500
1501
1502
1503
1504

static void
CommandAudit(
COMMAND)*command// IN:{// If the digest.size is one, it indicates the special case of changing// the audit hash algorithm. For this case, no audit is done on exit.
// NOTE: When the hash algorithm is changed, g_updateNV is set in order to// force an update to the NV on exit so that the change in digest will

Page 230
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528

Trusted Platform Module Library// be recorded. So, it is safe to exit here without setting any flags// because the digest change will be written to NV when this code exits.
if(gr.commandAuditDigest.t.size == 1){
gr.commandAuditDigest.t.size = 0;
return;}// If the digest size is zero, need to start a new digest and increment// the audit counter.
if(gr.commandAuditDigest.t.size == 0){
gr.commandAuditDigest.t.size = CryptHashGetDigestSize(gp.auditHashAlg);
MemorySet(gr.commandAuditDigest.t.buffer,0,
gr.commandAuditDigest.t.size);// Bump the counter and save its value to NV.
gp.auditCounter++;
NV_SYNC_PERSISTENT(auditCounter);}UpdateAuditDigest(command, gp.auditHashAlg, &gr.commandAuditDigest);
return;}#endif

6.4.5.7

UpdateAuditSessionStatus()

Function to update the internal audit related states of a session. It
initializes the session as audit session and sets it to be exclusive if this is the first time it is used foraudit or audit reset was requested;reports exclusive audit session;
extends audit log; andclears exclusive audit session if no audit session found in the command.
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555

static void
UpdateAuditSessionStatus(
COMMAND)*command// IN: primary control structure

UINT32
TPM_HANDLEi;auditSession = TPM_RH_UNASSIGNED;{//// Iterate through sessions
for(i = 0; i < command->sessionNum; i++){SESSION*session;//// PW session do not have a loaded session and can not be an audit// session either. Skip it.
if(s_sessionHandles[i] == TPM_RS_PW)
continue;
session = SessionGet(s_sessionHandles[i]);// If a session is used for audit
if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit)){// An audit session has been foundauditSession = s_sessionHandles[i];// If the session has not been an audit session yet, or// the auditSetting bits indicate a reset, initialize it and set

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 231
April 15, 2019

Trusted Platform Module Library
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591

Part 4: Supporting Routines// it to be the exclusive session
if(session->attributes.isAudit == CLEAR|| IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset)){
InitAuditSession(session);g_exclusiveAuditSession = auditSession;}
else{// Check if the audit session is the current exclusive audit// session and, if not, clear previous exclusive audit session.
if(g_exclusiveAuditSession != auditSession)g_exclusiveAuditSession = TPM_RH_UNASSIGNED;}// Report audit session exclusivity.
if(g_exclusiveAuditSession == auditSession){
SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);}
else{
CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);}// Extend audit log.
Audit(command, session);}}// If no audit session is found in the command, and the command allows// a session then, clear the current exclusive// audit session.
if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(command->index)){g_exclusiveAuditSession = TPM_RH_UNASSIGNED;}
return;}6.4.5.8

ComputeResponseHMAC()

Function to compute HMAC for authorization session in a response.
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614

static void
ComputeResponseHMAC(
COMMANDUINT32SESSIONTPM2B_DIGEST)*command,sessionIndex,*session,*hmac// IN: command structure// IN: session index to be processed// IN: loaded session// OUT: authHMAC{
TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));TPM2B_KEY
key;// HMAC key
BYTE
marshalBuffer[sizeof(TPMA_SESSION)];
BYTE*buffer;
UINT32marshalSize;
HMAC_STATE
hmacState;
TPM2B_DIGEST*rpHash = ComputeRpHash(command, session->authHashAlg);//// Generate HMAC key
MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));// Add the object authValue if required
if(session->attributes.includeAuth == SET){// Note: includeAuth may be SET for a policy that is used inPage 232
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

Trusted Platform Module Library// UndefineSpaceSpecial(). At this point, the Index has been deleted// so the includeAuth will have no meaning. However, the// s_associatedHandles[] value for the session is now set to TPM_RH_NULL so// this will return the authValue associated with TPM_RH_NULL and that is// and empty buffer.
TPM2B_AUTH
authValue;//// Get the authValue with trailing zeros removed
EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);// Add it to the key
MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));}// if the HMAC key size is 0, the response HMAC is computed according to the// input HMAC
if(key.t.size == 0&& s_inputAuthValues[sessionIndex].t.size == 0){
hmac->t.size = 0;
return;}// Start HMAC computation.
hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);// Add hash components.
CryptDigestUpdate2B(&hmacState.hashState, &rpHash->b);
CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);
CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);// Add session attributes.
buffer = marshalBuffer;marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL);
CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);// Finalize HMAC.
CryptHmacEnd2B(&hmacState, &hmac->b);
return;}6.4.5.9

UpdateInternalSession()

Updates internal sessions:
Restarts session time.
Clears a policy session since nonce is rolling.
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670

static void
UpdateInternalSession(
SESSIONUINT32)*session,i// IN: the session structure// IN: session number{// If nonce is rolling in a policy session, the policy related data// will be re-initialized.
if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION&& IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)){// When the nonce rolls it starts a new timing interval for the// policy session.
SessionResetPolicyData(session);
SessionSetStartTime(session);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 233
April 15, 2019

Trusted Platform Module Library
1671
1672

Part 4: Supporting Routines

return;}6.4.5.10

BuildSingleResponseAuth()

Function to compute response HMAC value for a policy or HMAC session.
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694

static TPM2B_NONCE *BuildSingleResponseAuth(
COMMANDUINT32TPM2B_AUTH)*command,sessionIndex,*auth// IN: command structure// IN: session index to be processed// OUT: authHMAC{// Fill in policy/HMAC based session response.
SESSION*session = SessionGet(s_sessionHandles[sessionIndex]);//// If the session is a policy session with isPasswordNeeded SET, the// authorization field is empty.
if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION&& session->attributes.isPasswordNeeded == SET)
auth->t.size = 0;else// Compute response HMAC.
ComputeResponseHMAC(command, sessionIndex, session, auth);UpdateInternalSession(session, sessionIndex);
return &session->nonceTPM;}

6.4.5.11

UpdateAllNonceTPM()

Updates TPM nonce for all sessions in command.
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715

static void
UpdateAllNonceTPM(
COMMAND)*command// IN: controlling structure{
UINT32SESSIONi;*session;//for(i = 0; i < command->sessionNum; i++){// If not a PW session, compute the new nonceTPM.
if(s_sessionHandles[i] != TPM_RS_PW){
session = SessionGet(s_sessionHandles[i]);// Update nonceTPM in both internal session and response.
CryptRandomGenerate(session->nonceTPM.t.size,
session->nonceTPM.t.buffer);}}
return;}6.4.5.12

BuildResponseSession()

Function to build Session buffer in a response. The authorization data is added to the end of command>responseBuffer. The size of the authorization area is accumulated in command->authSize. When this iscalled, command->responseBuffer is pointing at the next location in the response buffer to be filled. This
Page 234
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Libraryis where the authorization sessions will go, if any. command->parameterSize is the number of bytes thathave been marshaled as parameters in the output buffer.
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777

void
BuildResponseSession(
COMMAND*command// IN: structure that has relevant command//
information){
pAssert(command->authSize == 0);// Reset the parameter buffer to point to the start of the parameters so that// there is a starting point for any rpHash that might be generated and so there// is a place where parameter encryption would startcommand->parameterBuffer = command->responseBuffer - command->parameterSize;// Session nonces should be updated before parameter encryption
if(command->tag == TPM_ST_SESSIONS){
UpdateAllNonceTPM(command);// Encrypt first parameter if applicable. Parameter encryption should// happen after nonce update and before any rpHash is computed.
// If the encrypt session is associated with a handle, the authValue of// this handle will be concatenated with sessionKey to generate// encryption key, no matter if the handle is the session bound entity// or not. The authValue is added to sessionKey only when the authValue// is available.
if(s_encryptSessionIndex != UNDEFINED_INDEX){UINT32size;
TPM2B_AUTH
extraKey;//extraKey.b.size = 0;// If this is an authorization session, include the authValue in the// generation of the encryption key
if(s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED){
EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex],&extraKey);}size = EncryptSize(command->index);
CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex],&s_nonceCaller[s_encryptSessionIndex].b,(UINT16)size,&extraKey,
command->parameterBuffer);}}// Audit sessions should be processed regardless of the tag because// a command with no session may cause a change of the exclusivity state.
UpdateAuditSessionStatus(command);#if CC_GetCommandAuditDigest// Command Audit
if(CommandAuditIsRequired(command->index))CommandAudit(command);#endif// Process command with sessions.
if(command->tag == TPM_ST_SESSIONS){UINT32i;//
pAssert(command->sessionNum > 0);// Iterate over each session in the command session area, and create

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 235
April 15, 2019

Trusted Platform Module Library
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

Part 4: Supporting Routines// corresponding sessions for response.
for(i = 0; i < command->sessionNum; i++){TPM2B_NONCE*nonceTPM;
TPM2B_DIGEST
responseAuth;// Make sure that continueSession is SET on any Password session.
// This makes it marginally easier for the management software// to keep track of the closed sessions.
if(s_sessionHandles[i] == TPM_RS_PW){
SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession);
responseAuth.t.size = 0;
nonceTPM = (TPM2B_NONCE *)&responseAuth;}else{// Compute the response HMAC and get a pointer to the nonce used.
// This function will also update the values if needed. Note, thenonceTPM = BuildSingleResponseAuth(command, i, &responseAuth);}command->authSize += TPM2B_NONCE_Marshal(nonceTPM,&command->responseBuffer,
NULL);
command->authSize += TPMA_SESSION_Marshal(&s_attributes[i],&command->responseBuffer,
NULL);
command->authSize += TPM2B_DIGEST_Marshal(&responseAuth,&command->responseBuffer,
NULL);
if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
SessionFlush(s_sessionHandles[i]);}}return;}6.4.5.13

SessionRemoveAssociationToHandle()

This function deals with the case where an entity associated with an authorization is deleted duringcommand processing. The primary use of this is to support UndefineSpaceSpecial().
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827

void
SessionRemoveAssociationToHandle(
TPM_HANDLE)

handle{UINT32i;//for(i = 0; i < MAX_SESSION_NUM; i++){if(s_associatedHandles[i] == handle){s_associatedHandles[i] = TPM_RH_NULL;}}}

Page 236
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7

Trusted Platform Module Library

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
1
2

Includes#include "Tpm.h"#include "Attest_spt_fp.h"

7.2.2
7.2.2.1

Functions
FillInAttestInfo()

Fill in common fields of TPMS_ATTEST structure.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

void
FillInAttestInfo(TPMI_DH_OBJECT
TPMT_SIG_SCHEME
TPM2B_DATA
TPMS_ATTEST)

signHandle,*scheme,*data,*attest// IN: handle of signing object// IN/OUT: scheme to be used for signing// IN: qualifying data// OUT: attest structure

OBJECT*signObject = HandleToObject(signHandle);{// Magic number
attest->magic = TPM_GENERATED_VALUE;
if(signObject == NULL){// The name for a null handle is TPM_RH_NULL// This is defined because UINT32_TO_BYTE_ARRAY does a cast. If the// size of the cast is smaller than a constant, the compiler warns// about the truncation of a constant value.
TPM_HANDLE
nullHandle = TPM_RH_NULL;
attest->qualifiedSigner.t.size = sizeof(TPM_HANDLE);UINT32_TO_BYTE_ARRAY(nullHandle, attest->qualifiedSigner.t.name);}
else{// Certifying object qualified name// if the scheme is anonymous, this is an empty buffer
if(CryptIsSchemeAnonymous(scheme->scheme))
attest->qualifiedSigner.t.size = 0;
else
attest->qualifiedSigner = signObject->qualifiedName;}// current clock in plain text
TimeFillInfo(&attest->clockInfo);// Firmware version in plain text
attest->firmwareVersion = ((UINT64)gp.firmwareV1 << (sizeof(UINT32) * 8));attest->firmwareVersion += gp.firmwareV2;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 237
April 15, 2019

Trusted Platform Module Library
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

Part 4: Supporting Routines// Check the hierarchy of sign object. For NULL sign handle, the hierarchy// will be TPM_RH_NULL
if((signObject == NULL)|| (!signObject->attributes.epsHierarchy&& !signObject->attributes.ppsHierarchy)){// For signing key that is not in platform or endorsement hierarchy,// obfuscate the reset, restart and firmware version information
UINT64
obfuscation[2];CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gp.shProof.b, OBFUSCATE_STRING,&attest->qualifiedSigner.b, NULL, 128,(BYTE *)&obfuscation[0], NULL, FALSE);// Obfuscate dataattest->firmwareVersion += obfuscation[0];attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
attest->clockInfo.restartCount += (UINT32)obfuscation[1];}// External dataif(CryptIsSchemeAnonymous(scheme->scheme))
attest->extraData.t.size = 0;else{// If we move the data to the attestation structure, then it is not// used in the signing operation except as part of the signed dataattest->extraData = *data;
data->t.size = 0;}}

7.2.2.2

SignAttestInfo()

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

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

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 togenerate r value (for an ECC key)

TPM_RC
SignAttestInfo(OBJECT
TPMT_SIG_SCHEME
TPMS_ATTEST
TPM2B_DATA*signKey,*scheme,*certifyInfo,*qualifyingData,

TPM2B_ATTEST*attest,

TPMT_SIGNATURE)*signature// IN: sign object// IN: sign scheme// IN: the data to be signed// IN: extra data for the signing//
process// OUT: marshaled attest blob to be//signed// OUT: signature{
BYTE
HASH_STATETPM2B_DIGEST
TPM_RC*buffer;hashState;digest;result;// Marshal TPMS_ATTEST structure for hashbuffer = attest->t.attestationData;
attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL);
if(signKey == NULL)

Page 238
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

Trusted Platform Module Library{signature->sigAlg = TPM_ALG_NULL;
result = TPM_RC_SUCCESS;}
else{
TPMI_ALG_HASH
hashAlg;// Compute hashhashAlg = scheme->details.any.hashAlg;// need to set the receive buffer to get something put in itdigest.t.size = sizeof(digest.t.buffer);digest.t.size = CryptHashBlock(hashAlg, attest->t.size,
attest->t.attestationData,
digest.t.size, digest.t.buffer);// If there is qualifying data, need to rehash the data// hash(qualifyingData || hash(attestationData))
if(qualifyingData->t.size != 0){
CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate2B(&hashState, &qualifyingData->b);
CryptDigestUpdate2B(&hashState, &digest.b);
CryptHashEnd2B(&hashState, &digest.b);}// Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or// TPM_RC_ATTRIBUTES error may be returned at this point
result = CryptSign(signKey, scheme, &digest, signature);// Since the clock is used in an attestation, the state in NV is no longer// "orderly" with respect to the data in RAM if the signature is valid
if(result == TPM_RC_SUCCESS){// Command uses the clock so need to clear the orderly state if it is// set.
result = NvClearOrderly();}}
return result;}7.2.2.3

IsSigningObject()

Checks to see if the object is OK for signing. This is here rather than in Object_spt.c because all theattestation commands use this file but not Object_spt.c.

130
131
132
133
134
135
136
137
138

Return Value

Meaning

TRUE(1)

object may sign

FALSE(0)object may not sign

BOOL
IsSigningObject(
OBJECT)*object// IN:{
return ((object == NULL)|| ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)&& object->publicArea.type != TPM_ALG_SYMCIPHER)));}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 239
April 15, 2019

Trusted Platform Module Library

7.3

Context Management Command Support (Context_spt.c)

7.3.1
1
2

Part 4: Supporting Routines

Includes#include "Tpm.h"#include "Context_spt_fp.h"

7.3.2

Functions7.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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

void
ComputeContextProtectionKey(
TPMS_CONTEXTTPM2B_SYM_KEY
TPM2B_IV)*contextBlob,*symKey,*iv// IN: context blob// OUT: the symmetric key// OUT: the IV.

UINT16

symKeyBits;

TPM2B_PROOF*proof = NULL;// number of bits in the parent's//
symmetric key// the proof value to use. Is null for//everything but a primary object in//the Endorsement Hierarchy

BYTE

kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF

TPM2B_DATA

sequence2B, handle2B;{// Get proof value
proof = HierarchyGetProof(contextBlob->hierarchy);// Get sequence value in 2B format
sequence2B.t.size = sizeof(contextBlob->sequence);cAssert(sizeof(contextBlob->sequence) <= sizeof(sequence2B.t.buffer));
MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence,
sizeof(contextBlob->sequence));// Get handle value in 2B format
handle2B.t.size = sizeof(contextBlob->savedHandle);cAssert(sizeof(contextBlob->savedHandle) <= sizeof(handle2B.t.buffer));
MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle,
sizeof(contextBlob->savedHandle));// Get the symmetric encryption key size
symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;
symKeyBits = CONTEXT_ENCRYPT_KEY_BITS;// Get the size of the IV for the algorithmiv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits);// KDFa to generate symmetric key and IV value
CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &proof->b, CONTEXT_KEY, &sequence2B.b,&handle2B.b, (symKey->t.size + iv->t.size) * 8, kdfResult, NULL,FALSE);// Copy part of the returned value as the key
pAssert(symKey->t.size <= sizeof(symKey->t.buffer));
MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size);

Page 240
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
50
51
52
53
54
55

Trusted Platform Module Library// Copy the rest as the IV
pAssert(iv->t.size <= sizeof(iv->t.buffer));
MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size);
return;}7.3.2.2

ComputeContextIntegrity()

Generate the integrity hash for a context It is used by TPM2_ContextSave() to create an integrity hashand by TPM2_ContextLoad() to compare an integrity hash
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

void
ComputeContextIntegrity(
TPMS_CONTEXTTPM2B_DIGEST)*contextBlob,*integrity// IN: context blob// OUT: integrity{
HMAC_STATETPM2B_PROOF
UINT16

hmacState;*proof;integritySize;// Get proof value
proof = HierarchyGetProof(contextBlob->hierarchy);// Start HMAC
integrity->t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,&proof->b);// Compute integrity size at the beginning of context blob
integritySize = sizeof(integrity->t.size) + integrity->t.size;// Adding total reset counter so that the context cannot be// used after a TPM Reset
CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount),
gp.totalResetCount);// If this is a ST_CLEAR object, add the clear count// so that this contest cannot be loaded after a TPM Restartif(contextBlob->savedHandle == 0x80000002)
CryptDigestUpdateInt(&hmacState.hashState, sizeof(gr.clearCount),
gr.clearCount);// Adding sequence number to the HMAC to make sure that it doesn't// get changed
CryptDigestUpdateInt(&hmacState.hashState, sizeof(contextBlob->sequence),
contextBlob->sequence);// Protect the handle
CryptDigestUpdateInt(&hmacState.hashState, sizeof(contextBlob->savedHandle),
contextBlob->savedHandle);// Adding sensitive contextData, skip the leading integrity area
CryptDigestUpdate(&hmacState.hashState,contextBlob->contextBlob.t.size - integritySize,contextBlob->contextBlob.t.buffer + integritySize);// Complete HMAC
CryptHmacEnd2B(&hmacState, &integrity->b);
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 241
April 15, 2019

Trusted Platform Module Library

7.3.2.3

Part 4: Supporting Routines

SequenceDataExport()

This function is used scan through the sequence object and either modify the hash state data for export(contextSave) or to import it into the internal format (contextLoad). This function should only be called
after the sequence object has been copied to the context buffer (contextSave) or from the context buffer
into the sequence object. The presumption is that the context buffer version of the data is the same sizeas the internal representation so nothing outsize of the hash context area gets modified.
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

void
SequenceDataExport(
HASH_OBJECT
HASH_OBJECT_BUFFER)*object,*exportObject// IN: an internal hash object// OUT: a sequence context in a buffer{// If the hash object is not an event, then only one hash context is needed
intcount = (object->attributes.eventSeq) ? HASH_COUNT : 1;for(count--; count >= 0; count--){
HASH_STATE*hash = &object->state.hashState[count];
size_toffset = (BYTE *)hash - (BYTE *)object;
BYTE*exportHash = &((BYTE *)exportObject)[offset];
CryptHashExportState(hash, (EXPORT_HASH_STATE *)exportHash);}}

7.3.2.4

SequenceDataImport()

This function is used scan through the sequence object and either modify the hash state data for export(contextSave) or to import it into the internal format (contextLoad). This function should only be called
after the sequence object has been copied to the context buffer (contextSave) or from the context buffer
into the sequence object. The presumption is that the context buffer version of the data is the same sizeas the internal representation so nothing outsize of the hash context area gets modified.
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

void
SequenceDataImport(
HASH_OBJECT
HASH_OBJECT_BUFFER)*object,*exportObject// IN/OUT: an internal hash object// IN/OUT: a sequence context in a buffer{// If the hash object is not an event, then only one hash context is needed
intcount = (object->attributes.eventSeq) ? HASH_COUNT : 1;for(count--; count >= 0; count--){
HASH_STATE*hash = &object->state.hashState[count];
size_toffset = (BYTE *)hash - (BYTE *)object;
BYTE*importHash = &((BYTE *)exportObject)[offset];//
CryptHashImportState(hash, (EXPORT_HASH_STATE *)importHash);}}

Page 242
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.4

Policy Command Support (Policy_spt.c)

7.4.1
1
2
3
4
5

Trusted Platform Module Library

Includes#include "Tpm.h"#include "Policy_spt_fp.h"#include "PolicySigned_fp.h"#include "PolicySecret_fp.h"#include "PolicyTicket_fp.h"

7.4.2
7.4.2.1

Functions
PolicyParameterChecks()

This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The
common parameters are nonceTPM, expiration, and cpHashA.
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

TPM_RC
PolicyParameterChecks(
SESSIONUINT64TPM2B_DIGESTTPM2B_NONCE
TPM_RCTPM_RCTPM_RC)*session,
authTimeout,*cpHashA,*nonce,blameNonce,
blameCpHash,
blameExpiration{// Validate that input nonceTPM is correct if present
if(nonce != NULL && nonce->t.size != 0){if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b))
return TPM_RCS_NONCE + blameNonce;}// If authTimeout is set (expiration != 0...
if(authTimeout != 0){// Validate input expiration.
// Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE// or TPM_RC_NV_RATE error may be returned here.
RETURN_IF_NV_IS_NOT_AVAILABLE;// if the time has already passed or the time epoch has changed then the// time value is no longer good.
if((authTimeout < g_time)|| (session->epoch != g_timeEpoch))return TPM_RCS_EXPIRED + blameExpiration;}// If the cpHash is present, then check itif(cpHashA != NULL && cpHashA->t.size != 0){// The cpHash input has to have the correct size
if(cpHashA->t.size != session->u2.policyDigest.t.size)
return TPM_RCS_SIZE + blameCpHash;// If the cpHash has already been set, then this input value// must match the current value.
if(session->u1.cpHash.b.size != 0&& !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b))return TPM_RC_CPHASH;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 243
April 15, 2019

Trusted Platform Module Library
50
51

Part 4: Supporting Routines

return TPM_RC_SUCCESS;}

7.4.2.2

PolicyContextUpdate()

Update policy hash Update the policyDigest in policy session by extending policyRef and objectName toit. This will also update the cpHash if it is present.
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

void
PolicyContextUpdate(
TPM_CCTPM2B_NAME
TPM2B_NONCE
TPM2B_DIGESTUINT64SESSION)commandCode,// IN: command code*name,// IN: name of entity*ref,// IN: the reference data
*cpHash,// IN: the cpHash (optional)
policyTimeout, // IN: the timeout value for the policy*session// IN/OUT: policy session to be updated{
HASH_STATE

hashState;// Start hash
CryptHashStart(&hashState, session->authHashAlg);// policyDigest size should always be the digest size of session hash algorithm.
pAssert(session->u2.policyDigest.t.size== CryptHashGetDigestSize(session->authHashAlg));// add old digest
CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);// add commandCode
CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode);// add name if applicableif(name != NULL)
CryptDigestUpdate2B(&hashState, &name->b);// Complete the digest and get the results
CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);// If the policy reference is not null, do a second update to the digest.
if(ref != NULL){// Start second hash computation
CryptHashStart(&hashState, session->authHashAlg);// add policyDigest
CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);// add policyRef
CryptDigestUpdate2B(&hashState, &ref->b);// Complete second digest
CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);}// Deal with the cpHash. If the cpHash value is present// then it would have already been checked to make sure that// it is compatible with the current value so all we need// to do here is copy it and set the isCpHashDefined attributeif(cpHash != NULL && cpHash->t.size != 0){
session->u1.cpHash = *cpHash;session->attributes.isCpHashDefined = SET;

Page 244
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
108
109
110
111
112
113
114
115
116
117
118
119

Trusted Platform Module Library}// update the timeout if it is specified
if(policyTimeout != 0){// If the timeout has not been set, then set it to the new value// than the current timeout then set it to the new value
if(session->timeout == 0 || session->timeout > policyTimeout)
session->timeout = policyTimeout;}
return;}7.4.2.3

ComputeAuthTimeout()

This function is used to determine what the authorization timeout value for the session should be.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

UINT64ComputeAuthTimeout(
SESSION*session,

INT32

expiration,

TPM2B_NONCE)*nonce// IN: the session containing the time//values// IN: either the number of seconds from//the start of the session or the//time in g_timer;// IN: indicator of the time base{
UINT64
policyTime;// If no expiration, policy time is 0
if(expiration == 0)
policyTime = 0;
else{
if(expiration < 0)
expiration = -expiration;
if(nonce->t.size == 0)// The input time is absolute Time (not Clock), but it is expressed// in seconds. To make sure that we don't time out too early, take the// current value of milliseconds in g_time and add that to the input// seconds value.
policyTime = (((UINT64)expiration) * 1000) + g_time % 1000;
else// The policy timeout is the absolute value of the expiration in seconds// added to the start time of the policy.
policyTime = session->startTime + (((UINT64)expiration) * 1000);}
return policyTime;}

7.4.2.4

PolicyDigestClear()

Function to reset the policyDigest of a session
152
153
154
155
156
157
158
159
160

void
PolicyDigestClear(
SESSION)*session{session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg);
MemorySet(session->u2.policyDigest.t.buffer, 0,
session->u2.policyDigest.t.size);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 245
April 15, 2019

Trusted Platform Module Library

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

Part 4: Supporting Routines

BOOL
PolicySptCheckCondition(
TPM_EO
BYTE
BYTE
UINT16)

operation,
*opA,
*opB,
size

{
// Arithmetic Comparison
switch(operation){case TPM_EO_EQ:// compare A = B
return (UnsignedCompareB(size, opA, size, opB) == 0);
break;
case TPM_EO_NEQ:// compare A != B
return (UnsignedCompareB(size, opA, size, opB) != 0);
break;
case TPM_EO_SIGNED_GT:// compare A > B signed
return (SignedCompareB(size, opA, size, opB) > 0);
break;
case TPM_EO_UNSIGNED_GT:// compare A > B unsigned
return (UnsignedCompareB(size, opA, size, opB) > 0);
break;
case TPM_EO_SIGNED_LT:// compare A < B signed
return (SignedCompareB(size, opA, size, opB) < 0);
break;
case TPM_EO_UNSIGNED_LT:// compare A < B unsigned
return (UnsignedCompareB(size, opA, size, opB) < 0);
break;
case TPM_EO_SIGNED_GE:// compare A >= B signed
return (SignedCompareB(size, opA, size, opB) >= 0);
break;
case TPM_EO_UNSIGNED_GE:// compare A >= B unsigned
return (UnsignedCompareB(size, opA, size, opB) >= 0);
break;
case TPM_EO_SIGNED_LE:// compare A <= B signed
return (SignedCompareB(size, opA, size, opB) <= 0);
break;
case TPM_EO_UNSIGNED_LE:// compare A <= B unsigned
return (UnsignedCompareB(size, opA, size, opB) <= 0);
break;
case TPM_EO_BITSET:// All bits SET in B are SET in A. ((A&B)=B){
UINT32 i;for(i = 0; i < size; i++)if((opA[i] & opB[i]) != opB[i])return FALSE;}
break;
case TPM_EO_BITCLEAR:// All bits SET in B are CLEAR in A. ((A&B)=0){
UINT32 i;for(i = 0; i < size; i++)if((opA[i] & opB[i]) != 0)

Page 246
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
227
228
229
230
231
232
233
234
235

Trusted Platform Module Library

return FALSE;}
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return TRUE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 247
April 15, 2019

Trusted Platform Module Library

7.5

NV Command Support (NV_spt.c)

7.5.1
1
2

Part 4: Supporting Routines

Includes#include "Tpm.h"#include "NV_spt_fp.h"

7.5.2

Functions7.5.2.1

NvReadAccessChecks()

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

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

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

TPM_RC
NvReadAccessChecks(
TPM_HANDLE

authHandle,

TPM_HANDLE
TPMA_NV)

nvHandle,
attributes// IN: the handle that provided the//authorization// IN: the handle of the NV index to be read// IN: the attributes of 'nvHandle'{// If data is read locked, returns an error
if(IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED))
return TPM_RC_NV_LOCKED;// If the authorization was provided by the owner or platform, then check// that the attributes allow the read. If the authorization handle// is the same as the index, then the checks were made when the authorization// was checked..
if(authHandle == TPM_RH_OWNER){// If Owner provided authorization then ONWERWRITE must be SET
if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD))
return TPM_RC_NV_AUTHORIZATION;}
else if(authHandle == TPM_RH_PLATFORM){// If Platform provided authorization then PPWRITE must be SET
if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD))
return TPM_RC_NV_AUTHORIZATION;}// If neither Owner nor Platform provided authorization, make sure that it was// provided by this index.
else if(authHandle != nvHandle)
return TPM_RC_NV_AUTHORIZATION;// If the index has not been written, then the value cannot be read// NOTE: This has to come after other access checks to make sure that// the proper authorization is given to TPM2_NV_ReadLock()if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN))
return TPM_RC_NV_UNINITIALIZED;
return TPM_RC_SUCCESS;}

Page 248
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.5.2.2

Trusted Platform Module Library

NvWriteAccessChecks()

Common routine for validating a write
TPM2_SetBits(), and TPM2_NV_WriteLock()

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

Used

Error Returns

Meaning

TPM_RC_NV_AUTHORIZATION

Authorization fails

TPM_RC_NV_LOCKED

Write lockedby

TPM2_NV_Write(),

TPM2_NV_Increment(),

TPM_RC
NvWriteAccessChecks(
TPM_HANDLE

authHandle,

TPM_HANDLE
TPMA_NV)

nvHandle,
attributes// IN: the handle that provided the//authorization// IN: the handle of the NV index to be written// IN: the attributes of 'nvHandle'{// If data is write locked, returns an error
if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED))
return TPM_RC_NV_LOCKED;// If the authorization was provided by the owner or platform, then check// that the attributes allow the write. If the authorization handle// is the same as the index, then the checks were made when the authorization// was checked..
if(authHandle == TPM_RH_OWNER){// If Owner provided authorization then ONWERWRITE must be SET
if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE))
return TPM_RC_NV_AUTHORIZATION;}
else if(authHandle == TPM_RH_PLATFORM){// If Platform provided authorization then PPWRITE must be SET
if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE))
return TPM_RC_NV_AUTHORIZATION;}// If neither Owner nor Platform provided authorization, make sure that it was// provided by this index.
else if(authHandle != nvHandle)
return TPM_RC_NV_AUTHORIZATION;
return TPM_RC_SUCCESS;}

7.5.2.3

NvClearOrderly()This function is used to cause gp.orderlyState to be cleared to the non-orderly state.
76
77
78
79
80
81
82
83
84
85

TPM_RC
NvClearOrderly(void){
if(gp.orderlyState < SU_DA_USED_VALUE)
RETURN_IF_NV_IS_NOT_AVAILABLE;
g_clearOrderly = TRUE;
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 249
April 15, 2019

Trusted Platform Module Library

7.5.2.4

Part 4: Supporting Routines

NvIsPinPassIndex()

Function to check to see if an NV index is a PIN Pass Index

86
87
88
89
90
91
92
93
94
95
96
97
98

Return Value

Meaning

TRUE(1)

is pin pass

FALSE(0)is not pin passBOOL
NvIsPinPassIndex(
TPM_HANDLE
)

index

// IN: Handle to check{
if(HandleGetType(index) == TPM_HT_NV_INDEX){
NV_INDEX*nvIndex = NvGetIndexInfo(index, NULL);
return IsNvPinPassIndex(nvIndex->publicArea.attributes);}
return FALSE;}

Page 250
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.6

Object Command Support (Object_spt.c)

7.6.1
1
2

Trusted Platform Module Library

Includes#include "Tpm.h"#include "Object_spt_fp.h"

7.6.2

Local Functions

7.6.2.1

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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

static UINT16
GetIV2BSize(
OBJECT)*protector

TPM_ALG_ID
UINT16

symAlg;
keyBits;// IN: the protector handle{// Determine the symmetric algorithm and size of key
if(protector == NULL){// Use the context encryption algorithm and key size
symAlg = CONTEXT_ENCRYPT_ALG;
keyBits = CONTEXT_ENCRYPT_KEY_BITS;}
else{
symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm;
keyBits = protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym;}// The IV size is a UINT16 size field plus the block size of the symmetric// algorithm
return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits);}

7.6.2.2

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
28
29
30
31
32
33
34
35
36
37
38
39

static void
ComputeProtectionKeyParms(
OBJECT
TPM_ALG_ID
TPM2B
TPM2B

*protector,
hashAlg,*name,*seedIn,TPM_ALG_ID
UINT16
TPM2B_SYM_KEY)*symAlg,*keyBits,*symKey

Family “2.0”Level 00 Revision 01.55// IN: the protector object// IN: hash algorithm for KDFa// IN: name of the object// IN: optional seed for duplication blob.
//
For non duplication blob, this//parameter should be NULL// OUT: the symmetric algorithm// OUT: the symmetric key size in bits// OUT: the symmetric key

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 251
April 15, 2019

Trusted Platform Module Library
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

Part 4: Supporting Routines{
const TPM2B*seed = seedIn;// Determine the algorithms for the KDF and the encryption/decryption// For TPM_RH_NULL, using context settings
if(protector == NULL){// Use the context encryption algorithm and key size
*symAlg = CONTEXT_ENCRYPT_ALG;
symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;*keyBits = CONTEXT_ENCRYPT_KEY_BITS;}
else{
TPMT_SYM_DEF_OBJECT *symDef;
symDef = &protector->publicArea.parameters.asymDetail.symmetric;*symAlg = symDef->algorithm;*keyBits = symDef->keyBits.sym;
symKey->t.size = (*keyBits + 7) / 8;}// Get seed for KDF
if(seed == NULL)
seed = GetSeedForKDF(protector);// KDFa to generate symmetric key and IV value
CryptKDFa(hashAlg, seed, STORAGE_KEY, name, NULL,
symKey->t.size * 8, symKey->t.buffer, NULL, FALSE);
return;}7.6.2.3

ComputeOuterIntegrity()

The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaledsensitive area. The caller should skip over the area set aside for the integrity value and compute the hashof the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area
contents is an array of bytes.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

static void
ComputeOuterIntegrity(
TPM2B
OBJECT*name,*protector,

TPMI_ALG_HASH
TPM2B

hashAlg,*seedIn,UINT32BYTE
TPM2B_DIGEST)

sensitiveSize,*sensitiveData,*integrity

HMAC_STATETPM2B_DIGEST
const TPM2B

hmacState;
hmacKey;*seed = seedIn;// IN: the name of the object// IN: the object that//provides protection. For an object,//
it is a parent. For a credential, it//
is the encrypt object. For//a Temporary Object, it is NULL// IN: algorithm to use for integrity// IN: an external seed may be provided for//
duplication blob. For non duplication//
blob, this parameter should be NULL// IN: size of the marshaled sensitive data// IN: sensitive area// OUT: integrity{//// Get seed for KDF
if(seed == NULL)
seed = GetSeedForKDF(protector);// Determine the HMAC key bits
hmacKey.t.size = CryptHashGetDigestSize(hashAlg);// KDFa to generate HMAC key

Page 252
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

Trusted Platform Module Library

CryptKDFa(hashAlg, seed, INTEGRITY_KEY, NULL, NULL,
hmacKey.t.size * 8, hmacKey.t.buffer, NULL, FALSE);// Start HMAC and get the size of the digest which will become the integrity
integrity->t.size = CryptHmacStart2B(&hmacState, hashAlg, &hmacKey.b);// Adding the marshaled sensitive area to the integrity value
CryptDigestUpdate(&hmacState.hashState, sensitiveSize, sensitiveData);// Adding name
CryptDigestUpdate2B(&hmacState.hashState, name);// Compute HMAC
CryptHmacEnd2B(&hmacState, &integrity->b);
return;}7.6.2.4

ComputeInnerIntegrity()This function computes the integrity of an inner wrap
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

static void
ComputeInnerIntegrity(
TPM_ALG_ID
TPM2B
UINT16BYTE
TPM2B_DIGEST)

hashAlg,// IN: hash algorithm for inner wrap
*name,// IN: the name of the object
dataSize,// IN: the size of sensitive data
*sensitiveData, // IN: sensitive data*integrity// OUT: inner integrity

HASH_STATE

hashState;{//// Start hash and get the size of the digest which will become the integrity
integrity->t.size = CryptHashStart(&hashState, hashAlg);// Adding the marshaled sensitive area to the integrity value
CryptDigestUpdate(&hashState, dataSize, sensitiveData);// Adding name
CryptDigestUpdate2B(&hashState, name);// Compute hash
CryptHashEnd2B(&hashState, &integrity->b);
return;}7.6.2.5

ProduceInnerIntegrity()This function produces an inner integrity for regular private, credential or duplication blob It requires thesensitive 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
137
138
139
140
141
142
143
144

static UINT16
ProduceInnerIntegrity(
TPM2B
TPM_ALG_ID
UINT16*name,
hashAlg,
dataSize,

BYTE*innerBuffer

Family “2.0”Level 00 Revision 01.55// IN: the name of the object// IN: hash algorithm for inner wrap// IN: the size of sensitive data, excluding the//leading integrity buffer size// IN/OUT: inner buffer with sensitive data in//
it. At input, the leading bytes of thisTCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 253
April 15, 2019

Trusted Platform Module Library
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

Part 4: Supporting Routines//

buffer is reserved for integrity

)
{
BYTE
TPM2B_DIGESTUINT16
BYTE*sensitiveData; // pointer to the sensitive data
integrity;
integritySize;*buffer;// Auxiliary buffer pointer//// sensitiveData points to the beginning of sensitive data in innerBuffer
integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);sensitiveData = innerBuffer + integritySize;
ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity);// Add integrity at the beginning of inner buffer
buffer = innerBuffer;
TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
return dataSize + integritySize;}

7.6.2.6

CheckInnerIntegrity()This function check integrity of inner blob

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

Error Returns

Meaning

TPM_RC_INTEGRITY

if the outer blob integrity is bad

unmarshal errors

unmarshal errors while unmarshaling integrity

static TPM_RC
CheckInnerIntegrity(
TPM2B
TPM_ALG_ID
UINT16*name,
hashAlg,
dataSize,

BYTE*innerBuffer// IN: the name of the object// IN: hash algorithm for inner wrap// IN: the size of sensitive data, including the//leading integrity buffer size// IN/OUT: inner buffer with sensitive data in
//
it

)
{
TPM_RCTPM2B_DIGESTTPM2B_DIGEST
BYTE
INT32

result;integrity;
integrityToCompare;*buffer;size;// Auxiliary buffer pointer//// Unmarshal integrity
buffer = innerBuffer;size = (INT32)dataSize;
result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);if(result == TPM_RC_SUCCESS){// Compute integrity to compare
ComputeInnerIntegrity(hashAlg, name, (UINT16)size, buffer,&integrityToCompare);// Compare outer blob integrityif(!MemoryEqual2B(&integrity.b, &integrityToCompare.b))
result = TPM_RC_INTEGRITY;}
return result;}

Page 254
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.6.3
7.6.3.1

Trusted Platform Module Library

Public Functions
AdjustAuthSize()This function will validate that the input authValue is no larger than the digestSize for the nameAlg. It willthen pad with zeros to the size of the digest.
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

BOOL
AdjustAuthSize(
TPM2B_AUTH
TPMI_ALG_HASH)*auth,
nameAlg// IN/OUT: value to adjust// IN:UINT16

digestSize;{//// If there is no nameAlg, then this is a LoadExternal and the authVale can// be any size up to the maximum allowed by thedigestSize = (nameAlg == TPM_ALG_NULL) ? sizeof(TPMU_HA): CryptHashGetDigestSize(nameAlg);if(digestSize < MemoryRemoveTrailingZeros(auth))return FALSE;
else if(digestSize > auth->t.size)
MemoryPad2B(&auth->b, digestSize);auth->t.size = digestSize;
return TRUE;}

7.6.3.2

AreAttributesForParent()

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

216
217
218
219
220
221
222

The isParent attribute is SET when an object is loaded and it has attributes that are suitable for a parent object.

Return Value

Meaning

TRUE(1)properties are those of a parent

FALSE(0)properties are not those of a parent

BOOL
ObjectIsParent(
OBJECT)*parentObject// IN: parent handle{
return parentObject->attributes.isParent;}

7.6.3.3

CreateChecks()

Attribute checks that are unique to creation.

223
224

Error Returns

Meaning

TPM_RC_ATTRIBUTES

sensitiveDataOrigin is not consistent with the object typeotherreturns from PublicAttributesValidation()

TPM_RC
CreateChecks(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 255
April 15, 2019

Trusted Platform Module Library
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

Part 4: Supporting Routines

OBJECT
TPMT_PUBLIC
UINT16)*parentObject,*publicArea,sensitiveDataSize

TPMA_OBJECT
TPM_RC

attributes = publicArea->objectAttributes;
result = TPM_RC_SUCCESS;

{
//

//

// If the caller indicates that they have provided the data, then make sure that// they have provided some data.
if((!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))&& (sensitiveDataSize == 0))
return TPM_RCS_ATTRIBUTES;// For an ordinary object, data can only be provided when sensitiveDataOrigin// is CLEAR
if((parentObject != NULL)&& (IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))&& (sensitiveDataSize != 0))
return TPM_RCS_ATTRIBUTES;
switch(publicArea->type){case ALG_KEYEDHASH_VALUE:// if this is a data object (sign == decrypt == CLEAR) then the// TPM cannot be the data source.
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
result = TPM_RC_ATTRIBUTES;// comment out the next line in order to prevent a fixedTPM derivation// parent
break;
case ALG_SYMCIPHER_VALUE:// A restricted key symmetric key (SYMCIPHER and KEYEDHASH)// must have sensitiveDataOrigin SET unless it has fixedParent and// fixedTPM CLEAR.
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)|| IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
result = TPM_RCS_ATTRIBUTES;
break;
default: // Asymmetric keys cannot have the sensitive portion provided
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin))
result = TPM_RCS_ATTRIBUTES;
break;}
if(TPM_RC_SUCCESS == result){result = PublicAttributesValidation(parentObject, publicArea);}
return result;}7.6.3.4

SchemeChecks

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

Page 256
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

Trusted Platform Module Library

Error Returns

Meaning

TPM_RC_HASH

non-duplicable storage key and its parent have different namealgorithm

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_RCS_SCHEME

inconsistent attributes decrypt, sign, restricted and key's scheme ID;or hash algorithm is inconsistent with the scheme ID for keyed hashobject

TPM_RC_SYMMETRIC

a storage key with no symmetric algorithm specified; or non-storage
key with symmetric algorithm different from ALG_NULL

TPM_RC
SchemeChecks(
OBJECT
TPMT_PUBLIC)*parentObject,*publicArea// IN: parent (null if primary seed)// IN: public area of the object{
TPMT_SYM_DEF_OBJECT
TPM_ALG_ID
TPMA_OBJECT
TPMU_PUBLIC_PARMS*symAlgs = NULL;
scheme = TPM_ALG_NULL;
attributes = publicArea->objectAttributes;*parms = &publicArea->parameters;//
switch(publicArea->type){case ALG_SYMCIPHER_VALUE:
symAlgs = &parms->symDetail.sym;// If this is a decrypt key, then only the block cipher modes (not// SMAC) are valid. TPM_ALG_NULL is OK too. If this is a 'sign' key,// then any mode that got through the unmarshaling is OK.
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)&& !CryptSymModeIsValid(symAlgs->mode.sym, TRUE))
return TPM_RCS_SCHEME;
break;
case ALG_KEYEDHASH_VALUE:
scheme = parms->keyedHashDetail.scheme.scheme;// if both sign and decryptif(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)== IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){// if both sign and decrypt are set or clear, then need// ALG_NULL as scheme
if(scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;}
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)&& scheme != TPM_ALG_HMAC)
return TPM_RCS_SCHEME;
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){if(scheme != TPM_ALG_XOR)
return TPM_RCS_SCHEME;// If this is a derivation parent, then the KDF needs to be// SP800-108 for this implementation. This is the only derivation// supported by this implementation. Other implementations could// support additional schemes. There is no default.
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)){if(parms->keyedHashDetail.scheme.details.xor.kdf!= TPM_ALG_KDF1_SP800_108)
return TPM_RCS_SCHEME;// Must select a digest.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 257
April 15, 2019

Trusted Platform Module Library
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

Part 4: Supporting Routines

if(CryptHashGetDigestSize(parms->keyedHashDetail.scheme.details.xor.hashAlg) == 0)
return TPM_RCS_HASH;}}
break;
default: // handling for asymmetricscheme = parms->asymDetail.scheme.scheme;
symAlgs = &parms->asymDetail.symmetric;// if the key is both sign and decrypt, then the scheme must be// ALG_NULL because there is no way to specify both a sign and a// decrypt scheme in the key.
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)== IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){// scheme must be TPM_ALG_NULL
if(scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;}
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)){// If this is a signing key, see if it has a signing scheme
if(CryptIsAsymSignScheme(publicArea->type, scheme)){// if proper signing scheme then it needs a proper hashif(parms->asymDetail.scheme.details.anySig.hashAlg== TPM_ALG_NULL)
return TPM_RCS_SCHEME;}
else{// signing key that does not have a proper signing scheme.
// This is OK if the key is not restricted and its scheme// is TPM_ALG_NULL
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)|| scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;}}
else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)){// for a restricted decryption key (a parent), scheme// is required to be TPM_ALG_NULL
if(scheme != TPM_ALG_NULL)
return TPM_RCS_SCHEME;}
else{// For an unrestricted decryption key, the scheme has to// be a valid scheme or TPM_ALG_NULL
if(scheme != TPM_ALG_NULL &&!CryptIsAsymDecryptScheme(publicArea->type, scheme))
return TPM_RCS_SCHEME;}}
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)|| !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){// For an asymmetric key that is not a parent, the symmetric// algorithms must be TPM_ALG_NULL
if(symAlgs->algorithm != TPM_ALG_NULL)
return TPM_RCS_SYMMETRIC;}// Special checks for an ECC key

Page 258
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

#if

Trusted Platform Module Library

ALG_ECCif(publicArea->type == TPM_ALG_ECC){
TPM_ECC_CURVE
curveID;
const TPMT_ECC_SCHEME*curveScheme;
curveID = publicArea->parameters.eccDetail.curveID;
curveScheme = CryptGetCurveSignScheme(curveID);// The curveId must be valid or the unmarshaling is busted.
pAssert(curveScheme != NULL);// If the curveID requires a specific scheme, then the key must// select the same scheme
if(curveScheme->scheme != TPM_ALG_NULL){
TPMS_ECC_PARMS*ecc = &publicArea->parameters.eccDetail;if(scheme != curveScheme->scheme)
return TPM_RCS_SCHEME;// The scheme can allow any hash, or not...
if(curveScheme->details.anySig.hashAlg != TPM_ALG_NULL&& (ecc->scheme.details.anySig.hashAlg!= curveScheme->details.anySig.hashAlg))
return TPM_RCS_SCHEME;}// For now, the KDF must be TPM_ALG_NULL
if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL)
return TPM_RCS_KDF;}#endifbreak;}// If this is a restricted decryption key with symmetric algorithms, then it// is an ordinary parent (not a derivation parent). It needs to specific// symmetric algorithms other than TPM_ALG_NULL
if(symAlgs != NULL&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){if(symAlgs->algorithm == TPM_ALG_NULL)
return TPM_RCS_SYMMETRIC;
#if 0
//??
// This next check is under investigation. Need to see if it will break Windows// before it is enabled. If it does not, then it should be default because a// the mode used with a parent is always CFB and Part 2 indicates as much.
if(symAlgs->mode.sym != TPM_ALG_CFB)
return TPM_RCS_MODE;#endif// If this parent is not duplicable, then the symmetric algorithms// (encryption and hash) must match those of its parentif(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)&& (parentObject != NULL)){
if(publicArea->nameAlg != parentObject->publicArea.nameAlg)
return TPM_RCS_HASH;
if(!MemoryEqual(symAlgs, &parentObject->publicArea.parameters,
sizeof(TPMT_SYM_DEF_OBJECT)))
return TPM_RCS_SYMMETRIC;}}
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 259
April 15, 2019

Trusted Platform Module Library

7.6.3.5

Part 4: Supporting Routines

PublicAttributesValidation()

This function validates the values in the public area of an object. This function is used in the processing of
TPM2_Create(), TPM2_CreatePrimary(), TPM2_CreateLoaded(), TPM2_Load(), TPM2_Import(), andTPM2_LoadExternal(). For TPM2_Import() this is only used if the new parent has fixedTPM SET. For
TPM2_LoadExternal(), this is not used for a public-only key

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496

Error Returns

Meaning

TPM_RC_ATTRIBUTES

fixedTPM, fixedParent, or encryptedDuplication attributes areinconsistent between themselves or with those of the parent object;inconsistent restricted, decrypt and sign attributes; attempt to injectsensitive data for an asymmetric key; attempt to create a symmetriccipher key that is not a decryption key

TPM_RC_HASH

nameAlg is TPM_ALG_NULL

TPM_RC_SIZE

authPolicy size does not match digest size of the name algorithm inpublicArea

other

returns from SchemeChecks()

TPM_RC
PublicAttributesValidation(
OBJECT
TPMT_PUBLIC)*parentObject,*publicArea// IN: input parent object// IN: public area of the object

TPMA_OBJECT
TPMA_OBJECT

attributes = publicArea->objectAttributes;
parentAttributes = {0};{//if(parentObject != NULL)
parentAttributes = parentObject->publicArea.objectAttributes;
if(publicArea->nameAlg == TPM_ALG_NULL)
return TPM_RCS_HASH;// If there is an authPolicy, it needs to be the size of the digest produced// by the nameAlg of the object
if((publicArea->authPolicy.t.size != 0&& (publicArea->authPolicy.t.size!= CryptHashGetDigestSize(publicArea->nameAlg))))return TPM_RCS_SIZE;// If the parent is fixedTPM (including a Primary Object) the object must have// the same value for fixedTPM and fixedParent
if(parentObject == NULL|| IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)){
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)!= IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
return TPM_RCS_ATTRIBUTES;}
else{// The parent is not fixedTPM so the object can't be fixedTPM
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
return TPM_RCS_ATTRIBUTES;}// See if sign and decrypt are the sameif(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)== IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)){// a restricted key cannot have both SET or both CLEAR
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
return TPM_RC_ATTRIBUTES;// only a data object may have both sign and decrypt CLEAR// BTW, since we know that decrypt==sign, no need to check bothPage 260
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Trusted Platform Module Libraryif(publicArea->type != TPM_ALG_KEYEDHASH&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
return TPM_RC_ATTRIBUTES;}// If the object can't be duplicated (directly or indirectly) then there// is no justification for having encryptedDuplication SET
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)&& IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES;// If a parent object has fixedTPM CLEAR, the child must have the// same encryptedDuplication value as its parent.
// Primary objects are considered to have a fixedTPM parent (the seeds).
if(parentObject != NULL&& !IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)){
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)!= IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES;}// Special checks for derived objects
if((parentObject != NULL) && (parentObject->attributes.derivation == SET)){// A derived object has the same settings for fixedTPM as its parentif(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)!= IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM))
return TPM_RCS_ATTRIBUTES;// A derived object is required to be fixedParent
if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
return TPM_RCS_ATTRIBUTES;}
return SchemeChecks(parentObject, publicArea);}

7.6.3.6

FillInCreationData()

Fill in creation data for an object.
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

void
FillInCreationData(
TPMI_DH_OBJECT
TPMI_ALG_HASH
TPML_PCR_SELECTION
TPM2B_DATA
TPM2B_CREATION_DATA
TPM2B_DIGEST)

parentHandle, // IN: handle of parent
nameHashAlg,// IN: name hash algorithm*creationPCR,// IN: PCR selection*outsideData,// IN: outside data
*outCreation,// OUT: creation data for output*creationDigest // OUT: creation digest

{
BYTE
BYTE
HASH_STATE

creationBuffer[sizeof(TPMS_CREATION_DATA)];*buffer;hashState;//// Fill in TPMS_CREATION_DATA in outCreation// Compute PCR digest
PCRComputeCurrentDigest(nameHashAlg, creationPCR,&outCreation->creationData.pcrDigest);// Put back PCR selection list
outCreation->creationData.pcrSelect = *creationPCR;// Get locality
outCreation->creationData.locality= LocalityGetAttributes(_plat__LocalityGet());
outCreation->creationData.parentNameAlg = TPM_ALG_NULL;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 261
April 15, 2019

Trusted Platform Module Library
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

Part 4: Supporting Routines// If the parent is either a primary seed or TPM_ALG_NULL, then the Name// and QN of the parent are the parent's handle.
if(HandleGetType(parentHandle) == TPM_HT_PERMANENT){
buffer = &outCreation->creationData.parentName.t.name[0];outCreation->creationData.parentName.t.size =TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL);// For a primary or temporary object, the parent name (a handle) and the// parent's QN are the same
outCreation->creationData.parentQualifiedName= outCreation->creationData.parentName;}
else// Regular object{
OBJECT*parentObject = HandleToObject(parentHandle);//// Set name algorithm
outCreation->creationData.parentNameAlg = parentObject->publicArea.nameAlg;// Copy parent nameoutCreation->creationData.parentName = parentObject->name;// Copy parent qualified nameoutCreation->creationData.parentQualifiedName = parentObject->qualifiedName;}// Copy outside information
outCreation->creationData.outsideInfo = *outsideData;// Marshal creation data to canonical form
buffer = creationBuffer;
outCreation->size = TPMS_CREATION_DATA_Marshal(&outCreation->creationData,&buffer, NULL);// Compute hash for creation field in public template
creationDigest->t.size = CryptHashStart(&hashState, nameHashAlg);
CryptDigestUpdate(&hashState, outCreation->size, creationBuffer);
CryptHashEnd2B(&hashState, &creationDigest->b);
return;}7.6.3.7

GetSeedForKDF()

Get a seed for KDF. The KDF for encryption and HMAC key use the same seed.
596
597
598
599
600
601
602
603
604
605
606
607
608
609

const TPM2B *GetSeedForKDF(
OBJECT)*protector// IN: the protector handle{// Get seed for encryption key. Use input seed if provided.
// Otherwise, using protector object's seedValue. TPM_RH_NULL is the only// exception that we may not have a loaded object as protector. In such a// case, use nullProof as seed.
if(protector == NULL)
return &gr.nullProof.b;
else
return &protector->sensitive.seedValue.b;}

Page 262
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.6.3.8

Trusted Platform Module Library

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:
Add IV before sensitive area if required
encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv
add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

UINT16
ProduceOuterWrap(
OBJECT*protector,

TPM2B
TPM_ALG_ID
TPM2B*name,
hashAlg,*seed,BOOL
UINT16useIV,
dataSize,

BYTE*outerBuffer// IN: The handle of the object that provides//
protection. For object, it is parent//
handle. For credential, it is the handle//
of encrypt object.
// IN: the name of the object// IN: hash algorithm for outer wrap// IN: an external seed may be provided for//
duplication blob. For non duplication//
blob, this parameter should be NULL// IN: indicate if an IV is used// IN: the size of sensitive data, excluding the//leading integrity buffer size or the//
optional iv size// IN/OUT: outer buffer with sensitive data in
//
it

)
{
TPM_ALG_ID
UINT16
TPM2B_SYM_KEY
TPM2B_IV
TPM2B_IVUINT16BYTE
TPM2B_DIGESTUINT16
BYTE

symAlg;
keyBits;
symKey;ivRNG;// IV from RNG*iv = NULL;
ivSize = 0;// size of iv area, including the size field*sensitiveData; // pointer to the sensitive data
integrity;
integritySize;*buffer;// Auxiliary buffer pointer//// Compute the beginning of sensitive data. The outer integrity should// always exist if this function is called to make an outer wrap
integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);sensitiveData = outerBuffer + integritySize;// If iv is used, adjust the pointer of sensitive data and add iv before it
if(useIV){
ivSize = GetIV2BSize(protector);// Generate IV from RNG. The iv data size should be the total IV area// size minus the size of size fieldivRNG.t.size = ivSize - sizeof(UINT16);
CryptRandomGenerate(ivRNG.t.size, ivRNG.t.buffer);// Marshal IV to buffer
buffer = sensitiveData;
TPM2B_IV_Marshal(&ivRNG, &buffer, NULL);// adjust sensitive data starting after IV area
sensitiveData += ivSize;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 263
April 15, 2019

Trusted Platform Module Library
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682

Part 4: Supporting Routines// Use iv for encryptioniv = &ivRNG;}// Compute symmetric key parameters for outer buffer encryption
ComputeProtectionKeyParms(protector, hashAlg, name, seed,&symAlg, &keyBits, &symKey);// Encrypt inner buffer in place
CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits,
symKey.t.buffer, iv, TPM_ALG_CFB, dataSize,sensitiveData);// Compute outer integrity. Integrity computation includes the optional IV// area
ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize,outerBuffer + integritySize, &integrity);// Add integrity at the beginning of outer buffer
buffer = outerBuffer;
TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);// return the total size in outer wrap
return dataSize + integritySize + ivSize;}

7.6.3.9

UnwrapOuter()This function remove the outer wrap of a blob containing sensitive data This function performs:
check integrity of outer blobdecrypt outer blob

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707

Error Returns

Meaning

TPM_RCS_INSUFFICIENT

error during sensitive data unmarshaling

TPM_RCS_INTEGRITY

sensitive data integrity is broken

TPM_RCS_SIZE

error during sensitive data unmarshaling

TPM_RCS_VALUE

IV size for CFB does not match the encryption algorithm block size

TPM_RC
UnwrapOuter(
OBJECT*protector,// IN: The object that provides//
protection. For object, it is parent//
handle. For credential, it is the//encrypt object.
// IN: the name of the object// IN: hash algorithm for outer wrap// IN: an external seed may be provided for//
duplication blob. For non duplication//
blob, this parameter should be NULL.
// IN: indicates if an IV is used// IN: size of sensitive data in outerBuffer,//including the leading integrity buffer//
size, and an optional iv area// IN/OUT: sensitive data

TPM2B
TPM_ALG_ID
TPM2B*name,
hashAlg,*seed,BOOL
UINT16useIV,
dataSize,

BYTE)*outerBuffer

TPM_RCTPM_ALG_ID
TPM2B_SYM_KEY
UINT16
TPM2B_IV
TPM2B_IV
BYTE

result;symAlg = TPM_ALG_NULL;
symKey;keyBits = 0;
ivIn;// input IV retrieved from input buffer*iv = NULL;*sensitiveData;// pointer to the sensitive data{

Page 264
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751

TPM2B_DIGESTTPM2B_DIGEST
INT32

Trusted Platform Module Library

integrityToCompare;
integrity;
size;

//
// Unmarshal integrity
sensitiveData = outerBuffer;size = (INT32)dataSize;
result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size);if(result == TPM_RC_SUCCESS){// Compute integrity to compare
ComputeOuterIntegrity(name, protector, hashAlg, seed,(UINT16)size, sensitiveData,&integrityToCompare);// Compare outer blob integrityif(!MemoryEqual2B(&integrity.b, &integrityToCompare.b))
return TPM_RCS_INTEGRITY;// Get the symmetric algorithm parameters used for encryption
ComputeProtectionKeyParms(protector, hashAlg, name, seed,&symAlg, &keyBits, &symKey);// Retrieve IV if it is used
if(useIV){
result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size);if(result == TPM_RC_SUCCESS){// The input iv size for CFB must match the encryption algorithm// block size
if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits))
result = TPM_RC_VALUE;else
iv = &ivIn;}}}// If no errors, decrypt private in place. Since this function uses CFB,// CryptSymmetricDecrypt() will not return any errors. It may fail but it will// not return an error.
if(result == TPM_RC_SUCCESS)
CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits,
symKey.t.buffer, iv, TPM_ALG_CFB,(UINT16)size, sensitiveData);
return result;}7.6.3.10

MarshalSensitive()

This function is used to marshal a sensitive area. Among other things, it adjusts the size of the authValue
to be no smaller than the digest of nameAlg. It will also make sure that the RSA sensitive contains theright number of values. Returns the size of the marshaled area.
752
753
754
755
756
757
758
759
760
761
762
763
764

static UINT16
MarshalSensitive(
OBJECT
BYTE
TPMT_SENSITIVE
TPMI_ALG_HASH)*parent,*buffer,*sensitive,
nameAlg

BYTE*sizeField = buffer;

UINT16

retVal;// IN: the object parent (optional)// OUT: receiving buffer// IN: the sensitive area to marshal// IN:{// saved so that size can be// marshaled after it is known//// Pad the authValue if needed

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 265
April 15, 2019

Trusted Platform Module Library
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797

Part 4: Supporting Routines

MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg));
buffer += 2;// Marshal the structure#if ALG_RSA// If the sensitive size is the special case for a prime in the typeif((sensitive->sensitive.rsa.t.size & RSA_prime_flag) > 0){
UINT16
sizeSave = sensitive->sensitive.rsa.t.size;//// Turn off the flag that indicates that the sensitive->sensitive contains// the CRT form of the exponent.
sensitive->sensitive.rsa.t.size &= ~(RSA_prime_flag);// If the parent isn't fixedTPM, then truncate the sensitive data to be// the size of the prime. Otherwise, leave it at the current size which// is the full CRT size.
if(parent == NULL|| !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
TPMA_OBJECT, fixedTPM))
sensitive->sensitive.rsa.t.size /= 5;
retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL);// Restore the flag and the size.
sensitive->sensitive.rsa.t.size = sizeSave;}
else#endifretVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL);// Marshal the size
retVal = (UINT16)(retVal + UINT16_Marshal(&retVal, &sizeField, NULL));
return retVal;}

7.6.3.11

SensitiveToPrivate()

This function prepare the private blob for off the chip storage The operations in this function:
marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE
apply encryption to the sensitive area.
apply outer integrity computation.
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818

void
SensitiveToPrivate(
TPMT_SENSITIVE
TPM2B_NAMEOBJECT
TPM_ALG_ID*sensitive,*name,*parent,
nameAlg,

TPM2B_PRIVATE)*outPrivate// IN: sensitive structure// IN: the name of the object// IN: The parent object// IN: hash algorithm in public area. This//parameter is used when parentHandle is//
NULL, in which case the object is//
temporary.
// OUT: output private structure{
BYTE
UINT16
TPMI_ALG_HASHUINT16
UINT16*sensitiveData;
dataSize;
hashAlg;
integritySize;
ivSize;// pointer to the sensitive data// data blob size// hash algorithm for integrity//
pAssert(name != NULL && name->t.size != 0);// Find the hash algorithm for integrity computation

Page 266
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

Trusted Platform Module Libraryif(parent == NULL){// For Temporary Object, using self name algorithm
hashAlg = nameAlg;}
else{// Otherwise, using parent's name algorithm
hashAlg = parent->publicArea.nameAlg;}// Starting of sensitive data without wrappers
sensitiveData = outPrivate->t.buffer;// Compute the integrity size
integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);// Reserve space for integrity
sensitiveData += integritySize;// Get iv size
ivSize = GetIV2BSize(parent);// Reserve space for iv
sensitiveData += ivSize;// Marshal the sensitive area including authValue size adjustments.
dataSize = MarshalSensitive(parent, sensitiveData, sensitive, nameAlg);//Produce outer wrap, including encryption and HMAC
outPrivate->t.size = ProduceOuterWrap(parent, &name->b, hashAlg, NULL,
TRUE, dataSize, outPrivate->t.buffer);
return;}7.6.3.12

PrivateToSensitive()

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

852
853
854
855
856
857
858
859
860
861

Error Returns

Meaning

TPM_RCS_INTEGRITY

if the private area integrity is bad

TPM_RC_SENSITIVE

unmarshal errors while unmarshaling TPMS_ENCRYPT from input
private

TPM_RCS_SIZE

error during sensitive data unmarshaling

TPM_RCS_VALUE

outer wrapper does not have an iV of the correct size

TPM_RCPrivateToSensitive(
TPM2B
TPM2B
OBJECT
TPM_ALG_ID*inPrivate,*name,*parent,
nameAlg,

Family “2.0”Level 00 Revision 01.55// IN: input private structure// IN: the name of the object// IN: parent object// IN: hash algorithm in public area. It is//passed separately because we only pass//
name, rather than the whole public area//of the object. This parameter is used in//
the following two cases: 1. primary

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 267
April 15, 2019

Trusted Platform Module Library
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920

Part 4: Supporting Routines//
objects. 2. duplication blob with inner//wrap. In other cases, this parameter//
will be ignored// OUT: sensitive structure

TPMT_SENSITIVE)*sensitive

TPM_RC
BYTE
INT32
BYTE
UINT16
UINT16
TPMI_ALG_HASHUINT16
UINT16

result;*buffer;size;*sensitiveData; // pointer to the sensitive data
dataSize;
dataSizeInput;
hashAlg;// hash algorithm for integrity
integritySize;
ivSize;{//// Make sure that name is provided
pAssert(name != NULL && name->size != 0);// Find the hash algorithm for integrity computation// For Temporary Object (parent == NULL) use self name algorithm;// Otherwise, using parent's name algorithm
hashAlg = (parent == NULL) ? nameAlg : parent->publicArea.nameAlg;// unwrap outerresult = UnwrapOuter(parent, name, hashAlg, NULL, TRUE,
inPrivate->size, inPrivate->buffer);
if(result != TPM_RC_SUCCESS)
return result;// Compute the inner integrity size.
integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg);// Get iv size
ivSize = GetIV2BSize(parent);// The starting of sensitive data and data size without outer wrapper
sensitiveData = inPrivate->buffer + integritySize + ivSize;
dataSize = inPrivate->size - integritySize - ivSize;// Unmarshal input data size
buffer = sensitiveData;
size = (INT32)dataSize;
result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);if(result == TPM_RC_SUCCESS){
if((dataSizeInput + sizeof(UINT16)) != dataSize)
result = TPM_RC_SENSITIVE;
else{// Unmarshal sensitive buffer to sensitive structure
result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);if(result != TPM_RC_SUCCESS || size != 0){
result = TPM_RC_SENSITIVE;}}}
return result;}7.6.3.13

SensitiveToDuplicate()

This function prepare the duplication blob from the sensitive area. The operations in this function:

Page 268
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE
apply inner wrap to the sensitive area if required
apply outer wrap if required
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980

void
SensitiveToDuplicate(
TPMT_SENSITIVE
TPM2B
OBJECT
TPM_ALG_ID*sensitive,*name,*parent,
nameAlg,

TPM2B*seed,

TPMT_SYM_DEF_OBJECT *symDef,
TPM2B_DATA*innerSymKey,

TPM2B_PRIVATE)*outPrivate// IN: sensitive structure// IN: the name of the object// IN: The new parent object// IN: hash algorithm in public area. It//
is passed separately because we//only pass name, rather than the//whole public area of the object.
// IN: the external seed. If external//
seed is provided with size of 0,//
no outer wrap should be applied//
to duplication blob.
// IN: Symmetric key definition. If the//symmetric key algorithm is NULL,//
no inner wrap should be applied.
// IN/OUT: a symmetric key may be//provided to encrypt the inner//
wrap of a duplication blob. May//
be generated here if needed.
// OUT: output private structure{
BYTE
TPMI_ALG_HASH
TPMI_ALG_HASHUINT16
BOOL
BOOL*sensitiveData; // pointer to the sensitive data
outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap
innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap
dataSize;// data blob size
doInnerWrap = FALSE;
doOuterWrap = FALSE;//// Make sure that name is provided
pAssert(name != NULL && name->size != 0);// Make sure symDef and innerSymKey are not NULL
pAssert(symDef != NULL && innerSymKey != NULL);// Starting of sensitive data without wrappers
sensitiveData = outPrivate->t.buffer;// Find out if inner wrap is requiredif(symDef->algorithm != TPM_ALG_NULL){
doInnerWrap = TRUE;// Use self nameAlg as inner hash algorithm
innerHash = nameAlg;// Adjust sensitive data pointersensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(innerHash);}// Find out if outer wrap is required
if(seed->size != 0){
doOuterWrap = TRUE;// Use parent nameAlg as outer hash algorithm
outerHash = parent->publicArea.nameAlg;// Adjust sensitive data pointersensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 269
April 15, 2019

Trusted Platform Module Library
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

Part 4: Supporting Routines}// Marshal sensitive area
dataSize = MarshalSensitive(NULL, sensitiveData, sensitive, nameAlg);// Apply inner wrap for duplication blob. It includes both integrity and// encryption
if(doInnerWrap){
BYTE*innerBuffer = NULL;
BOOL
symKeyInput = TRUE;
innerBuffer = outPrivate->t.buffer;// Skip outer integrity space
if(doOuterWrap)
innerBuffer += sizeof(UINT16) + CryptHashGetDigestSize(outerHash);dataSize = ProduceInnerIntegrity(name, innerHash, dataSize,
innerBuffer);// Generate inner encryption key if needed
if(innerSymKey->t.size == 0){
innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8;
CryptRandomGenerate(innerSymKey->t.size, innerSymKey->t.buffer);// TPM generates symmetric encryption.
symKeyInput = FALSE;

Set the flag to FALSE

}
else
{
// assume the input key size should matches the symmetric definition
pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);}// Encrypt inner buffer in place
CryptSymmetricEncrypt(innerBuffer, symDef->algorithm,
symDef->keyBits.sym, innerSymKey->t.buffer, NULL,
TPM_ALG_CFB, dataSize, innerBuffer);// If the symmetric encryption key is imported, clear the buffer for// output
if(symKeyInput)
innerSymKey->t.size = 0;}// Apply outer wrap for duplication blob. It includes both integrity and// encryption
if(doOuterWrap){
dataSize = ProduceOuterWrap(parent, name, outerHash, seed, FALSE,
dataSize, outPrivate->t.buffer);}// Data size for output
outPrivate->t.size = dataSize;
return;}7.6.3.14

DuplicateToSensitive()

Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The
operations in this function:

Page 270
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Librarycheck the integrity HMAC of the input private area
decrypt the private buffer
unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085

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

TPM_RC
DuplicateToSensitive(
TPM2B
TPM2B
OBJECT
TPM_ALG_ID
TPM2B*inPrivate,*name,*parent,
nameAlg,*seed,

TPMT_SYM_DEF_OBJECT *symDef,// IN: input private structure// IN: the name of the object// IN: the parent// IN: hash algorithm in public area.
// IN: an external seed may be provided.
//
If external seed is provided with//size of 0, no outer wrap is//applied// IN: Symmetric key definition. If the//symmetric key algorithm is NULL,//
no inner wrap is applied// IN: a symmetric key may be provided//
to decrypt the inner wrap of a//
duplication blob.
// OUT: sensitive structure

TPM2B*innerSymKey,

TPMT_SENSITIVE)*sensitive

TPM_RC
BYTE
INT32
BYTE
UINT16
UINT16

result;*buffer;size;*sensitiveData; // pointer to the sensitive data
dataSize;
dataSizeInput;{//// Make sure that name is provided
pAssert(name != NULL && name->size != 0);// Make sure symDef and innerSymKey are not NULL
pAssert(symDef != NULL && innerSymKey != NULL);// Starting of sensitive data
sensitiveData = inPrivate->buffer;
dataSize = inPrivate->size;// Find out if outer wrap is appliedif(seed->size != 0){// Use parent nameAlg as outer hash algorithm
TPMI_ALG_HASH
outerHash = parent->publicArea.nameAlg;
result = UnwrapOuter(parent, name, outerHash, seed, FALSE,
dataSize, sensitiveData);
if(result != TPM_RC_SUCCESS)
return result;// Adjust sensitive data pointer and size
sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash);dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(outerHash);}// Find out if inner wrap is appliedif(symDef->algorithm != TPM_ALG_NULL)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 271
April 15, 2019

Trusted Platform Module Library
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

Part 4: Supporting Routines{// assume the input key size matches the symmetric definition
pAssert(innerSymKey->size == (symDef->keyBits.sym + 7) / 8);// Decrypt inner buffer in place
CryptSymmetricDecrypt(sensitiveData, symDef->algorithm,
symDef->keyBits.sym, innerSymKey->buffer, NULL,
TPM_ALG_CFB, dataSize, sensitiveData);// Check inner integrity
result = CheckInnerIntegrity(name, nameAlg, dataSize, sensitiveData);
if(result != TPM_RC_SUCCESS)
return result;// Adjust sensitive data pointer and size
sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(nameAlg);
dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(nameAlg);}// Unmarshal input data size
buffer = sensitiveData;
size = (INT32)dataSize;
result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);if(result == TPM_RC_SUCCESS){
if((dataSizeInput + sizeof(UINT16)) != dataSize)
result = TPM_RC_SIZE;
else{// Unmarshal sensitive buffer to sensitive structure
result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);// if the results is OK make sure that all the data was unmarshaled
if(result == TPM_RC_SUCCESS && size != 0)
result = TPM_RC_SIZE;}}
return result;}7.6.3.15

SecretToCredential()

This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in thisfunction:
marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT
encrypt the private buffer, excluding the leading integrity HMAC area
compute integrity HMAC and append to the beginning of the buffer.
Set the total size of TPM2B_ID_OBJECT buffer
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136

void
SecretToCredential(
TPM2B_DIGEST
TPM2B
TPM2B
OBJECT
TPM2B_ID_OBJECT)*secret,*name,*seed,*protector,*outIDObject// IN: secret information// IN: the name of the object// IN: an external seed.
// IN: the protector// OUT: output credential

BYTE
BYTE
TPMI_ALG_HASHUINT16*buffer;// Auxiliary buffer pointer*sensitiveData; // pointer to the sensitive data
outerHash;// The hash algorithm for outer wrap
dataSize;// data blob size{//
pAssert(secret != NULL && outIDObject != NULL);

Page 272
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

Trusted Platform Module Library// use protector's name algorithm as outer hash ????
outerHash = protector->publicArea.nameAlg;// Marshal secret area to credential buffer, leave space for integrity
sensitiveData = outIDObject->t.credential+ sizeof(UINT16) + CryptHashGetDigestSize(outerHash);// Marshal secret area
buffer = sensitiveData;
dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL);// Apply outer wrap
outIDObject->t.size = ProduceOuterWrap(protector, name, outerHash, seed, FALSE,
dataSize, outIDObject->t.credential);
return;}7.6.3.16

CredentialToSecret()

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

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180

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

TPM_RC
CredentialToSecret(
TPM2B
TPM2B
TPM2B
OBJECT
TPM2B_DIGEST)*inIDObject,*name,*seed,*protector,*secret// IN: input credential blob// IN: the name of the object// IN: an external seed.
// IN: the protector// OUT: secret information{
TPM_RCBYTE
INT32
TPMI_ALG_HASH
BYTE
UINT16

result;*buffer;size;outerHash;// The hash algorithm for outer wrap
*sensitiveData; // pointer to the sensitive data
dataSize;//// use protector's name algorithm as outer hashouterHash = protector->publicArea.nameAlg;// Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point
result = UnwrapOuter(protector, name, outerHash, seed, FALSE,
inIDObject->size, inIDObject->buffer);
if(result == TPM_RC_SUCCESS){// Compute the beginning of sensitive data
sensitiveData = inIDObject->buffer+ sizeof(UINT16) + CryptHashGetDigestSize(outerHash);dataSize = inIDObject->size

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 273
April 15, 2019

Trusted Platform Module Library
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

Part 4: Supporting Routines- (sizeof(UINT16) + CryptHashGetDigestSize(outerHash));// Unmarshal secret buffer to TPM2B_DIGEST structure
buffer = sensitiveData;
size = (INT32)dataSize;
result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size);// If there were no other unmarshaling errors, make sure that the// expected amount of data was recovered
if(result == TPM_RC_SUCCESS && size != 0)
return TPM_RC_SIZE;}
return result;}7.6.3.17

MemoryRemoveTrailingZeros()This function is used to adjust the length of an authorization value. It adjusts the size of the TPM2B sothat it does not include octets at the end of the buffer that contain zero. The function returns the numberof non-zero octets in the buffer.
1194
1195
1196
1197
1198
1199
1200
1201
1202

UINT16
MemoryRemoveTrailingZeros(
TPM2B_AUTH
)

*auth

// IN/OUT: value to adjust{
while((auth->t.size > 0) && (auth->t.buffer[auth->t.size - 1] == 0))auth->t.size--;
return auth->t.size;}

7.6.3.18

SetLabelAndContext()

This function sets the label and context for a derived key. It is possible that label or context can end up
being an Empty Buffer.
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229

TPM_RC
SetLabelAndContext(
TPMS_DERIVE*labelContext,

TPM2B_SENSITIVE_DATA)*sensitive

TPMS_DERIVETPM_RC
INT32
BYTE

sensitiveValue;
result;size;*buff;// IN/OUT: the recovered label and//context// IN: the sensitive data{//// Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer// If there is something to unmarshal...
if(sensitive->t.size != 0){
size = sensitive->t.size;
buff = sensitive->t.buffer;result = TPMS_DERIVE_Unmarshal(&sensitiveValue, &buff, &size);if(result != TPM_RC_SUCCESS)
return result;// If there was a label in the public area leave it there, otherwise, copy// the new value
if(labelContext->label.t.size == 0)
MemoryCopy2B(&labelContext->label.b, &sensitiveValue.label.b,
sizeof(labelContext->label.t.buffer));// if there was a context string in publicArea, it overrides

Page 274
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1230
1231
1232
1233
1234
1235

Trusted Platform Module Libraryif(labelContext->context.t.size == 0)
MemoryCopy2B(&labelContext->context.b, &sensitiveValue.context.b,
sizeof(labelContext->label.t.buffer));}
return TPM_RC_SUCCESS;}

7.6.3.19

UnmarshalToPublic()

Support function to unmarshal the template. This is used because the Input may be a TPMT_TEMPLATEand that structure does not have the same size as a TPMT_PUBLIC because of the difference between
the unique and seed fields. If derive is not NULL, then the seed field is assumed to contain a label andcontext that are unmarshaled into derive.
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279

TPM_RC
UnmarshalToPublic(
TPMT_PUBLIC
TPM2B_TEMPLATEBOOL
TPMS_DERIVE)*tOut,// OUT: output*tIn,// IN:
derivation, // IN: indicates if this is for a derivation*labelContext// OUT: label and context if derivation

BYTE
INT32
TPM_RC*buffer = tIn->t.buffer;size = tIn->t.size;
result;{//// make sure that tOut is zeroed so that there are no remnants from previous// uses
MemorySet(tOut, 0, sizeof(TPMT_PUBLIC));// Unmarshal the components of the TPMT_PUBLIC up to the unique field
result = TPMI_ALG_PUBLIC_Unmarshal(&tOut->type, &buffer, &size);if(result != TPM_RC_SUCCESS)
return result;result = TPMI_ALG_HASH_Unmarshal(&tOut->nameAlg, &buffer, &size, FALSE);
if(result != TPM_RC_SUCCESS)
return result;result = TPMA_OBJECT_Unmarshal(&tOut->objectAttributes, &buffer, &size);if(result != TPM_RC_SUCCESS)
return result;result = TPM2B_DIGEST_Unmarshal(&tOut->authPolicy, &buffer, &size);if(result != TPM_RC_SUCCESS)
return result;result = TPMU_PUBLIC_PARMS_Unmarshal(&tOut->parameters, &buffer, &size,tOut->type);
if(result != TPM_RC_SUCCESS)
return result;// Now unmarshal a TPMS_DERIVE if this is for derivation
if(derivation)
result = TPMS_DERIVE_Unmarshal(labelContext, &buffer, &size);else// otherwise, unmarshal a TPMU_PUBLIC_ID
result = TPMU_PUBLIC_ID_Unmarshal(&tOut->unique, &buffer, &size,tOut->type);// Make sure the template was used upif((result == TPM_RC_SUCCESS) && (size != 0))
result = TPM_RC_SIZE;
return result;}7.6.3.20

ObjectSetExternal()

Set the external attributes for an object.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 275
April 15, 2019

Trusted Platform Module Library

1280
1281
1282
1283
1284
1285
1286

Part 4: Supporting Routines

void
ObjectSetExternal(
OBJECT)*object{
object->attributes.external = SET;}

Page 276
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

7.7
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

Trusted Platform Module Library

Encrypt Decrypt Support (EncryptDecrypt_spt.c)#include "Tpm.h"#include "EncryptDecrypt_fp.h"#include "EncryptDecrypt_spt_fp.h"#if CC_EncryptDecrypt2
Error Returns

Meaning

TPM_RC_KEY

is not a symmetric decryption key with both public and private
portions loaded

TPM_RC_SIZEIvIn size is incompatible with the block cipher mode; or inData size is
not an even multiple of the block size for CBC or ECB mode

TPM_RC_VALUE

keyHandle is restricted and the argument mode does not match the
key's mode

TPM_RC
EncryptDecryptShared(
TPMI_DH_OBJECT
TPMI_YES_NO
TPMI_ALG_SYM_MODE
TPM2B_IV
TPM2B_MAX_BUFFER
EncryptDecrypt_Out)

keyHandleIn,decryptIn,
modeIn,*ivIn,*inData,*out{
OBJECT*symKey;
UINT16
keySize;
UINT16blockSize;
BYTE
*key;
TPM_ALG_IDalg;
TPM_ALG_ID
mode;
TPM_RC
result;BOOL
OK;// Input Validation
symKey = HandleToObject(keyHandleIn);mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;// The input key should be a symmetric key
if(symKey->publicArea.type != TPM_ALG_SYMCIPHER)
return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle;// The key must be unrestricted and allow the selected operation
OK = !IS_ATTRIBUTE(symKey->publicArea.objectAttributes,
TPMA_OBJECT, restricted);if(YES == decryptIn)
OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes,
TPMA_OBJECT, decrypt);else
OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes,
TPMA_OBJECT, sign);
if(!OK)
return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle;// Make sure that key is an encrypt/decrypt key and not SMAC
if(!CryptSymModeIsValid(mode, TRUE))
return TPM_RCS_MODE + RC_EncryptDecrypt_keyHandle;// If the key mode is not TPM_ALG_NULL...
// or TPM_ALG_NULL
if(mode != TPM_ALG_NULL){// then the input mode has to be TPM_ALG_NULL or the same as the key

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 277
April 15, 2019

Trusted Platform Module Library
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

Part 4: Supporting Routines

if((modeIn != TPM_ALG_NULL) && (modeIn != mode))
return TPM_RCS_MODE + RC_EncryptDecrypt_mode;}else{// if the key mode is null, then the input can't be nullif(modeIn == TPM_ALG_NULL)
return TPM_RCS_MODE + RC_EncryptDecrypt_mode;
mode = modeIn;}// The input iv for ECB mode should be an Empty Buffer. All the other modes// should have an iv size same as encryption block size
keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym;
alg = symKey->publicArea.parameters.symDetail.sym.algorithm;
blockSize = CryptGetSymmetricBlockSize(alg, keySize);// reverify the algorithm. This is mainly to keep static analysis tools happyif(blockSize == 0)
return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle;// Note: When an algorithm is not supported by a TPM, the TPM_ALG_xxx for that// algorithm is not defined. However, it is assumed that the ALG_xxx_VALUE for// the algorithm is always defined. Both have the same numeric value.
// ALG_xxx_VALUE is used here so that the code does not get cluttered with// #ifdef's. Having this check does not mean that the algorithm is supported.
// If it was not supported the unmarshaling code would have rejected it before// this function were called. This means that, depending on the implementation,// the check could be redundant but it doesn't hurt.
if(((mode == ALG_ECB_VALUE) && (ivIn->t.size != 0))|| ((mode != ALG_ECB_VALUE) && (ivIn->t.size != blockSize)))
return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn;// The input data size of CBC mode or ECB mode must be an even multiple of// the symmetric algorithm's block sizeif(((mode == ALG_CBC_VALUE) || (mode == ALG_ECB_VALUE))&& ((inData->t.size % blockSize) != 0))
return TPM_RCS_SIZE + RC_EncryptDecrypt_inData;// Copy IV// Note: This is copied here so that the calls to the encrypt/decrypt functions// will modify the output buffer, not the input buffer
out->ivOut = *ivIn;// Command Output
key = symKey->sensitive.sensitive.sym.t.buffer;// For symmetric encryption, the cipher data size is the same as plain data// size.
out->outData.t.size = inData->t.size;
if(decryptIn == YES){// Decrypt data to output
result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key,&(out->ivOut), mode, inData->t.size,
inData->t.buffer);}else{// Encrypt data to output
result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key,&(out->ivOut), mode, inData->t.size,
inData->t.buffer);}
return result;}#endif // CC_EncryptDecrypt

Page 278
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8

Trusted Platform Module Library

Subsystem

8.1

CommandAudit.c

8.1.1

Introduction

This file contains the functions that support command audit.
8.1.2
1Includes#include "Tpm.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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

void
CommandAuditPreInstall_Init(
void){// Clear all the audit commands
MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands));// TPM_CC_SetCommandCodeAuditStatus always being audited
CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus);// Set initial command audit hash algorithm to be context integrity hash// algorithm
gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG;// Set up audit counter to be 0
gp.auditCounter = 0;// Write command audit persistent data to NV
NV_SYNC_PERSISTENT(auditCommands);
NV_SYNC_PERSISTENT(auditHashAlg);
NV_SYNC_PERSISTENT(auditCounter);return;}8.1.3.2

CommandAuditStartup()This function clears the command audit digest on a TPM Reset.
27
28
29
30
31
32

BOOL
CommandAuditStartup(
STARTUP_TYPE)

type// IN: start up type{if((type != SU_RESTART) && (type != SU_RESUME))

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 279
April 15, 2019

Trusted Platform Module Library
33
34
35
36
37
38

Part 4: Supporting Routines{// Reset the digest size to initialize the digest
gr.commandAuditDigest.t.size = 0;}
return TRUE;}

8.1.3.3

CommandAuditSet()

This function will SET the audit flag for a command. This function will not SET the audit flag for acommand 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.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

Return Value

Meaning

TRUE(1)

command code audit status was changed

FALSE(0)command code audit status was not changed

BOOL
CommandAuditSet(
TPM_CC)

commandCode// IN: command code{
COMMAND_INDEX

commandIndex = CommandCodeToCommandIndex(commandCode);// Only SET a bit if the corresponding command is implemented
if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX){// Can't audit shutdown
if(commandCode != TPM_CC_Shutdown){
if(!TEST_BIT(commandIndex, gp.auditCommands)){// Set bit
SET_BIT(commandIndex, gp.auditCommands);
return TRUE;}}}// No change
return FALSE;}

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 280
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)

command code audit status was changed

FALSE(0)command code audit status was not changed

BOOL
CommandAuditClear(
TPM_CC)

commandCode// IN: command code{
COMMAND_INDEX

commandIndex = CommandCodeToCommandIndex(commandCode);// Do nothing if the command is not implemented
if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX){// The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be// clearedif(commandCode != TPM_CC_SetCommandCodeAuditStatus){
if(TEST_BIT(commandIndex, gp.auditCommands)){// Clear bit
CLEAR_BIT(commandIndex, gp.auditCommands);
return TRUE;}}}// No change
return FALSE;}

8.1.3.5

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

88
89
90
91
92
93
94
95

Return Value

Meaning

TRUE(1)

command is audited

FALSE(0)command is not audited

BOOL
CommandAuditIsRequired(
COMMAND_INDEX)

commandIndex// IN: command index{// Check the bit map. If the bit is SET, command audit is required
return(TEST_BIT(commandIndex, gp.auditCommands));}

8.1.3.6

CommandAuditCapGetCCList()

This function returns a list of commands that have their audit bit SET.
The list starts at the input commandCode.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 281
April 15, 2019

Trusted Platform Module Library

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

Part 4: Supporting Routines

Return Value

Meaning

YES

if there are more command code available

NO

all the available command code has been returned

TPMI_YES_NO
CommandAuditCapGetCCList(
TPM_CCUINT32
TPML_CC)

commandCode,count,*commandList

TPMI_YES_NO
COMMAND_INDEX

more = NO;commandIndex;// IN: start command code// IN: count of returned TPM_CC// OUT: list of TPM_CC{// Initialize output handle list
commandList->count = 0;// The maximum count of command we may return is MAX_CAP_CC
if(count > MAX_CAP_CC) count = MAX_CAP_CC;// Find the implemented command that has a command code that is the same or// higher than the input// Collect audit commandsfor(commandIndex = GetClosestCommandIndex(commandCode);
commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
commandIndex = GetNextCommandIndex(commandIndex)){if(CommandAuditIsRequired(commandIndex)){
if(commandList->count < count){// If we have not filled up the return list, add this command// code to its
TPM_CC
cc = GET_ATTRIBUTE(s_ccAttr[commandIndex],
TPMA_CC, commandIndex);if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
cc += (1 << 29);
commandList->commandCodes[commandList->count] = cc;commandList->count++;}else{// If the return list is full but we still have command// available, report this and stop iterating
more = YES;
break;}}}
return more;}

8.1.3.7

CommandAuditGetDigest

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

void
CommandAuditGetDigest(

Page 282
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

TPM2B_DIGEST)*digestTrusted Platform Module Library// OUT: command digest{
TPM_CCCOMMAND_INDEXHASH_STATE

commandCode;commandIndex;
hashState;// Start hashdigest->t.size = CryptHashStart(&hashState, gp.auditHashAlg);// Add command codefor(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++){if(CommandAuditIsRequired(commandIndex)){commandCode = GetCommandCode(commandIndex);
CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode);}}// Complete hash
CryptHashEnd2B(&hashState, &digest->b);
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 283
April 15, 2019

Trusted Platform Module Library

8.2

Part 4: Supporting Routines

DA.c

8.2.1

Introduction

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

Includes and Data Definitions#define DA_C
#include "Tpm.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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

void
DAPreInstall_Init(
void){
gp.failedTries = 0;
gp.maxTries = 3;
gp.recoveryTime = 1000;
gp.lockoutRecovery = 1000;
gp.lockOutAuthEnabled = TRUE;// in seconds (~16.67 minutes)// in seconds// Use of lockoutAuth is enabled// Record persistent DA parameter changes to NV
NV_SYNC_PERSISTENT(failedTries);
NV_SYNC_PERSISTENT(maxTries);
NV_SYNC_PERSISTENT(recoveryTime);
NV_SYNC_PERSISTENT(lockoutRecovery);
NV_SYNC_PERSISTENT(lockOutAuthEnabled);
return;}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 beenabled until the TPM has been continuously powered for the lockoutRecovery time.
This function requires that NV be available and not rate limiting.
23
24
25
26
27
28
29
30

BOOL
DAStartup(
STARTUP_TYPE)

type// IN: startup type{
NOT_REFERENCED(type);#if !ACCUMULATE_SELF_HEAL_TIMER_plat__TimerWasReset();Page 284
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

Trusted Platform Module Librarys_selfHealTimer = 0;
s_lockoutTimer = 0;
#else
if(_plat__TimerWasReset()){
if(!NV_IS_ORDERLY){// If shutdown was not orderly, then don't really know if go.time has// any useful value so reset the timer to 0. This is what the tick// was reset tos_selfHealTimer = 0;
s_lockoutTimer = 0;}else{// If we know how much time was accumulated at the last orderly shutdown// subtract that from the saved timer values so that they effectively// have the accumulated values
s_selfHealTimer -= go.time;s_lockoutTimer -= go.time;}}#endif// For any Startup(), if lockoutRecovery is 0, enable use of lockoutAuth.
if(gp.lockoutRecovery == 0){
gp.lockOutAuthEnabled = TRUE;// Record the changes to NV
NV_SYNC_PERSISTENT(lockOutAuthEnabled);}// If DA has not been disabled and the previous shutdown is not orderly// failedTries is not already at its maximum then increment 'failedTries'
if(gp.recoveryTime != 0&& gp.failedTries < gp.maxTries&& !IS_ORDERLY(g_prevOrderlyState)){#if USE_DA_USED
gp.failedTries += g_daUsed;
g_daUsed = FALSE;#else
gp.failedTries++;#endif// Record the change to NV
NV_SYNC_PERSISTENT(failedTries);}// Before Startup, the TPM will not do clock updates. At startup, need to// do a time update which will do the DA update.
TimeUpdate();return TRUE;}

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.
84
85
86
87

void
DARegisterFailure(
TPM_HANDLE)

handleFamily “2.0”Level 00 Revision 01.55// IN: handle for failure

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 285
April 15, 2019

Trusted Platform Module Library
88
89
90
91
92
93
94
95

Part 4: Supporting Routines{// Reset the timer associated with lockout if the handle is the lockoutAuth.
if(handle == TPM_RH_LOCKOUT)
s_lockoutTimer = g_time;else
s_selfHealTimer = g_time;
return;}8.2.3.4

DASelfHeal()

This function is called to check if sufficient time has passed to allow decrement of failedTries or to reenable use of lockoutAuth.
This function should be called when the time interval is updated.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

void
DASelfHeal(
void){// Regular authorization self healing logic// If no failed authorization tries, do nothing. Otherwise, try to// decrease failedTriesif(gp.failedTries != 0){// if recovery time is 0, DA logic has been disabled. Clear failed tries// immediately
if(gp.recoveryTime == 0){
gp.failedTries = 0;// Update NV record
NV_SYNC_PERSISTENT(failedTries);}
else{
UINT64decreaseCount;#if 0 // Errata eliminates this code// In the unlikely event that failedTries should become larger than// maxTriesif(gp.failedTries > gp.maxTries)
gp.failedTries = gp.maxTries;#endif// How much can failedTries be decreased// Cast s_selfHealTimer to an int in case it became negative at// startup
decreaseCount = ((g_time - (INT64)s_selfHealTimer) / 1000)/ gp.recoveryTime;if(gp.failedTries <= (UINT32)decreaseCount)// should not set failedTries below zerogp.failedTries = 0;
else
gp.failedTries -= (UINT32)decreaseCount;// the cast prevents overflow of the products_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000;if(decreaseCount != 0)// If there was a change to the failedTries, record the changes// to NV
NV_SYNC_PERSISTENT(failedTries);}}

Page 286
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

Trusted Platform Module Library// LockoutAuth self healing logic// If lockoutAuth is enabled, do nothing. Otherwise, try to see if we// may enable itif(!gp.lockOutAuthEnabled){// if lockout authorization recovery time is 0, a reboot is required to// re-enable use of lockout authorization. Self-healing would not// apply in this case.
if(gp.lockoutRecovery != 0){
if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery){
gp.lockOutAuthEnabled = TRUE;// Record the changes to NV
NV_SYNC_PERSISTENT(lockOutAuthEnabled);}}}
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 287
April 15, 2019

Trusted Platform Module Library

8.3

Part 4: Supporting Routines

Hierarchy.c

8.3.1

Introduction

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

Includes#include "Tpm.h"

8.3.3

Functions

8.3.3.1

HierarchyPreInstall()This function performs the initialization functions for the hierarchy when the TPM is simulated. Thisfunction should not be called if the TPM is not in a manufacturing mode at the manufacturer, or in asimulated environment.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

void
HierarchyPreInstall_Init(
void){// Allow lockout clear command
gp.disableClear = FALSE;// Initialize Primary Seeds
gp.EPSeed.t.size = sizeof(gp.EPSeed.t.buffer);
gp.SPSeed.t.size = sizeof(gp.SPSeed.t.buffer);
gp.PPSeed.t.size = sizeof(gp.PPSeed.t.buffer);#if (defined USE_PLATFORM_EPS) && (USE_PLATFORM_EPS != NO)_plat__GetEPS(gp.EPSeed.t.size, gp.EPSeed.t.buffer);#else
CryptRandomGenerate(gp.EPSeed.t.size, gp.EPSeed.t.buffer);#endifCryptRandomGenerate(gp.SPSeed.t.size, gp.SPSeed.t.buffer);
CryptRandomGenerate(gp.PPSeed.t.size, gp.PPSeed.t.buffer);// Initialize owner, endorsement and lockout authorization
gp.ownerAuth.t.size = 0;
gp.endorsementAuth.t.size = 0;
gp.lockoutAuth.t.size = 0;// Initialize owner, endorsement, and lockout policy
gp.ownerAlg = TPM_ALG_NULL;
gp.ownerPolicy.t.size = 0;
gp.endorsementAlg = TPM_ALG_NULL;
gp.endorsementPolicy.t.size = 0;
gp.lockoutAlg = TPM_ALG_NULL;
gp.lockoutPolicy.t.size = 0;// Initialize ehProof, shProof and phProof
gp.phProof.t.size = sizeof(gp.phProof.t.buffer);
gp.shProof.t.size = sizeof(gp.shProof.t.buffer);
gp.ehProof.t.size = sizeof(gp.ehProof.t.buffer);
CryptRandomGenerate(gp.phProof.t.size, gp.phProof.t.buffer);
CryptRandomGenerate(gp.shProof.t.size, gp.shProof.t.buffer);
CryptRandomGenerate(gp.ehProof.t.size, gp.ehProof.t.buffer);// Write hierarchy data to NV

Page 288
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

Trusted Platform Module Library

NV_SYNC_PERSISTENT(disableClear);
NV_SYNC_PERSISTENT(EPSeed);
NV_SYNC_PERSISTENT(SPSeed);
NV_SYNC_PERSISTENT(PPSeed);
NV_SYNC_PERSISTENT(ownerAuth);
NV_SYNC_PERSISTENT(endorsementAuth);
NV_SYNC_PERSISTENT(lockoutAuth);
NV_SYNC_PERSISTENT(ownerAlg);
NV_SYNC_PERSISTENT(ownerPolicy);
NV_SYNC_PERSISTENT(endorsementAlg);
NV_SYNC_PERSISTENT(endorsementPolicy);
NV_SYNC_PERSISTENT(lockoutAlg);
NV_SYNC_PERSISTENT(lockoutPolicy);
NV_SYNC_PERSISTENT(phProof);
NV_SYNC_PERSISTENT(shProof);
NV_SYNC_PERSISTENT(ehProof);
return;}8.3.3.2

HierarchyStartup()This function is called at TPM2_Startup() to initialize the hierarchy related values.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

BOOL
HierarchyStartup(
STARTUP_TYPE)

type// IN: start up type{// phEnable is SET on any startup
g_phEnable = TRUE;// Reset platformAuth, platformPolicy; enable SH and EH at TPM_RESET and// TPM_RESTART
if(type != SU_RESUME){
gc.platformAuth.t.size = 0;
gc.platformPolicy.t.size = 0;
gc.platformAlg = TPM_ALG_NULL;// enable the storage and endorsement hierarchies and the platformNV
gc.shEnable = gc.ehEnable = gc.phEnableNV = TRUE;}// nullProof and nullSeed are updated at every TPM_RESET
if((type != SU_RESTART) && (type != SU_RESUME)){
gr.nullProof.t.size = sizeof(gr.nullProof.t.buffer);
CryptRandomGenerate(gr.nullProof.t.size, gr.nullProof.t.buffer);
gr.nullSeed.t.size = sizeof(gr.nullSeed.t.buffer);
CryptRandomGenerate(gr.nullSeed.t.size, gr.nullSeed.t.buffer);}
return TRUE;}

8.3.3.3

HierarchyGetProof()

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

TPM2B_PROOF *HierarchyGetProof(
TPMI_RH_HIERARCHY

Family “2.0”Level 00 Revision 01.55

hierarchy// IN: hierarchy constant

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 289
April 15, 2019

Trusted Platform Module Library
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

Part 4: Supporting Routines){
TPM2B_PROOF*proof = NULL;

switch(hierarchy){
case TPM_RH_PLATFORM:// phProof for TPM_RH_PLATFORM
proof = &gp.phProof;
break;
case TPM_RH_ENDORSEMENT:// ehProof for TPM_RH_ENDORSEMENT
proof = &gp.ehProof;
break;
case TPM_RH_OWNER:// shProof for TPM_RH_OWNER
proof = &gp.shProof;
break;
default:// nullProof for TPM_RH_NULL or anything else
proof = &gr.nullProof;
break;}
return proof;}

8.3.3.4

HierarchyGetPrimarySeed()

This function returns the primary seed of a hierarchy.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

TPM2B_SEED *HierarchyGetPrimarySeed(
TPMI_RH_HIERARCHY)

hierarchy// IN: hierarchy{
TPM2B_SEED*seed = NULL;
switch(hierarchy){
case TPM_RH_PLATFORM:
seed = &gp.PPSeed;
break;
case TPM_RH_OWNER:
seed = &gp.SPSeed;
break;
case TPM_RH_ENDORSEMENT:
seed = &gp.EPSeed;
break;
default:
seed = &gr.nullSeed;
break;}
return seed;}

8.3.3.5

HierarchyIsEnabled()

This function checks to see if a hierarchy is enabled.

Page 290
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

NOTE:

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

Trusted Platform Module Library

The TPM_RH_NULL hierarchy is always enabled.

Return Value

Meaning

TRUE(1)hierarchy is enabled

FALSE(0)hierarchy is disabled

BOOL
HierarchyIsEnabled(
TPMI_RH_HIERARCHY)

hierarchy// IN: hierarchy{
BOOL

enabled = FALSE;

switch(hierarchy){
case TPM_RH_PLATFORM:
enabled = g_phEnable;
break;
case TPM_RH_OWNER:
enabled = gc.shEnable;
break;
case TPM_RH_ENDORSEMENT:
enabled = gc.ehEnable;
break;
case TPM_RH_NULL:
enabled = TRUE;
break;
default:
enabled = FALSE;
break;}
return enabled;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 291
April 15, 2019

Trusted Platform Module Library

8.4

Part 4: Supporting Routines

NvDynamic.c

8.4.1

Introduction

The NV memory is divided into two area: dynamic space for user defined NV indexes and evict objects,
and reserved space for TPM persistent and state save data.
The entries in dynamic space are a linked list of entries. Each entry has, as its first field, a size. If the size
field is zero, it marks the end of the list.
An Index allocation will contain an NV_INDEX structure. If the Index does not have the orderly attribute,the NV_INDEX is followed immediately by the NV data.
An evict object entry contains a handle followed by an OBJECT structure. This results in both the Indexand Evict Object having an identifying handle as the first field following the size field.
When an Index has the orderly attribute, the data is kept in RAM. This RAM is saved to backing store in
NV memory on any orderly shutdown. The entries in orderly memory are also a linked list using a size
field as the first entry.
The attributes of an orderly index are maintained in RAM memory in order to reduce the number of NV
writes needed for orderly data. When an orderly index is created, an entry is made in the dynamic NV
memory space that holds the Index authorizations (authPolicy and authValue) and the size of the data.
This entry is only modified if the authValue of the index is changed. The more volatile data of the index is
kept in RAM. When an orderly Index is created or deleted, the RAM data is copied to NV backing store sothat the image in the backing store matches the layout of RAM. In normal operation. The RAM data isalso copied on any orderly shutdown. In normal operation, the only other reason for writing to the backing
store for RAM is when a counter is first written (TPMA_NV_WRITTEN changes from CLEAR to SET) or
when a counter "rolls over."Static space contains items that are individually modifiable. ThePERSISTEND_DATA structure in RAM and mapped to locations in NV.
8.4.2
1
2
3

values

are

in

the

gp

Includes, Defines and Data Definitions#define NV_C
#include "Tpm.h"#include "PlatformData.h"

8.4.3

Local Functions

8.4.3.1

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_REF_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.
4
5
6
7
8
9
10
11
12

static NV_REF
NvNext(
NV_REF
TPM_HANDLE)*iter,*handle// IN/OUT: the list iterator// OUT: the handle of the next item.

{
NV_REF
NV_ENTRY_HEADER

currentAddr;
header;//Page 292
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

Trusted Platform Module Library// If iterator is at the beginning of list
if(*iter == NV_REF_INIT){// Initialize iterator*iter = NV_USER_DYNAMIC;}// Step over the size field and point to the handle
currentAddr = *iter + sizeof(UINT32);// read the header of the next entry
NvRead(&header, *iter, sizeof(NV_ENTRY_HEADER));// if the size field is zero, then we have hit the end of the list
if(header.size == 0)// leave the *iter pointing at the end of the list
return 0;// advance the header by the size of the entry*iter += header.size;
if(handle != NULL)*handle = header.handle;
return currentAddr;}

8.4.3.2

NvNextByType()This function returns a reference to the next NV entry of the desired type

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

Return Value

Meaning0

end of list!= 0

the next entry of the indicated typestatic NV_REF
NvNextByType(TPM_HANDLE
NV_REF
TPM_HT)*handle,*iter,
type

NV_REF
TPM_HANDLE

addr;
nvHandle;// OUT: the handle of the found type// IN: the iterator// IN: the handle type to look for{//while((addr = NvNext(iter, &nvHandle)) != 0){// addr: the address of the location containing the handle of the value// iter: the next location.
if(HandleGetType(nvHandle) == type)break;}
if(handle != NULL)*handle = nvHandle;
return addr;}

8.4.3.3

NvNextIndex()

This function returns the reference to the next NV Index entry. A value of 0 indicates the end of the list.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 293
April 15, 2019

Trusted Platform Module Library

57
58

Part 4: Supporting Routines

Return Value

Meaning0

end of list!= 0

the next reference#define NvNextIndex(handle, iter)
NvNextByType(handle, iter, TPM_HT_NV_INDEX)

8.4.3.4\

NvNextEvict()

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

#define NvNextEvict(handle, iter)
NvNextByType(handle, iter, TPM_HT_PERSISTENT)

8.4.3.5\

NvGetEnd()

Function to find the end of the NV dynamic data list
61
62
63
64
65
66
67
68
69
70
71
72

static NV_REF
NvGetEnd(
void){
NV_REF
NV_REF

iter = NV_REF_INIT;
currentAddr;//// Scan until the next address is 0
while((currentAddr = NvNext(&iter, NULL)) != 0);
return iter;}

8.4.3.6

NvGetFreeBytes

This function returns the number of free octets in NV space.
73
74
75
76
77
78
79
80
81
82
83

static UINT32
NvGetFreeBytes(
void){// This does not have an overflow issue because NvGetEnd() cannot return a value// that is larger than s_evictNvEnd. This is because there is always a 'stop'// word in the NV memory that terminates the search for the end before the// value can go past s_evictNvEnd.
return s_evictNvEnd - NvGetEnd();}8.4.3.7

NvTestSpace()

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

Page 294
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)

space available

FALSE(0)no enough spacestatic BOOL
NvTestSpace(
UINT32
BOOL
BOOL
)

size,
isIndex,isCounter// IN: size of the entity to be added// IN: TRUE if the entity is an index// IN: TRUE if the index is a counter{
UINT32
remainBytes = NvGetFreeBytes();
UINT32
reserved = sizeof(UINT32)// size of the forward pointer+ sizeof(NV_LIST_TERMINATOR);//// Do a compile time sanity check on the setting for NV_MEMORY_SIZE#if NV_MEMORY_SIZE < 1024
#error "NV_MEMORY_SIZE probably isn't large enough"#endif// For NV Index, need to make sure that we do not allocate an Index if this// would mean that the TPM cannot allocate the minimum number of evict// objects.
if(isIndex){// Get the number of persistent objects allocatedUINT32
persistentNum = NvCapGetPersistentNumber();// If we have not allocated the requisite number of evict objects, then we// need to reserve space for them.
// NOTE: some of this is not written as simply as it might seem because// the values are all unsigned and subtracting needs to be done carefully// so that an underflow doesn't cause problems.
if(persistentNum < MIN_EVICT_OBJECTS)
reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE;}// If this is not an index or is not a counter, reserve space for the// required number of counter indexes
if(!isIndex || !isCounter){// Get the number of counters
UINT32
counterNum = NvCapGetCounterNumber();// If the required number of counters have not been allocated, reserved// space for the extra needed counters
if(counterNum < MIN_COUNTER_INDICES)
reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE;}// Check that the requested allocation will fit after making sure that there// will be no chance of overflow
return ((reserved < remainBytes)&& (size <= remainBytes)&& (size + reserved <= remainBytes));}

8.4.3.8

NvWriteNvListEnd()

Function to write the list terminator.
134
135
136

NV_REF
NvWriteNvListEnd(
NV_REF

end

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 295
April 15, 2019

Trusted Platform Module Library
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

Part 4: Supporting Routines){// Marker is initialized with zeros
BYTE
listEndMarker[sizeof(NV_LIST_TERMINATOR)] = {0};UINT64maxCount = NvReadMaxCount();//// This is a constant check that can be resolved at compile time.
cAssert(sizeof(UINT64) <= sizeof(NV_LIST_TERMINATOR) - sizeof(UINT32));// Copy the maxCount value to the marker buffer
MemoryCopy(&listEndMarker[sizeof(UINT32)], &maxCount, sizeof(UINT64));
pAssert(end + sizeof(NV_LIST_TERMINATOR) <= s_evictNvEnd);// Write it to memory
NvWrite(end, sizeof(NV_LIST_TERMINATOR), &listEndMarker);return end + sizeof(NV_LIST_TERMINATOR);}

8.4.3.9

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 beencalled and the available space is at least as large as the required space).
The totalSize will be the size of entity. If a handle is added, this function will increase the size accordingly.
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

static TPM_RC
NvAdd(UINT32

totalSize,UINT32
TPM_HANDLE
BYTE)

bufferSize,
handle,*entity

NV_REF
NV_REF

newAddr;nextAddr;// IN: total size needed for this entity For//
evict object, totalSize is the same as//
bufferSize. For NV Index, totalSize is//bufferSize plus index data size// IN: size of initial buffer// IN: optional handle// IN: initial buffer{// IN: where the new entity will start//
RETURN_IF_NV_IS_NOT_AVAILABLE;// Get the end of data list
newAddr = NvGetEnd();// Step over the forward pointernextAddr = newAddr + sizeof(UINT32);// Optionally write the handle. For indexes, the handle is TPM_RH_UNASSIGNED// so that the handle in the nvIndex is used instead of writing this value
if(handle != TPM_RH_UNASSIGNED){
NvWrite((UINT32)nextAddr, sizeof(TPM_HANDLE), &handle);
nextAddr += sizeof(TPM_HANDLE);}// Write entity data
NvWrite((UINT32)nextAddr, bufferSize, entity);// Advance the pointer by the amount of the total
nextAddr += totalSize;// Finish by writing the link value// Write the next offset (relative addressing)Page 296
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
192
193
194
195
196
197
198
199
200
201

Trusted Platform Module Library

totalSize = nextAddr - newAddr;// Write link value
NvWrite((UINT32)newAddr, sizeof(UINT32), &totalSize);// Write the list terminator
NvWriteNvListEnd(nextAddr);
return TPM_RC_SUCCESS;}

8.4.3.10

NvDelete()

This function is used to delete an NV Index or persistent object from NV memory.
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

static TPM_RC
NvDelete(
NV_REF)

entityRef// IN: reference to entity to be deleted{
UINT32entrySize;// adjust entityAddr to back up and point to the forward pointer
NV_REF
entryRef = entityRef - sizeof(UINT32);
NV_REF
endRef = NvGetEnd();
NV_REF
nextAddr; // address of the next entry//
RETURN_IF_NV_IS_NOT_AVAILABLE;// Get the offset of the next entry. That is, back up and point to the size// field of the entry
NvRead(&entrySize, entryRef, sizeof(UINT32));// The next entry after the one being deleted is at a relative offset// from the current entry
nextAddr = entryRef + entrySize;// If this is not the last entry, move everything up
if(nextAddr < endRef){
pAssert(nextAddr > entryRef);_plat__NvMemoryMove(nextAddr,
entryRef,(endRef - nextAddr));}// The end of the used space is now moved up by the amount of space we just// reclaimed
endRef -= entrySize;// Write the end marker, and make the new end equal to the first byte after// the just added end value. This will automatically update the NV value for// maxCounter.
// NOTE: This is the call that sets flag to cause NV to be updated
endRef = NvWriteNvListEnd(endRef);// Clear the reclaimed memory_plat__NvMemoryClear(endRef, entrySize);
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 297
April 15, 2019

Trusted Platform Module Library

8.4.4

Part 4: Supporting Routines

RAM-based NV Index Data Access Functions

8.4.4.1

Introduction

The data layout in ram buffer is {size of(NV_handle + attributes + data NV_handle, attributes, data} foreach NV Index data stored in RAM.
NV storage associated with orderly data is updated when a NV Index is added but NOT when the data or
attributes are changed. Orderly data is only updated to NV on an orderly shutdown (TPM2_Shutdown())
8.4.4.2

NvRamNext()

This function is used to iterate trough the list of Ram Index values. *iter needs to be initialized by calling
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

static NV_RAM_REF
NvRamNext(
NV_RAM_REF
TPM_HANDLE)*iter,*handle// IN/OUT: the list iterator// OUT: the handle of the next item.

{
NV_RAM_REF
NV_RAM_HEADER

currentAddr;
header;//// If iterator is at the beginning of list
if(*iter == NV_RAM_REF_INIT){// Initialize iterator*iter = &s_indexOrderlyRam[0];}// if we are going to return what the iter is currently pointing to...
currentAddr = *iter;// If iterator reaches the end of NV space, then don't advance and return// that we are at the end of the list. The end of the list occurs when// we don't have space for a size and a handle
if(currentAddr + sizeof(NV_RAM_HEADER) > RAM_ORDERLY_END)
return NULL;// read the header of the next entry
MemoryCopy(&header, currentAddr, sizeof(NV_RAM_HEADER));// if the size field is zero, then we have hit the end of the list
if(header.size == 0)// leave the *iter pointing at the end of the list
return NULL;// advance the header by the size of the entry*iter = currentAddr + header.size;//

pAssert(*iter <= RAM_ORDERLY_END);
if(handle != NULL)*handle = header.handle;
return currentAddr;}

8.4.4.3

NvRamGetEnd()

This routine performs the same function as NvGetEnd() but for the RAM data.
284
285
286
287

static NV_RAM_REF
NvRamGetEnd(
void)

Page 298
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
288
289
290
291
292
293
294
295

Trusted Platform Module Library{
NV_RAM_REF
NV_RAM_REF

iter = NV_RAM_REF_INIT;
currentAddr;//// Scan until the next address is 0
while((currentAddr = NvRamNext(&iter, NULL)) != 0);
return iter;}

8.4.4.4

NvRamTestSpaceIndex()

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

296
297
298
299
300
301
302
303
304
305
306

Return Value

Meaning

TRUE(1)

space available

FALSE(0)no enough spacestatic BOOL
NvRamTestSpaceIndex(
UINT32)size// IN: size of the data to be added to RAM

UINT32
UINT32

remaining = RAM_ORDERLY_END - NvRamGetEnd();needed = sizeof(NV_RAM_HEADER) + size;{//// NvRamGetEnd points to the next available byte.
return remaining >= needed;}

8.4.4.5

NvRamGetIndex()

This function returns the offset of NV data in the RAM bufferThis function requires that NV Index is in RAM. That is, the index must be known to exist.
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

static NV_RAM_REF
NvRamGetIndex(
TPMI_RH_NV_INDEX)

handle// IN: NV handle

NV_RAM_REF
NV_RAM_REF
TPM_HANDLE

iter = NV_RAM_REF_INIT;
currentAddr;
foundHandle;{//
while((currentAddr = NvRamNext(&iter, &foundHandle)) != 0){
if(handle == foundHandle)
break;}
return currentAddr;}

8.4.4.6

NvUpdateIndexOrderlyData()

This function is used to cause an update of the orderly data to the NV backing store.
323
324
325
326

void
NvUpdateIndexOrderlyData(
void)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 299
April 15, 2019

Trusted Platform Module Library
327
328
329
330

Part 4: Supporting Routines{// Write reserved RAM space to NV
NvWrite(NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam), s_indexOrderlyRam);}

8.4.4.7

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.
This function should be called after the NV Index space has been updated and the index removed. This
insures that NV is available so that checking for NV availability is not required during this function.
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361

static void
NvAddRAM(
TPMS_NV_PUBLIC)*index// IN: the index descriptor{
NV_RAM_HEADER
NV_RAM_REF

header;end = NvRamGetEnd();//header.size = sizeof(NV_RAM_HEADER) + index->dataSize;
header.handle = index->nvIndex;
MemoryCopy(&header.attributes, &index->attributes, sizeof(TPMA_NV));
pAssert(ORDERLY_RAM_ADDRESS_OK(end, header.size));// Copy the header to the memory
MemoryCopy(end, &header, sizeof(NV_RAM_HEADER));// Clear the data area (just in case)
MemorySet(end + sizeof(NV_RAM_HEADER), 0, index->dataSize);// Step over this new entry
end += header.size;// If the end marker will fit, add it
if(end + sizeof(UINT32) < RAM_ORDERLY_END)
MemorySet(end, 0, sizeof(UINT32));// Write reserved RAM space to NV to reflect the newly added NV Index
SET_NV_UPDATE(UT_ORDERLY);
return;}8.4.4.8

NvDeleteRAM()

This function is used to delete a RAM-backed NV Index data area. The space used by the entry are
overwritten by the contents of the Index data that comes after (the data is moved up to fill the hole left byremoving this index. The reclaimed space is cleared to zeros. This function assumes the data of NV Index
exists in RAM.
This function should be called after the NV Index space has been updated and the index removed. This
insures that NV is available so that checking for NV availability is not required during this function.
362
363
364
365
366
367
368

static void
NvDeleteRAM(
TPMI_RH_NV_INDEX)

handle// IN: NV handle

NV_RAM_REF
NV_RAM_REF

nodeAddress;
nextNode;{

Page 300
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

UINT32
NV_RAM_REF

Trusted Platform Module Library
size;
lastUsed = NvRamGetEnd();//
nodeAddress = NvRamGetIndex(handle);
pAssert(nodeAddress != 0);// Get node size
MemoryCopy(&size, nodeAddress, sizeof(size));// Get the offset of next node
nextNode = nodeAddress + size;// Copy the data
MemoryCopy(nodeAddress, nextNode, lastUsed - nextNode);// Clear out the reclaimed space
MemorySet(lastUsed - size, 0, size);// Write reserved RAM space to NV to reflect the newly delete NV Index
SET_NV_UPDATE(UT_ORDERLY);
return;}8.4.4.9

NvReadIndex()

This function is used to read the NV Index NV_INDEX. This is used so that the index information can becompressed and only this function would be needed to decompress it. Mostly, compression would only beable to save the space needed by the policy.
393
394
395
396
397
398
399
400
401
402

void
NvReadNvIndexInfo(
NV_REF
NV_INDEX)

ref,*nvIndex// IN: points to NV where index is located// OUT: place to receive index data{
pAssert(nvIndex != NULL);
NvRead(nvIndex, ref, sizeof(NV_INDEX));
return;}8.4.4.10

NvReadObject()

This function is used to read a persistent object. This is used so that the object information can becompressed and only this function would be needed to uncompress it.
403
404
405
406
407
408
409
410
411

void
NvReadObject(
NV_REFOBJECT)ref,*object// IN: points to NV where index is located// OUT: place to receive the object data{
NvRead(object, (ref + sizeof(TPM_HANDLE)), sizeof(OBJECT));
return;}8.4.4.11

NvFindEvict()

This function will return the NV offset of an evict object
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 301
April 15, 2019

Trusted Platform Module Library

412
413
414
415
416
417
418
419
420
421
422
423
424

Part 4: Supporting Routines

Return Value

Meaning0

evict object not found!= 0

offset of evict object

static NV_REF
NvFindEvict(
TPM_HANDLEOBJECT)

nvHandle,*object

NV_REF

found = NvFindHandle(nvHandle);{//// If we found the handle and the request included an object pointer, fill it inif(found != 0 && object != NULL)
NvReadObject(found, object);return found;}

8.4.4.12

NvIndexIsDefined()

See if an index is already defined
425
426
427
428
429
430
431

BOOL
NvIndexIsDefined(
TPM_HANDLE)

nvHandle// IN: Index to look for{
return (NvFindHandle(nvHandle) != 0);}

8.4.4.13

NvConditionallyWrite()

Function to check if the data to be written has changed and write it if it has

432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

Error Returns

Meaning

TPM_RC_NV_RATE

NV is unavailable because of rate limit

TPM_RC_NV_UNAVAILABLE

NV is inaccessible

static TPM_RC
NvConditionallyWrite(
NV_REF
UINT32void)

entryAddr,
size,
*data

// IN: stating address// IN: size of the data to write// IN: the data to write{// If the index data is actually changed, then a write to NV is required
if(_plat__NvIsDifferent(entryAddr, size, data)){// Write the data if NV is available
if(g_NvStatus == TPM_RC_SUCCESS){
NvWrite(entryAddr, size, data);}
return g_NvStatus;}
return TPM_RC_SUCCESS;}

Page 302
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.4.4.14

Trusted Platform Module Library

NvReadNvIndexAttributes()

This function returns the attributes of an NV Index.
451
452
453
454
455
456
457
458
459
460
461
462

static TPMA_NV
NvReadNvIndexAttributes(
NV_REF)

locator// IN: reference to an NV index{
TPMA_NV

attributes;//
NvRead(&attributes,
locator + offsetof(NV_INDEX, publicArea.attributes),sizeof(TPMA_NV));
return attributes;}

8.4.4.15

NvReadRamIndexAttributes()

This function returns the attributes from the RAM header structure. This function is used to deal with thefact that the header structure is only byte aligned.
463
464
465
466
467
468
469
470
471
472
473

static TPMA_NV
NvReadRamIndexAttributes(
NV_RAM_REF)

ref// IN: pointer to a NV_RAM_HEADER

TPMA_NV

attributes;{//
MemoryCopy(&attributes, ref + offsetof(NV_RAM_HEADER, attributes),sizeof(TPMA_NV));
return attributes;}

8.4.4.16

NvWriteNvIndexAttributes()

This function is used to write just the attributes of an index to NV.

474
475
476
477
478
479
480
481
482
483
484

Error Returns

Meaning

TPM_RC_NV_RATE

NV is rate limiting so retry

TPM_RC_NV_UNAVAILABLE

NV is not available

static TPM_RC
NvWriteNvIndexAttributes(
NV_REF
TPMA_NV)

locator,attributes// IN: location of the index// IN: attributes to write{
return NvConditionallyWrite(
locator + offsetof(NV_INDEX, publicArea.attributes),sizeof(TPMA_NV),&attributes);}

8.4.4.17

NvWriteRamIndexAttributes()

This function is used to write the index attributes into an unaligned structure

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 303
April 15, 2019

Trusted Platform Module Library

485
486
487
488
489
490
491
492
493
494

Part 4: Supporting Routines

static void
NvWriteRamIndexAttributes(
NV_RAM_REF
TPMA_NV)ref,attributes// IN: address of the header// IN: the attributes to write{
MemoryCopy(ref + offsetof(NV_RAM_HEADER, attributes), &attributes,
sizeof(TPMA_NV));
return;}8.4.5

Externally Accessible Functions

8.4.5.1

NvIsPlatformPersistentHandle()

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

495
496
497
498
499
500
501

Return Value

Meaning

TRUE(1)

handle references a platform persistent object and may reference anowner persistent object either

FALSE(0)handle does not reference platform persistent object

BOOL
NvIsPlatformPersistentHandle(
TPM_HANDLE)

handle// IN: handle{
return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST);}

8.4.5.2

NvIsOwnerPersistentHandle()

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

502
503
504
505
506
507
508

Return Value

Meaning

TRUE(1)

handle is owner persistent handle

FALSE(0)handle is not owner persistent handle and may not be a persistenthandle at all

BOOL
NvIsOwnerPersistentHandle(
TPM_HANDLE)

handle// IN: handle{
return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT);}

8.4.5.3

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

Page 304
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556

Trusted Platform Module Library

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 platformAuth

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 theindex

TPM_RC
NvIndexIsAccessible(
TPMI_RH_NV_INDEX)

handle// IN: handle

NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);{//
if(nvIndex == NULL)// If index is not found, return TPM_RC_HANDLE
return TPM_RC_HANDLE;
if(gc.shEnable == FALSE || gc.phEnableNV == FALSE){// if shEnable is CLEAR, an ownerCreate NV Index should not be// indicated as present
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)){
if(gc.shEnable == FALSE)
return TPM_RC_HANDLE;}// if phEnableNV is CLEAR, a platform created Index should not// be visible
else if(gc.phEnableNV == FALSE)
return TPM_RC_HANDLE;}#if 0 // Writelock test for debug// If the Index is write locked and this is an NV Write operation...
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITELOCKED)&& IsWriteOperation(commandIndex)){// then return a locked indication unless the command is TPM2_NV_WriteLockif(GetCommandCode(commandIndex) != TPM_CC_NV_WriteLock)return TPM_RC_NV_LOCKED;
return TPM_RC_SUCCESS;}#endif#if 0// Readlock Test for debug// If the Index is read locked and this is an NV Read operation...
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, READLOCKED)&& IsReadOperation(commandIndex)){// then return a locked indication unless the command is TPM2_NV_ReadLockif(GetCommandCode(commandIndex) != TPM_CC_NV_ReadLock)return TPM_RC_NV_LOCKED;}#endif// NV Index is accessible
return TPM_RC_SUCCESS;}

8.4.5.4

NvGetEvictObject()

This function is used to dereference an evict object handle and get a pointer to the object.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 305
April 15, 2019

Trusted Platform Module Library

557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

Part 4: Supporting Routines

Error Returns

Meaning

TPM_RC_HANDLE

the handle does not point to an existing persistent object

TPM_RC
NvGetEvictObject(
TPM_HANDLEOBJECT)

handle,*object// IN: handle// OUT: object data

NV_REF

entityAddr;{// offset points to the entity//// Find the address of evict object and copy to object
entityAddr = NvFindEvict(handle, object);// whether there is an error or not, make sure that the evict// status of the object is set so that the slot will get freed on exit// Must do this after NvFindEvict loads the object
object->attributes.evict = SET;// If handle is not found, return an error
if(entityAddr == 0)
return TPM_RC_HANDLE;
return TPM_RC_SUCCESS;}

8.4.5.5

NvIndexCacheInit()

Function to initialize the Index cache
578
579
580
581
582
583
584
585
586
587

void
NvIndexCacheInit(void){
s_cachedNvRef = NV_REF_INIT;
s_cachedNvRamRef = NV_RAM_REF_INIT;
s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED;
return;}8.4.5.6

NvGetIndexData()

This function is used to access the data in an NV Index. The data is returned as a byte sequence.
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.
588
589
590
591
592
593
594
595
596
597
598
599
600
601

void
NvGetIndexData(
NV_INDEX
NV_REF
UINT32
UINT16
void)*nvIndex,
locator,offset,
size,
*data

// IN: the in RAM index descriptor// IN: where the data is located// IN: offset of NV data// IN: number of octets of NV data to read// OUT: data buffer

TPMA_NV

nvAttributes;{//
pAssert(nvIndex != NULL);
nvAttributes = nvIndex->publicArea.attributes;

Page 306
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

Trusted Platform Module LibrarypAssert(IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN));
if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, ORDERLY)){// Get data from RAM buffer
NV_RAM_REF
ramAddr = NvRamGetIndex(nvIndex->publicArea.nvIndex);
pAssert(ramAddr != 0 && (size <=((NV_RAM_HEADER *)ramAddr)->size - sizeof(NV_RAM_HEADER) - offset));MemoryCopy(data, ramAddr + sizeof(NV_RAM_HEADER) + offset, size);}else{// Validate that read falls within range of the index
pAssert(offset <= nvIndex->publicArea.dataSize&& size <= (nvIndex->publicArea.dataSize - offset));NvRead(data, locator + sizeof(NV_INDEX) + offset, size);}
return;}8.4.5.7

NvHashIndexData()

This function adds Index data to a hash. It does this in parts to avoid large stack buffers.
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

void
NvHashIndexData(
HASH_STATE
NV_INDEX
NV_REF
UINT32
UINT16*hashState,*nvIndex,
locator,offset,size// IN: Initialized hash state// IN: Index// IN: where the data is located// IN: starting offset// IN: amount to hash){#define BUFFER_SIZE
64
BYTE
buffer[BUFFER_SIZE];
if (offset > nvIndex->publicArea.dataSize)
return;// Make sure that we don't try to read off the end.
if ((offset + size) > nvIndex->publicArea.dataSize)
size = nvIndex->publicArea.dataSize - (UINT16)offset;#if BUFFER_SIZE >= MAX_NV_INDEX_SIZE
NvGetIndexData(nvIndex, locator, offset, size, buffer);
CryptDigestUpdate(hashState, size, buffer);
#else
{
INT16
i;
UINT16
readSize;//for (i = size; i > 0; offset += readSize, i -= readSize){
readSize = (i < BUFFER_SIZE) ? i : BUFFER_SIZE;
NvGetIndexData(nvIndex, locator, offset, readSize, buffer);
CryptDigestUpdate(hashState, readSize, buffer);}}#endif // BUFFER_SIZE >= MAX_NV_INDEX_SIZE#undef BUFFER_SIZE}

8.4.5.8

NvGetUINT64Data()

Get data in integer format of a bit or counter NV Index.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 307
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

This function requires that the NV Index is defined and that the NV Index previously has been written.
656
657
658
659
660
661
662
663
664
665
666
667

UINT64
NvGetUINT64Data(
NV_INDEX
NV_REF)*nvIndex,
locatorUINT64

intVal;// IN: the in RAM index descriptor// IN: where index exists in NV{//// Read the value and convert it to internal format
NvGetIndexData(nvIndex, locator, 0, 8, &intVal);
return BYTE_ARRAY_TO_UINT64(((BYTE *)&intVal));}8.4.5.9

NvWriteIndexAttributes()

This function is used to write just the attributes of an index.

668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

Error Returns

Meaning

TPM_RC_NV_RATE

NV is rate limiting so retry

TPM_RC_NV_UNAVAILABLE

NV is not available

TPM_RC
NvWriteIndexAttributes(
TPM_HANDLE
NV_REF
TPMA_NV)

handle,locator,attributes// IN: location of the index// IN: attributes to write{
TPM_RC

result;//if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)){
NV_RAM_REF
ram = NvRamGetIndex(handle);
NvWriteRamIndexAttributes(ram, attributes);
result = TPM_RC_SUCCESS;}
else{
result = NvWriteNvIndexAttributes(locator, attributes);}
return result;}8.4.5.10

NvWriteIndexAuth()This function is used to write the authValue of an index. It is used by TPM2_NV_ChangeAuth()

689
690
691
692
693

Error Returns

Meaning

TPM_RC_NV_RATE

NV is rate limiting so retry

TPM_RC_NV_UNAVAILABLE

NV is not available

TPM_RC
NvWriteIndexAuth(
NV_REF
TPM2B_AUTH)Page 308
April 15, 2019locator,*authValue// IN: location of the index// IN: the authValue to write

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710

Trusted Platform Module Library{
TPM_RC

result;//// If the locator is pointing to the cached index value...
if(locator == s_cachedNvRef){// copy the authValue to the cached index so it will be there if we// look for it. This is a safety thing.
MemoryCopy2B(&s_cachedNvIndex.authValue.b, &authValue->b,
sizeof(s_cachedNvIndex.authValue.t.buffer));}
result = NvConditionallyWrite(
locator + offsetof(NV_INDEX, authValue),sizeof(UINT16) + authValue->t.size,
authValue);
return result;}8.4.5.11

NvGetIndexInfo()

This function loads the nvIndex Info into the NV cache and returns a pointer to the NV_INDEX. If the
returned value is zero, the index was not found. The locator parameter, if not NULL, will be set to theoffset in NV of the Index (the location of the handle of the Index).
This function will set the index cache. If the index is orderly, the attributes from RAM are substituted forthe attributes in the cached index
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735

NV_INDEX *NvGetIndexInfo(
TPM_HANDLE
NV_REF)

nvHandle,*locator// IN: the index handle// OUT: location of the index{
if(s_cachedNvIndex.publicArea.nvIndex != nvHandle){s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED;
s_cachedNvRamRef = 0;s_cachedNvRef = NvFindHandle(nvHandle);
if(s_cachedNvRef == 0)
return NULL;
NvReadNvIndexInfo(s_cachedNvRef, &s_cachedNvIndex);if(IS_ATTRIBUTE(s_cachedNvIndex.publicArea.attributes, TPMA_NV, ORDERLY)){
s_cachedNvRamRef = NvRamGetIndex(nvHandle);s_cachedNvIndex.publicArea.attributes =NvReadRamIndexAttributes(s_cachedNvRamRef);}}
if(locator != NULL)*locator = s_cachedNvRef;
return &s_cachedNvIndex;}

8.4.5.12

NvWriteIndexData()

This function is used to write NV index data. It is intended to be used to update the data associated withthe default index.
This function requires that the NV Index is defined, and the data is within the defined data range for theindex.
Index data is only written due to a command that modifies the data in a single index. There is no casewhere changes are made to multiple indexes data at the same time. Multiple attributes may be change
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 309
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

but not multiple index data. This is important because we will normally be handling the index for which wehave the cached pointer values.

736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

Error Returns

Meaning

TPM_RC_NV_RATE

NV is rate limiting so retry

TPM_RC_NV_UNAVAILABLE

NV is not available

TPM_RC
NvWriteIndexData(
NV_INDEXUINT32
UINT32
void)*nvIndex,
offset,
size,
*data

// IN: the description of the index// IN: offset of NV data// IN: size of NV data// IN: data buffer{
TPM_RC

result = TPM_RC_SUCCESS;//
pAssert(nvIndex != NULL);// Make sure that this is dealing with the 'default' index.
// Note: it is tempting to change the calling sequence so that the 'default' is// presumed.
pAssert(nvIndex->publicArea.nvIndex == s_cachedNvIndex.publicArea.nvIndex);// Validate that write falls within range of the index
pAssert(offset <= nvIndex->publicArea.dataSize&& size <= (nvIndex->publicArea.dataSize - offset));// Update TPMA_NV_WRITTEN bit if necessary
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)){// Update the in memory version of the attributes
SET_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN);// If this is not orderly, then update the NV version of// the attributes
if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)){
result = NvWriteNvIndexAttributes(s_cachedNvRef,
nvIndex->publicArea.attributes);
if(result != TPM_RC_SUCCESS)
return result;// If this is a partial write of an ordinary index, clear the whole// index.
if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes)&& (nvIndex->publicArea.dataSize > size))_plat__NvMemoryClear(s_cachedNvRef + sizeof(NV_INDEX),
nvIndex->publicArea.dataSize);}else{// This is orderly so update the RAM version
MemoryCopy(s_cachedNvRamRef + offsetof(NV_RAM_HEADER, attributes),&nvIndex->publicArea.attributes, sizeof(TPMA_NV));// If setting WRITTEN for an orderly counter, make sure that the// state saved version of the counter is saved
if(IsNvCounterIndex(nvIndex->publicArea.attributes))
SET_NV_UPDATE(UT_ORDERLY);// If setting the written attribute on an ordinary index, make sure that// the data is all cleared out in case there is a partial write. This// is only necessary for ordinary indexes because all of the other types// are always written in total.
else if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes))
MemorySet(s_cachedNvRamRef + sizeof(NV_RAM_HEADER),

Page 310
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

Trusted Platform Module Library
0, nvIndex->publicArea.dataSize);}}// If this is orderly data, write it to RAM
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)){// Note: if this is the first write to a counter, the code above will queue// the write to NV of the RAM data in order to update TPMA_NV_WRITTEN. In// process of doing that write, it will also write the initial counter value// Update RAM
MemoryCopy(s_cachedNvRamRef + sizeof(NV_RAM_HEADER) + offset, data, size);// And indicate that the TPM is no longer orderlyg_clearOrderly = TRUE;}
else{// Offset into the index to the first byte of the data to be written to NV
result = NvConditionallyWrite(s_cachedNvRef + sizeof(NV_INDEX) + offset,
size, data);}
return result;}8.4.5.13

NvWriteUINT64Data()

This function to write back a UINT64 value. The various UINT64 values (bits, counters, and PINs) are
kept in canonical format but manipulate in native format. This takes a native format value converts it andsaves it back as in canonical format.
This function will return the value from NV or RAM depending on the type of the index (orderly or not)
816
817
818
819
820
821
822
823
824
825
826

TPM_RC
NvWriteUINT64Data(
NV_INDEXUINT64)*nvIndex,
intValue// IN: the description of the index// IN: the value to write{
BYTE
bytes[8];UINT64_TO_BYTE_ARRAY(intValue, bytes);//
return NvWriteIndexData(nvIndex, 0, 8, &bytes);}

8.4.5.14

NvGetIndexName()

This function computes the Name of an index The name buffer receives the bytes of the Name and thereturn value is the number of octets in the Name.
This function requires that the NV Index is defined.
827
828
829
830
831
832
833
834
835
836
837

TPM2B_NAME *NvGetIndexName(
NV_INDEX*nvIndex,

TPM2B_NAME
)

*name

// IN: the index over which the name is to be//computed// OUT: name of the index{
UINT16
BYTE
BYTE
HASH_STATE

Family “2.0”Level 00 Revision 01.55

dataSize, digestSize;marshalBuffer[sizeof(TPMS_NV_PUBLIC)];*buffer;hashState;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 311
April 15, 2019

Trusted Platform Module Library
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854

Part 4: Supporting Routines//// Marshal public area
buffer = marshalBuffer;
dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex->publicArea, &buffer, NULL);// hash public area
digestSize = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg);
CryptDigestUpdate(&hashState, dataSize, marshalBuffer);// Complete digest leaving room for the nameAlg
CryptHashEnd(&hashState, digestSize, &name->b.buffer[2]);// Include the nameAlg
UINT16_TO_BYTE_ARRAY(nvIndex->publicArea.nameAlg, name->b.buffer);
name->t.size = digestSize + 2;
return name;}

8.4.5.15

NvGetNameByIndexHandle()

This function is used to compute the Name of an NV Index referenced by handle.
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.
855
856
857
858
859
860
861
862
863
864

TPM2B_NAME *NvGetNameByIndexHandle(
TPMI_RH_NV_INDEXTPM2B_NAME)

handle,*name// IN: handle of the index// OUT: name of the index

NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);{//
return NvGetIndexName(nvIndex, name);}

8.4.5.16

NvDefineIndex()

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

865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

Error Returns

Meaning

TPM_RC_NV_SPACE

insufficient NV space

TPM_RC
NvDefineIndex(
TPMS_NV_PUBLIC
TPM2B_AUTH)*publicArea,*authValue// IN: A template for an area to create.
// IN: The initial authorization value{// The buffer to be written to NV memory
NV_INDEX
nvIndex;// the index data
UINT16entrySize;// size of entry
TPM_RC
result;//entrySize = sizeof(NV_INDEX);// only allocate data space for indexes that are going to be written to NV.
// Orderly indexes don't need space.
if(!IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY))
entrySize += publicArea->dataSize;

Page 312
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910

Trusted Platform Module Library// Check if we have enough space to create the NV Index// In this implementation, the only resource limitation is the available NV// space (and possibly RAM space.) Other implementation may have other// limitation on counter or on NV slots
if(!NvTestSpace(entrySize, TRUE, IsNvCounterIndex(publicArea->attributes)))return TPM_RC_NV_SPACE;// if the index to be defined is RAM backed, check RAM space availability// as wellif(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)&& !NvRamTestSpaceIndex(publicArea->dataSize))
return TPM_RC_NV_SPACE;// Copy input value to nvBuffer
nvIndex.publicArea = *publicArea;// Copy the authValue
nvIndex.authValue = *authValue;// Add index to NV memory
result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED,(BYTE *)&nvIndex);
if(result == TPM_RC_SUCCESS){// If the data of NV Index is RAM backed, add the data area in RAM as wellif(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY))
NvAddRAM(publicArea);}
return result;}8.4.5.17

NvAddEvictObject()

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

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934

Error Returns

Meaning

TPM_RC_NV_HANDLE

the requested handle is already in use

TPM_RC_NV_SPACE

insufficient NV space

TPM_RC
NvAddEvictObject(
TPMI_DH_OBJECTOBJECT)evictHandle,*object// IN: new evict handle// IN: object to be added

TPM_HANDLE
TPM_RC

temp = object->evictHandle;
result;{//// Check if we have enough space to add the evict object// An evict object needs 8 bytes in index table + sizeof OBJECT// In this implementation, the only resource limitation is the available NV// space. Other implementation may have other limitation on evict object// handle spaceif(!NvTestSpace(sizeof(OBJECT) + sizeof(TPM_HANDLE), FALSE, FALSE))
return TPM_RC_NV_SPACE;// Set evict attribute and handle
object->attributes.evict = SET;
object->evictHandle = evictHandle;// Now put this in NV
result = NvAdd(sizeof(OBJECT), sizeof(OBJECT), evictHandle, (BYTE *)object);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 313
April 15, 2019

Trusted Platform Module Library
935
936
937
938
939
940

Part 4: Supporting Routines// Put things back the way they were
object->attributes.evict = CLEAR;
object->evictHandle = temp;
return result;}8.4.5.18

NvDeleteIndex()

This function is used to delete an NV Index.

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965

Error Returns

Meaning

TPM_RC_NV_UNAVAILABLE

NV is not accessible

TPM_RC_NV_RATE

NV is rate limiting

TPM_RC
NvDeleteIndex(
NV_INDEX
NV_REF)*nvIndex,
entityAddr

TPM_RC

result;// IN: an in RAM index descriptor// IN: location in NV{//
if(nvIndex != NULL){// Whenever a counter is deleted, make sure that the MaxCounter value is// updated to reflect the value
if(IsNvCounterIndex(nvIndex->publicArea.attributes)&& IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
NvUpdateMaxCount(NvGetUINT64Data(nvIndex, entityAddr));result = NvDelete(entityAddr);
if(result != TPM_RC_SUCCESS)
return result;// If the NV Index is RAM backed, delete the RAM data as wellif(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
NvDeleteRAM(nvIndex->publicArea.nvIndex);
NvIndexCacheInit();}return TPM_RC_SUCCESS;}

8.4.5.19

NvDeleteEvict()

This function will delete a NV evict object. Will return success if object deleted or if it does not exist
966
967
968
969
970
971
972
973
974
975
976
977

TPM_RC
NvDeleteEvict(
TPM_HANDLE)

handle// IN: handle of entity to be deleted{
NV_REFTPM_RC

entityAddr = NvFindEvict(handle, NULL);
result = TPM_RC_SUCCESS;// pointer to entity//
if(entityAddr != 0)
result = NvDelete(entityAddr);
return result;}

Page 314
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.4.5.20

Trusted Platform Module Library

NvFlushHierarchy()

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

978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031

Error Returns

Meaning

TPM_RC_NV_RATE

NV is unavailable because of rate limit

TPM_RC_NV_UNAVAILABLE

NV is inaccessible

TPM_RCNvFlushHierarchy(
TPMI_RH_HIERARCHY)

hierarchy// IN: hierarchy to be flushed.

{
NV_REF
NV_REF
TPM_HANDLE
TPM_RC

iter = NV_REF_INIT;
currentAddr;
entityHandle;
result = TPM_RC_SUCCESS;//
while((currentAddr = NvNext(&iter, &entityHandle)) != 0){
if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX){
NV_INDEX
nvIndex;//// If flush endorsement or platform hierarchy, no NV Index would be// flushedif(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
continue;// Get the index information
NvReadNvIndexInfo(currentAddr, &nvIndex);// For storage hierarchy, flush OwnerCreated index
if(!IS_ATTRIBUTE(nvIndex.publicArea.attributes, TPMA_NV,
PLATFORMCREATE)){// Delete the index (including RAM for orderly)
result = NvDeleteIndex(&nvIndex, currentAddr);
if(result != TPM_RC_SUCCESS)
break;// Re-iterate from beginning after a delete
iter = NV_REF_INIT;}}
else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT){OBJECT_ATTRIBUTES
attributes;//
NvRead(&attributes,(UINT32)(currentAddr+ sizeof(TPM_HANDLE)+ offsetof(OBJECT, attributes)),sizeof(OBJECT_ATTRIBUTES));// If the evict object belongs to the hierarchy to be flushed...
if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET)|| (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET)|| (hierarchy == TPM_RH_ENDORSEMENT&& attributes.epsHierarchy == SET)){// ...then delete the evict object
result = NvDelete(currentAddr);
if(result != TPM_RC_SUCCESS)
break;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 315
April 15, 2019

Trusted Platform Module Library
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

Part 4: Supporting Routines// Re-iterate from beginning after a delete
iter = NV_REF_INIT;
}
}
else
{
FAIL(FATAL_ERROR_INTERNAL);}}
return result;}8.4.5.21

NvSetGlobalLock()

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

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081

Error Returns

Meaning

TPM_RC_NV_RATE

NV is unavailable because of rate limit

TPM_RC_NV_UNAVAILABLE

NV is inaccessible

TPM_RC
NvSetGlobalLock(
void){
NV_REF
NV_RAM_REF
NV_REF
NV_RAM_REF
TPM_RC

iter = NV_REF_INIT;
ramIter = NV_RAM_REF_INIT;
currentAddr;
currentRamAddr;
result = TPM_RC_SUCCESS;//// Check all normal indexes
while((currentAddr = NvNextIndex(NULL, &iter)) != 0){
TPMA_NV
attributes = NvReadNvIndexAttributes(currentAddr);//// See if it should be locked
if(!IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)&& IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)){SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
result = NvWriteNvIndexAttributes(currentAddr, attributes);
if(result != TPM_RC_SUCCESS)
return result;}}// Now search all the orderly attributes
while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0){// See if it should be locked
TPMA_NV
attributes = NvReadRamIndexAttributes(currentRamAddr);
if(IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)){SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
NvWriteRamIndexAttributes(currentRamAddr, attributes);}}
return result;}

Page 316
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.4.5.22

Trusted Platform Module LibraryInsertSort()

Sort a handle into handle list in ascending order. The total handle number in the list should not exceed
MAX_CAP_HANDLES
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122

static void
InsertSort(
TPML_HANDLEUINT32
TPM_HANDLE)*handleList,
count,
entityHandle// IN/OUT: sorted handle list// IN: maximum count in the handle list// IN: handle to be inserted

UINT32
UINT32i, j;originalCount;{//// For a corner case that the maximum count is 0, do nothingif(count == 0)
return;// For empty list, add the handle at the beginning and returnif(handleList->count == 0){
handleList->handle[0] = entityHandle;
handleList->count++;
return;}// Check if the maximum of the list has been reachedoriginalCount = handleList->count;if(originalCount < count)handleList->count++;// Insert the handle to the list
for(i = 0; i < originalCount; i++){if(handleList->handle[i] > entityHandle){
for(j = handleList->count - 1; j > i; j--){handleList->handle[j] = handleList->handle[j - 1];}
break;}}// If a slot was found, insert the handle in this position
if(i < originalCount || handleList->count > originalCount)handleList->handle[i] = entityHandle;
return;}8.4.5.23

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.

1123
1124
1125
1126

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
NvCapGetPersistent(
TPMI_DH_OBJECTUINT32handle,count,

Family “2.0”Level 00 Revision 01.55// IN: start handle// IN: maximum number of returned handles

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 317
April 15, 2019

Trusted Platform Module Library
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161

TPML_HANDLE)

Part 4: Supporting Routines*handleList// OUT: list of handle{
TPMI_YES_NO
NV_REF
NV_REF
TPM_HANDLE

more = NO;iter = NV_REF_INIT;
currentAddr;
entityHandle;//
pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);// Initialize output handle list
handleList->count = 0;// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
while((currentAddr = NvNextEvict(&entityHandle, &iter)) != 0){// Ignore persistent handles that have values less than the input handle
if(entityHandle < handle)
continue;// if the handles in the list have reached the requested count, and there// are still handles need to be inserted, indicate that there are more.
if(handleList->count == count)more = YES;// A handle with a value larger than start handle is a candidate// for return. Insert sort it to the return list. Insert sort algorithm// is chosen here for simplicity based on the assumption that the total// number of NV indexes is small. For an implementation that may allow// large number of NV indexes, a more efficient sorting algorithm may be// used here.
InsertSort(handleList, count, entityHandle);}
return more;}

8.4.5.24

NvCapGetIndex()

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

1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

Return Value

Meaning

YES

if there are more handles to reportNO

all the available handles has been reported

TPMI_YES_NO
NvCapGetIndex(
TPMI_DH_OBJECTUINT32
TPML_HANDLE)

handle,count,*handleList// IN: start handle// IN: max number of returned handles// OUT: list of handle{
TPMI_YES_NO
NV_REF
NV_REF
TPM_HANDLE

more = NO;iter = NV_REF_INIT;
currentAddr;
nvHandle;//
pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);// Initialize output handle list
handleList->count = 0;Page 318
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200

Trusted Platform Module Library// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0){// Ignore index handles that have values less than the 'handle'
if(nvHandle < handle)
continue;// if the count of handles in the list has reached the requested count,// and there are still handles to report, set more.
if(handleList->count == count)more = YES;// A handle with a value larger than start handle is a candidate// for return. Insert sort it to the return list. Insert sort algorithm// is chosen here for simplicity based on the assumption that the total// number of NV indexes is small. For an implementation that may allow// large number of NV indexes, a more efficient sorting algorithm may be// used here.
InsertSort(handleList, count, nvHandle);}
return more;}

8.4.5.25

NvCapGetIndexNumber()This function returns the count of NV Indexes currently defined.
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

UINT32
NvCapGetIndexNumber(
void){
UINT32
NV_REFnum = 0;iter = NV_REF_INIT;//
while(NvNextIndex(NULL, &iter) != 0)num++;
return num;}

8.4.5.26

NvCapGetPersistentNumber()

Function returns the count of persistent objects currently in NV memory.
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225

UINT32
NvCapGetPersistentNumber(
void){
UINT32
NV_REF
TPM_HANDLE

num = 0;iter = NV_REF_INIT;
handle;//while(NvNextEvict(&handle, &iter) != 0)num++;
return num;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 319
April 15, 2019

Trusted Platform Module Library

8.4.5.27

Part 4: Supporting Routines

NvCapGetPersistentAvail()This function returns an estimate of the number of additional persistent objects that could be loaded into
NV memory.
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248

UINT32
NvCapGetPersistentAvail(
void){
UINT32
UINT32
UINT32

availNVSpace;counterNum = NvCapGetCounterNumber();
reserved = sizeof(NV_LIST_TERMINATOR);//// Get the available space in NV storage
availNVSpace = NvGetFreeBytes();if(counterNum < MIN_COUNTER_INDICES){// Some space has to be reserved for counter objects.
reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE;
if(reserved > availNVSpace)availNVSpace = 0;
else
availNVSpace -= reserved;}
return availNVSpace / NV_EVICT_OBJECT_SIZE;}

8.4.5.28

NvCapGetCounterNumber()

Get the number of defined NV Indexes that are counter indexes.
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265

UINT32
NvCapGetCounterNumber(void){
NV_REF
NV_REF
UINT32iter = NV_REF_INIT;
currentAddr;
num = 0;//while((currentAddr = NvNextIndex(NULL, &iter)) != 0){
TPMA_NV
attributes = NvReadNvIndexAttributes(currentAddr);
if(IsNvCounterIndex(attributes))
num++;}
return num;}

8.4.5.29

NvSetStartupAttributes()

Local function to set the attributes of an Index at TPM Reset and TPM Restart.
1266
1267
1268
1269
1270
1271
1272

static TPMA_NV
NvSetStartupAttributes(
TPMA_NV
STARTUP_TYPE)

attributes,
type// IN: attributes to change// IN: start up type{// Clear read lockPage 320
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291

Trusted Platform Module Library

CLEAR_ATTRIBUTE(attributes, TPMA_NV, READLOCKED);// Will change a non counter index to the unwritten state if:// a) TPMA_NV_CLEAR_STCLEAR is SET// b) orderly and TPM Resetif(!IsNvCounterIndex(attributes)){if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)|| (IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)&& (type == SU_RESET)))
CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITTEN);}// Unlock any index that is not written or that does not have// TPMA_NV_WRITEDEFINE SET.
if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)|| !IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
return attributes;}

8.4.5.30

NvEntityStartup()This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action istaken. If the startup is a TPM Reset or a TPM Restart, then this function will:clear read/write lock;reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; andset 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.
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

BOOL
NvEntityStartup(
STARTUP_TYPE)

type// IN: start up type{
NV_REF
NV_RAM_REF
NV_REF
NV_RAM_REF
TPM_HANDLE
TPMA_NV

iter = NV_REF_INIT;
ramIter = NV_RAM_REF_INIT;
currentAddr;// offset points to the current entity
currentRamAddr;
nvHandle;
attributes;//// Restore RAM index data
NvRead(s_indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam));// Initialize the max NV counter value
NvSetMaxCount(NvGetMaxCount());// If recovering from state save, do nothing elseif(type == SU_RESUME)
return TRUE;// Iterate all the NV Index to clear the locks
while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0){
attributes = NvReadNvIndexAttributes(currentAddr);// If this is an orderly index, defer processing until loop below
if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY))
continue;// Set the attributes appropriate for this startup typeattributes = NvSetStartupAttributes(attributes, type);
NvWriteNvIndexAttributes(currentAddr, attributes);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 321
April 15, 2019

Trusted Platform Module Library
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354

Part 4: Supporting Routines}// Iterate all the orderly indexes to clear the locks and initialize counterswhile((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0){
attributes = NvReadRamIndexAttributes(currentRamAddr);
attributes = NvSetStartupAttributes(attributes, type);// update attributes in RAM
NvWriteRamIndexAttributes(currentRamAddr, attributes);// Set the lower bits in an orderly counter to 1 for a non-orderly startupif(IsNvCounterIndex(attributes)&& (g_prevOrderlyState == SU_NONE_VALUE)){UINT64
counter;//// Read the counter value last saved to NV.
counter = BYTE_ARRAY_TO_UINT64(currentRamAddr + sizeof(NV_RAM_HEADER));// Set the lower bits of counter to 1's
counter |= MAX_ORDERLY_COUNT;// Write back to RAM// NOTE: Do not want to force a write to NV here. The counter value will// stay in RAM until the next shutdown or rollover.
UINT64_TO_BYTE_ARRAY(counter, currentRamAddr + sizeof(NV_RAM_HEADER));}}return TRUE;}

8.4.5.31

NvCapGetCounterAvail()This function returns an estimate of the number of additional counter type NV indexes that can be
defined.
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381

UINT32
NvCapGetCounterAvail(
void){
UINT32
UINT32
UINT32
UINT32

availNVSpace;availRAMSpace;persistentNum = NvCapGetPersistentNumber();
reserved = sizeof(NV_LIST_TERMINATOR);//// Get the available space in NV storage
availNVSpace = NvGetFreeBytes();if(persistentNum < MIN_EVICT_OBJECTS){// Some space has to be reserved for evict object. Adjust availNVSpace.
reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE;
if(reserved > availNVSpace)availNVSpace = 0;
else
availNVSpace -= reserved;}// Compute the available space in RAM
availRAMSpace = RAM_ORDERLY_END - NvRamGetEnd();// Return the min of counter number in NV and in RAM
if(availNVSpace / NV_INDEX_COUNTER_SIZEPage 322
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1382
1383
1384
1385
1386

Trusted Platform Module Library> availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE)
return availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE;
else
return availNVSpace / NV_INDEX_COUNTER_SIZE;}

8.4.5.32

NvFindHandle()

this function returns the offset in NV memory of the entity associated with the input handle. A value ofzero indicates that handle does not exist reference an existing persistent object or defined NV Index.
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402

NV_REF
NvFindHandle(
TPM_HANDLE)

handle

NV_REF
NV_REF
TPM_HANDLE

addr;
iter = NV_REF_INIT;
nextHandle;{//
while((addr = NvNext(&iter, &nextHandle)) != 0){
if(nextHandle == handle)
break;}
return addr;
}

8.4.6

NV Max Counter

8.4.6.1

Introduction

The TPM keeps track of the highest value of a deleted counter index. When an index is deleted, thisvalue is updated if the deleted counter index is greater than the previous value. When a new index iscreated and first incremented, it will get a value that is at least one greater than any other index than any
previously deleted index. This insures that it is not possible to roll back an index.
The highest counter value is keep in NV in a special end-of-list marker. This marker is only updated when
an index is deleted. Otherwise it just moves.
When the TPM starts up, it searches NV for the end of list marker and initializes an in memory value(s_maxCounter).
8.4.6.2

NvReadMaxCount()

This function returns the max NV counter value.
1403
1404
1405
1406
1407
1408
1409

UINT64
NvReadMaxCount(void){
return s_maxCounter;}

8.4.6.3

NvUpdateMaxCount()

This function updates the max counter value to NV memory. This is just staging for the actual write thatwill occur when the NV index memory is modified.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 323
April 15, 2019

Trusted Platform Module Library

1410
1411
1412
1413
1414
1415
1416
1417

Part 4: Supporting Routines

void
NvUpdateMaxCount(
UINT64)

count{if(count > s_maxCounter)s_maxCounter = count;}

8.4.6.4

NvSetMaxCount()

This function is used at NV initialization time to set the initial value of the maximum counter.
1418
1419
1420
1421
1422
1423
1424

void
NvSetMaxCount(
UINT64)value{
s_maxCounter = value;}

8.4.6.5

NvGetMaxCount()

Function to get the NV max counter value from the end-of-list marker
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441

UINT64
NvGetMaxCount(
void){
NV_REF
NV_REFUINT64iter = NV_REF_INIT;
currentAddr;
maxCount;//// Find the end of list marker and initialize the NV Max Counter value.
while((currentAddr = NvNext(&iter, NULL )) != 0);// 'iter' should be pointing at the end of list marker so read in the current// value of the s_maxCounter.
NvRead(&maxCount, iter + sizeof(UINT32), sizeof(maxCount));
return maxCount;}

Page 324
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.5

NvReserved.c

8.5.1

Introduction

Trusted Platform Module Library

The NV memory is divided into two areas: dynamic space for user defined NV Indices and evict objects,
and reserved space for TPM persistent and state save data.
The entries in dynamic space are a linked list of entries. Each entry has, as its first field, a size. If the size
field is zero, it marks the end of the list.
An allocation of an Index or evict object may use almost all of the remaining NV space such that the size
field will not fit. The functions that search the list are aware of this and will terminate the search if theyeither find a zero size or recognize that there is insufficient space for the size field.
An Index allocation will contain an NV_INDEX structure. If the Index does not have the orderly attribute,the NV_INDEX is followed immediately by the NV data.
An evict object entry contains a handle followed by an OBJECT structure. This results in both the Indexand Evict Object having an identifying handle as the first field following the size field.
When an Index has the orderly attribute, the data is kept in RAM. This RAM is saved to backing store in
NV memory on any orderly shutdown. The entries in orderly memory are also a linked list using a size
field as the first entry. As with the NV memory, the list is terminated by a zero size field or when the lastentry leaves insufficient space for the terminating size field.
The attributes of an orderly index are maintained in RAM memory in order to reduce the number of NV
writes needed for orderly data. When an orderly index is created, an entry is made in the dynamic NV
memory space that holds the Index authorizations (authPolicy and authValue) and the size of the data.
This entry is only modified if the authValue of the index is changed. The more volatile data of the index is
kept in RAM. When an orderly Index is created or deleted, the RAM data is copied to NV backing store sothat the image in the backing store matches the layout of RAM. In normal operation. The RAM data isalso copied on any orderly shutdown. In normal operation, the only other reason for writing to the backing
store for RAM is when a counter is first written (TPMA_NV_WRITTEN changes from CLEAR to SET) or
when a counter "rolls over."Static space contains items that are individually modifiable. ThePERSISTEND_DATA structure in RAM and mapped to locations in NV.
8.5.2
1
2

values

are

in

the

gp

Includes, Defines#define NV_C
#include"Tpm.h"8.5.3

Functions

8.5.3.1

NvInitStatic()

This function initializes the static variables used in the NV subsystem.
3
4
5
6
7
8
9
10
11
12

static void
NvInitStatic(void){// In some implementations, the end of NV is variable and is set at boot time.
// This value will be the same for each boot, but is not necessarily known// at compile time.
s_evictNvEnd = (NV_REF)NV_MEMORY_SIZE;
return;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 325
April 15, 2019

Trusted Platform Module Library
13

Part 4: Supporting Routines}

8.5.3.2

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 check of g_NvStatus.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

void
NvCheckState(
void
)
{
int

func_return;//
func_return = _plat__IsNvAvailable();if(func_return == 0)
g_NvStatus = TPM_RC_SUCCESS;
else if(func_return == 1)
g_NvStatus = TPM_RC_NV_UNAVAILABLE;
else
g_NvStatus = TPM_RC_NV_RATE;
return;}8.5.3.3

NvCommit

This is a wrapper for the platform function to commit pending NV writes.
30
31
32
33
34
35
36

BOOL
NvCommit(void){
return (_plat__NvCommit() == 0);}

8.5.3.4

NvPowerOn()

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

37
38
39
40
41
42
43
44
45
46
47
48

Return Value

Meaning

TRUE(1)

all NV was initialized

FALSE(0)theNVcontaining savedstate
TPM2_Startup(CLEAR) is required

had

an

error

and

BOOL
NvPowerOn(
void
)
{
int
nvError = 0;// If power was lost, need to re-establish the RAM data that is loaded from// NV and initialize the static variables
if(g_powerWasLost){
if((nvError = _plat__NVEnable(0)) < 0)
FAIL(FATAL_ERROR_NV_UNRECOVERABLE);

Page 326
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
49
50
51
52

Trusted Platform Module Library

NvInitStatic();}
return nvError == 0;}

8.5.3.5

NvManufacture()

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.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

void
NvManufacture(void){#if SIMULATION// Simulate the NV memory being in the erased state.
_plat__NvMemoryClear(0, NV_MEMORY_SIZE);#endif// Initialize static variables
NvInitStatic();// Clear the RAM used for Orderly Index data
MemorySet(s_indexOrderlyRam, 0, RAM_INDEX_SPACE);// Write that Orderly Index data to NV
NvUpdateIndexOrderlyData();// Initialize the next offset of the first entry in evict/index list to 0 (the// end of list marker) and the initial s_maxCounterValue;
NvSetMaxCount(0);// Put the end of list marker at the end of memory. This contains the MaxCount// value as well as the end marker.
NvWriteNvListEnd(NV_USER_DYNAMIC);
return;}8.5.3.6

NvRead()This function is used to move reserved data from NV memory to RAM.
76
77
78
79
80
81
82
83
84
85
86
87

void
NvRead(void
UINT32
UINT32)*outBuffer,
nvOffset,size// OUT: buffer to receive data// IN: offset in NV of value// IN: size of the value to read{// Input type should be valid
pAssert(nvOffset + size < NV_MEMORY_SIZE);_plat__NvMemoryRead(nvOffset, size, outBuffer);
return;}8.5.3.7

NvWrite()This function is used to post reserved data for writing to NV memory. Before the TPM completes theoperation, the value will be written.
88
89
90

BOOL
NvWrite(UINT32

nvOffset,

Family “2.0”Level 00 Revision 01.55// IN: location in NV to receive data

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 327
April 15, 2019

Trusted Platform Module Library
91
92
93
94
95
96
97
98
99
100
101
102
103

UINT32void

size,*inBuffer

Part 4: Supporting Routines// IN: size of the data to move// IN: location containing data to write){// Input type should be valid
if(nvOffset + size <= NV_MEMORY_SIZE){// Set the flag that a NV write happened
SET_NV_UPDATE(UT_NV);
return _plat__NvMemoryWrite(nvOffset, size, inBuffer);}
return FALSE;}

8.5.3.8

NvUpdatePersistent()

This function is used to update a value in the PERSISTENT_DATA structure and commits the value to
NV.
104
105
106
107
108
109
110
111
112
113
114

void
NvUpdatePersistent(
UINT32
UINT32
void)

offset,size,*buffer// IN: location in PERMANENT_DATA to be updated// IN: size of the value// IN: the new data{
pAssert(offset + size <= sizeof(gp));
MemoryCopy(&gp + offset, buffer, size);
NvWrite(offset, size, buffer);}

8.5.3.9

NvClearPersistent()

This function is used to clear a persistent data entry and commit it to NV
115
116
117
118
119
120
121
122
123
124
125

void
NvClearPersistent(
UINT32

offset,UINT32)size// IN: the offset in the PERMANENT_DATA//
structure to be cleared (zeroed)// IN: number of bytes to clear{
pAssert(offset + size <= sizeof(gp));
MemorySet((&gp) + offset, 0, size);
NvWrite(offset, size, (&gp) + offset);}

8.5.3.10

NvReadPersistent()

This function reads persistent data to the RAM copy of the gp structure.
126
127
128
129
130
131
132
133

void
NvReadPersistent(
void){
NvRead(&gp, NV_PERSISTENT_DATA, sizeof(gp));
return;}Page 328
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.6

Trusted Platform Module Library

Object.c

8.6.1

Introduction

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

Includes and Data Definitions#define OBJECT_C#include "Tpm.h"

8.6.3

Functions

8.6.3.1

ObjectFlush()

This function marks an object slot as available. Since there is no checking of the input parameters, it
should be used judiciously.
NOTE:

3
4
5
6
7
8
9

This could be converted to a macro.

void
ObjectFlush(
OBJECT)*object{
object->attributes.occupied = CLEAR;}

8.6.3.2

ObjectSetInUse()

This access function sets the occupied attribute of an object slot.
10
11
12
13
14
15
16

void
ObjectSetInUse(
OBJECT)*object{
object->attributes.occupied = SET;}

8.6.3.3

ObjectStartup()This function is called at TPM2_Startup() to initialize the object subsystem.
17
18
19
20
21
22
23
24
25
26
27
28
29

BOOL
ObjectStartup(
void){
UINT32i;//// object slots initialization
for(i = 0; i < MAX_LOADED_OBJECTS; i++){//Set the slot to not occupied
ObjectFlush(&s_objects[i]);}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 329
April 15, 2019

Trusted Platform Module Library30
31Part 4: Supporting Routines

return TRUE;}

8.6.3.4

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().
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

void
ObjectCleanupEvict(
void){
UINT32i;//// This has to be iterated because a command may have two handles// and they may both be persistent.
// This could be made to be more efficient so that a search is not needed.
for(i = 0; i < MAX_LOADED_OBJECTS; i++){// If an object is a temporary evict object, flush it from slot
OBJECT*object = &s_objects[i];if(object->attributes.evict == SET)
ObjectFlush(object);}return;}8.6.3.5

IsObjectPresent()

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

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

Return Value

Meaning

TRUE(1)

handle references a loaded object

FALSE(0)handle is not an object handle, or it does not reference to a loaded
objectBOOL
IsObjectPresent(
TPMI_DH_OBJECT)

handle// IN: handle to be checked{
UINT32
slotIndex = handle - TRANSIENT_FIRST;// Since the handle is just an index into the array that is zero based, any// handle value outsize of the range of://
TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1)// will now be greater than or equal to MAX_LOADED_OBJECTS
if(slotIndex >= MAX_LOADED_OBJECTS)
return FALSE;// Indicate if the slot is occupied
return (s_objects[slotIndex].attributes.occupied == TRUE);}

8.6.3.6

ObjectIsSequence()

This function is used to check if the object is a sequence object. This function should not be called if thehandle does not reference a loaded object.
Page 330
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

66
67
68
69
70
71
72
73
74
75

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)

object is an HMAC, hash, or event sequence object

FALSE(0)object is not an HMAC, hash, or event sequence object

BOOL
ObjectIsSequence(
OBJECT)*object// IN: handle to be checked{
pAssert(object != NULL);
return (object->attributes.hmacSeq == SET|| object->attributes.hashSeq == SET|| object->attributes.eventSeq == SET);}

8.6.3.7

HandleToObject()

This function is used to find the object structure associated with a handle.
This function requires that handle references a loaded object or a permanent handle.
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

OBJECT*
HandleToObject(
TPMI_DH_OBJECT)

handle// IN: handle of the object{
UINT32index;//// Return NULL if the handle references a permanent handle because there is no// associated OBJECT.
if(HandleGetType(handle) == TPM_HT_PERMANENT)
return NULL;// In this implementation, the handle is determined by the slot occupied by the// object.
index = handle - TRANSIENT_FIRST;
pAssert(index < MAX_LOADED_OBJECTS);
pAssert(s_objects[index].attributes.occupied);
return &s_objects[index];}

8.6.3.8

GetQualifiedName()

This function returns the Qualified Name of the object. In this implementation, the Qualified Name iscomputed 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 takethe same amount of space so it is not recommended that the alternate be used.
This function requires that handle references a loaded object.
94
95
96
97
98
99
100
101
102
103
104

void
GetQualifiedName(TPMI_DH_OBJECT
TPM2B_NAME)

handle,*qualifiedName// IN: handle of the object// OUT: qualified name of the object{
OBJECT*object;//
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 331
April 15, 2019

Trusted Platform Module Library
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

Part 4: Supporting Routines

qualifiedName->t.size = sizeof(TPM_HANDLE);UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name);break;
case TPM_HT_TRANSIENT:
object = HandleToObject(handle);
if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL)
qualifiedName->t.size = 0;else// Copy the name*qualifiedName = object->qualifiedName;
break;
default:
FAIL(FATAL_ERROR_INTERNAL);}
return;}8.6.3.9

ObjectGetHierarchy()

This function returns the handle for the hierarchy of an object.
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

TPMI_RH_HIERARCHY
ObjectGetHierarchy(
OBJECT)*object// IN :object{
if(object->attributes.spsHierarchy){
return TPM_RH_OWNER;}
else if(object->attributes.epsHierarchy){
return TPM_RH_ENDORSEMENT;}
else if(object->attributes.ppsHierarchy){
return TPM_RH_PLATFORM;}
else{
return TPM_RH_NULL;}}

8.6.3.10

GetHeriarchy()

This function returns the handle of the hierarchy to which a handle belongs. This function is similar to
ObjectGetHierarchy() but this routine takes a handle but ObjectGetHierarchy() takes an pointer to an
object.
This function requires that handle references a loaded object.
143
144
145
146
147
148
149
150
151

TPMI_RH_HIERARCHY
GetHeriarchy(
TPMI_DH_OBJECT)

handle// IN :object handle

OBJECT*object = HandleToObject(handle);{//
return ObjectGetHierarchy(object);}

Page 332
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.6.3.11

Trusted Platform Module Library

FindEmptyObjectSlot()

This function finds an open object slot, if any. It will clear the attributes but will not set the occupied
attribute. This is so that a slot may be used and discarded if everything does not go as planned.

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

Return Value

Meaning

NULL

no open slot found!= NULL

pointer to available slot

OBJECT *FindEmptyObjectSlot(
TPMI_DH_OBJECT)*handle// OUT: (optional){
UINT32OBJECTi;*object;//
for(i = 0; i < MAX_LOADED_OBJECTS; i++){object = &s_objects[i];if(object->attributes.occupied == CLEAR){
if(handle)*handle = i + TRANSIENT_FIRST;// Initialize the object attributes
MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES));
return object;}}return NULL;}

8.6.3.12

ObjectAllocateSlot()

This function is used to allocate a slot in internal object array.
174
175
176
177
178
179
180
181
182
183
184
185
186
187

OBJECT *ObjectAllocateSlot(
TPMI_DH_OBJECT)*handle// OUT: handle of allocated object

OBJECT*object = FindEmptyObjectSlot(handle);{//
if(object != NULL){// if found, mark as occupied
ObjectSetInUse(object);}return object;}

8.6.3.13

ObjectSetLoadedAttributes()

This function sets the internal attributes for a loaded object. It is called to finalize the OBJECT attributes(not the TPMA_OBJECT attributes) for a loaded object.
188
189
190
191

void
ObjectSetLoadedAttributes(
OBJECTTPM_HANDLE*object,parentHandle

Family “2.0”Level 00 Revision 01.55// IN: object attributes to finalize// IN: the parent handle

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 333
April 15, 2019

Trusted Platform Module Library
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

Part 4: Supporting Routines){
OBJECT
TPMA_OBJECT*parent = HandleToObject(parentHandle);
objectAttributes = object->publicArea.objectAttributes;//// Copy the stClear attribute from the public area. This could be overwritten// if the parent has stClear SET
object->attributes.stClear =IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear);// If parent handle is a permanent handle, it is a primary (unless it is NULL
if(parent == NULL){
object->attributes.primary = SET;
switch(parentHandle){
case TPM_RH_ENDORSEMENT:
object->attributes.epsHierarchy = SET;
break;
case TPM_RH_OWNER:
object->attributes.spsHierarchy = SET;
break;
case TPM_RH_PLATFORM:
object->attributes.ppsHierarchy = SET;
break;
default:// Treat the temporary attribute as a hierarchy
object->attributes.temporary = SET;
object->attributes.primary = CLEAR;
break;}}
else{// is this a stClear object
object->attributes.stClear =(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear)|| (parent->attributes.stClear == SET));
object->attributes.epsHierarchy = parent->attributes.epsHierarchy;
object->attributes.spsHierarchy = parent->attributes.spsHierarchy;
object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy;// An object is temporary if its parent is temporary or if the object// is external
object->attributes.temporary = parent->attributes.temporary|| object->attributes.external;}// If this is an external object, set the QN == name but don't SET other// key properties ('parent' or 'derived')
if(object->attributes.external)
object->qualifiedName = object->name;else{// check attributes for different types of parents
if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted)&& !object->attributes.publicOnly&& IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt)&& object->publicArea.nameAlg != TPM_ALG_NULL){// This is a parent. If it is not a KEYEDHASH, it is an ordinary parent.
// Otherwise, it is a derivation parent.
if(object->publicArea.type == TPM_ALG_KEYEDHASH)
object->attributes.derivation = SET;
else
object->attributes.isParent = SET;}
ComputeQualifiedName(parentHandle, object->publicArea.nameAlg,&object->name, &object->qualifiedName);

Page 334
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
258
259
260
261
262

Trusted Platform Module Library}// Set slot occupied
ObjectSetInUse(object);return;}8.6.3.14

ObjectLoad()Common function to load an object. A loaded object has its public area validated (unless its nameAlg is
TPM_ALG_NULL). If a sensitive part is loaded, it is verified to be correct and if both public and sensitive
parts are loaded, then the cryptographic binding between the objects is validated. This function does notcause the allocated slot to be marked as in use.
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

TPM_RC
ObjectLoad(OBJECTOBJECT
TPMT_PUBLIC
TPMT_SENSITIVE
TPM_RCTPM_RCTPM2B_NAME*object,// IN: pointer to object slot//
object*parent,// IN: (optional) the parent object*publicArea,// IN: public area to be installed in the object*sensitive,// IN: (optional) sensitive area to be//installed in the object
blamePublic,// IN: parameter number to associate with the//
publicArea errors
blameSensitive,// IN: parameter number to associate with the//sensitive area errors*name// IN: (optional)){
TPM_RC
result = TPM_RC_SUCCESS;//// Do validations of public area object descriptions
pAssert(publicArea != NULL);// Is this public only or a no-name object?
if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL){// Need to have schemes checked so that we do the right thing with the// public key.
result = SchemeChecks(NULL, publicArea);}else{// For any sensitive area, make sure that the seedSize is no larger than the// digest size of nameAlg
if(sensitive->seedValue.t.size > CryptHashGetDigestSize(publicArea->nameAlg))
return TPM_RCS_KEY_SIZE + blameSensitive;// Check attributes and schemes for consistency
result = PublicAttributesValidation(parent, publicArea);}
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, blamePublic);// Sensitive area and binding checks// On load, check nothing if the parent is fixedTPM. For all other cases, validate// the keys.
if((parent == NULL)|| ((parent != NULL) && !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
TPMA_OBJECT, fixedTPM))){// Do the cryptographic key validation
result = CryptValidateKeys(publicArea, sensitive, blamePublic,
blameSensitive);
if(result != TPM_RC_SUCCESS)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 335
April 15, 2019

Trusted Platform Module Library
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345

Part 4: Supporting Routines

return result;}#if ALG_RSA// If this is an RSA key, then expand the private exponent.
// Note: ObjectLoad() is only called by TPM2_Import() if the parent is fixedTPM.
// For any key that does not have a fixedTPM parent, the exponent is computed// whenever it is loaded
if((publicArea->type == TPM_ALG_RSA) && (sensitive != NULL)){
result = CryptRsaLoadPrivateExponent(publicArea, sensitive);
if(result != TPM_RC_SUCCESS)
return result;}#endif // ALG_RSA// See if there is an object to populateif((result == TPM_RC_SUCCESS) && (object != NULL)){// Initialize public
object->publicArea = *publicArea;// Copy sensitive if there is oneif(sensitive == NULL)
object->attributes.publicOnly = SET;
else
object->sensitive = *sensitive;// Set the name, if one was provided
if(name != NULL)
object->name = *name;else
object->name.t.size = 0;}
return result;}8.6.3.15

AllocateSequenceSlot()

This function allocates a sequence slot and initializes the parts that are used by the normal objects sothat a sequence object is not inadvertently used for an operation that is not appropriate for a sequence.
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

static HASH_OBJECT *AllocateSequenceSlot(
TPM_HANDLE
TPM2B_AUTH)*newHandle,*auth// OUT: receives the allocated handle// IN: the authValue for the slot

HASH_OBJECT*object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle);{//// Validate that the proper location of the hash state data relative to the// object state data. It would be good if this could have been done at compile// time but it can't so do it in something that can be removed after debug.
cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy));if(object != NULL){// Set the common values that a sequence object shares with an ordinary object// First, clear all attributes
MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT));// The type is TPM_ALG_NULL
object->type = TPM_ALG_NULL;// This has no name algorithm and the name is the Empty Buffer
object->nameAlg = TPM_ALG_NULL;

Page 336
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

Trusted Platform Module Library// A sequence object is considered to be in the NULL hierarchy so it should// be marked as temporary so that it can't be persisted
object->attributes.temporary = SET;// A sequence object is DA exempt.
SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA);// Copy the authorization value
if(auth != NULL)
object->auth = *auth;else
object->auth.t.size = 0;}
return object;}#if CC_HMAC_Start || CC_MAC_Start

8.6.3.16

ObjectCreateHMACSequence()

This function creates an internal HMAC sequence object.

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

Error Returns

Meaning

TPM_RC_OBJECT_MEMORY

if there is no free slot for an object

TPM_RC
ObjectCreateHMACSequence(
TPMI_ALG_HASHOBJECT
TPM2B_AUTH
TPMI_DH_OBJECT)

hashAlg,*keyObject,*auth,*newHandle// IN: hash algorithm// IN: the object containing the HMAC key// IN: authValue// OUT: HMAC sequence object handle{
HASH_OBJECT*hmacObject;//// Try to allocate a slot for new object
hmacObject = AllocateSequenceSlot(newHandle, auth);if(hmacObject == NULL)
return TPM_RC_OBJECT_MEMORY;// Set HMAC sequence bit
hmacObject->attributes.hmacSeq = SET;
#if !SMAC_IMPLEMENTED
if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg,
keyObject->sensitive.sensitive.bits.b.size,
keyObject->sensitive.sensitive.bits.b.buffer) == 0)#else
if(CryptMacStart(&hmacObject->state.hmacState,&keyObject->publicArea.parameters,
hashAlg, &keyObject->sensitive.sensitive.any.b) == 0)#endif // SMAC_IMPLEMENTED
return TPM_RC_FAILURE;
return TPM_RC_SUCCESS;}#endif

8.6.3.17

ObjectCreateHashSequence()

This function creates a hash sequence object.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 337
April 15, 2019

Trusted Platform Module Library

419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

Part 4: Supporting Routines

Error Returns

Meaning

TPM_RC_OBJECT_MEMORY

if there is no free slot for an object

TPM_RC
ObjectCreateHashSequence(
TPMI_ALG_HASH
TPM2B_AUTH
TPMI_DH_OBJECT)

hashAlg,*auth,*newHandle// IN: hash algorithm// IN: authValue// OUT: sequence object handle{
HASH_OBJECT*hashObject = AllocateSequenceSlot(newHandle, auth);//// See if slot allocatedif(hashObject == NULL)
return TPM_RC_OBJECT_MEMORY;// Set hash sequence bit
hashObject->attributes.hashSeq = SET;// Start hash for hash sequence
CryptHashStart(&hashObject->state.hashState[0], hashAlg);
return TPM_RC_SUCCESS;}

8.6.3.18

ObjectCreateEventSequence()

This function creates an event sequence object.

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

Error Returns

Meaning

TPM_RC_OBJECT_MEMORY

if there is no free slot for an object

TPM_RC
ObjectCreateEventSequence(
TPM2B_AUTH
TPMI_DH_OBJECT)*auth,*newHandle// IN: authValue// OUT: sequence object handle{
HASH_OBJECTUINT32
TPM_ALG_ID*hashObject = AllocateSequenceSlot(newHandle, auth);count;
hash;//// See if slot allocatedif(hashObject == NULL)
return TPM_RC_OBJECT_MEMORY;// Set the event sequence attributehashObject->attributes.eventSeq = SET;// Initialize hash states for each implemented PCR algorithms
for(count = 0; (hash = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++)
CryptHashStart(&hashObject->state.hashState[count], hash);return TPM_RC_SUCCESS;}

8.6.3.19

ObjectTerminateEvent()

This function is called to close out the event sequence and clean up the hash context states.
460
461
462

void
ObjectTerminateEvent(
void

Page 338
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486

Trusted Platform Module Library){
HASH_OBJECT
int
BYTE

*hashObject;count;
buffer[MAX_DIGEST_SIZE];//
hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);// Don't assume that this is a proper sequence object
if(hashObject->attributes.eventSeq){// If it is, close any open hash contexts. This is done in case// the cryptographic implementation has some context values that need to be// cleaned up (hygiene).
//for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++){
CryptHashEnd(&hashObject->state.hashState[count], 0, buffer);}// Flush sequence object
FlushObject(g_DRTMHandle);}
g_DRTMHandle = TPM_RH_UNASSIGNED;}

8.6.3.20

ObjectContextLoad()This function loads an object from a saved object context.

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515

Return Value

Meaning

NULL

if there is no free slot for an object!= NULL

points to the loaded object

OBJECT *ObjectContextLoad(
ANY_OBJECT_BUFFER*object,

TPMI_DH_OBJECT)*handle// IN: pointer to object structure in saved//
context// OUT: object handle{
OBJECT*newObject = ObjectAllocateSlot(handle);//// Try to allocate a slot for new object
if(newObject != NULL){// Copy the first part of the object
MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state));// See if this is a sequence object
if(ObjectIsSequence(newObject)){// If this is a sequence object, import the data
SequenceDataImport((HASH_OBJECT *)newObject,(HASH_OBJECT_BUFFER *)object);}else{// Copy input object data to internal structure
MemoryCopy(newObject, object, sizeof(OBJECT));}}
return newObject;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 339
April 15, 2019

Trusted Platform Module Library

8.6.3.21

Part 4: Supporting Routines

FlushObject()

This function frees an object slot.
This function requires that the object is loaded.
516
517
518
519
520
521
522
523
524
525
526
527
528

void
FlushObject(
TPMI_DH_OBJECT)

handle// IN: handle to be freed{
UINT32index = handle - TRANSIENT_FIRST;//
pAssert(index < MAX_LOADED_OBJECTS);// Clear all the object attributes
MemorySet((BYTE*)&(s_objects[index].attributes),
0, sizeof(OBJECT_ATTRIBUTES));
return;}8.6.3.22

ObjectFlushHierarchy()

This function is called to flush all the loaded transient objects associated with a hierarchy when thehierarchy is disabled.
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563

void
ObjectFlushHierarchy(
TPMI_RH_HIERARCHY)

hierarchy// IN: hierarchy to be flush{
UINT16i;//// iterate object slotsfor(i = 0; i < MAX_LOADED_OBJECTS; i++){if(s_objects[i].attributes.occupied)// If found an occupied slot{
switch(hierarchy){
case TPM_RH_PLATFORM:
if(s_objects[i].attributes.ppsHierarchy == SET)s_objects[i].attributes.occupied = FALSE;
break;
case TPM_RH_OWNER:
if(s_objects[i].attributes.spsHierarchy == SET)s_objects[i].attributes.occupied = FALSE;
break;
case TPM_RH_ENDORSEMENT:
if(s_objects[i].attributes.epsHierarchy == SET)s_objects[i].attributes.occupied = FALSE;
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}}}
return;}Page 340
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.6.3.23

Trusted Platform Module Library

ObjectLoadEvict()

This function loads a persistent object into a transient object slot.
This function requires that handle is associated with a persistent object.

564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

Error Returns

Meaning

TPM_RC_HANDLE

the persistent object does not exist or the associated hierarchy isdisabled.

TPM_RC_OBJECT_MEMORY

no object slot

TPM_RC
ObjectLoadEvict(
TPM_HANDLE*handle,// IN:OUT: evict object handle. If success, it// will be replace by the loaded object handle// IN: the command being processed

COMMAND_INDEX)

commandIndex

TPM_RCTPM_HANDLEOBJECT

result;evictHandle = *handle;*object;{// Save the evict handle//// If this is an index that references a persistent object created by// the platform, then return TPM_RH_HANDLE if the phEnable is FALSE
if(*handle >= PLATFORM_PERSISTENT){// belongs to platform
if(g_phEnable == CLEAR)
return TPM_RC_HANDLE;}// belongs to ownerelse if(gc.shEnable == CLEAR)
return TPM_RC_HANDLE;// Try to allocate a slot for an object
object = ObjectAllocateSlot(handle);
if(object == NULL)
return TPM_RC_OBJECT_MEMORY;// Copy persistent object to transient object slot. A TPM_RC_HANDLE// may be returned at this point. This will mark the slot as containing// a transient object so that it will be flushed at the end of the// command
result = NvGetEvictObject(evictHandle, object);// Bail out if this failed
if(result != TPM_RC_SUCCESS)
return result;// check the object to see if it is in the endorsement hierarchy// if it is and this is not a TPM2_EvictControl() command, indicate// that the hierarchy is disabled.
// If the associated hierarchy is disabled, make it look like the// handle is not definedif(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT&& gc.ehEnable == CLEAR&& GetCommandCode(commandIndex) != TPM_CC_EvictControl)
return TPM_RC_HANDLE;
return result;}8.6.3.24

ObjectComputeName()

This does the name computation from a public area (can be marshaled or not).
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 341
April 15, 2019

Trusted Platform Module Library

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

Part 4: Supporting Routines

TPM2B_NAME *ObjectComputeName(UINT32BYTE
TPM_ALG_ID
TPM2B_NAME)size,*publicArea,
nameAlg,*name// IN: the size of the area to digest// IN: the public area to digest// IN: the hash algorithm to use// OUT: Computed name{// Hash the publicArea into the name buffer leaving room for the nameAlg
name->t.size = CryptHashBlock(nameAlg, size, publicArea,sizeof(name->t.name) - 2,
&name->t.name[2]);// set the nameAlg
UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name);
name->t.size += 2;
return name;}

8.6.3.25

PublicMarshalAndComputeName()

This function computes the Name of an object from its public area.
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

TPM2B_NAME *PublicMarshalAndComputeName(
TPMT_PUBLIC
TPM2B_NAME)*publicArea,*name// IN: public area of an object// OUT: name of the object{// Will marshal a public area into a template. This is because the internal// format for a TPM2B_PUBLIC is a structure and not a simple BYTE buffer.
TPM2B_TEMPLATE
marshaled;// this is big enough to hold a// marshaled TPMT_PUBLIC
BYTE*buffer = (BYTE *)&marshaled.t.buffer;//// if the nameAlg is NULL then there is no name.
if(publicArea->nameAlg == TPM_ALG_NULL)
name->t.size = 0;
else{// Marshal the public area into its canonical form
marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL);// and compute the nameObjectComputeName(marshaled.t.size, marshaled.t.buffer,publicArea->nameAlg, name);}
return name;}

8.6.3.26

ComputeQualifiedName()

This function computes the qualified name of an object.
653
654
655
656
657
658
659
660
661
662
663

void
ComputeQualifiedName(
TPM_HANDLE
TPM_ALG_ID
TPM2B_NAME
TPM2B_NAME)

parentHandle,
nameAlg,*name,*qualifiedName

HASH_STATETPM2B_NAME

hashState;parentName;// IN: parent's handle// IN: name hash// IN: name of the object// OUT: qualified name of the object{// hash state//

Page 342
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691

Trusted Platform Module Libraryif(parentHandle == TPM_RH_UNASSIGNED){
MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name));*qualifiedName = *name;}else{
GetQualifiedName(parentHandle, &parentName);//

QN_A = hash_A (QN of parent || NAME_A)// Start hashqualifiedName->t.size = CryptHashStart(&hashState, nameAlg);// Add parent's qualified name
CryptDigestUpdate2B(&hashState, &parentName.b);// Add self name
CryptDigestUpdate2B(&hashState, &name->b);// Complete hash leaving room for the name algorithm
CryptHashEnd(&hashState, qualifiedName->t.size,&qualifiedName->t.name[2]);UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);qualifiedName->t.size += 2;}
return;}8.6.3.27

ObjectIsStorage()This function determines if an object has the attributes associated with a parent. A parent is anasymmetric or symmetric block cipher key that has its restricted and decrypt attributes SET, and sign
CLEAR.

692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

Return Value

Meaning

TRUE(1)

object is a storage key

FALSE(0)object is not a storage key

BOOL
ObjectIsStorage(
TPMI_DH_OBJECT)

handle// IN: object handle

OBJECT
TPMT_PUBLIC*object = HandleToObject(handle);*publicArea = ((object != NULL) ? &object->publicArea : NULL);{//
return (publicArea != NULL&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)&& !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)&& (object->publicArea.type == ALG_RSA_VALUE|| object->publicArea.type == ALG_ECC_VALUE));}

8.6.3.28

ObjectCapGetLoaded()This function returns a a list of handles of loaded object, starting from handle. Handle must be in therange of valid transient object handles, but does not have to be the handle of a loaded transient object.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 343
April 15, 2019

Trusted Platform Module Library

707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751

Part 4: Supporting Routines

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
ObjectCapGetLoaded(
TPMI_DH_OBJECTUINT32
TPML_HANDLE)

handle,count,*handleList// IN: start handle// IN: count of returned handles// OUT: list of handle{
TPMI_YES_NOUINT32more = NO;i;//pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);// Initialize output handle list
handleList->count = 0;// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;// Iterate object slots to get loaded object handles
for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++){if(s_objects[i].attributes.occupied == TRUE){// A valid transient object can not be the copy of a persistent object
pAssert(s_objects[i].attributes.evict == CLEAR);
if(handleList->count < count){// If we have not filled up the return list, add this object// handle to it
handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
handleList->count++;}else{// If the return list is full but we still have loaded object// available, report this and stop iterating
more = YES;
break;}}}
return more;}

8.6.3.29

ObjectCapGetTransientAvail()This function returns an estimate of the number of additional transient objects that could be loaded into
the TPM.
752
753
754
755
756
757
758

UINT32
ObjectCapGetTransientAvail(
void){
UINT32
UINT32

Page 344
April 15, 2019i;num = 0;TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
759
760
761
762
763
764
765
766
767

Trusted Platform Module Library//// Iterate object slot to get the number of unoccupied slotsfor(i = 0; i < MAX_LOADED_OBJECTS; i++){if(s_objects[i].attributes.occupied == FALSE) num++;}
return num;}

8.6.3.30

ObjectGetPublicAttributes()

Returns the attributes associated with an object handles.
768
769
770
771
772
773
774
775
776
777
778
779
780
781

TPMA_OBJECT
ObjectGetPublicAttributes(
TPM_HANDLE)

handle{return HandleToObject(handle)->publicArea.objectAttributes;}

OBJECT_ATTRIBUTES
ObjectGetProperties(
TPM_HANDLE)

handle{return HandleToObject(handle)->attributes;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 345
April 15, 2019

Trusted Platform Module Library

8.7

Part 4: Supporting Routines

PCR.c

8.7.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 allocatedwhether the PCR is implemented or not.
8.7.2
1
2

Includes, Defines, and Data Definitions#define PCR_C#include "Tpm.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.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

static const PCR_Attributes s_initAttributes[] ={// PCR 0 - 15, static RTM{1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F},{1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F},{1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F},{1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F},{0, 0x0F, 0x1F},{0, 0x10, 0x1C},{0, 0x10, 0x1C},{0, 0x10, 0x0C},{0, 0x14, 0x0E},{0, 0x14, 0x04},{0, 0x14, 0x04},{0, 0x0F, 0x1F},{0, 0x0F, 0x1F}// PCR 16, Debug// PCR 17, Locality 4// PCR 18, Locality 3// PCR 19, Locality 2// PCR 20, Locality 1// PCR 21, Dynamic OS// PCR 22, Dynamic OS// PCR 23, Application specific// PCR 24, testing policy

};

8.7.3

Functions8.7.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 theplatform specification.

21
22
23
24

Return Value

Meaning

TRUE(1)

PCR belongs an authorization group

FALSE(0)PCR does not belong an authorization group

BOOL
PCRBelongsAuthGroup(
TPMI_DH_PCR
UINT32

Page 346
April 15, 2019

handle,*groupIndex// IN: handle of PCR// OUT: group index if PCR belongs a

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

Trusted Platform Module Library
//
//
//
//

group that allows authValue. If PCR
does not belong to an authorizationgroup, the value in this parameter isinvalid){#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0// Platform specification determines to which authorization group a PCR belongs// (if any). In this implementation, we assume there is only// one authorization group which contains PCR[20-22]. If the platform// specification requires differently, the implementation should be changed// accordingly
if(handle >= 20 && handle <= 22){*groupIndex = 0;
return TRUE;}#endifreturn FALSE;}

8.7.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 theplatform specification.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

Return Value

Meaning

TRUE(1)

PCR belongs a policy group

FALSE(0)PCR does not belong a policy group

BOOL
PCRBelongsPolicyGroup(
TPMI_DH_PCR
UINT32handle,*groupIndex// IN: handle of PCR// OUT: group index if PCR belongs a group that//allows policy. If PCR does not belong to//a policy group, the value in this//parameter is invalid){#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0// Platform specification decides if a PCR belongs to a policy group and// belongs to which group. In this implementation, we assume there is only// one policy group which contains PCR20-22. If the platform specification// requires differently, the implementation should be changed accordingly
if(handle >= 20 && handle <= 22){*groupIndex = 0;
return TRUE;}#endifreturn FALSE;}

8.7.3.3

PCRBelongsTCBGroup()This function indicates if a PCR belongs to the TCB group.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 347
April 15, 2019

Trusted Platform Module Library

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

Part 4: Supporting Routines

Return Value

Meaning

TRUE(1)

PCR belongs to TCB group

FALSE(0)PCR does not belong to TCB group

static BOOL
PCRBelongsTCBGroup(
TPMI_DH_PCR)

handle// IN: handle of PCR{#if ENABLE_PCR_NO_INCREMENT == YES// Platform specification decides if a PCR belongs to a TCB group. In this// implementation, we assume PCR[20-22] belong to TCB group. If the platform// specification requires differently, the implementation should be// changed accordingly
if(handle >= 20 && handle <= 22)
return TRUE;#endifreturn FALSE;}

8.7.3.4

PCRPolicyIsAvailable()This function indicates if a policy is available for a PCR.

84
85
86
87
88
89
90
91
92

Return Value

Meaning

TRUE(1)the PCR should be authorized by policy

FALSE(0)the PCR does not allow policy

BOOL
PCRPolicyIsAvailable(
TPMI_DH_PCR)

handle// IN: PCR handle

UINT32groupIndex;{
return PCRBelongsPolicyGroup(handle, &groupIndex);}

8.7.3.5

PCRGetAuthValue()

This function is used to access the authValue of a PCR. If PCR does not belong to an authValue group,an EmptyAuth() will be returned.
93
94
95
96
97
98
99
100
101
102
103
104
105
106

TPM2B_AUTH *PCRGetAuthValue(
TPMI_DH_PCR)

handle// IN: PCR handle{
UINT32groupIndex;

if(PCRBelongsAuthGroup(handle, &groupIndex)){
return &gc.pcrAuthValues.auth[groupIndex];}
else{
return NULL;

Page 348
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
107
108

Trusted Platform Module Library}}

8.7.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.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

TPMI_ALG_HASHPCRGetAuthPolicy(
TPMI_DH_PCR
TPM2B_DIGEST)

handle,*policy// IN: PCR handle// OUT: policy of PCR

UINT32groupIndex;{
if(PCRBelongsPolicyGroup(handle, &groupIndex)){*policy = gp.pcrPolicies.policy[groupIndex];
return gp.pcrPolicies.hashAlg[groupIndex];}else{
policy->t.size = 0;
return TPM_ALG_NULL;}}

8.7.3.7

PCRSimStart()

This function is used to initialize the policies when a TPM is manufactured. This function would only becalled in a manufacturing environment or in a TPM simulator.
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

void
PCRSimStart(
void){
UINT32 i;#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0
for(i = 0; i < NUM_POLICY_PCR_GROUP; i++){gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
gp.pcrPolicies.policy[i].t.size = 0;}
#endif#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0
for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++){gc.pcrAuthValues.auth[i].t.size = 0;}
#endif// We need to give an initial configuration on allocated PCR before// receiving any TPM2_PCR_Allocate command to change this configuration// When the simulation environment starts, we allocate all the PCRsfor(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT;
gp.pcrAllocated.count++){
gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash= CryptHashGetAlgByIndex(gp.pcrAllocated.count);
gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelectFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 349
April 15, 2019

Trusted Platform Module Library
157
158
159
160
161
162
163
164
165
166
167
168

Part 4: Supporting Routines= PCR_SELECT_MAX;
for(i = 0; i < PCR_SELECT_MAX; i++)gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i]= 0xFF;}// Store the initial configuration to NV
NV_SYNC_PERSISTENT(pcrPolicies);
NV_SYNC_PERSISTENT(pcrAllocated);
return;}8.7.3.8

GetSavedPcrPointer()This function returns the address of an array of state saved PCR based on the hash algorithm.

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

Return Value

Meaning

NULL

no such algorithm!= NULL

pointer to the 0th byte of the 0th PCR

static BYTE *GetSavedPcrPointer(
TPM_ALG_ID
UINT32)alg,
pcrIndex// IN: algorithm for bank// IN: PCR index in PCR_SAVE{
BYTE*retVal;switch(alg){#if ALG_SHA1
case ALG_SHA1_VALUE:
retVal = gc.pcrSave.sha1[pcrIndex];
break;#endif#if ALG_SHA256
case ALG_SHA256_VALUE:
retVal = gc.pcrSave.sha256[pcrIndex];
break;#endif#if ALG_SHA384
case ALG_SHA384_VALUE:
retVal = gc.pcrSave.sha384[pcrIndex];
break;#endif#if ALG_SHA512
case ALG_SHA512_VALUE:
retVal = gc.pcrSave.sha512[pcrIndex];
break;#endif#if ALG_SM3_256
case ALG_SM3_256_VALUE:
retVal = gc.pcrSave.sm3_256[pcrIndex];
break;#endifdefault:
FAIL(FATAL_ERROR_INTERNAL);}
return retVal;}

Page 350
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.7.3.9

Trusted Platform Module Library

PcrIsAllocated()

This function indicates if a PCR number for the particular hash algorithm is allocated.

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

Return Value

Meaning

TRUE(1)

PCR is allocated

FALSE(0)PCR is not allocatedBOOL
PcrIsAllocated(
UINT32
TPMI_ALG_HASH)

pcr,
hashAlg// IN: The number of the PCR// IN: The PCR algorithm{
UINT32BOOL

i;allocated = FALSE;

if(pcr < IMPLEMENTATION_PCR){
for(i = 0; i < gp.pcrAllocated.count; i++){if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg){
if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr / 8])& (1 << (pcr % 8))) != 0)
allocated = TRUE;
else
allocated = FALSE;
break;}}}
return allocated;}

8.7.3.10

GetPcrPointer()This function returns the address of an array of PCR based on the hash algorithm.

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

Return Value

Meaning

NULL

no such algorithm!= NULL

pointer to the 0th byte of the 0th PCR

static BYTE *GetPcrPointer(
TPM_ALG_ID
UINT32)alg,
pcrNumber// IN: algorithm for bank// IN: PCR number

static BYTE

*pcr = NULL;{
if(!PcrIsAllocated(pcrNumber, alg))
return NULL;
switch(alg){#if ALG_SHA1
case ALG_SHA1_VALUE:
pcr = s_pcrs[pcrNumber].sha1Pcr;
break;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 351
April 15, 2019

Trusted Platform Module Library
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

Part 4: Supporting Routines#endif#if ALG_SHA256
case ALG_SHA256_VALUE:
pcr = s_pcrs[pcrNumber].sha256Pcr;
break;#endif#if ALG_SHA384
case ALG_SHA384_VALUE:
pcr = s_pcrs[pcrNumber].sha384Pcr;
break;#endif#if ALG_SHA512
case ALG_SHA512_VALUE:
pcr = s_pcrs[pcrNumber].sha512Pcr;
break;#endif#if ALG_SM3_256
case ALG_SM3_256_VALUE:
pcr = s_pcrs[pcrNumber].sm3_256Pcr;
break;#endifdefault:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return pcr;}

8.7.3.11

IsPcrSelected()

This function indicates if an indicated PCR number is selected by the bit map in selection.

279
280
281
282
283
284
285
286
287
288
289

Return Value

Meaning

TRUE(1)

PCR is selected

FALSE(0)PCR is not selected

static BOOL
IsPcrSelected(
UINT32
TPMS_PCR_SELECTION)

pcr,*selection// IN: The number of the PCR// IN: The selection structure{
BOOL
selected;
selected = (pcr < IMPLEMENTATION_PCR&& ((selection->pcrSelect[pcr / 8]) & (1 << (pcr % 8))) != 0);
return selected;}

8.7.3.12

FilterPcr()

This function modifies a PCR selection array based on the implemented PCR.
290
291
292
293
294
295
296
297
298

static void
FilterPcr(
TPMS_PCR_SELECTION)*selection// IN: input PCR selection{
UINT32i;
TPMS_PCR_SELECTION*allocated = NULL;// If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR

Page 352
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

Trusted Platform Module Libraryfor(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++)selection->pcrSelect[i] = 0;// Find the internal configuration for the bankfor(i = 0; i < gp.pcrAllocated.count; i++){if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash){allocated = &gp.pcrAllocated.pcrSelections[i];break;}}
for(i = 0; i < selection->sizeofSelect; i++){if(allocated == NULL){// If the required bank does not exist, clear input selection
selection->pcrSelect[i] = 0;}
else
selection->pcrSelect[i] &= allocated->pcrSelect[i];}return;}8.7.3.13

PcrDrtm()

This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End().
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348

void
PcrDrtm(const TPMI_DH_PCR

pcrHandle,

const TPMI_ALG_HASH
const TPM2B_DIGEST)

hash,*digest// IN: the index of the PCR to be//modified// IN: the bank identifier// IN: the digest to modify the PCR{
BYTE*pcrData = GetPcrPointer(hash, pcrHandle);

if(pcrData != NULL){// Rest the PCR to zeros
MemorySet(pcrData, 0, digest->t.size);// if the TPM has not started, then set the PCR to 0...04 and then extend
if(!TPMIsStarted()){
pcrData[digest->t.size - 1] = 4;}// Now, extend the value
PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer);}}

8.7.3.14

PCR_ClearAuth()This function is used to reset the PCR authorization values. It is called on TPM2_Startup(CLEAR) andTPM2_Clear().
349
350

void
PCR_ClearAuth(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 353
April 15, 2019

Trusted Platform Module Library
351
352
353
354
355
356
357
358
359
360
361

Part 4: Supporting Routines

void
)
{
#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0intj;for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++){gc.pcrAuthValues.auth[j].t.size = 0;}
#endif}

8.7.3.15

PCRStartup()This function initializes the PCR subsystem at TPM2_Startup().
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

BOOL
PCRStartup(
STARTUP_TYPE
BYTE
)

type,
locality// IN: startup type// IN: startup locality{
UINT32
UINT32

pcr, j;saveIndex = 0;

g_pcrReConfig = FALSE;// Don't test for SU_RESET because that should be the default when nothing// else is selected
if(type != SU_RESUME && type != SU_RESTART){// PCR generation counter is cleared at TPM_RESET
gr.pcrCounter = 0;}// Initialize/Restore PCR valuesfor(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++){// On resume, need to know if this PCR had its state saved or not
UINT32stateSaved;if(type == SU_RESUME&& s_initAttributes[pcr].stateSave == SET){
stateSaved = 1;}
else{
stateSaved = 0;
PCRChanged(pcr);}// If this is the H-CRTM PCR and we are not doing a resume and we// had an H-CRTM event, then we don't change this PCR
if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE)
continue;// Iterate each hash algorithm bankfor(j = 0; j < gp.pcrAllocated.count; j++){
TPMI_ALG_HASHhash = gp.pcrAllocated.pcrSelections[j].hash;
BYTE*pcrData = GetPcrPointer(hash, pcr);
UINT16
pcrSize = CryptHashGetDigestSize(hash);

Page 354
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447

Trusted Platform Module Libraryif(pcrData != NULL){// if state was saved
if(stateSaved == 1){// Restore saved PCR value
BYTE*pcrSavedData;
pcrSavedData = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash,saveIndex);
if(pcrSavedData == NULL)
return FALSE;
MemoryCopy(pcrData, pcrSavedData, pcrSize);}else// PCR was not restored by state save{// If the reset locality of the PCR is 4, then// the reset value is all one's, otherwise it is// all zero.
if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
MemorySet(pcrData, 0xFF, pcrSize);
else{
MemorySet(pcrData, 0, pcrSize);
if(pcr == HCRTM_PCR)
pcrData[pcrSize - 1] = locality;}}}}
saveIndex += stateSaved;}// Reset authValues on TPM2_Startup(CLEAR)
if(type != SU_RESUME)PCR_ClearAuth();return TRUE;}

8.7.3.16

PCRStateSave()This function is used to save the PCR values that will be restored on TPM Resume.
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468

void
PCRStateSave(
TPM_SU)

type// IN: startup type

UINT32
UINT32

pcr, j;saveIndex = 0;{// if state save CLEAR, nothing to be done.
if(type == TPM_SU_CLEAR)
return;Return here// Copy PCR values to the structure that should be saved to NV
for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++){UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0;// Iterate each hash algorithm bankfor(j = 0; j < gp.pcrAllocated.count; j++){
BYTE
*pcrData;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 355
April 15, 2019

Trusted Platform Module Library
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493

UINT32

Part 4: Supporting Routines

pcrSize;

pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr);
if(pcrData != NULL){
pcrSize= CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[j].hash);if(stateSaved == 1){// Restore saved PCR value
BYTE*pcrSavedData;
pcrSavedData= GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash,saveIndex);
MemoryCopy(pcrSavedData, pcrData, pcrSize);}}}
saveIndex += stateSaved;}
return;}8.7.3.17

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.

494
495
496
497
498
499
500
501
502
503
504
505

Return Value

Meaning

TRUE(1)

PCR is state saved

FALSE(0)PCR is not state saved

BOOL
PCRIsStateSaved(
TPMI_DH_PCR)

handle// IN: PCR handle to be extended{
UINT32

pcr = handle - PCR_FIRST;

if(s_initAttributes[pcr].stateSave == SET)
return TRUE;
else
return FALSE;}

8.7.3.18

PCRIsResetAllowed()

This function indicates if a PCR may be reset by the current command locality. The return value is basedon PCR attributes, and not the PCR allocation.

506
507

Return Value

Meaning

TRUE(1)

TPM2_PCR_Reset() is allowed

FALSE(0)TPM2_PCR_Reset() is not allowed

BOOL
PCRIsResetAllowed(

Page 356
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

TPMI_DH_PCR)

Trusted Platform Module Libraryhandle// IN: PCR handle to be extended

{
UINT8
UINT8
UINT32

commandLocality;
localityBits = 1;
pcr = handle - PCR_FIRST;// Check for the localitycommandLocality = _plat__LocalityGet();#ifdef DRTM_PCR// For a TPM that does DRTM, Reset is not allowed at locality 4if(commandLocality == 4)
return FALSE;#endiflocalityBits = localityBits << commandLocality;if((localityBits & s_initAttributes[pcr].resetLocality) == 0)
return FALSE;
else
return TRUE;}

8.7.3.19

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. Will also
bump the counter if the handle is zero which means that PCR 0 can not be in the TCB group. Bump on
zero is used by TPM2_Clear().
530
531
532
533
534
535
536
537
538
539
540
541
542
543

void
PCRChanged(
TPM_HANDLE)

pcrHandle// IN: the handle of the PCR that changed.

{// For the reference implementation, the only change that does not cause// increment is a change to a PCR in the TCB group.
if((pcrHandle == 0) || !PCRBelongsTCBGroup(pcrHandle)){
gr.pcrCounter++;if(gr.pcrCounter == 0)
FAIL(FATAL_ERROR_COUNTER_OVERFLOW);}}

8.7.3.20

PCRIsExtendAllowed()

This function indicates a PCR may be extended at the current command locality. The return value isbased on PCR attributes, and not the PCR allocation.

544
545
546
547
548
549

Return Value

Meaning

TRUE(1)extend is allowed

FALSE(0)extend is not allowed

BOOL
PCRIsExtendAllowed(
TPMI_DH_PCR)

handle// IN: PCR handle to be extended

{
UINT8

Family “2.0”Level 00 Revision 01.55

commandLocality;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 357
April 15, 2019

Trusted Platform Module Library
550
551
552
553
554
555
556
557
558
559
560

UINT8
UINT32

Part 4: Supporting Routines

localityBits = 1;
pcr = handle - PCR_FIRST;// Check for the localitycommandLocality = _plat__LocalityGet();localityBits = localityBits << commandLocality;if((localityBits & s_initAttributes[pcr].extendLocality) == 0)
return FALSE;
else
return TRUE;}

8.7.3.21

PCRExtend()

This function is used to extend a PCR in a specific bank.
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589

void
PCRExtend(
TPMI_DH_PCR
TPMI_ALG_HASHUINT32
BYTE)

handle,
hash,
size,
*data

// IN: PCR handle to be extended// IN: hash algorithm of PCR// IN: size of data to be extended// IN: data to be extended{
BYTE
HASH_STATEUINT16*pcrData;
hashState;
pcrSize;

pcrData = GetPcrPointer(hash, handle - PCR_FIRST);// Extend PCR if it is allocatedif(pcrData != NULL){
pcrSize = CryptHashGetDigestSize(hash);
CryptHashStart(&hashState, hash);
CryptDigestUpdate(&hashState, pcrSize, pcrData);
CryptDigestUpdate(&hashState, size, data);
CryptHashEnd(&hashState, pcrSize, pcrData);// PCR has changed so update the pcrCounter if necessary
PCRChanged(handle);}
return;}8.7.3.22

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.
590
591
592
593
594
595
596
597
598
599
600

void
PCRComputeCurrentDigest(
TPMI_ALG_HASH
TPML_PCR_SELECTION

hashAlg,*selection,

TPM2B_DIGEST)*digest// IN: hash algorithm to compute digest// IN/OUT: PCR selection (filtered on//
output)// OUT: digest{
HASH_STATETPMS_PCR_SELECTION
BYTE

Page 358
April 15, 2019

hashState;*select;*pcrData;// will point to a digest

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

UINT32
UINT32
UINT32Trusted Platform Module Library
pcrSize;pcr;i;// Initialize the hashdigest->t.size = CryptHashStart(&hashState, hashAlg);
pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX);// Iterate through the list of PCR selection structuresfor(i = 0; i < selection->count; i++){// Point to the current selection
select = &selection->pcrSelections[i]; // Point to the current selection
FilterPcr(select);// Clear out the bits for unimplemented PCR// Need the size of each digest
pcrSize = CryptHashGetDigestSize(selection->pcrSelections[i].hash);// Iterate through the selection
for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++){if(IsPcrSelected(pcr, select))// Is this PCR selected{// Get pointer to the digest data for the bank
pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr);
pAssert(pcrData != NULL);
CryptDigestUpdate(&hashState, pcrSize, pcrData); // add to digest}}}// Complete hash stack
CryptHashEnd2B(&hashState, &digest->b);
return;}8.7.3.23

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.
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

void
PCRRead(
TPML_PCR_SELECTION*selection,

TPML_DIGESTUINT32*digest,*pcrCounter// IN/OUT: PCR selection (filtered on//
output)// OUT: digest// OUT: the current value of PCR generation//
number){
TPMS_PCR_SELECTION
BYTE
UINT32
UINT32*select;*pcrData;
pcr;
i;// will point to a digest

digest->count = 0;// Iterate through the list of PCR selection structuresfor(i = 0; i < selection->count; i++){// Point to the current selection
select = &selection->pcrSelections[i]; // Point to the current selection
FilterPcr(select);// Clear out the bits for unimplemented PCR

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 359
April 15, 2019

Trusted Platform Module Library
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711

Part 4: Supporting Routines// Iterate through the selection
for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++){if(IsPcrSelected(pcr, select))// Is this PCR selected{// Check if number of digest exceed upper boundif(digest->count > 7){// Clear rest of the current select bitmap
while(pcr < IMPLEMENTATION_PCR// do not round up!
&& (pcr / 8) < select->sizeofSelect){// do not round up!
select->pcrSelect[pcr / 8] &= (BYTE)~(1 << (pcr % 8));
pcr++;}// Exit inner loop
break;}// Need the size of each digest
digest->digests[digest->count].t.size =CryptHashGetDigestSize(selection->pcrSelections[i].hash);// Get pointer to the digest data for the bank
pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr);
pAssert(pcrData != NULL);// Add to the data to digest
MemoryCopy(digest->digests[digest->count].t.buffer,
pcrData,digest->digests[digest->count].t.size);digest->count++;}}// If we exit inner loop because we have exceed the output upper boundif(digest->count > 7 && pcr < IMPLEMENTATION_PCR){// Clear rest of the selection
while(i < selection->count){
MemorySet(selection->pcrSelections[i].pcrSelect, 0,
selection->pcrSelections[i].sizeofSelect);i++;}// exit outer loop
break;}}*pcrCounter = gr.pcrCounter;
return;}8.7.3.24

PcrWrite()This function is used by _TPM_Hash_End() to set a PCR to the computed hash of the H-CRTM event.
712
713
714
715
716
717

void
PcrWrite(
TPMI_DH_PCR
TPMI_ALG_HASH
TPM2B_DIGEST)

Page 360
April 15, 2019

handle,hash,*digest// IN: PCR handle to be extended// IN: hash algorithm of PCR// IN: the new value

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
718
719
720
721
722
723
724
725
726
727
728
729
730

Trusted Platform Module Library{
UINT32
BYTE

pcr = handle - PCR_FIRST;*pcrData;// Copy value to the PCR if it is allocatedpcrData = GetPcrPointer(hash, pcr);
if(pcrData != NULL){
MemoryCopy(pcrData, digest->t.buffer, digest->t.size);}
return;}8.7.3.25

PCRAllocate()

This function is used to change the PCR allocation.

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770

Error Returns

Meaning

TPM_RC_NO_RESULT

allocate failed

TPM_RC_PCR

improper allocation

TPM_RC
PCRAllocate(
TPML_PCR_SELECTIONUINT32
UINT32
UINT32)*allocate,*maxPCR,*sizeNeeded,*sizeAvailable// IN: required allocation// OUT: Maximum number of PCR// OUT: required space// OUT: available space{
UINT32i, j, k;
TPML_PCR_SELECTION
newAllocate;// Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated.
BOOL
pcrHcrtm = FALSE;
BOOL
pcrDrtm = FALSE;// Create the expected new PCR allocation based on the existing allocation// and the new input:// 1. if a PCR bank does not appear in the new allocation, the existing//
allocation of this PCR bank will be preserved.
// 2. if a PCR bank appears multiple times in the new allocation, only the//last one will be in effect.
newAllocate = gp.pcrAllocated;
for(i = 0; i < allocate->count; i++){for(j = 0; j < newAllocate.count; j++){// If hash matches, the new allocation covers the old allocation// for this particular bank.
// The assumption is the initial PCR allocation (from manufacture)// has all the supported hash algorithms with an assigned bank// (possibly empty). So there must be a match for any new bank// allocation from the input.
if(newAllocate.pcrSelections[j].hash ==allocate->pcrSelections[i].hash){
newAllocate.pcrSelections[j] = allocate->pcrSelections[i];break;}}// The j loop must exit with a match.
pAssert(j < newAllocate.count);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 361
April 15, 2019

Trusted Platform Module Library
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

Part 4: Supporting Routines}// Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined)*maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes);
if(*maxPCR > IMPLEMENTATION_PCR)*maxPCR = IMPLEMENTATION_PCR;// Compute required size for allocation*sizeNeeded = 0;
for(i = 0; i < newAllocate.count; i++){UINT32digestSize= CryptHashGetDigestSize(newAllocate.pcrSelections[i].hash);#if defined(DRTM_PCR)// Make sure that we end up with at least one DRTM PCR
pcrDrtm = pcrDrtm || TestBit(DRTM_PCR,
newAllocate.pcrSelections[i].pcrSelect,
newAllocate.pcrSelections[i].sizeofSelect);#else// if DRTM PCR is not required, indicate that the allocation is OK
pcrDrtm = TRUE;#endif#if defined(HCRTM_PCR)// and one HCRTM PCR (since this is usually PCR 0...)pcrHcrtm = pcrHcrtm || TestBit(HCRTM_PCR,
newAllocate.pcrSelections[i].pcrSelect,
newAllocate.pcrSelections[i].sizeofSelect);#else
pcrHcrtm = TRUE;#endiffor(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++){
BYTE
mask = 1;
for(k = 0; k < 8; k++){if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0)*sizeNeeded += digestSize;mask = mask << 1;}}}
if(!pcrDrtm || !pcrHcrtm)
return TPM_RC_PCR;// In this particular implementation, we always have enough space to// allocate PCR. Different implementation may return a sizeAvailable less// than the sizeNeed.
*sizeAvailable = sizeof(s_pcrs);// Save the required allocation to NV. Note that after NV is written, the// PCR allocation in NV is no longer consistent with the RAM data// gp.pcrAllocated. The NV version reflect the allocate after next// TPM_RESET, while the RAM version reflects the current allocation
NV_WRITE_PERSISTENT(pcrAllocated, newAllocate);
return TPM_RC_SUCCESS;}

8.7.3.26

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.
Page 362
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869

Trusted Platform Module Libraryvoid
PCRSetValue(
TPM_HANDLE
INT8)

handle,initialValue// IN: the handle of the PCR to set// IN: the value to set

int
UINT32
TPMI_ALG_HASHUINT16BYTEi;
pcr = handle - PCR_FIRST;
hash;digestSize;*pcrData;{// Iterate supported PCR bank algorithms to reset
for(i = 0; i < HASH_COUNT; i++){hash = CryptHashGetAlgByIndex(i);// Prevent runaway
if(hash == TPM_ALG_NULL)
break;// Get a pointer to the data
pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);// If the PCR is allocatedif(pcrData != NULL){// And the size of the digest
digestSize = CryptHashGetDigestSize(hash);// Set the LSO to the input value
pcrData[digestSize - 1] = initialValue;// Sign extend
if(initialValue >= 0)
MemorySet(pcrData, 0, digestSize - 1);
else
MemorySet(pcrData, -1, digestSize - 1);}}}

8.7.3.27

PCRResetDynamics

This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence.
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888

void
PCRResetDynamics(
void){
UINT32

pcr, i;// Initialize PCR valuesfor(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++){// Iterate each hash algorithm bankfor(i = 0; i < gp.pcrAllocated.count; i++){
BYTE
*pcrData;
UINT32 pcrSize;
pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);
if(pcrData != NULL)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 363
April 15, 2019

Trusted Platform Module Library
889
890
891
892
893
894
895
896
897
898
899
900
901

Part 4: Supporting Routines{
pcrSize =CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[i].hash);// Reset PCR// Any PCR can be reset by locality 4 should be reset to 0if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
MemorySet(pcrData, 0, pcrSize);}}}
return;}8.7.3.28

PCRCapGetAllocation()

This function is used to get the current allocation of PCR banks.

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918

Return Value

Meaning

YES

if the return count is 0NO

if the return count is not 0

TPMI_YES_NO
PCRCapGetAllocation(
UINT32
TPML_PCR_SELECTION)

count,*pcrSelection// IN: count of return// OUT: PCR allocation list{
if(count == 0){
pcrSelection->count = 0;
return YES;}
else{
*pcrSelection = gp.pcrAllocated;
return NO;}}

8.7.3.29

PCRSetSelectBit()

This function sets a bit in a bitmap array.
919
920
921
922
923
924
925
926
927

static void
PCRSetSelectBit(
UINT32
BYTE)

pcr,*bitmap// IN: PCR number// OUT: bit map to be set{
bitmap[pcr / 8] |= (1 << (pcr % 8));return;}8.7.3.30

PCRGetProperty()

This function returns the selected PCR property.

Page 364
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)the property type is implemented

FALSE(0)the property type is not implemented

static BOOL
PCRGetProperty(
TPM_PT_PCR
TPMS_TAGGED_PCR_SELECT)

property,*select{
UINT32
UINT32pcr;
groupIndex;

select->tag = property;// Always set the bitmap to be the size of all PCR
select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8;// Initialize bitmap
MemorySet(select->pcrSelect, 0, select->sizeofSelect);// Collecting properties
for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++){switch(property){case TPM_PT_PCR_SAVE:
if(s_initAttributes[pcr].stateSave == SET)PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_EXTEND_L0:
if((s_initAttributes[pcr].extendLocality & 0x01) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_RESET_L0:
if((s_initAttributes[pcr].resetLocality & 0x01) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_EXTEND_L1:
if((s_initAttributes[pcr].extendLocality & 0x02) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_RESET_L1:
if((s_initAttributes[pcr].resetLocality & 0x02) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_EXTEND_L2:
if((s_initAttributes[pcr].extendLocality & 0x04) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_RESET_L2:
if((s_initAttributes[pcr].resetLocality & 0x04) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_EXTEND_L3:
if((s_initAttributes[pcr].extendLocality & 0x08) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_RESET_L3:
if((s_initAttributes[pcr].resetLocality & 0x08) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_EXTEND_L4:
if((s_initAttributes[pcr].extendLocality & 0x10) != 0)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 365
April 15, 2019

Trusted Platform Module Library
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

Part 4: Supporting Routines

PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_RESET_L4:
if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_DRTM_RESET:// DRTM reset PCRs are the PCR reset by locality 4if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
PCRSetSelectBit(pcr, select->pcrSelect);break;#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0case TPM_PT_PCR_POLICY:
if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex))
PCRSetSelectBit(pcr, select->pcrSelect);break;#endif#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0case TPM_PT_PCR_AUTH:
if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex))
PCRSetSelectBit(pcr, select->pcrSelect);break;#endif#if ENABLE_PCR_NO_INCREMENT == YES
case TPM_PT_PCR_NO_INCREMENT:
if(PCRBelongsTCBGroup(pcr + PCR_FIRST))PCRSetSelectBit(pcr, select->pcrSelect);break;#endifdefault:// If property is not supported, stop scanning PCR attributes// and return.
return FALSE;
break;}}
return TRUE;}

8.7.3.31

PCRCapGetProperties()

This function returns a list of PCR properties starting at property.

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

Return Value

Meaning

YES

if no more property is availableNO

if there are more properties not reported

TPMI_YES_NO
PCRCapGetProperties(
TPM_PT_PCR
UINT32
TPML_TAGGED_PCR_PROPERTY)

property,
count,*select// IN: the starting PCR property// IN: count of returned properties// OUT: PCR select{
TPMI_YES_NOUINT32more = NO;i;// Initialize output property list
select->count = 0;// The maximum count of properties we may return is MAX_PCR_PROPERTIES
if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES;Page 366
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065

Trusted Platform Module Library// TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property// value would never be less than TPM_PT_PCR_FIRST
cAssert(TPM_PT_PCR_FIRST == 0);// Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property// implemented on the TPM.
for(i = property; i <= TPM_PT_PCR_LAST; i++){if(select->count < count){// If we have not filled up the return list, add more properties to itif(PCRGetProperty(i, &select->pcrProperty[select->count]))// only increment if the property is implemented
select->count++;}else{// If the return list is full but we still have properties// available, report this and stop iterating.
more = YES;
break;}}
return more;}

8.7.3.32

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.

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
PCRCapGetHandles(
TPMI_DH_PCR
UINT32
TPML_HANDLE)

handle,count,*handleList

TPMI_YES_NOUINT32more = NO;i;// IN: start handle// IN: count of returned handles// OUT: list of handle{

pAssert(HandleGetType(handle) == TPM_HT_PCR);// Initialize output handle list
handleList->count = 0;// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;// Iterate PCR handle range
for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++){if(handleList->count < count){// If we have not filled up the return list, add this PCR// handle to it
handleList->handle[handleList->count] = i + PCR_FIRST;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 367
April 15, 2019

Trusted Platform Module Library
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103

Part 4: Supporting Routines

handleList->count++;}else{// If the return list is full but we still have PCR handle// available, report this and stop iterating
more = YES;
break;}}
return more;}

Page 368
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.8

Trusted Platform Module Library

PP.c

8.8.1

Introduction

This file contains the functions that support the physical presence operations of the TPM.
8.8.2
1

Includes#include "Tpm.h"

8.8.3

Functions

8.8.3.1

PhysicalPresencePreInstall_Init()

This function is used to initialize the array of commands that always require confirmation with physicalpresence. 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.
When set, these cannot be cleared.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

void
PhysicalPresencePreInstall_Init(
void){
COMMAND_INDEX
commandIndex;// Clear all the PP commands
MemorySet(&gp.ppList, 0, sizeof(gp.ppList));// Any command that is PP_REQUIRED should be SETfor(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++){if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED&& s_commandAttributes[commandIndex] & PP_REQUIRED)
SET_BIT(commandIndex, gp.ppList);}// Write PP list to NV
NV_SYNC_PERSISTENT(ppList);
return;}8.8.3.2

PhysicalPresenceCommandSet()

This function is used to set the indicator that a command requires PP confirmation.
22
23
24
25
26
27
28
29
30
31
32
33
34

void
PhysicalPresenceCommandSet(
TPM_CC)

commandCode// IN: command code{
COMMAND_INDEX

commandIndex = CommandCodeToCommandIndex(commandCode);// if the command isn't implemented, the do nothingif(commandIndex == UNIMPLEMENTED_COMMAND_INDEX)
return;// only set the bit if this is a command for which PP is allowed
if(s_commandAttributes[commandIndex] & PP_COMMAND)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 369
April 15, 2019

Trusted Platform Module Library
35
36
37

Part 4: Supporting Routines

SET_BIT(commandIndex, gp.ppList);
return;}8.8.3.3

PhysicalPresenceCommandClear()This function is used to clear the indicator that a command requires PP confirmation.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

void
PhysicalPresenceCommandClear(
TPM_CC)

commandCode// IN: command code{
COMMAND_INDEX

commandIndex = CommandCodeToCommandIndex(commandCode);// If the command isn't implemented, then don't do anythingif(commandIndex == UNIMPLEMENTED_COMMAND_INDEX)
return;// Only clear the bit if the command does not require PP
if((s_commandAttributes[commandIndex] & PP_REQUIRED) == 0)
CLEAR_BIT(commandIndex, gp.ppList);
return;}8.8.3.4

PhysicalPresenceIsRequired()This function indicates if PP confirmation is required for a command.

55
56
57
58
59
60
61
62

Return Value

Meaning

TRUE(1)

physical presence is required

FALSE(0)physical presence is not required

BOOL
PhysicalPresenceIsRequired(
COMMAND_INDEX)

commandIndex// IN: command index{// Check the bit map. If the bit is SET, PP authorization is required
return (TEST_BIT(commandIndex, gp.ppList));}8.8.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.

63
64
65
66
67

Return Value

Meaning

YES

if there are more command codes available

NO

all the available command codes have been returned

TPMI_YES_NO
PhysicalPresenceCapGetCCList(
TPM_CCUINT32
TPML_CC

Page 370
April 15, 2019

commandCode,count,*commandList// IN: start command code// IN: count of returned TPM_CC// OUT: list of TPM_CC

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

Trusted Platform Module Library){
TPMI_YES_NO
COMMAND_INDEX

more = NO;commandIndex;// Initialize output handle list
commandList->count = 0;// The maximum count of command we may return is MAX_CAP_CC
if(count > MAX_CAP_CC) count = MAX_CAP_CC;// Collect PP commandsfor(commandIndex = GetClosestCommandIndex(commandCode);
commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
commandIndex = GetNextCommandIndex(commandIndex)){if(PhysicalPresenceIsRequired(commandIndex)){
if(commandList->count < count){// If we have not filled up the return list, add this command// code to itcommandList->commandCodes[commandList->count]= GetCommandCode(commandIndex);commandList->count++;}else{// If the return list is full but we still have PP command// available, report this and stop iterating
more = YES;
break;}}}
return more;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 371
April 15, 2019

Trusted Platform Module Library

8.9

Part 4: Supporting Routines

Session.c

8.9.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 oftime 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 andrestored 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 ofbytes 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 itwould 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 isthat the context will be flushed before its count value is needed again but it is always possible to havelong-lived sessions.
The contextID is assigned when the context is saved (TPM2_ContextSave()). At that time, the TPM willcompare 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 thematching value is the oldest context).
The expected remediation by the TRM is to load the oldest saved session context (the one found by theTPM), 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-bitsof contextCount, the TPM can copy the low bits to the contextArray associated with the session, andincrement contextCount.
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 asession. 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 thezero-based slot number.

There is one significant corner case in this scheme. When the contextCount is equal to a value in thecontextArray, 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 thecontextArray when a session is created. This prevents the last session slot from being used when it islikely 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 ofactive 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
Page 372
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Librarya 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.9.2
1
2

Includes, Defines, and Local Variables#define SESSION_C#include "Tpm.h"

8.9.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 thevalue 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 thecontextCounter 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.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

static void
ContextIdSetOldest(
void){
CONTEXT_SLOTCONTEXT_SLOTCONTEXT_SLOTUINT32 i;

lowBits;
entry;
smallest = ((CONTEXT_SLOT)~0);// Set oldestSaveContext to a value indicating none assigned
s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
lowBits = (CONTEXT_SLOT)gr.contextCounter;for(i = 0; i < MAX_ACTIVE_SESSIONS; i++){entry = gr.contextArray[i];// only look at entries that are saved contexts
if(entry > MAX_LOADED_SESSIONS){// Use a less than or equal in case the oldest// is brand new (= lowBits-1) and equal to our initial// value for smallest.
if(((CONTEXT_SLOT)(entry - lowBits)) <= smallest){
smallest = (entry - lowBits);s_oldestSavedSession = i;}}}// When we finish, either the s_oldestSavedSession still has its initial// value, or it has the index of the oldest saved context.
}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 373
April 15, 2019

Trusted Platform Module Library

8.9.4

Part 4: Supporting Routines

Startup Function -- SessionStartup()This function initializes the session subsystem on TPM2_Startup().
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

BOOL
SessionStartup(
STARTUP_TYPE
)

type

{
UINT32i;// Initialize session slots. At startup, all the in-memory session slots// are cleared and marked as not occupied
for(i = 0; i < MAX_LOADED_SESSIONS; i++)s_sessions[i].occupied = FALSE;// session slot is not occupied// The free session slots the number of maximum allowed loaded sessions
s_freeSessionSlots = MAX_LOADED_SESSIONS;// Initialize context ID data. On a ST_SAVE or hibernate sequence, it will// scan the saved array of session context counts, and clear any entry that// references a session that was in memory during the state save since that// memory was not preserved over the ST_SAVE.
if(type == SU_RESUME || type == SU_RESTART){// On ST_SAVE we preserve the contexts that were saved but not the ones// in memoryfor(i = 0; i < MAX_ACTIVE_SESSIONS; i++){// If the array value is unused or references a loaded session then// that loaded session context is lost and the array entry is// reclaimed.
if(gr.contextArray[i] <= MAX_LOADED_SESSIONS)
gr.contextArray[i] = 0;}// Find the oldest session in context ID data and set it in// s_oldestSavedSession
ContextIdSetOldest();}else{// For STARTUP_CLEAR, clear out the contextArrayfor(i = 0; i < MAX_ACTIVE_SESSIONS; i++)gr.contextArray[i] = 0;// reset the context countergr.contextCounter = MAX_LOADED_SESSIONS + 1;// Initialize oldest saved session
s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;}
return TRUE;
}

8.9.5

Access Functions

8.9.5.1

SessionIsLoaded()This function test a session handle references a loaded session. The handle must have previously beenchecked to make sure that it is a valid handle for an authorization session.

Page 374
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

NOTE:

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

Trusted Platform Module Library

A PWAP authorization does not have a session.

Return Value

Meaning

TRUE(1)session is loaded

FALSE(0)session is not loaded

BOOL
SessionIsLoaded(
TPM_HANDLE)

handle// IN: session handle{
pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION|| HandleGetType(handle) == TPM_HT_HMAC_SESSION);
handle = handle & HR_HANDLE_MASK;// if out of range of possible active session, or not assigned to a loaded// session return false
if(handle >= MAX_ACTIVE_SESSIONS|| gr.contextArray[handle] == 0|| gr.contextArray[handle] > MAX_LOADED_SESSIONS)
return FALSE;
return TRUE;}

8.9.5.2

SessionIsSaved()

This function test a session handle references a saved session. The handle must have previously beenchecked 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.

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

Return Value

Meaning

TRUE(1)session is saved

FALSE(0)session is not saved

BOOL
SessionIsSaved(
TPM_HANDLE)

handle// IN: session handle{
pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION|| HandleGetType(handle) == TPM_HT_HMAC_SESSION);
handle = handle & HR_HANDLE_MASK;// if out of range of possible active session, or not assigned, or// assigned to a loaded session, return false
if(handle >= MAX_ACTIVE_SESSIONS|| gr.contextArray[handle] == 0|| gr.contextArray[handle] <= MAX_LOADED_SESSIONS)
return FALSE;
return TRUE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 375
April 15, 2019

Trusted Platform Module Library

8.9.5.3

Part 4: Supporting Routines

SequenceNumberForSavedContextIsValid()

This function validates that the sequence number and handle value within a saved context are valid.
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

BOOL
SequenceNumberForSavedContextIsValid(
TPMS_CONTEXT*context// IN: pointer to a context structure to be//validated){#define MAX_CONTEXT_GAP ((UINT64)((CONTEXT_SLOT) ~0) + 1)
TPM_HANDLE

handle = context->savedHandle & HR_HANDLE_MASK;

if(// Handle must be with the range of active sessions
handle >= MAX_ACTIVE_SESSIONS// the array entry must be for a saved context|| gr.contextArray[handle] <= MAX_LOADED_SESSIONS// the array entry must agree with the sequence number|| gr.contextArray[handle] != (CONTEXT_SLOT)context->sequence// the provided sequence number has to be less than the current counter|| context->sequence > gr.contextCounter// but not so much that it could not be a valid sequence number|| gr.contextCounter - context->sequence > MAX_CONTEXT_GAP)
return FALSE;
return TRUE;}

8.9.5.4

SessionPCRValueIsCurrent()

This function is used to check if PCR values have been updated since the last time they were checked ina policy session.
This function requires the session is loaded.

148
149
150
151
152
153
154
155
156
157
158
159

Return Value

Meaning

TRUE(1)

PCR value is current

FALSE(0)PCR value is not current

BOOL
SessionPCRValueIsCurrent(
SESSION)*session// IN: session structure{if(session->pcrCounter != 0&& session->pcrCounter != gr.pcrCounter)
return FALSE;
else
return TRUE;}

8.9.5.5

SessionGet()

This function returns a pointer to the session object associated with a session handle.
The function requires that the session is loaded.
160

SESSION *Page 376
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

Trusted Platform Module Library

SessionGet(
TPM_HANDLE)

handle// IN: session handle

size_tCONTEXT_SLOT

slotIndex;
sessionIndex;{

pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION|| HandleGetType(handle) == TPM_HT_HMAC_SESSION);
slotIndex = handle & HR_HANDLE_MASK;
pAssert(slotIndex < MAX_ACTIVE_SESSIONS);// get the contents of the session array. Because session is loaded, we// should always get a valid sessionIndex
sessionIndex = gr.contextArray[slotIndex] - 1;
pAssert(sessionIndex < MAX_LOADED_SESSIONS);
return &s_sessions[sessionIndex].session;}

8.9.6
8.9.6.1

Utility Functions
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.

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

Error Returns

Meaning

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 thissession context

static TPM_RC
ContextIdSessionCreate(
TPM_HANDLE*handle,UINT32

sessionIndex// OUT: receives the assigned handle. This will//
be an index that must be adjusted by the//caller according to the type of the//session created// IN: The session context array entry that will//
be occupied by the created session){
pAssert(sessionIndex < MAX_LOADED_SESSIONS);// check to see if creating the context is safe// Is this going to be an assignment for the last session context// array entry? If so, then there will be no room to recycle the// oldest context if needed. If the gap is not at maximum, then// it will be possible to save a context if it becomes necessary.
if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS&& s_freeSessionSlots == 1){// See if the gap is at maximum

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 377
April 15, 2019

Trusted Platform Module Library
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

Part 4: Supporting Routines// The current value of the contextCounter will be assigned to the next// saved context. If the value to be assigned would make the same as an// existing context, then we can't use it because of the ambiguity it would// create.
if((CONTEXT_SLOT)gr.contextCounter== gr.contextArray[s_oldestSavedSession])
return TPM_RC_CONTEXT_GAP;}// Find an unoccupied entry in the contextArrayfor(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++){if(gr.contextArray[*handle] == 0){// indicate that the session associated with this handle// references a loaded session
gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex + 1);
return TPM_RC_SUCCESS;}}
return TPM_RC_SESSION_HANDLES;}

8.9.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 thecontextID for the saved contexts.

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

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

TPM_RC
SessionCreate(
TPM_SE
TPMI_ALG_HASH
TPM2B_NONCE
TPMT_SYM_DEF
TPMI_DH_ENTITY
TPM2B_DATA
TPM_HANDLE
TPM2B_NONCE)

sessionType,// IN: the session type
authHash,// IN: the hash algorithm*nonceCaller,// IN: initial nonceCaller*symmetric,// IN: the symmetric algorithmbind,// IN: the bind object*seed,// IN: seed data
*sessionHandle, // OUT: the session handle*nonceTpm// OUT: the session nonce{
TPM_RCCONTEXT_SLOTSESSION

result = TPM_RC_SUCCESS;
slotIndex;*session = NULL;

pAssert(sessionType == TPM_SE_HMAC|| sessionType == TPM_SE_POLICY|| sessionType == TPM_SE_TRIAL);// If there are no open spots in the session array, then no point in searchingif(s_freeSessionSlots == 0)
return TPM_RC_SESSION_MEMORY;// Find a space for loading a session
for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)Page 378
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Trusted Platform Module Library{// Is this available?
if(s_sessions[slotIndex].occupied == FALSE){
session = &s_sessions[slotIndex].session;
break;}}// if no spot found, then this is an internal error
if(slotIndex >= MAX_LOADED_SESSIONS)FAIL(FATAL_ERROR_INTERNAL);// Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be// returned from ContextIdHandelAssign()
result = ContextIdSessionCreate(sessionHandle, slotIndex);
if(result != TPM_RC_SUCCESS)
return result;//*** Only return from this point on is TPM_RC_SUCCESS// Can now indicate that the session array entry is occupied.
s_freeSessionSlots--;s_sessions[slotIndex].occupied = TRUE;// Initialize the session data
MemorySet(session, 0, sizeof(SESSION));// Initialize internal session data
session->authHashAlg = authHash;// Initialize session typeif(sessionType == TPM_SE_HMAC){*sessionHandle += HMAC_SESSION_FIRST;}
else{*sessionHandle += POLICY_SESSION_FIRST;// For TPM_SE_POLICY or TPM_SE_TRIAL
session->attributes.isPolicy = SET;
if(sessionType == TPM_SE_TRIAL)
session->attributes.isTrialPolicy = SET;
SessionSetStartTime(session);// Initialize policyDigest. policyDigest is initialized with a string of 0// of session algorithm digest size. Since the session is already clear.
// Just need to set the size
session->u2.policyDigest.t.size =CryptHashGetDigestSize(session->authHashAlg);}// Create initial session nonce
session->nonceTPM.t.size = nonceCaller->t.size;
CryptRandomGenerate(session->nonceTPM.t.size, session->nonceTPM.t.buffer);
MemoryCopy2B(&nonceTpm->b, &session->nonceTPM.b,
sizeof(nonceTpm->t.buffer));// Set up session parameter encryption algorithm
session->symmetric = *symmetric;// If there is a bind object or a session secret, then need to compute// a sessionKey.
if(bind != TPM_RH_NULL || seed->t.size != 0){// sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM,//
nonceCaller, bits)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 379
April 15, 2019

Trusted Platform Module Library
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

Part 4: Supporting Routines// The HMAC key for generating the sessionSecret can be the concatenation// of an authorization value and a seed value
TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer)));TPM2B_KEY
key;// Get hash size, which is also the length of sessionKey
session->sessionKey.t.size = CryptHashGetDigestSize(session->authHashAlg);// Get authValue of associated entity
EntityGetAuthValue(bind, (TPM2B_AUTH *)&key);pAssert(key.t.size + seed->t.size <= sizeof(key.t.buffer));// Concatenate authValue and seed
MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer));// Compute the session key
CryptKDFa(session->authHashAlg, &key.b, SESSION_KEY, &session->nonceTPM.b,&nonceCaller->b,
session->sessionKey.t.size * 8, session->sessionKey.t.buffer,
NULL, FALSE);}// Copy the name of the entity that the HMAC session is bound to// Policy session is not bound to an entity
if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC){
session->attributes.isBound = SET;
SessionComputeBoundEntity(bind, &session->u1.boundEntity);}// If there is a bind object and it is subject to DA, then use of this session// is subject to DA regardless of how it is used.
session->attributes.isDaBound = (bind != TPM_RH_NULL)&& (IsDAExempted(bind) == FALSE);// If the session is bound, then check to see if it is bound to lockoutAuth
session->attributes.isLockoutBound = (session->attributes.isDaBound == SET)&& (bind == TPM_RH_LOCKOUT);
return TPM_RC_SUCCESS;}

8.9.6.3

SessionContextSave()This function is called when a session context is to be saved. The contextID of the saved session isreturned. If no contextID can be assigned, then the routine returns TPM_RC_CONTEXT_GAP. If thefunction completes normally, the session slot will be freed.
This function requires that handle references a loaded session. Otherwise, it should not be called at thefirst place.

358
359
360
361
362
363
364
365
366
367

Error Returns

Meaning

TPM_RC_CONTEXT_GAP

acontextID
could
not
be
assigned.
TPM_RC_TOO_MANY_CONTEXTSthe counter maxed out

TPM_RC
SessionContextSave(
TPM_HANDLECONTEXT_COUNTER)

handle,*contextID// IN: session handle// OUT: assigned contextID{
UINT32
CONTEXT_SLOT

contextIndex;
slotIndex;

pAssert(SessionIsLoaded(handle));Page 380
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

Trusted Platform Module Library// check to see if the gap is already maxed out// Need to have a saved session
if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS// if the oldest saved session has the same value as the low bits// of the contextCounter, then the GAP is maxed out.
&& gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter)
return TPM_RC_CONTEXT_GAP;// if the caller wants the context counter, set it
if(contextID != NULL)*contextID = gr.contextCounter;
contextIndex = handle & HR_HANDLE_MASK;
pAssert(contextIndex < MAX_ACTIVE_SESSIONS);// Extract the session slot number referenced by the contextArray// because we are going to overwrite this with the low order// contextID value.
slotIndex = gr.contextArray[contextIndex] - 1;// Set the contextID for the contextArraygr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter;// Increment the countergr.contextCounter++;// In the unlikely event that the 64-bit context counter rolls over...
if(gr.contextCounter == 0){// back it up
gr.contextCounter--;// return an error
return TPM_RC_TOO_MANY_CONTEXTS;}// if the low-order bits wrapped, need to advance the value to skip over// the values used to indicate that a session is loadedif(((CONTEXT_SLOT)gr.contextCounter) == 0)
gr.contextCounter += MAX_LOADED_SESSIONS + 1;// If no other sessions are saved, this is now the oldest.
if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS)
s_oldestSavedSession = contextIndex;// Mark the session slot as unoccupied
s_sessions[slotIndex].occupied = FALSE;// and indicate that there is an additional open slot
s_freeSessionSlots++;
return TPM_RC_SUCCESS;}

8.9.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.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 381
April 15, 2019

Trusted Platform Module Library

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

Part 4: Supporting Routines

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

TPM_RC
SessionContextLoad(
SESSION_BUF
TPM_HANDLE)*session,*handle// IN: session structure from saved context// IN/OUT: session handle{
UINT32
CONTEXT_SLOT

contextIndex;
slotIndex;

pAssert(HandleGetType(*handle) == TPM_HT_POLICY_SESSION|| HandleGetType(*handle) == TPM_HT_HMAC_SESSION);// Don't bother looking if no openings
if(s_freeSessionSlots == 0)
return TPM_RC_SESSION_MEMORY;// Find a free session slot to load the session
for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)if(s_sessions[slotIndex].occupied == FALSE) break;// if no spot found, then this is an internal error
pAssert(slotIndex < MAX_LOADED_SESSIONS);
contextIndex = *handle & HR_HANDLE_MASK;// extract the index// If there is only one slot left, and the gap is at maximum, the only session// context that we can safely load is the oldest one.
if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS&& s_freeSessionSlots == 1&& (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession]&& contextIndex != s_oldestSavedSession)
return TPM_RC_CONTEXT_GAP;
pAssert(contextIndex < MAX_ACTIVE_SESSIONS);// set the contextArray value to point to the session slot where// the context is loaded
gr.contextArray[contextIndex] = slotIndex + 1;// if this was the oldest context, find the new oldest
if(contextIndex == s_oldestSavedSession)
ContextIdSetOldest();// Copy session data to session slot
MemoryCopy(&s_sessions[slotIndex].session, session, sizeof(SESSION));// Set session slot as occupied
s_sessions[slotIndex].occupied = TRUE;// Reduce the number of open spots
s_freeSessionSlots--;
return TPM_RC_SUCCESS;}

Page 382
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.9.6.5

Trusted Platform Module Library

SessionFlush()

This function is used to flush a session referenced by its handle. If the session associated with handle isloaded, the session array entry is marked as available.
This function requires that handle be a valid active session.
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519

void
SessionFlush(
TPM_HANDLE)

handle// IN: loaded or saved session handle{
CONTEXT_SLOTUINT32

slotIndex;
contextIndex;// Index into contextArraypAssert((HandleGetType(handle) == TPM_HT_POLICY_SESSION|| HandleGetType(handle) == TPM_HT_HMAC_SESSION)&& (SessionIsLoaded(handle) || SessionIsSaved(handle)));// Flush context ID of this session// Convert handle to an index into the contextArray
contextIndex = handle & HR_HANDLE_MASK;
pAssert(contextIndex < sizeof(gr.contextArray) / sizeof(gr.contextArray[0]));// Get the current contents of the array
slotIndex = gr.contextArray[contextIndex];// Mark context array entry as available
gr.contextArray[contextIndex] = 0;// Is this a saved session being flushedif(slotIndex > MAX_LOADED_SESSIONS){// Flushing the oldest session?
if(contextIndex == s_oldestSavedSession)// If so, find a new value for oldest.
ContextIdSetOldest();}else{// Adjust slot index to point to session array index
slotIndex -= 1;// Free session array index
s_sessions[slotIndex].occupied = FALSE;
s_freeSessionSlots++;}
return;}8.9.6.6

SessionComputeBoundEntity()This function computes the binding value for a session. The binding value for a reserved handle is thehandle 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.
520
521

void
SessionComputeBoundEntity(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 383
April 15, 2019

Trusted Platform Module Library
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

Part 4: Supporting Routines

TPMI_DH_ENTITY
TPM2B_NAME)

entityHandle,*bind// IN: handle of entity// OUT: binding value

TPM2B_AUTH
BYTE
UINT16auth;*pAuth = auth.t.buffer;i;{// Get nameEntityGetName(entityHandle, bind);////// The bound value of a reserved handle is the handle itself
if(bind->t.size == sizeof(TPM_HANDLE)) return;// For all the other entities, concatenate the authorization value to the name.
// Get a local copy of the authorization value because some overlapping// may be necessary.
EntityGetAuthValue(entityHandle, &auth);// Make sure that the extra space is zeroed
MemorySet(&bind->t.name[bind->t.size], 0, sizeof(bind->t.name) - bind->t.size);// XOR the authValue at the end of the namefor(i = sizeof(bind->t.name) - auth.t.size; i < sizeof(bind->t.name); i++)bind->t.name[i] ^= *pAuth++;// Set the bind value to the maximum sizebind->t.size = sizeof(bind->t.name);
return;}8.9.6.7

SessionSetStartTime()

This function is used to initialize the session timing
552
553
554
555
556
557
558
559
560

void
SessionSetStartTime(SESSION)*session// IN: the session to update{
session->startTime = g_time;
session->epoch = g_timeEpoch;session->timeout = 0;}

8.9.6.8

SessionResetPolicyData()

This function is used to reset the policy data without changing the nonce or the start time of the session.
561
562
563
564
565
566
567
568
569
570
571
572
573
574

void
SessionResetPolicyData(
SESSION)*session// IN: the session to reset{
SESSION_ATTRIBUTES
oldAttributes;
pAssert(session != NULL);// Will need later
oldAttributes = session->attributes;// No commandsession->commandCode = 0;Page 384
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

Trusted Platform Module Library// No locality selected
MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality));// The cpHash size to zerosession->u1.cpHash.b.size = 0;// No timeout
session->timeout = 0;// Reset the pcrCountersession->pcrCounter = 0;// Reset the policy hashMemorySet(&session->u2.policyDigest.t.buffer, 0,
session->u2.policyDigest.t.size);// Reset the session attributes
MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES));// Restore the policy attributes
session->attributes.isPolicy = SET;
session->attributes.isTrialPolicy = oldAttributes.isTrialPolicy;// Restore the bind attributes
session->attributes.isDaBound = oldAttributes.isDaBound;session->attributes.isLockoutBound = oldAttributes.isLockoutBound;}

8.9.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.

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
SessionCapGetLoaded(
TPMI_SH_POLICYUINT32
TPML_HANDLE)

handle,count,*handleList

TPMI_YES_NOUINT32more = NO;i;// IN: start handle// IN: count of returned handles// OUT: list of handle{

pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION);// Initialize output handle list
handleList->count = 0;// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;// Iterate session context ID slots to get loaded session handles
for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++){// If session is activeif(gr.contextArray[i] != 0){// If session is loaded

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 385
April 15, 2019

Trusted Platform Module Library
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

Part 4: Supporting Routines

if(gr.contextArray[i] <= MAX_LOADED_SESSIONS){
if(handleList->count < count){
SESSION*session;// If we have not filled up the return list, add this// session handle to it// assume that this is going to be an HMAC session
handle = i + HMAC_SESSION_FIRST;
session = SessionGet(handle);
if(session->attributes.isPolicy)
handle = i + POLICY_SESSION_FIRST;
handleList->handle[handleList->count] = handle;
handleList->count++;}else{// If the return list is full but we still have loaded object// available, report this and stop iterating
more = YES;
break;}}}}
return more;}

8.9.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

656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
SessionCapGetSaved(
TPMI_SH_HMAC
UINT32
TPML_HANDLE)

handle,count,*handleList

TPMI_YES_NOUINT32more = NO;i;// IN: start handle// IN: count of returned handles// OUT: list of handle{#ifdef TPM_HT_SAVED_SESSION
pAssert(HandleGetType(handle) == TPM_HT_SAVED_SESSION);#else
pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION);#endif// Initialize output handle list
handleList->count = 0;// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;// Iterate session context ID slots to get loaded session handles

Page 386
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

Trusted Platform Module Libraryfor(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++){// If session is activeif(gr.contextArray[i] != 0){// If session is savedif(gr.contextArray[i] > MAX_LOADED_SESSIONS){
if(handleList->count < count){// If we have not filled up the return list, add this// session handle to it
handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST;
handleList->count++;}else{// If the return list is full but we still have loaded object// available, report this and stop iterating
more = YES;
break;}}}}
return more;}

8.9.6.11

SessionCapGetLoadedNumber()This function return the number of authorization sessions currently loaded into TPM RAM.
707
708
709
710
711
712
713

UINT32
SessionCapGetLoadedNumber(void){
return MAX_LOADED_SESSIONS - s_freeSessionSlots;}

8.9.6.12

SessionCapGetLoadedAvail()This function returns the number of additional authorization sessions, of any type, that could be loaded
into TPM RAM.
NOTE:

714
715
716
717
718
719
720

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.

UINT32
SessionCapGetLoadedAvail(
void){
return s_freeSessionSlots;}

8.9.6.13

SessionCapGetActiveNumber()This function returns the number of active authorization sessions currently being tracked by the TPM.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 387
April 15, 2019

Trusted Platform Module Library

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736

Part 4: Supporting RoutinesUINT32
SessionCapGetActiveNumber(
void){
UINT32
UINT32i;num = 0;// Iterate the context array to find the number of non-zero slotsfor(i = 0; i < MAX_ACTIVE_SESSIONS; i++){if(gr.contextArray[i] != 0) num++;}
return num;}

8.9.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 capableof tracking.
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752

UINT32
SessionCapGetActiveAvail(
void){
UINT32
UINT32i;num = 0;// Iterate the context array to find the number of zero slotsfor(i = 0; i < MAX_ACTIVE_SESSIONS; i++){if(gr.contextArray[i] == 0) num++;}
return num;}

Page 388
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

8.10

Trusted Platform Module Library

Time.c8.10.1Introduction

This file contains the functions relating to the TPM's time functions including the interface to theimplementation-specific time functions.
8.10.2
1
2Includes#include "Tpm.h"#include "PlatformData.h"

8.10.3Functions8.10.3.1

TimePowerOn()

This function initialize time info at _TPM_Init().
This function is called at _TPM_Init() so that the TPM time can start counting as soon as the TPM comesout of reset and doesn't have to wait until TPM2_Startup() in order to begin the new time epoch. This
could be significant for systems that could get powered up but not run any TPM commands for someperiod of time.
3
4
5
6
7
8
9

void
TimePowerOn(void){
g_time = _plat__TimerRead();}8.10.3.2

TimeNewEpoch()This function does the processing to generate a new time epoch nonce and set NV for update. Thisfunction is only called when NV is known to be available and the clock is running. The epoch is updated
to persistent data.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

static void
TimeNewEpoch(void){#if CLOCK_STOPS
CryptRandomGenerate(sizeof(CLOCK_NONCE), (BYTE *)&g_timeEpoch);#else// if the epoch is kept in NV, update it.
gp.timeEpoch++;
NV_SYNC_PERSISTENT(timeEpoch);#endif// Clean out any lingering state_plat__TimerWasStopped();}8.10.3.3

TimeStartup()This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at
TPM2_Startup().
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 389
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

This function will deal with the deferred creation of a new epoch. TimeUpdateToCurrent() will not start a
new epoch even if one is due when TPM_Startup() has not been run. This is because the state of NV is
not known until startup completes. When Startup is done, then it will create the epoch nonce to complete
the initializations by calling this function.
25
26
27
28
29
30
31
32
33
34
35
36

BOOL
TimeStartup(
STARTUP_TYPE)

type// IN: start up type{
NOT_REFERENCED(type);// If the previous cycle is orderly shut down, the value of the safe bit// the same as previously saved. Otherwise, it is not safe.
if(!NV_IS_ORDERLY)
go.clockSafe = NO;
return TRUE;}

8.10.3.4

TimeClockUpdate()

This function updates go.clock. If newTime requires an update of NV, then NV is checked for availability.
If it is not available or is rate limiting, then go.clock is not updated and the function returns an error. If
newTime would not cause an NV write, then go.clock is updated. If an NV write occurs, then go.safe is
SET.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

void
TimeClockUpdate(
UINT64)

newTime{#define CLOCK_UPDATE_MASK// IN: New time value in mS.

((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)// Check to see if the update will cause a need for an nvClock update
if((newTime | CLOCK_UPDATE_MASK) > (go.clock | CLOCK_UPDATE_MASK)){
pAssert(g_NvStatus == TPM_RC_SUCCESS);// Going to update the NV time state so SET the safe flaggo.clockSafe = YES;// update the timego.clock = newTime;
NvWrite(NV_ORDERLY_DATA, sizeof(go), &go);}else// No NV update needed so just updatego.clock = newTime;}8.10.3.5

TimeUpdate()

This function is used to update the time and clock values. If the TPM has run TPM2_Startup(), thisfunction is called at the start of each command. If the TPM has not run TPM2_Startup(), this is called from
TPM2_Startup() to get the clock values initialized. It is not called on command entry because, in this
implementation, the go structure is not read from NV until TPM2_Startup(). The reason for this is that theinitialization code (_TPM_Init()) may run before NV is accessible.
62
63

void
TimeUpdate(

Page 390
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

Trusted Platform Module Library

void
)
{
UINT64

elapsed;//// Make sure that we consume the current _plat__TimerWasStopped() state.
if(_plat__TimerWasStopped()){
TimeNewEpoch();}// Get the difference between this call and the last time we updated the tick// timer.
elapsed = _plat__TimerRead() - g_time;// Don't read +g_time += elapsed;// Don't need to check the result because it has to be success because have// already checked that NV is available.
TimeClockUpdate(go.clock + elapsed);// Call self healing logic for dictionary attack parameters
DASelfHeal();}8.10.3.6

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 implementation does not do rate limiting. If the implementation does do rate limiting, then the Clockupdate should not be inhibited even when doing rate limiting.
87
88
89
90
91
92
93
94
95
96
97
98
99

void
TimeUpdateToCurrent(
void){// Can't update time during the dark interval or when rate limiting so don't// make any modifications to the internal clock value. Also, defer any clock// processing until TPM has run TPM2_Startup()if(!NV_IS_AVAILABLE || !TPMIsStarted())
return;TimeUpdate();}8.10.3.7

TimeSetAdjustRate()

This function is used to perform rate adjustment on Time and Clock.
100
101
102
103
104
105
106

void
TimeSetAdjustRate(
TPM_CLOCK_ADJUST)

adjust// IN: adjust constant{switch(adjust){Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 391
April 15, 2019

Trusted Platform Module Library
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

Part 4: Supporting Routinescase TPM_CLOCK_COARSE_SLOWER:_plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
break;
case TPM_CLOCK_COARSE_FASTER:_plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
break;
case TPM_CLOCK_MEDIUM_SLOWER:_plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
break;
case TPM_CLOCK_MEDIUM_FASTER:_plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
break;
case TPM_CLOCK_FINE_SLOWER:_plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
break;
case TPM_CLOCK_FINE_FASTER:_plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
break;
case TPM_CLOCK_NO_CHANGE:
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return;}8.10.3.8

TimeGetMarshaled()

This function is used to access TPMS_TIME_INFO in canonical form. The function collects the time
information and marshals it into dataBuffer and returns the marshaled size
134
135
136
137
138
139
140
141
142
143
144
145
146
147

UINT16
TimeGetMarshaled(
TIME_INFO)*dataBuffer// OUT: result buffer{
TPMS_TIME_INFO

timeInfo;// Fill TPMS_TIME_INFO structure
timeInfo.time = g_time;
TimeFillInfo(&timeInfo.clockInfo);// Marshal TPMS_TIME_INFO to canonical form
return TPMS_TIME_INFO_Marshal(&timeInfo, (BYTE **)&dataBuffer, NULL);}

8.10.3.9

TimeFillInfo

This function gathers information to fill in a TPMS_CLOCK_INFO structure.
148
149
150
151
152
153
154
155
156
157
158

void
TimeFillInfo(TPMS_CLOCK_INFO)*clockInfo{
clockInfo->clock = go.clock;
clockInfo->resetCount = gp.resetCount;clockInfo->restartCount = gr.restartCount;// If NV is not available, clock stopped advancing and the value reported is// not "safe".

Page 392
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
159
160
161
162
163
164
165

Trusted Platform Module Libraryif(NV_IS_AVAILABLE)
clockInfo->safe = go.clockSafe;elseclockInfo->safe = NO;
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 393
April 15, 2019

Trusted Platform Module Library

9Part 4: Supporting Routines

Support9.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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Includes and Defines#include "Tpm.h"
typedef struct{
TPM_ALG_ID
algID;
TPMA_ALGORITHM
attributes;} ALGORITHM;
static const ALGORITHM
s_algorithms[] ={// The entries in this table need to be in ascending order but the table doesn't// need to be full (gaps are allowed). One day, a tool might exist to fill in the// table from the TPM_ALG description#if ALG_RSA{TPM_ALG_RSA,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)},#endif#if ALG_TDES{TPM_ALG_TDES,
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},#endif#if ALG_SHA1{TPM_ALG_SHA1,
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},#endif{TPM_ALG_HMAC,#if ALG_AES{TPM_ALG_AES,#endif#if ALG_MGF1{TPM_ALG_MGF1,#endif{TPM_ALG_KEYEDHASH,#if ALG_XOR{TPM_ALG_XOR,#endif#if ALG_SHA256{TPM_ALG_SHA256,#endif#if ALG_SHA384{TPM_ALG_SHA384,#endif#if ALG_SHA512{TPM_ALG_SHA512,#endif#if ALG_SM3_256{TPM_ALG_SM3_256,#endif#if ALG_SM4{TPM_ALG_SM4,#endifPage 394
April 15, 2019

TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 1, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 1, 0, 1, 1, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 1, 0, 0, 0, 0, 0, 0)},

TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

Trusted Platform Module Library#if ALG_RSASSA{TPM_ALG_RSASSA,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},#endif#if ALG_RSAES{TPM_ALG_RSAES,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)},#endif#if ALG_RSAPSS{TPM_ALG_RSAPSS,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},#endif#if ALG_OAEP{TPM_ALG_OAEP,TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)},#endif#if ALG_ECDSA{TPM_ALG_ECDSA,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)},#endif#if ALG_ECDH{TPM_ALG_ECDH,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)},#endif#if ALG_ECDAA{TPM_ALG_ECDAA,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},#endif#if ALG_SM2{TPM_ALG_SM2,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)},#endif#if ALG_ECSCHNORR{TPM_ALG_ECSCHNORR,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)},#endif#if ALG_ECMQV{TPM_ALG_ECMQV,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)},#endif#if ALG_KDF1_SP800_56A{TPM_ALG_KDF1_SP800_56A, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},#endif#if ALG_KDF2{TPM_ALG_KDF2,
TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},#endif#if ALG_KDF1_SP800_108{TPM_ALG_KDF1_SP800_108, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)},#endif#if ALG_ECC{TPM_ALG_ECC,
TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)},#endif{TPM_ALG_SYMCIPHER,#if ALG_CAMELLIA{TPM_ALG_CAMELLIA,#endif#if ALG_CMAC{TPM_ALG_CMAC,#endif#if ALG_CTR{TPM_ALG_CTR,#endif#if ALG_OFB{TPM_ALG_OFB,#endif#if ALG_CBC{TPM_ALG_CBC,#endif#if ALG_CFB{TPM_ALG_CFB,#endif#if ALG_ECB{TPM_ALG_ECB,#endifFamily “2.0”Level 00 Revision 01.55

TPMA_ALGORITHM_INITIALIZER(0, 0, 0, 1, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 1, 0, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 395
April 15, 2019

Trusted Platform Module Library
118

Part 4: Supporting Routines

};

9.1.3

AlgorithmCapGetImplemented()

This function is used by TPM2_GetCapability() to return a list of the implemented algorithms.

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

Return Value

Meaning

YES

more algorithms to reportNOno more algorithms to report

TPMI_YES_NO
AlgorithmCapGetImplemented(
TPM_ALG_ID
UINT32
TPML_ALG_PROPERTY)

algID,
count,*algList// IN: the starting algorithm ID// IN: count of returned algorithms// OUT: algorithm list{
TPMI_YES_NOUINT32
UINT32more = NO;i;
algNum;// initialize output algorithm list
algList->count = 0;// The maximum count of algorithms we may return is MAX_CAP_ALGS.
if(count > MAX_CAP_ALGS)
count = MAX_CAP_ALGS;// Compute how many algorithms are defined in s_algorithms array.
algNum = sizeof(s_algorithms) / sizeof(s_algorithms[0]);// Scan the implemented algorithm list to see if there is a match to 'algID'.
for(i = 0; i < algNum; i++){// If algID is less than the starting algorithm ID, skip it
if(s_algorithms[i].algID < algID)
continue;if(algList->count < count){// If we have not filled up the return list, add more algorithms// to italgList->algProperties[algList->count].alg = s_algorithms[i].algID;
algList->algProperties[algList->count].algProperties =s_algorithms[i].attributes;
algList->count++;}else{// If the return list is full but we still have algorithms// available, report this and stop scanning.
more = YES;
break;}}
return more;
}

9.1.4

AlgorithmGetImplementedVector()

This function returns the bit vector of the implemented algorithms.
Page 396
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

Trusted Platform Module Library

LIB_EXPORT
void
AlgorithmGetImplementedVector(
ALGORITHM_VECTOR)*implemented// OUT: the implemented bits are SET{
int

index;// Nothing implemented until we say it isMemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR));for(index = (sizeof(s_algorithms) / sizeof(s_algorithms[0])) - 1;
index >= 0;
index--)
SET_BIT(s_algorithms[index].algID, *implemented);
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 397
April 15, 2019

Trusted Platform Module Library

9.2

Part 4: Supporting Routines

Bits.c9.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:

9.2.2
1

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.

Includes#include "Tpm.h"

9.2.3

Functions9.2.3.1

TestBit()This function is used to check the setting of a bit in an array of bits.

2
3
4
5
6
7
8
9
10
11

Return Value

Meaning

TRUE(1)

bit is set

FALSE(0)bit is not set

BOOL
TestBit(unsigned int
BYTE
unsigned int)

bitNum,*bArray,
bytesInArray// IN: number of the bit in 'bArray'// IN: array containing the bits// IN: size in bytes of 'bArray'{
pAssert(bytesInArray > (bitNum >> 3));return((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0);}

9.2.3.2

SetBit()This function will set the indicated bit in bArray.
12
13
14
15
16
17
18
19
20
21

void
SetBit(unsigned int
BYTE
unsigned int)

bitNum,*bArray,
bytesInArray// IN: number of the bit in 'bArray'// IN: array containing the bits// IN: size in bytes of 'bArray'{
pAssert(bytesInArray > (bitNum >> 3));bArray[bitNum >> 3] |= (1 << (bitNum & 7));}9.2.3.3

ClearBit()

This function will clear the indicated bit in bArray.
22

void

Page 398
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

23
24
25
26
27
28
29
30
31

Trusted Platform Module Library

ClearBit(
unsigned int
BYTE
unsigned int)

bitNum,*bArray,
bytesInArray// IN: number of the bit in 'bArray'.
// IN: array containing the bits// IN: size in bytes of 'bArray'{
pAssert(bytesInArray > (bitNum >> 3));bArray[bitNum >> 3] &= ~(1 << (bitNum & 7));}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 399
April 15, 2019

Trusted Platform Module Library

9.3

Part 4: Supporting Routines

CommandCodeAttributes.c

9.3.1

Introduction

This file contains the functions for testing various command properties.
9.3.2
1
2

Includes and Defines#include "Tpm.h"#include "CommandCodeAttributes_fp.h"

Set the default value for CC_VEND if not already set
34
56#ifndef CC_VEND#define
CC_VEND#endiftypedef UINT16(TPM_CC)(0x20000000)
ATTRIBUTE_TYPE;

The following file is produced from the command tables in part 3 of the specification. It defines theattributes for each of the commands.
NOTE:

7
8

This file is currently produced by an automated process. Files produced from Part 2 or Part 3 tables throughautomated processes are not included in the specification so that their is no ambiguity about the tablecontaining the information being the normative definition.

#define _COMMAND_CODE_ATTRIBUTES_#include"CommandAttributeData.h"

9.3.3

Command Attribute Functions

9.3.3.1

NextImplementedIndex()

This function is used when the lists are not compressed. In a compressed list, only the implemented
commands are present. So, a search might find a value but that value may not be implemented. Thisfunction checks to see if the input commandIndex points to an implemented command and, if not, it
searches upwards until it finds one. When the list is compressed, this function gets defined as a no-op.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX

command is not implemented

otherindex of the command#if !COMPRESSED_LISTS

static COMMAND_INDEXNextImplementedIndex(
COMMAND_INDEX)

commandIndex{for(;commandIndex < COMMAND_COUNT; commandIndex++){if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED)
return commandIndex;}
return UNIMPLEMENTED_COMMAND_INDEX;}#else#define NextImplementedIndex(x) (x)#endifPage 400
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.3.3.2

Trusted Platform Module Library

GetClosestCommandIndex()

This function returns the command index for the command with a value that is equal to or greater than the
input value

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX

command is not implemented

otherindex of a command

COMMAND_INDEX
GetClosestCommandIndex(
TPM_CC)

commandCode// IN: the command code to start at{
BOOL
COMMAND_INDEX

vendor = (commandCode & CC_VEND) != 0;
searchIndex = (COMMAND_INDEX)commandCode;// The commandCode is a UINT32 and the search index is UINT16. We are going to// search for a match but need to make sure that the commandCode value is not// out of range. To do this, need to clear the vendor bit of the commandCode// (if set) and compare the result to the 16-bit searchIndex value. If it is// out of range, indicate that the command is not implemented
if((commandCode & ~CC_VEND) != searchIndex)
return UNIMPLEMENTED_COMMAND_INDEX;// if there is at least one vendor command, the last entry in the array will// have the v bit set. If the input commandCode is larger than the last// vendor-command, then it is out of range.
if(vendor){#if VENDOR_COMMAND_ARRAY_SIZE > 0
COMMAND_INDEX
commandIndex;
COMMAND_INDEXmin;
COMMAND_INDEX
max;
int
diff;
#if LIBRARY_COMMAND_ARRAY_SIZE == COMMAND_COUNT#error "Constants are not consistent."#endif// Check to see if the value is equal to or below the minimum// entry.
// Note: Put this check first so that the typical case of only one vendor// specific command doesn't waste any more time.
if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE], TPMA_CC,
commandIndex) >= searchIndex){// the vendor array is always assumed to be packed so there is// no need to check to see if the command is implemented
return LIBRARY_COMMAND_ARRAY_SIZE;}// See if this is out of range on the top
if(GET_ATTRIBUTE(s_ccAttr[COMMAND_COUNT - 1], TPMA_CC, commandIndex)< searchIndex){
return UNIMPLEMENTED_COMMAND_INDEX;}
commandIndex = UNIMPLEMENTED_COMMAND_INDEX; // Needs initialization to keep// compiler happy
min = LIBRARY_COMMAND_ARRAY_SIZE;// first vendor command
max = COMMAND_COUNT - 1;// last vendor command
diff = 1;// needs initialization to keep// compiler happy
while(min <= max){

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 401
April 15, 2019

Trusted Platform Module Library
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

Part 4: Supporting RoutinescommandIndex = (min + max + 1) / 2;
diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)- searchIndex;
if(diff == 0)
return commandIndex;
if(diff > 0)
max = commandIndex - 1;else
min = commandIndex + 1;}// didn't find and exact match. commandIndex will be pointing at the last// item tested. If 'diff' is positive, then the last item tested was// larger index of the command code so it is the smallest value// larger than the requested value.
if(diff > 0)
return commandIndex;// if 'diff' is negative, then the value tested was smaller than// the commandCode index and the next higher value is the correct one.
// Note: this will necessarily be in range because of the earlier check// that the index was within range.
return commandIndex + 1;
#else// If there are no vendor commands so anything with the vendor bit set is out// of range
return UNIMPLEMENTED_COMMAND_INDEX;#endif}// Get here if the V-Bit was not set in 'commandCode'if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1], TPMA_CC,
commandIndex) < searchIndex){// requested index is out of the range to the top#if VENDOR_COMMAND_ARRAY_SIZE > 0// If there are vendor commands, then the first vendor command// is the next value greater than the commandCode.
// NOTE: we got here if the starting index did not have the V bit but we// reached the end of the array of library commands (non-vendor). Since// there is at least one vendor command, and vendor commands are always// in a compressed list that starts after the library list, the next// index value contains a valid vendor command.
return LIBRARY_COMMAND_ARRAY_SIZE;#else// if there are no vendor commands, then this is out of range
return UNIMPLEMENTED_COMMAND_INDEX;#endif}// If the request is lower than any value in the array, then return// the lowest value (needs to be an index for an implemented commandif(GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex) >= searchIndex){
return NextImplementedIndex(0);}else{#if COMPRESSED_LISTSCOMMAND_INDEX
commandIndex = UNIMPLEMENTED_COMMAND_INDEX;COMMAND_INDEX
min = 0;
COMMAND_INDEX
max = LIBRARY_COMMAND_ARRAY_SIZE - 1;
intdiff = 1;#if LIBRARY_COMMAND_ARRAY_SIZE == 0#error "Something is terribly wrong"#endif// The s_ccAttr array contains an extra entry at the end (a zero value).
// Don't count this as an array entry. This means that max should start// out pointing to the last valid entry in the array which is - 2

Page 402
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

Trusted Platform Module LibrarypAssert(max == (sizeof(s_ccAttr) / sizeof(TPMA_CC)- VENDOR_COMMAND_ARRAY_SIZE - 2));
while(min <= max){
commandIndex = (min + max + 1) / 2;
diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC,
commandIndex) - searchIndex;
if(diff == 0)
return commandIndex;
if(diff > 0)
max = commandIndex - 1;else
min = commandIndex + 1;}// didn't find and exact match. commandIndex will be pointing at the// last item tested. If diff is positive, then the last item tested was// larger index of the command code so it is the smallest value// larger than the requested value.
if(diff > 0)
return commandIndex;// if diff is negative, then the value tested was smaller than// the commandCode index and the next higher value is the correct one.
// Note: this will necessarily be in range because of the earlier check// that the index was within range.
return commandIndex + 1;
#else// The list is not compressed so offset into the array by the command// code value of the first entry in the list. Then go find the first// implemented command.
return NextImplementedIndex(searchIndex- (COMMAND_INDEX)s_ccAttr[0].commandIndex);#endif}}9.3.3.3

CommandCodeToComandIndex()

This function returns the index in the various attributes arrays of the command.

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX

command is not implemented

otherindex of the command

COMMAND_INDEX
CommandCodeToCommandIndex(
TPM_CC)

commandCode// IN: the command code to look up{// Extract the low 16-bits of the command code to get the starting search index
COMMAND_INDEX
searchIndex = (COMMAND_INDEX)commandCode;
BOOL
vendor = (commandCode & CC_VEND) != 0;
COMMAND_INDEX
commandIndex;#if !COMPRESSED_LISTS
if(!vendor){
commandIndex = searchIndex - (COMMAND_INDEX)s_ccAttr[0].commandIndex;// Check for out of range or unimplemented.
// Note, since a COMMAND_INDEX is unsigned, if searchIndex is smaller than// the lowest value of command, it will become a 'negative' number making// it look like a large unsigned number, this will cause it to fail// the unsigned check below.
if(commandIndex >= LIBRARY_COMMAND_ARRAY_SIZEFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 403
April 15, 2019

Trusted Platform Module Library
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

Part 4: Supporting Routines|| (s_commandAttributes[commandIndex] & IS_IMPLEMENTED) == 0)
return UNIMPLEMENTED_COMMAND_INDEX;
return commandIndex;}#endif// Need this code for any vendor code lookup or for compressed lists
commandIndex = GetClosestCommandIndex(commandCode);// Look at the returned value from get closest. If it isn't the one that was// requested, then the command is not implemented.
if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX){
if((GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)!= searchIndex)|| (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) != vendor)
commandIndex = UNIMPLEMENTED_COMMAND_INDEX;}
return commandIndex;}

9.3.3.4

GetNextCommandIndex()

This function returns the index of the next implemented command.

217
218
219
220
221
222
223
224
225
226
227
228
229
230

Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX

no more implemented commands

otherthe index of the next implemented command

COMMAND_INDEX
GetNextCommandIndex(
COMMAND_INDEX)

commandIndex// IN: the starting index{
while(++commandIndex < COMMAND_COUNT){#if !COMPRESSED_LISTS
if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED)#endifreturn commandIndex;}
return UNIMPLEMENTED_COMMAND_INDEX;}

9.3.3.5

GetCommandCode()This function returns the commandCode associated with the command index
231
232
233
234
235
236
237
238
239
240
241

TPM_CC
GetCommandCode(COMMAND_INDEX)

commandIndex// IN: the command index{
TPM_CC

commandCode = GET_ATTRIBUTE(s_ccAttr[commandIndex],
TPMA_CC, commandIndex);if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))commandCode += CC_VEND;
return commandCode;}

Page 404
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.3.3.6

Trusted Platform Module Library

CommandAuthRole()

This function returns the authorization role required of a handle.

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

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

AUTH_ROLE
CommandAuthRole(
COMMAND_INDEXUINT32)

commandIndex,
handleIndex// IN: command index// IN: handle index (zero based){if(0 == handleIndex){// Any authorization role set?
COMMAND_ATTRIBUTES properties = s_commandAttributes[commandIndex];if(properties & HANDLE_1_USER)
return AUTH_USER;
if(properties & HANDLE_1_ADMIN)
return AUTH_ADMIN;
if(properties & HANDLE_1_DUP)
return AUTH_DUP;}
else if(1 == handleIndex){
if(s_commandAttributes[commandIndex] & HANDLE_2_USER)
return AUTH_USER;}
return AUTH_NONE;}

9.3.3.7

EncryptSize()This function returns the size of the decrypt size field. This function returns 0 if encryption is not allowed

267
268
269
270
271
272
273
274

Return Value

Meaning0

encryption not allowed2

size field is two bytes

4

size field is four bytes

int
EncryptSize(
COMMAND_INDEX)

commandIndex// IN: command index{
return ((s_commandAttributes[commandIndex] & ENCRYPT_2) ? 2 :(s_commandAttributes[commandIndex] & ENCRYPT_4) ? 4 : 0);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 405
April 15, 2019

Trusted Platform Module Library

9.3.3.8

Part 4: Supporting Routines

DecryptSize()This function returns the size of the decrypt size field. This function returns 0 if decryption is not allowed

275
276
277
278
279
280
281
282

Return Value

Meaning0

encryption not allowed2

size field is two bytes

4

size field is four bytes

int
DecryptSize(
COMMAND_INDEX)

commandIndex// IN: command index{
return ((s_commandAttributes[commandIndex] & DECRYPT_2) ? 2 :(s_commandAttributes[commandIndex] & DECRYPT_4) ? 4 : 0);}

9.3.3.9

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.

283
284
285
286
287
288
289

Return Value

Meaning

TRUE(1)session is allowed with this command

FALSE(0)session is not allowed with this command

BOOL
IsSessionAllowed(
COMMAND_INDEX)

commandIndex// IN: the command to be checked{
return ((s_commandAttributes[commandIndex] & NO_SESSIONS) == 0);}

9.3.3.10

IsHandleInResponse()

This function determines if a command has a handle in the response
290
291
292
293
294
295
296

BOOL
IsHandleInResponse(
COMMAND_INDEX)

commandIndex{
return ((s_commandAttributes[commandIndex] & R_HANDLE) != 0);}

9.3.3.11

IsWriteOperation()

Checks to see if an operation will write to an NV Index and is subject to being blocked by read-lock
297
298
299
300

BOOL
IsWriteOperation(
COMMAND_INDEX)

Page 406
April 15, 2019

commandIndex// IN: Command to check

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

Trusted Platform Module Library{#ifdef WRITE_LOCK
return ((s_commandAttributes[commandIndex] & WRITE_LOCK) != 0);#else
if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)){
switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)){
case TPM_CC_NV_Write:#if CC_NV_Incrementcase TPM_CC_NV_Increment:#endif#if CC_NV_SetBits
case TPM_CC_NV_SetBits:#endif#if CC_NV_Extend
case TPM_CC_NV_Extend:#endif#if CC_AC_Sendcase TPM_CC_AC_Send:#endif// NV write lock counts as a write operation for authorization purposes.
// We check to see if the NV is write locked before we do the// authorization. If it is locked, we fail the command early.
case TPM_CC_NV_WriteLock:return TRUE;
default:
break;}}
return FALSE;#endif}9.3.3.12

IsReadOperation()

Checks to see if an operation will write to an NV Index and is subject to being blocked by write-lock.
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

BOOL
IsReadOperation(
COMMAND_INDEX)

commandIndex// IN: Command to check{#ifdef READ_LOCK
return ((s_commandAttributes[commandIndex] & READ_LOCK) != 0);#else
if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)){
switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)){
case TPM_CC_NV_Read:case TPM_CC_PolicyNV:
case TPM_CC_NV_Certify:// NV read lock counts as a read operation for authorization purposes.
// We check to see if the NV is read locked before we do the// authorization. If it is locked, we fail the command early.
case TPM_CC_NV_ReadLock:return TRUE;
default:
break;}}
return FALSE;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 407
April 15, 2019

Trusted Platform Module Library360
361Part 4: Supporting Routines#endif}9.3.3.13

CommandCapGetCCList()

This function returns a list of implemented commands and command attributes starting from thecommand in commandCode.

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

Return Value

Meaning

YES

more command attributes are available

NOno more command attributes are available

TPMI_YES_NO
CommandCapGetCCList(
TPM_CCUINT32

commandCode,count,// IN: start command code// IN: maximum count for number of entries in//'commandList'// OUT: list of TPMA_CC

TPML_CCA)*commandList

TPMI_YES_NO
COMMAND_INDEX

more = NO;commandIndex;{// initialize output handle list countcommandList->count = 0;
for(commandIndex = GetClosestCommandIndex(commandCode);
commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
commandIndex = GetNextCommandIndex(commandIndex)){#if !COMPRESSED_LISTS// this check isn't needed for compressed lists.
if(!(s_commandAttributes[commandIndex] & IS_IMPLEMENTED))
continue;#endifif(commandList->count < count){// If the list is not full, add the attributes for this command.
commandList->commandAttributes[commandList->count]= s_ccAttr[commandIndex];commandList->count++;}else{// If the list is full but there are more commands to report,// indicate this and return.
more = YES;
break;}}
return more;}

9.3.3.14

IsVendorCommand()Function indicates if a command index references a vendor command.

Page 408
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

402
403
404
405
406
407
408

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)

command is a vendor command

FALSE(0)command is not a vendor command

BOOL
IsVendorCommand(
COMMAND_INDEX)

commandIndex// IN: command index to check{
return (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V));}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 409
April 15, 2019

Trusted Platform Module Library

9.4

Part 4: Supporting Routines

Entity.c

9.4.1

Description

The functions in this file are used for accessing properties for handles of various types. Functions in otherfiles require handles of a specific type but the functions in this file allow use of any handle type.
9.4.2
1

Includes#include "Tpm.h"

9.4.3

Functions9.4.3.1

EntityGetLoadStatus()

This function will check that all the handles access loaded entities.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

Error Returns

Meaning

TPM_RC_HANDLE

handle type does not match

TPM_RC_REFERENCE_Hx

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

TPM_RC
EntityGetLoadStatus(
COMMAND)*command// IN/OUT: command parsing structure{
UINT32
TPM_RCi;
result = TPM_RC_SUCCESS;//
for(i = 0; i < command->handleNum; i++){
TPM_HANDLE
handle = command->handles[i];switch(HandleGetType(handle)){// For handles associated with hierarchies, the entity is present// only if the associated enable is SET.
case TPM_HT_PERMANENT:
switch(handle){
case TPM_RH_OWNER:
if(!gc.shEnable)
result = TPM_RC_HIERARCHY;
break;#ifdef

VENDOR_PERMANENT
case VENDOR_PERMANENT:#endifcase TPM_RH_ENDORSEMENT:if(!gc.ehEnable)
result = TPM_RC_HIERARCHY;
break;
case TPM_RH_PLATFORM:
if(!g_phEnable)
result = TPM_RC_HIERARCHY;
break;

Page 410
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

Trusted Platform Module Library// null handle, PW session handle and lockout// handle are always available
case TPM_RH_NULL:
case TPM_RS_PW:// Need to be careful for lockout. Lockout is always available// for policy checks but not always available when authValue// is being checked.
case TPM_RH_LOCKOUT:
break;
default:// handling of the manufacture_specific handles
if(((TPM_RH)handle >= TPM_RH_AUTH_00)&& ((TPM_RH)handle <= TPM_RH_AUTH_FF))// use the value that would have been returned from// unmarshaling if it did the handle filteringresult = TPM_RC_VALUE;
else
FAIL(FATAL_ERROR_INTERNAL);
break;}
break;
case TPM_HT_TRANSIENT:// For a transient object, check if the handle is associated// with a loaded object.
if(!IsObjectPresent(handle))
result = TPM_RC_REFERENCE_H0;
break;
case TPM_HT_PERSISTENT:// Persistent object// Copy the persistent object to RAM and replace the handle with the// handle of the assigned slot. A TPM_RC_OBJECT_MEMORY,// TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by// ObjectLoadEvict()
result = ObjectLoadEvict(&command->handles[i], command->index);
break;
case TPM_HT_HMAC_SESSION:// For an HMAC session, see if the session is loaded// and if the session in the session slot is actually// an HMAC session.
if(SessionIsLoaded(handle)){
SESSION*session;session = SessionGet(handle);// Check if the session is a HMAC session
if(session->attributes.isPolicy == SET)
result = TPM_RC_HANDLE;}
elseresult = TPM_RC_REFERENCE_H0;
break;
case TPM_HT_POLICY_SESSION:// For a policy session, see if the session is loaded// and if the session in the session slot is actually// a policy session.
if(SessionIsLoaded(handle)){
SESSION*session;session = SessionGet(handle);// Check if the session is a policy session
if(session->attributes.isPolicy == CLEAR)
result = TPM_RC_HANDLE;}
elseresult = TPM_RC_REFERENCE_H0;
break;
case TPM_HT_NV_INDEX:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 411
April 15, 2019

Trusted Platform Module Library
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

Part 4: Supporting Routines// For an NV Index, use the TPM-specific routine// to search the IN Index space.
result = NvIndexIsAccessible(handle);
break;
case TPM_HT_PCR:// Any PCR handle that is unmarshaled successfully referenced// a PCR that is defined.
break;#if CC_AC_Sendcase TPM_HT_AC:// Use the TPM-specific routine to search for the AC
result = AcIsAccessible(handle);
break;#endifdefault:// Any other handle type is a defect in the unmarshaling code.
FAIL(FATAL_ERROR_INTERNAL);
break;}
if(result != TPM_RC_SUCCESS){
if(result == TPM_RC_REFERENCE_H0)
result = result + i;
else
result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]);break;}}
return result;}9.4.3.2

EntityGetAuthValue()

This function is used to access the authValue associated with a handle. This function assumes that thehandle 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 beenverified by IsAuthValueAvailable().
This function copies the authorization value of the entity to auth.

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

Return Value

Meaningcountnumber of bytes in the authValue with 0's stripped

UINT16
EntityGetAuthValue(
TPMI_DH_ENTITY
TPM2B_AUTH)

handle,*auth// IN: handle of entity// OUT: authValue of the entity

TPM2B_AUTH*pAuth = NULL;{
auth->t.size = 0;
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:{
switch(handle){
case TPM_RH_OWNER:// ownerAuth for TPM_RH_OWNER
pAuth = &gp.ownerAuth;break;

Page 412
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

#ifdefTrusted Platform Module Librarycase TPM_RH_ENDORSEMENT:// endorsementAuth for TPM_RH_ENDORSEMENT
pAuth = &gp.endorsementAuth;break;
case TPM_RH_PLATFORM:// platformAuth for TPM_RH_PLATFORM
pAuth = &gc.platformAuth;break;
case TPM_RH_LOCKOUT:// lockoutAuth for TPM_RH_LOCKOUT
pAuth = &gp.lockoutAuth;break;
case TPM_RH_NULL:// nullAuth for TPM_RH_NULL. Return 0 directly here
return 0;
break;VENDOR_PERMANENT
case VENDOR_PERMANENT:// vendor authorization value
pAauth = &g_platformUniqueDetails;#endifdefault:// If any other permanent handle is present it is// a code defect.
FAIL(FATAL_ERROR_INTERNAL);
break;}
break;}
case TPM_HT_TRANSIENT:// authValue for an object// A persistent object would have been copied into RAM// and would have an transient object handle here.
{
OBJECT*object;
object = HandleToObject(handle);// special handling if this is a sequence object
if(ObjectIsSequence(object)){pAuth = &((HASH_OBJECT *)object)->auth;}else{// Authorization is available only when the private portion of// the object is loaded. The check should be made before// this function is called
pAssert(object->attributes.publicOnly == CLEAR);
pAuth = &object->sensitive.authValue;}}
break;
case TPM_HT_NV_INDEX:// authValue for an NV index{
NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);
pAssert(nvIndex != NULL);
pAuth = &nvIndex->authValue;}
break;
case TPM_HT_PCR:// authValue for PCR
pAuth = PCRGetAuthValue(handle);
break;
default:// If any other handle type is present here, then there is a defectFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 413
April 15, 2019

Trusted Platform Module Library
218
219
220
221
222
223
224
225
226

Part 4: Supporting Routines// in the unmarshaling code.
FAIL(FATAL_ERROR_INTERNAL);
break;}// Copy the authValue
MemoryCopy2B(&auth->b, &pAuth->b, sizeof(auth->t.buffer));
MemoryRemoveTrailingZeros(auth);return auth->t.size;}

9.4.3.3

EntityGetAuthPolicy()

This function is used to access the authPolicy associated with a handle. This function assumes that thehandle 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 havebeen verified by IsAuthPolicyAvailable().
This function copies the authorization policy of the entity to authPolicy.
The return value is the hash algorithm for the policy.
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

TPMI_ALG_HASH
EntityGetAuthPolicy(
TPMI_DH_ENTITY
TPM2B_DIGEST)

handle,*authPolicy// IN: handle of entity// OUT: authPolicy of the entity{
TPMI_ALG_HASH
hashAlg = TPM_ALG_NULL;
authPolicy->t.size = 0;
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:
switch(handle){
case TPM_RH_OWNER:// ownerPolicy for TPM_RH_OWNER*authPolicy = gp.ownerPolicy;
hashAlg = gp.ownerAlg;
break;
case TPM_RH_ENDORSEMENT:// endorsementPolicy for TPM_RH_ENDORSEMENT*authPolicy = gp.endorsementPolicy;
hashAlg = gp.endorsementAlg;
break;
case TPM_RH_PLATFORM:// platformPolicy for TPM_RH_PLATFORM*authPolicy = gc.platformPolicy;
hashAlg = gc.platformAlg;
break;
case TPM_RH_LOCKOUT:// lockoutPolicy for TPM_RH_LOCKOUT*authPolicy = gp.lockoutPolicy;
hashAlg = gp.lockoutAlg;
break;
default:
return TPM_ALG_ERROR;
break;}
break;
case TPM_HT_TRANSIENT:// authPolicy for an object{
OBJECT *object = HandleToObject(handle);

Page 414
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

Trusted Platform Module Library*authPolicy = object->publicArea.authPolicy;
hashAlg = object->publicArea.nameAlg;}
break;
case TPM_HT_NV_INDEX:// authPolicy for a NV index{
NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);
pAssert(nvIndex != 0);*authPolicy = nvIndex->publicArea.authPolicy;
hashAlg = nvIndex->publicArea.nameAlg;}
break;
case TPM_HT_PCR:// authPolicy for a PCR
hashAlg = PCRGetAuthPolicy(handle, authPolicy);
break;
default:// If any other handle type is present it is a code defect.
FAIL(FATAL_ERROR_INTERNAL);
break;}
return hashAlg;}

9.4.3.4

EntityGetName()

This function returns the Name associated with a handle.
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

TPM2B_NAME *EntityGetName(TPMI_DH_ENTITY
TPM2B_NAME)

handle,*name// IN: handle of entity// OUT: name of entity{
switch(HandleGetType(handle)){case TPM_HT_TRANSIENT:{// Name for an object
OBJECT*object = HandleToObject(handle);// an object with no nameAlg has no nameif(object->publicArea.nameAlg == TPM_ALG_NULL)
name->b.size = 0;
else
*name = object->name;break;}
case TPM_HT_NV_INDEX:// Name for a NV index
NvGetNameByIndexHandle(handle, name);break;
default:// For all other types, the handle is the Name
name->t.size = sizeof(TPM_HANDLE);UINT32_TO_BYTE_ARRAY(handle, name->t.name);break;}
return name;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 415
April 15, 2019

Trusted Platform Module Library

9.4.3.5

Part 4: Supporting Routines

EntityGetHierarchy()

This function returns the hierarchy handle associated with an entity.
A handle that is a hierarchy handle is associated with itself.
An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET,
otherwise it belongs to TPM_RH_OWNER
An object handle belongs to its hierarchy.
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

TPMI_RH_HIERARCHY
EntityGetHierarchy(
TPMI_DH_ENTITY)

handle// IN :handle of entity{
TPMI_RH_HIERARCHY

hierarchy = TPM_RH_NULL;

switch(HandleGetType(handle)){case TPM_HT_PERMANENT:// hierarchy for a permanent handle
switch(handle){
case TPM_RH_PLATFORM:
case TPM_RH_ENDORSEMENT:
case TPM_RH_NULL:
hierarchy = handle;
break;// all other permanent handles are associated with the owner// hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT)
default:
hierarchy = TPM_RH_OWNER;
break;}
break;
case TPM_HT_NV_INDEX:// hierarchy for NV index{
NV_INDEX*nvIndex = NvGetIndexInfo(handle, NULL);
pAssert(nvIndex != NULL);// If only the platform can delete the index, then it is// considered to be in the platform hierarchy, otherwise it// is in the owner hierarchy.
if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV,
PLATFORMCREATE))
hierarchy = TPM_RH_PLATFORM;
else
hierarchy = TPM_RH_OWNER;}
break;
case TPM_HT_TRANSIENT:// hierarchy for an object{
OBJECT*object;
object = HandleToObject(handle);
if(object->attributes.ppsHierarchy){hierarchy = TPM_RH_PLATFORM;}
else if(object->attributes.epsHierarchy){hierarchy = TPM_RH_ENDORSEMENT;}
else if(object->attributes.spsHierarchy)

Page 416
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395

Trusted Platform Module Library{hierarchy = TPM_RH_OWNER;}}
break;
case TPM_HT_PCR:
hierarchy = TPM_RH_OWNER;
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}// this is unreachable but it provides a return value for the default// case which makes the complier happy
return hierarchy;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 417
April 15, 2019

Trusted Platform Module Library

9.5
9.5.1

Part 4: Supporting Routines

Global.cDescription

This file will instance the TPM variables that are not stack allocated. Descriptions of global variables are
in Global.h. There macro macro definitions that allows a variable to be instanced or simply defined as anexternal variable. When global.h is included from this .c file, GLOBAL_C is defined and values are
instanced (and possibly initialized), but when global.h is included by any other file, they are simply defined
as external values. DO NOT DEFINE GLOBAL_C IN ANY OTHER FILE.
NOTE:This is a change from previous implementations where Global.h just contained the extern declaration andvalues were instanced in this file. This change keeps the definition and instance in one file making maintenanceeasier. The instanced data will still be in the global.obj file.

The OIDs.h file works in a way that is similar to the Global.h with the definition of the values in OIDs.hsuch that they are instanced in global.obj. The macros that are defined in Global.h are used in OIDs.h in
the same way as they are in Global.h.
9.5.2
1
2
3

Defines and Includes#define GLOBAL_C#include "Tpm.h"#include "OIDS.h"

Page 418
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.6

Trusted Platform Module LibraryHandle.c

9.6.1

Description

This file contains the functions that return the type of a handle.
9.6.2
1

Includes#include "Tpm.h"

9.6.3
9.6.3.1

FunctionsHandleGetType()This function returns the type of a handle which is the MSO of the handle.
2
3
4
5
6
7
8
9

TPM_HT
HandleGetType(TPM_HANDLE)

handle// IN: a handle to be checked{// return the upper bytes of input data
return (TPM_HT)((handle & HR_RANGE_MASK) >> HR_SHIFT);}

9.6.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:
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

TPM_HANDLE
NextPermanentHandle(
TPM_HANDLE)

inHandle// IN: the handle to check{// If inHandle is below the start of the range of permanent handles// set it to the start and scan from there
if(inHandle < TPM_RH_FIRST)
inHandle = TPM_RH_FIRST;// scan from input value until we find an implemented permanent handle// or go out of rangefor(; inHandle <= TPM_RH_LAST; inHandle++){switch(inHandle){
case TPM_RH_OWNER:
case TPM_RH_NULL:
case TPM_RS_PW:
case TPM_RH_LOCKOUT:
case TPM_RH_ENDORSEMENT:
case TPM_RH_PLATFORM:
case TPM_RH_PLATFORM_NV:#ifdef VENDOR_PERMANENT
case VENDOR_PERMANENT:#endifreturn inHandle;
break;
default:
break;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 419
April 15, 2019

Trusted Platform Module Library
39
40
41
42
43

Part 4: Supporting Routines}}// Out of range on the top
return 0;}

9.6.3.3

PermanentCapGetHandles()This function returns a list of the permanent handles of PCR, started from handle. If handle is larger thanthe largest permanent handle, an empty list will be returned with more set to NO.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
PermanentCapGetHandles(
TPM_HANDLEUINT32
TPML_HANDLE)

handle,count,*handleList

TPMI_YES_NOUINT32more = NO;i;// IN: start handle// IN: count of returned handles// OUT: list of handle{

pAssert(HandleGetType(handle) == TPM_HT_PERMANENT);// Initialize output handle list
handleList->count = 0;// The maximum count of handles we may return is MAX_CAP_HANDLES
if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;// Iterate permanent handle range
for(i = NextPermanentHandle(handle);
i != 0; i = NextPermanentHandle(i + 1)){
if(handleList->count < count){// If we have not filled up the return list, add this permanent// handle to it
handleList->handle[handleList->count] = i;handleList->count++;}else{// If the return list is full but we still have permanent handle// available, report this and stop iterating
more = YES;
break;}}
return more;}

9.6.3.4

PermanentHandleGetPolicy()

This function returns a list of the permanent handles of PCR, started from handle. If handle is larger thanthe largest permanent handle, an empty list will be returned with more set to NO.

Page 420
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

Trusted Platform Module Library

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
PermanentHandleGetPolicy(
TPM_HANDLEUINT32
TPML_TAGGED_POLICY)

handle,count,*policyList// IN: start handle// IN: max count of returned handles// OUT: list of handle{
TPMI_YES_NO

more = NO;

pAssert(HandleGetType(handle) == TPM_HT_PERMANENT);// Initialize output handle list
policyList->count = 0;// The maximum count of policies we may return is MAX_TAGGED_POLICIES
if(count > MAX_TAGGED_POLICIES)
count = MAX_TAGGED_POLICIES;// Iterate permanent handle range
for(handle = NextPermanentHandle(handle);
handle != 0;
handle = NextPermanentHandle(handle + 1)){
TPM2B_DIGEST
policyDigest;
TPM_ALG_ID
policyAlg;// Check to see if this permanent handle has a policy
policyAlg = EntityGetAuthPolicy(handle, &policyDigest);
if(policyAlg == TPM_ALG_ERROR)
continue;if(policyList->count < count){// If we have not filled up the return list, add this// policy to the list;
policyList->policies[policyList->count].handle = handle;
policyList->policies[policyList->count].policyHash.hashAlg = policyAlg;
MemoryCopy(&policyList->policies[policyList->count].policyHash.digest,policyDigest.t.buffer, policyDigest.t.size);policyList->count++;}else{// If the return list is full but we still have permanent handle// available, report this and stop iterating
more = YES;
break;}}
return more;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 421
April 15, 2019

Trusted Platform Module Library

9.7

Part 4: Supporting Routines

IoBuffers.c

9.7.1

Includes and Data Definitions

This definition allows this module to see the values that are private to this module but kept in Global.c forease of state migration.
1
2
3#define IO_BUFFER_C#include "Tpm.h"#include "IoBuffers_fp.h"

9.7.2

Buffers and Functions

These buffers are set aside to hold command and response values. In this implementation, it is notguaranteed that the code will stop accessing the s_actionInputBuffer before starting to put values in thes_actionOutputBuffer so different buffers are required.
9.7.2.1

MemoryIoBufferAllocationReset()This function is used to reset the allocation of buffers.
4
5
6
7
8
9
10

void
MemoryIoBufferAllocationReset(
void){
s_actionIoAllocation = 0;}

9.7.2.2

MemoryIoBufferZero()

Function zeros the action I/O buffer at the end of a command. Calling this is not mandatory for proper
functionality.
11
12
13
14
15
16
17

void
MemoryIoBufferZero(void){
memset(s_actionIoBuffer, 0, s_actionIoAllocation);}

9.7.2.3

MemoryGetInBuffer()

This function returns the address of the buffer into which the command parameters will be unmarshaled in
preparation for calling the command actions.
18
19
20
21
22
23
24
25
26
27

BYTE *
MemoryGetInBuffer(
UINT32size// Size, in bytes, required for the input// unmarshaling){
pAssert(size <= sizeof(s_actionIoBuffer));// In this implementation, a static buffer is set aside for the command action// buffers. The buffer is shared between input and output. This is because// there is no need to allocate for the worst case input and worst case output

Page 422
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
28
29
30
31
32
33
34
35

Trusted Platform Module Library// at the same time.
// Round size up#define UoM (sizeof(s_actionIoBuffer[0]))size = (size + (UoM - 1)) & (UINT32_MAX - (UoM - 1));
memset(s_actionIoBuffer, 0, size);s_actionIoAllocation = size;
return (BYTE *)&s_actionIoBuffer[0];}9.7.2.4

MemoryGetOutBuffer()

This function returns the address of the buffer into which the command action code places its output
values.
36
37
38
39
40
41
42
43
44
45
46
47
48

BYTE *
MemoryGetOutBuffer(
UINT32)size// required size of the buffer{
BYTE*retVal = (BYTE *)(&s_actionIoBuffer[s_actionIoAllocation / UoM]);
pAssert((size + s_actionIoAllocation) < (sizeof(s_actionIoBuffer)));// In this implementation, a static buffer is set aside for the command action// output buffer.
memset(retVal, 0, size);s_actionIoAllocation += size;
return retVal;}

9.7.2.5

IsLabelProperlyFormatted()

This function checks that a label is a null-terminated string.
NOTE:

49
50
51
52
53
54
55

this function is here because there was no better place for it.

Return Value

Meaning

TRUE(1)string is null terminated

FALSE(0)string is not null terminated

BOOL
IsLabelProperlyFormatted(
TPM2B
)

*x

{
return (((x)->size == 0) || ((x)->buffer[(x)->size - 1] == 0));}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 423
April 15, 2019

Trusted Platform Module Library

9.8

Locality.c

9.8.1
1

Part 4: Supporting Routines

Includes#include "Tpm.h"

9.8.2

LocalityGetAttributes()

This function will convert a locality expressed as an integer into TPMA_LOCALITY form.
The function returns the locality attribute.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

TPMA_LOCALITY
LocalityGetAttributes(
UINT8)

locality// IN: locality value{
TPMA_LOCALITY
BYTE

locality_attributes;*localityAsByte = (BYTE *)&locality_attributes;

MemorySet(&locality_attributes, 0, sizeof(TPMA_LOCALITY));
switch(locality){case 0:
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ZERO);
break;
case 1:
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ONE);
break;
case 2:
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_TWO);
break;
case 3:
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_THREE);
break;
case 4:
SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_FOUR);
break;
default:
pAssert(locality > 31);
*localityAsByte = locality;
break;}
return locality_attributes;}

Page 424
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.9

Manufacture.c

9.9.1

Description

Trusted Platform Module LibraryThis 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.9.2
1
2
3

Includes and Data Definitions#define MANUFACTURE_C#include "Tpm.h"#include "TpmSizeChecks_fp.h"

9.9.3
9.9.3.1

Functions
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 thisfunction again.

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Return Value

Meaning0

success1

manufacturing process previously performed

LIB_EXPORT int
TPM_Manufacture(int

firstTime// IN: indicates if this is the first call from//main()){TPM_SUorderlyShutdown;#if RUNTIME_SIZE_CHECKS// Call the function to verify the sizes of values that result from different// compile options.
TpmSizeChecks();#endif// If TPM has been manufactured, return indication.
if(!firstTime && g_manufactured)
return 1;// Do power on initializations of the cryptographic libraries.
CryptInit();s_DAPendingOnNV = FALSE;// initialize NV
NvManufacture();// Clear the magic value in the DRBG statego.drbgState.magic = 0;
CryptStartup(SU_RESET);// default configuration for PCR
PCRSimStart();Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 425
April 15, 2019

Trusted Platform Module Library
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

Part 4: Supporting Routines// initialize pre-installed hierarchy data// This should happen after NV is initialized because hierarchy data is// stored in NV.
HierarchyPreInstall_Init();// initialize dictionary attack parameters
DAPreInstall_Init();// initialize PP list
PhysicalPresencePreInstall_Init();// initialize command audit list
CommandAuditPreInstall_Init();// first start up is required to be Startup(CLEAR)
orderlyShutdown = TPM_SU_CLEAR;
NV_WRITE_PERSISTENT(orderlyState, orderlyShutdown);// initialize the firmware version
gp.firmwareV1 = FIRMWARE_V1;#ifdef FIRMWARE_V2
gp.firmwareV2 = FIRMWARE_V2;#else
gp.firmwareV2 = 0;
#endif
NV_SYNC_PERSISTENT(firmwareV1);
NV_SYNC_PERSISTENT(firmwareV2);// initialize the total reset counter to 0
gp.totalResetCount = 0;
NV_SYNC_PERSISTENT(totalResetCount);// initialize the clock stuff
go.clock = 0;
go.clockSafe = YES;
NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go);// Commit NV writes. Manufacture process is an artificial process existing// only in simulator environment and it is not defined in the specification// that what should be the expected behavior if the NV write fails at this// point. Therefore, it is assumed the NV write here is always success and// no return code of this function is checked.
NvCommit();g_manufactured = TRUE;
return 0;}

9.9.3.2

TPM_TearDown()

This function prepares the TPM for re-manufacture. It should not be implemented in anything other than asimulated 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 processagain.

Page 426
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

87
88
89
90
91
92
93
94

Trusted Platform Module Library

Return Value

Meaning0

success

1

TPM not previously manufactured

LIB_EXPORT int
TPM_TearDown(
void){
g_manufactured = FALSE;
return 0;}

9.9.3.3

TpmEndSimulation()

This function is called at the end of the simulation run. It is used to provoke printing of any statistics thatmight be needed.
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

LIB_EXPORT void
TpmEndSimulation(
void){#if SIMULATION
HashLibSimulationEnd();
SymLibSimulationEnd();MathLibSimulationEnd();#if
ALG_RSA
RsaSimulationEnd();#endif#if
ALG_ECC
EccSimulationEnd();#endif#endif // SIMULATION}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 427
April 15, 2019

Trusted Platform Module Library

9.10

Part 4: Supporting Routines

Marshal.c

9.10.1Introduction

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 theothers 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 andmarshaling code is generated (i.e., generation of both marshaling and unmarshaling code is the default).
9.10.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
ValuesComments{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_VALUEThis generates the following unmarshaling code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

TPM_RC
TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size,
BOOL flag){
TPM_RC
result;result = TPM_HANDLE_Unmarshal((TPM_HANDLE *)target, buffer, size);if(result != TPM_RC_SUCCESS)
return result;if(*target == TPM_RH_NULL){
if(flag)
return TPM_RC_SUCCESS;
else
return TPM_RC_VALUE;}
if(((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST))&&((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST)))
return TPM_RC_VALUE;
return TPM_RC_SUCCESS;}

and the following marshaling code:
NOTE

1
2

The marshaling code does not do parameter checking, as the TPM is the source of the marshaling data .

UINT16
TPMI_DH_OBJECT_Marshal(TPMI_DH_OBJECT *source, BYTE **buffer, INT32 *size)

Page 428
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
3
4
5

Trusted Platform Module Library{
return UINT32_Marshal((UINT32 *)source, buffer, size);}An additional script is used to do the work that might be done by a linker or globally optimizing compiler. It
searches for functions like TPMI_DH_OBJECT_Marshal() that do nothing but call another function andreplaces the function with a #define.
6
7#define TPMI_DH_OBJECT_Marshal(source, buffer, size)
UINT32_Marshal((UINT32 *)source, buffer, size)\

When replacing the function with a #define, the #define is placed in marshal_fp.h and the function body isremoved from marshal.c.
9.10.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>
ParameterType

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
2

TPM_RCTPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size,
UINT32 selector)

3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

{
switch(selector) {#if ALG_KEYEDHASH
case TPM_ALG_KEYEDHASH:
return TPMS_KEYEDHASH_PARMS_Unmarshal((TPMS_KEYEDHASH_PARMS *)&(target->keyedHash), buffer, size);#endif#if ALG_SYMCIPHER
case TPM_ALG_SYMCIPHER:
return TPMT_SYM_DEF_OBJECT_Unmarshal((TPMT_SYM_DEF_OBJECT *)&(target->symDetail), buffer, size, FALSE);#endif#if ALG_RSA
case TPM_ALG_RSA:
return TPMS_RSA_PARMS_Unmarshal((TPMS_RSA_PARMS *)&(target->rsaDetail), buffer, size);#endif#if ALG_ECC
case TPM_ALG_ECC:
return TPMS_ECC_PARMS_Unmarshal((TPMS_ECC_PARMS *)&(target->eccDetail), buffer, size);#endif}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 429
April 15, 2019

Trusted Platform Module Library27
28

Part 4: Supporting Routines

return TPM_RC_SELECTOR;}NOTE

The #if/#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
2
3
4
5
6
7
8
9
10

11
12
13
14
15

16
17
18
19
20

21
22
23
24
25

26
27
28
29

UINT16
TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size,
UINT32 selector){
switch(selector) {#if ALG_KEYEDHASH
case TPM_ALG_KEYEDHASH:
return TPMS_KEYEDHASH_PARMS_Marshal((TPMS_KEYEDHASH_PARMS *)&(source->keyedHash), buffer, size);#endif#if ALG_SYMCIPHER
case TPM_ALG_SYMCIPHER:
return TPMT_SYM_DEF_OBJECT_Marshal((TPMT_SYM_DEF_OBJECT *)&(source->symDetail), buffer, size);#endif#if ALG_RSA
case TPM_ALG_RSA:
return TPMS_RSA_PARMS_Marshal((TPMS_RSA_PARMS *)&(source->rsaDetail), buffer, size);#endif#if ALG_ECC
case TPM_ALG_ECC:
return TPMS_ECC_PARMS_Marshal((TPMS_ECC_PARMS *)&(source->eccDetail), buffer, size);#endif}assert(1);return 0;}

For the marshaling and unmarshaling code, a value in the structure containing the union provides thevalue used for selector. The example in the next section illustrates this.

Page 430
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.10.4

Trusted Platform Module Library

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 havea "+" to indicate that the nameAlg may be TPM_ALG_NULL.

objectAttributes

TPMA_OBJECT

attributes that, along with type, determine the manipulations of thisobjectauthPolicy

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 theunion selector is emphasized below.
The unmarshaling code for the structure in the table above is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

TPM_RCTPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL flag){
TPM_RC
result;result = TPMI_ALG_PUBLIC_Unmarshal((TPMI_ALG_PUBLIC *)&(target->type),
buffer, size);if(result != TPM_RC_SUCCESS)
return result;result = TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH *)&(target->nameAlg),
buffer, size, flag);if(result != TPM_RC_SUCCESS)
return result;result = TPMA_OBJECT_Unmarshal((TPMA_OBJECT *)&(target->objectAttributes),
buffer, size);if(result != TPM_RC_SUCCESS)
return result;result = TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST *)&(target->authPolicy),
buffer, size);if(result != TPM_RC_SUCCESS)
return result;result = TPMU_PUBLIC_PARMS_Unmarshal((TPMU_PUBLIC_PARMS *)&(target->parameters),
buffer, size,);
if(result != TPM_RC_SUCCESS)
return result;result = TPMU_PUBLIC_ID_Unmarshal((TPMU_PUBLIC_ID *)&(target->unique),buffer, size,)
if(result != TPM_RC_SUCCESS)
return result;
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 431
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

The marshaling code for the TPMT_PUBLIC structure is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

UINT16
TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size){
UINT16
result = 0;
result = (UINT16)(result + TPMI_ALG_PUBLIC_Marshal((TPMI_ALG_PUBLIC *)&(source->type), buffer, size));
result = (UINT16)(result + TPMI_ALG_HASH_Marshal((TPMI_ALG_HASH *)&(source->nameAlg), buffer, size));
result = (UINT16)(result + TPMA_OBJECT_Marshal((TPMA_OBJECT *)&(source->objectAttributes), buffer, size));
result = (UINT16)(result + TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&(source->authPolicy), buffer, size));
result = (UINT16)(result + TPMU_PUBLIC_PARMS_Marshal((TPMU_PUBLIC_PARMS *)&(source->parameters), buffer, size,));
result = (UINT16)(result + TPMU_PUBLIC_ID_Marshal((TPMU_PUBLIC_ID *)&(source->unique), buffer, size,));
return result;}9.10.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 twodigests[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 thedigest for the bank containing the PCR.

#TPM_RC_SIZE

response code when count is not at least two or isgreater 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
2
3
4
5
6
7
8
9
10
11
12
13

TPM_RC
TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size){
TPM_RC
result;result = UINT32_Unmarshal((UINT32 *)&(target->count), buffer, size);if(result != TPM_RC_SUCCESS)
return result;if( (target->count < 2))// This check is triggered by the {2:} notation// on ‘count’

return TPM_RC_SIZE;
if((target->count) > 8)

Page 432
April 15, 2019// This check is triggered by the {:8} notation

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
14
15
16
17
18
19
20
21
22
23

Trusted Platform Module Library// on ‘digests’.

return TPM_RC_SIZE;
result = TPM2B_DIGEST_Array_Unmarshal((TPM2B_DIGEST *)(target->digests),
buffer, size,
if(result != TPM_RC_SUCCESS)
return result;);

return TPM_RC_SUCCESS;}

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
2
3
4
5
6
7
8
9
10
11
12
13
14

TPM_RCTPM2B_DIGEST_Array_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size,
INT32 count){
TPM_RC
result;INT32 i;for(i = 0; i < count; i++) {result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size);if(result != TPM_RC_SUCCESS)
return result;}
return TPM_RC_SUCCESS;}

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
2
3
4
5
6
7
8
9
10
11
12

UINT16
TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size){
UINT16
result = 0;
result = (UINT16)(result + UINT32_Marshal((UINT32 *)&(source->count), buffer,size));
result = (UINT16)(result + TPM2B_DIGEST_Array_Marshal((TPM2B_DIGEST *)(source->digests), buffer, size,(INT32)(source->count)));return result;}

The marshaling code for the array is:
1
2
3
4
5
6
7
8
9
10
11
12
13

TPM_RCTPM2B_DIGEST_Array_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size,
INT32 count){
TPM_RC
result;INT32 i;for(i = 0; i < count; i++) {result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size);if(result != TPM_RC_SUCCESS)
return result;}
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 433
April 15, 2019

Trusted Platform Module Library

9.10.6

Part 4: Supporting Routines

TPM2B Handling

A TPM2B structure is handled as a special case. The unmarshaling code is similar to what is shown in
9.10.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 otherfunctions 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.
When marshaling a TPM2B where the second member is a BYTE array, the size parameter indicates thesize of the array. The second member can also be a structure. In this case, the caller does not prefill thesize member. The marshaling code must marshal the structure and then back fill the calculated size.
Table xxx — Definition of TPM2B_EVENT Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Parameter

Type

Description

size

UINT16Size of the operandbuffer [size] {:1024}

BYTE

The operand

TPM_RCTPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size){
TPM_RC
result;result = UINT16_Unmarshal((UINT16 *)&(target->t.size), buffer, size);if(result != TPM_RC_SUCCESS)
return result;// if size equal to 0, the rest of the structure is a zero buffer// so stop processing
if(target->t.size == 0)
return TPM_RC_SUCCESS;
if((target->t.size) > 1024)// This check is triggered by the {:1024}// notation on ‘buffer’
return TPM_RC_SIZE;
result = BYTE_Array_Unmarshal((BYTE *)(target->t.buffer), buffer, size,(INT32)(target->t.size));if(result != TPM_RC_SUCCESS)
return result;
return TPM_RC_SUCCESS;}

using these structure definitions:
1
2
3
4
5
6
7

typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_EVENT;

Page 434
April 15, 2019size;
buffer[1024];t;b;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.11

Trusted Platform Module Library

MathOnByteBuffers.c

9.11.1Introduction

This file contains implementation of the math functions that are performed with canonical integers in byte
buffers. The canonical integer is big-endian bytes.
1#include "Tpm.h"

9.11.29.11.2.1

Functions
UnsignedCmpBThis function compare two unsigned values. The values are byte-aligned, big-endian numbers (e.g, ahash).

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Return Value

Meaning1

if (a > b)0

if (a = b)-1

if (a < b)

LIB_EXPORT int
UnsignedCompareB(
UINT32const BYTEUINT32const BYTE)

aSize,*a,bSize,*b// IN: size of a// IN: a// IN: size of b// IN: b{
UINT32i;
if(aSize > bSize)
return 1;
else if(aSize < bSize)
return -1;
else{
for(i = 0; i < aSize; i++){if(a[i] != b[i])return (a[i] > b[i]) ? 1 : -1;}}
return 0;}

9.11.2.2

SignedCompareB()

Compare two signed integers:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 435
April 15, 2019

Trusted Platform Module Library

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Part 4: Supporting Routines

Return Value

Meaning1

if a > b0

if a = b-1

if a < bint
SignedCompareB(
const UINT32
const BYTE
const UINT32
const BYTE)

aSize,*a,bSize,*b// IN: size of a// IN: a buffer// IN: size of b// IN: b buffer

signA, signB;// sign of a and b{
int// For positive or 0, sign_a is 1// for negative, sign_a is 0
signA = ((a[0] & 0x80) == 0) ? 1 : 0;// For positive or 0, sign_b is 1// for negative, sign_b is 0
signB = ((b[0] & 0x80) == 0) ? 1 : 0;if(signA != signB){
return signA - signB;}
if(signA == 1)// do unsigned compare function
return UnsignedCompareB(aSize, a, bSize, b);else// do unsigned compare the other way
return 0 - UnsignedCompareB(aSize, a, bSize, b);}

9.11.2.3

ModExpB

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 thefunction 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.

54
55
56
57
58
59
60
61
62

Error Returns

Meaning

TPM_RC_SIZE

number to exponentiate is larger than the modulus

TPM_RC_NO_RESULT

result will not fit into the provided buffer

TPM_RCModExpB(
UINT32

cSize,

BYTE*c,const UINT32
const BYTE

mSize,*m,

Page 436
April 15, 2019// IN: the size of the output buffer. It will//need to be the same size as the modulus// OUT: the buffer to receive the results//(c->size must be set to the maximum size//for the returned value)// IN: number to exponentiate

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

const UINT32
const BYTE
const UINT32
const BYTE)

Trusted Platform Module LibraryeSize,*e,nSize,*n// IN: power// IN: modulus{
BN_MAX(bnC);
BN_MAX(bnM);
BN_MAX(bnE);
BN_MAX(bnN);
NUMBYTES
TPM_RCtSize = (NUMBYTES)nSize;
retVal = TPM_RC_SUCCESS;// Convert input parameters
BnFromBytes(bnM, m, (NUMBYTES)mSize);
BnFromBytes(bnE, e, (NUMBYTES)eSize);
BnFromBytes(bnN, n, (NUMBYTES)nSize);// Make sure that the output is big enough to hold the result// and that 'm' is less than 'n' (the modulus)
if(cSize < nSize)
ERROR_RETURN(TPM_RC_NO_RESULT);
if(BnUnsignedCmp(bnM, bnN) >= 0)
ERROR_RETURN(TPM_RC_SIZE);
BnModExp(bnC, bnM, bnE, bnN);
BnToBytes(bnC, c, &tSize);Exit:
return retVal;}

9.11.2.4

DivideB()

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.

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

Error Returns

Meaning

TPM_RC_NO_RESULT

q or r is too small to receive the result

LIB_EXPORT TPM_RC
DivideB(
const TPM2B
const TPM2B
TPM2B
TPM2B
)

*n,
*d,
*q,
*r

// IN: numerator// IN: denominator// OUT: quotient// OUT: remainder{
BN_MAX_INITIALIZED(bnN, n);BN_MAX_INITIALIZED(bnD, d);
BN_MAX(bnQ);
BN_MAX(bnR);//// Do divide with converted values
BnDiv(bnQ, bnR, bnN, bnD);// Convert the BIGNUM result back to 2B format using the size of the original// number
if(q != NULL)
if(!BnTo2B(bnQ, q, q->size))
return TPM_RC_NO_RESULT;
if(r != NULL)
if(!BnTo2B(bnR, r, r->size))
return TPM_RC_NO_RESULT;
return TPM_RC_SUCCESS;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 437
April 15, 2019

Trusted Platform Module Library
117

Part 4: Supporting Routines}

9.11.2.5

AdjustNumberB()

Remove/add leading zeros from a number in a TPM2B. Will try to make the number by adding or
removing leading zeros. If the number is larger than the requested size, it will make the number as small
as possible. Setting requestedSize to zero is equivalent to requesting that the number be normalized.
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

UINT16
AdjustNumberB(
TPM2B
UINT16)*num,
requestedSize{
BYTE*from;UINT16i;// See if number is already the requested size
if(num->size == requestedSize)
return requestedSize;from = num->buffer;
if (num->size > requestedSize){// This is a request to shift the number to the left (remove leading zeros)// Find the first non-zero byte. Don't look past the point where removing// more zeros would make the number smaller than requested, and don't throw// away any significant digits.
for(i = num->size; *from == 0 && i > requestedSize; from++, i--);if(i < num->size){num->size = i;MemoryCopy(num->buffer, from, i);}}// This is a request to shift the number to the right (add leading zeros)
else{
MemoryCopy(&num->buffer[requestedSize - num->size], num->buffer, num->size);
MemorySet(num->buffer, 0, requestedSize- num->size);num->size = requestedSize;}
return num->size;}

9.11.2.6

ShiftLeft()

This function shifts a byte buffer (a TPM2B) one byte to the left. That is, the most significant bit of themost significant byte is lost.
152
153
154
155
156
157
158
159
160
161
162
163
164
165

TPM2B *
ShiftLeft(
TPM2B*value// IN/OUT: value to shift and shifted value out){
UINT16
count = value->size;
BYTE*buffer = value->buffer;
if(count > 0){for(count -= 1; count > 0; buffer++, count--){
buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0);}*buffer <<= 1;

Page 438
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
166
167
168

Trusted Platform Module Library}
return value;}

9.11.2.7

IsNumeric()

Verifies that all the characters are simple numeric (0-9)
169
170
171
172
173
174
175
176
177
178
179
180
181

BOOL
IsNumeric(
TPM2B*value){UINT16i;for(i = 0; i < value->size; i++){if(value->buffer[i] < '0' || value->buffer[i] > '9')
return FALSE;}
return TRUE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 439
April 15, 2019

Trusted Platform Module Library

9.12

Part 4: Supporting Routines

Memory.c9.12.1

Description

This file contains a set of miscellaneous memory manipulation routines. Many of the functions have thesame semantics as functions defined in string.h. Those functions are not used directly in the TPM
because they are not safeThis version uses string.h after adding guards. This is because the math libraries invariably use thosefunctions so it is not practical to prevent those library functions from being pulled into the build.
9.12.2
1
2Includes and Data Definitions#include "Tpm.h"#include "Memory_fp.h"

9.12.3Functions9.12.3.1

MemoryCopy()

This is an alias for memmove. This is used in place of memcpy because some of the moves may overlap
and rather than try to make sure that memmove is used when necessary, it is always used.
3
4
5
6
7
8
9
10
11
12

void
MemoryCopy(
void
const voidint)

*dest,
*src,
sSize

{
if(dest != src)
memmove(dest, src, sSize);}

9.12.3.2

MemoryEqual()This function indicates if two buffers have the same values in the indicated number of bytes.

13
14
15
16
17
18
19
20
21
22
23
24
25
26

Return Value

Meaning

TRUE(1)all octets are the same

FALSE(0)all octets are not the same

BOOL
MemoryEqual(
const void
const void
unsigned int)*buffer1,*buffer2,
size// IN: compare buffer1// IN: compare buffer2// IN: size of bytes being compared{
BYTE
const BYTE
const BYTE

equal = 0;*b1 = (BYTE *)buffer1;*b2 = (BYTE *)buffer2;//// Compare all bytes so that there is no leakage of information// due to timing differences.
for(; size > 0; size--)

Page 440
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
27
28
29

Trusted Platform Module Libraryequal |= (*b1++ ^ *b2++);
return (equal == 0);}

9.12.3.3

MemoryCopy2B()

This function copies a TPM2B. This can be used when the TPM2B types are the same or different.
This function returns the number of octets in the data buffer of the TPM2B.
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

LIB_EXPORT INT16
MemoryCopy2B(
TPM2B
const TPM2B
unsigned int)*dest,*source,dSize// OUT: receiving TPM2B// IN: source TPM2B// IN: size of the receiving buffer{
pAssert(dest != NULL);
if(source == NULL)
dest->size = 0;
else{
pAssert(source->size <= dSize);
MemoryCopy(dest->buffer, source->buffer, source->size);
dest->size = source->size;}
return dest->size;}

9.12.3.4

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)).
48
49
50
51
52
53
54
55
56
57
58
59
60

void
MemoryConcat2B(
TPM2B
TPM2B
unsigned int*aInOut,*bIn,
aMaxSize// IN/OUT: destination 2B// IN: second 2B// IN: The size of aInOut.buffer (max values for//
aInOut.size)){
pAssert(bIn->size <= aMaxSize - aInOut->size);
MemoryCopy(&aInOut->buffer[aInOut->size], &bIn->buffer, bIn->size);
aInOut->size = aInOut->size + bIn->size;
return;}9.12.3.5

MemoryEqual2B()

This function will compare two TPM2B structures. To be equal, they need to be the same size and thebuffer contexts need to be the same in all octets.

61
62

Return Value

Meaning

TRUE(1)size and buffer contents are the same

FALSE(0)size or buffer contents are not the same

BOOL
MemoryEqual2B(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 441
April 15, 2019

Trusted Platform Module Library
63
64
65
66
67
68
69
70

const TPM2B
const TPM2B)

Part 4: Supporting Routines

*aIn,
*bIn

// IN: compare value// IN: compare value{
if(aIn->size != bIn->size)
return FALSE;
return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size);}

9.12.3.6

MemorySet()

This function will set all the octets in the specified memory range to the specified octet value.
NOTE:

71
72
73
74
75
76
77
78
79

A previous version had an additional parameter (dSize) that was intended to make sure that the destination
would not be overrun. The problem is that, in use, all that was happening was that the value of size was used
for dSize so there was no benefit in the extra parameter.

void
MemorySet(
void
int
size_t)*dest,
value,
size{
memset(dest, value, size);}

9.12.3.7

MemoryPad2B()

Function to pad a TPM2B with zeros and adjust the size.
80
81
82
83
84
85
86
87
88

void
MemoryPad2B(
TPM2B
UINT16)*b,
newSize{
MemorySet(&b->buffer[b->size], 0, newSize - b->size);b->size = newSize;}

9.12.3.8

Uint16ToByteArray()

Function to write an integer to a byte array
89
90
91
92
93
94
95
96
97

void
Uint16ToByteArray(
UINT16
BYTE
)

i,
*a

{
a[1] = (BYTE)(i); i >>= 8;a[0] = (BYTE)(i);}9.12.3.9

Uint32ToByteArray()

Function to write an integer to a byte array
98

void

Page 442
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

99
100
101
102
103
104
105
106
107
108

Trusted Platform Module Library

Uint32ToByteArray(
UINT32
BYTE
)

i,
*a

{
a[3] = (BYTE)(i); i >>= 8;a[2] = (BYTE)(i); i >>= 8;
a[1] = (BYTE)(i); i >>= 8;a[0] = (BYTE)(i);}9.12.3.10 Uint64ToByteArray()
Function to write an integer to a byte array
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

void
Uint64ToByteArray(
UINT64
BYTE
)

i,
*a

{
a[7] = (BYTE)(i); i >>= 8;a[6] = (BYTE)(i); i >>= 8;a[5] = (BYTE)(i); i >>= 8;
a[4] = (BYTE)(i); i >>= 8;a[3] = (BYTE)(i); i >>= 8;a[2] = (BYTE)(i); i >>= 8;
a[1] = (BYTE)(i); i >>= 8;a[0] = (BYTE)(i);}9.12.3.11 ByteArrayToUint8()
Function to write a UINT8 to a byte array. This is included for completeness and to allow certain macro
expansions
124
125
126
127
128
129
130

UINT8
ByteArrayToUint8(
BYTE

*a

)
{
return*a;}

9.12.3.12 ByteArrayToUint16()
Function to write an integer to a byte array
131
132
133
134
135
136
137

UINT16
ByteArrayToUint16(
BYTE

*a

)
{
return ((UINT16)a[0] << 8) + a[1];}9.12.3.13 ByteArrayToUint32()
Function to write an integer to a byte array
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 443
April 15, 2019

Trusted Platform Module Library

138
139
140
141
142
143
144

Part 4: Supporting RoutinesUINT32
ByteArrayToUint32(
BYTE

*a

)
{
return (UINT32)((((((UINT32)a[0] << 8) + a[1]) << 8) + (UINT32)a[2]) << 8) + a[3];}9.12.3.14 ByteArrayToUint64()
Function to write an integer to a byte array
145
146
147
148
149
150
151

UINT64
ByteArrayToUint64(
BYTE
)

*a

{
return (((UINT64)BYTE_ARRAY_TO_UINT32(a)) << 32) + BYTE_ARRAY_TO_UINT32(&a[4]);}Page 444
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.13

Trusted Platform Module LibraryPower.c9.13.1

Description

This file contains functions that receive the simulated power state transitions of the TPM.
9.13.2
1
2Includes and Data Definitions#define POWER_C#include "Tpm.h"

9.13.3Functions9.13.3.1

TPMInit()This function is used to process a power on event.
3
4
5
6
7
8
9
10
11

void
TPMInit(void){// Set state as not initialized. This means that Startup is required
g_initialized = FALSE;
return;}9.13.3.2

TPMRegisterStartup()This function registers the fact that the TPM has been initialized (a TPM2_Startup() has completed
successfully).
12
13
14
15
16
17
18
19

BOOL
TPMRegisterStartup(void){
g_initialized = TRUE;
return TRUE;}

9.13.3.3

TPMIsStarted()

Indicates if the TPM has been initialized (a TPM2_Startup() has completed successfully after a_TPM_Init()).

20
21
22
23
24

Return Value

Meaning

TRUE(1)

TPM has been initialized

FALSE(0)TPM has not been initialized

BOOL
TPMIsStarted(
void
)
{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 445
April 15, 2019

Trusted Platform Module Library
25
26

Part 4: Supporting Routines

return g_initialized;}

Page 446
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.14

PropertyCap.c

9.14.1

Description

Trusted Platform Module LibraryThis file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values.
9.14.2
1

Includes#include "Tpm.h"

9.14.39.14.3.1

Functions
TPMPropertyIsDefined()

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.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Return Value

Meaning

TRUE(1)

referenced property exists and value set

FALSE(0)referenced property does not exist

static BOOL
TPMPropertyIsDefined(
TPM_PTUINT32)

property,*value// IN: property// OUT: property value{
switch(property){case TPM_PT_FAMILY_INDICATOR:// from the title page of the specification// For this specification, the value is "2.0".
*value = TPM_SPEC_FAMILY;
break;
case TPM_PT_LEVEL:// from the title page of the specification*value = TPM_SPEC_LEVEL;
break;
case TPM_PT_REVISION:// from the title page of the specification*value = TPM_SPEC_VERSION;
break;
case TPM_PT_DAY_OF_YEAR:// computed from the date value on the title page of the specification*value = TPM_SPEC_DAY_OF_YEAR;
break;
case TPM_PT_YEAR:// from the title page of the specification*value = TPM_SPEC_YEAR;
break;
case TPM_PT_MANUFACTURER:// vendor ID unique to each TPM manufacturer*value = BYTE_ARRAY_TO_UINT32(MANUFACTURER);
break;
case TPM_PT_VENDOR_STRING_1:// first four characters of the vendor ID string*value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 447
April 15, 2019

Trusted Platform Module Library
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

Part 4: Supporting Routines

break;
case TPM_PT_VENDOR_STRING_2:// second four characters of the vendor ID string#ifdef VENDOR_STRING_2*value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2);#else*value = 0;
#endifbreak;
case TPM_PT_VENDOR_STRING_3:// third four characters of the vendor ID string#ifdef VENDOR_STRING_3*value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3);#else*value = 0;
#endifbreak;
case TPM_PT_VENDOR_STRING_4:// fourth four characters of the vendor ID string#ifdef VENDOR_STRING_4*value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4);#else*value = 0;
#endifbreak;
case TPM_PT_VENDOR_TPM_TYPE:// vendor-defined value indicating the TPM model*value = 1;
break;
case TPM_PT_FIRMWARE_VERSION_1:// more significant 32-bits of a vendor-specific value*value = gp.firmwareV1;
break;
case TPM_PT_FIRMWARE_VERSION_2:// less significant 32-bits of a vendor-specific value*value = gp.firmwareV2;
break;
case TPM_PT_INPUT_BUFFER:// maximum size of TPM2B_MAX_BUFFER*value = MAX_DIGEST_BUFFER;
break;
case TPM_PT_HR_TRANSIENT_MIN:// minimum number of transient objects that can be held in TPM// RAM*value = MAX_LOADED_OBJECTS;
break;
case TPM_PT_HR_PERSISTENT_MIN:// minimum number of persistent objects that can be held in// TPM NV memory// In this implementation, there is no minimum number of// persistent objects.
*value = MIN_EVICT_OBJECTS;
break;
case TPM_PT_HR_LOADED_MIN:// minimum number of authorization sessions that can be held in// TPM RAM*value = MAX_LOADED_SESSIONS;
break;
case TPM_PT_ACTIVE_SESSIONS_MAX:// number of authorization sessions that may be active at a time*value = MAX_ACTIVE_SESSIONS;
break;
case TPM_PT_PCR_COUNT:// number of PCR implemented*value = IMPLEMENTATION_PCR;
break;

Page 448
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

Trusted Platform Module Librarycase TPM_PT_PCR_SELECT_MIN:// minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect*value = PCR_SELECT_MIN;
break;
case TPM_PT_CONTEXT_GAP_MAX:// maximum allowed difference (unsigned) between the contextID// values of two saved session contexts*value = ((UINT32)1 << (sizeof(CONTEXT_SLOT) * 8)) - 1;
break;
case TPM_PT_NV_COUNTERS_MAX:// maximum number of NV indexes that are allowed to have the// TPMA_NV_COUNTER attribute SET// In this implementation, there is no limitation on the number// of counters, except for the size of the NV Index memory.
*value = 0;
break;
case TPM_PT_NV_INDEX_MAX:// maximum size of an NV index data area*value = MAX_NV_INDEX_SIZE;
break;
case TPM_PT_MEMORY:// a TPMA_MEMORY indicating the memory management method for the TPM
{
union
{
TPMA_MEMORY
att;
UINT32u32;} attributes = {{0}};SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, sharedNV);
SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, objectCopiedToRam);// Note: For a LSb0 machine, the bits in a bit field are in the correct// order even if the machine is MSB0. For a MSb0 machine, a TPMA will// be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will// be NO) so the bits are manipulate correctly.
*value = attributes.u32;
break;}
case TPM_PT_CLOCK_UPDATE:// interval, in seconds, between updates to the copy of// TPMS_TIME_INFO .clock in NV*value = (1 << NV_CLOCK_UPDATE_INTERVAL);
break;
case TPM_PT_CONTEXT_HASH:// algorithm used for the integrity hash on saved contexts and// for digesting the fuData of TPM2_FirmwareRead()*value = CONTEXT_INTEGRITY_HASH_ALG;
break;
case TPM_PT_CONTEXT_SYM:// algorithm used for encryption of saved contexts*value = CONTEXT_ENCRYPT_ALG;
break;
case TPM_PT_CONTEXT_SYM_SIZE:// size of the key used for encryption of saved contexts*value = CONTEXT_ENCRYPT_KEY_BITS;
break;
case TPM_PT_ORDERLY_COUNT:// maximum difference between the volatile and non-volatile// versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET*value = MAX_ORDERLY_COUNT;
break;
case TPM_PT_MAX_COMMAND_SIZE:// maximum value for 'commandSize'*value = MAX_COMMAND_SIZE;
break;
case TPM_PT_MAX_RESPONSE_SIZE:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 449
April 15, 2019

Trusted Platform Module Library
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

Part 4: Supporting Routines// maximum value for 'responseSize'*value = MAX_RESPONSE_SIZE;
break;
case TPM_PT_MAX_DIGEST:// maximum size of a digest that can be produced by the TPM*value = sizeof(TPMU_HA);
break;
case TPM_PT_MAX_OBJECT_CONTEXT:// Header has 'sequence', 'handle' and 'hierarchy'#define SIZE_OF_CONTEXT_HEADER\
sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY)#define SIZE_OF_CONTEXT_INTEGRITY (sizeof(UINT16) + CONTEXT_INTEGRITY_HASH_SIZE)#define SIZE_OF_FINGERPRINT
sizeof(UINT64)#define SIZE_OF_CONTEXT_BLOB_OVERHEAD\(sizeof(UINT16) + SIZE_OF_CONTEXT_INTEGRITY + SIZE_OF_FINGERPRINT)#define SIZE_OF_CONTEXT_OVERHEAD\(SIZE_OF_CONTEXT_HEADER + SIZE_OF_CONTEXT_BLOB_OVERHEAD)#if 0// maximum size of a TPMS_CONTEXT that will be returned by// TPM2_ContextSave for object context*value = 0;// adding sequence, saved handle and hierarchy*value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +sizeof(TPMI_RH_HIERARCHY);// add size field in TPM2B_CONTEXT*value += sizeof(UINT16);// add integrity hash size
*value += sizeof(UINT16) +CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);// Add fingerprint size, which is the same as sequence size
*value += sizeof(UINT64);// Add OBJECT structure size
*value += sizeof(OBJECT);#else// the maximum size of a TPMS_CONTEXT that will be returned by// TPM2_ContextSave for object context*value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(OBJECT);#endifbreak;
case TPM_PT_MAX_SESSION_CONTEXT:#if 0// the maximum size of a TPMS_CONTEXT that will be returned by// TPM2_ContextSave for object context*value = 0;// adding sequence, saved handle and hierarchy*value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +sizeof(TPMI_RH_HIERARCHY);// Add size field in TPM2B_CONTEXT*value += sizeof(UINT16);// Add integrity hash size
*value += sizeof(UINT16) +CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);// Add fingerprint size, which is the same as sequence size
*value += sizeof(UINT64);// Add SESSION structure size
*value += sizeof(SESSION);#else// the maximum size of a TPMS_CONTEXT that will be returned by// TPM2_ContextSave for object context*value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(SESSION);#endifbreak;
case TPM_PT_PS_FAMILY_INDICATOR:// platform specific values for the TPM_PT_PS parameters from// the relevant platform-specific specification

Page 450
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

#if

Trusted Platform Module Library// In this reference implementation, all of these values are 0.
*value = PLATFORM_FAMILY;
break;
case TPM_PT_PS_LEVEL:// level of the platform-specific specification*value = PLATFORM_LEVEL;
break;
case TPM_PT_PS_REVISION:// specification Revision times 100 for the platform-specific// specification*value = PLATFORM_VERSION;
break;
case TPM_PT_PS_DAY_OF_YEAR:// platform-specific specification day of year using TCG calendar*value = PLATFORM_DAY_OF_YEAR;
break;
case TPM_PT_PS_YEAR:// platform-specific specification year using the CE*value = PLATFORM_YEAR;
break;
case TPM_PT_SPLIT_MAX:// number of split signing operations supported by the TPM*value = 0;
ALG_ECC*value = sizeof(gr.commitArray) * 8;#endifbreak;
case TPM_PT_TOTAL_COMMANDS:// total number of commands implemented in the TPM// Since the reference implementation does not have any// vendor-defined commands, this will be the same as the// number of library commands.
{#if COMPRESSED_LISTS(*value) = COMMAND_COUNT;#else
COMMAND_INDEX
commandIndex;*value = 0;// scan all implemented commandsfor(commandIndex = GetClosestCommandIndex(0);commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
commandIndex = GetNextCommandIndex(commandIndex)){(*value)++;// count of all implemented}#endifbreak;}
case TPM_PT_LIBRARY_COMMANDS:// number of commands from the TPM library that are implemented{#if COMPRESSED_LISTS*value = LIBRARY_COMMAND_ARRAY_SIZE;#else
COMMAND_INDEX
commandIndex;*value = 0;// scan all implemented commandsfor(commandIndex = GetClosestCommandIndex(0);commandIndex < LIBRARY_COMMAND_ARRAY_SIZE;
commandIndex = GetNextCommandIndex(commandIndex)){(*value)++;}#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 451
April 15, 2019

Trusted Platform Module Library
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367

Part 4: Supporting Routines

break;}
case TPM_PT_VENDOR_COMMANDS:// number of vendor commands that are implemented*value = VENDOR_COMMAND_ARRAY_SIZE;
break;
case TPM_PT_NV_BUFFER_MAX:// Maximum data size in an NV write command*value = MAX_NV_BUFFER_SIZE;
break;
case TPM_PT_MODES:#if FIPS_COMPLIANT*value = 1;
#else
*value = 0;
#endifbreak;
case TPM_PT_MAX_CAP_BUFFER:*value = MAX_CAP_BUFFER;
break;// Start of variable commands
case TPM_PT_PERMANENT:// TPMA_PERMANENT{
union {
TPMA_PERMANENT
attr;
UINT32u32;} flags = {{0}};if(gp.ownerAuth.t.size != 0)
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, ownerAuthSet);
if(gp.endorsementAuth.t.size != 0)
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, endorsementAuthSet);
if(gp.lockoutAuth.t.size != 0)
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, lockoutAuthSet);
if(gp.disableClear)
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, disableClear);if(gp.failedTries >= gp.maxTries)
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, inLockout);// In this implementation, EPS is always generated by TPM
SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, tpmGeneratedEPS);// Note: For a LSb0 machine, the bits in a bit field are in the correct// order even if the machine is MSB0. For a MSb0 machine, a TPMA will// be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will// be NO) so the bits are manipulate correctly.
*value = flags.u32;
break;}
case TPM_PT_STARTUP_CLEAR:// TPMA_STARTUP_CLEAR{
union {
TPMA_STARTUP_CLEARUINT32} flags = {{0}};

attr;
u32;

//
if(g_phEnable)
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnable);
if(gc.shEnable)
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, shEnable);
if(gc.ehEnable)
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, ehEnable);
if(gc.phEnableNV)
SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnableNV);
if(g_prevOrderlyState != SU_NONE_VALUE)

Page 452
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

Trusted Platform Module Library

SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, orderly);// Note: For a LSb0 machine, the bits in a bit field are in the correct// order even if the machine is MSB0. For a MSb0 machine, a TPMA will// be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will// be NO) so the bits are manipulate correctly.
*value = flags.u32;
break;#if}case TPM_PT_HR_NV_INDEX:// number of NV indexes currently defined*value = NvCapGetIndexNumber();break;
case TPM_PT_HR_LOADED:// number of authorization sessions currently loaded into TPM// RAM*value = SessionCapGetLoadedNumber();break;
case TPM_PT_HR_LOADED_AVAIL:// number of additional authorization sessions, of any type,// that could be loaded into TPM RAM*value = SessionCapGetLoadedAvail();break;
case TPM_PT_HR_ACTIVE:// number of active authorization sessions currently being// tracked by the TPM*value = SessionCapGetActiveNumber();break;
case TPM_PT_HR_ACTIVE_AVAIL:// number of additional authorization sessions, of any type,// that could be created*value = SessionCapGetActiveAvail();break;
case TPM_PT_HR_TRANSIENT_AVAIL:// estimate of the number of additional transient objects that// could be loaded into TPM RAM*value = ObjectCapGetTransientAvail();break;
case TPM_PT_HR_PERSISTENT:// number of persistent objects currently loaded into TPM// NV memory*value = NvCapGetPersistentNumber();break;
case TPM_PT_HR_PERSISTENT_AVAIL:// number of additional persistent objects that could be loaded// into NV memory*value = NvCapGetPersistentAvail();break;
case TPM_PT_NV_COUNTERS:// number of defined NV indexes that have NV TPMA_NV_COUNTER// attribute SET*value = NvCapGetCounterNumber();break;
case TPM_PT_NV_COUNTERS_AVAIL:// number of additional NV indexes that can be defined with their// TPMA_NV_COUNTER attribute SET*value = NvCapGetCounterAvail();break;
case TPM_PT_ALGORITHM_SET:// region code for the TPM*value = gp.algorithmSet;
break;
case TPM_PT_LOADED_CURVES:
ALG_ECC// number of loaded ECC curves*value = ECC_CURVE_COUNT;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 453
April 15, 2019

Trusted Platform Module Library
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

Part 4: Supporting Routines#else // ALG_ECC*value = 0;
#endif // ALG_ECC
break;
case TPM_PT_LOCKOUT_COUNTER:// current value of the lockout counter*value = gp.failedTries;
break;
case TPM_PT_MAX_AUTH_FAIL:// number of authorization failures before DA lockout is invoked*value = gp.maxTries;
break;
case TPM_PT_LOCKOUT_INTERVAL:// number of seconds before the value reported by// TPM_PT_LOCKOUT_COUNTER is decremented*value = gp.recoveryTime;
break;
case TPM_PT_LOCKOUT_RECOVERY:// number of seconds after a lockoutAuth failure before use of// lockoutAuth may be attempted again*value = gp.lockoutRecovery;
break;
case TPM_PT_NV_WRITE_RECOVERY:// number of milliseconds before the TPM will accept another command// that will modify NV.
// This should make a call to the platform code that is doing rate// limiting of NV. Rate limiting is not implemented in the reference// code so no call is made.
*value = 0;
break;
case TPM_PT_AUDIT_COUNTER_0:// high-order 32 bits of the command audit counter*value = (UINT32)(gp.auditCounter >> 32);
break;
case TPM_PT_AUDIT_COUNTER_1:// low-order 32 bits of the command audit counter*value = (UINT32)(gp.auditCounter);break;
default:// property is not defined
return FALSE;
break;}
return TRUE;}

9.14.3.2

TPMCapGetProperties()

This function is used to get the TPM_PT values. The search of properties will start at property andcontinue 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.

479
480
481
482
483
484

Return Value

Meaning

YES

more properties are available

NOno more properties to be reported

TPMI_YES_NO
TPMCapGetProperties(
TPM_PTUINT32

property,
count,TPML_TAGGED_TPM_PROPERTY*propertyList

Page 454
April 15, 2019// IN: the starting TPM property// IN: maximum number of returned//
properties// OUT: property list

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535

Trusted Platform Module Library){
TPMI_YES_NOUINT32
UINT32more = NO;i;nextGroup;// initialize output property list
propertyList->count = 0;// maximum count of properties we may return is MAX_PCR_PROPERTIES
if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES;// if property is less than PT_FIXED, start from PT_FIXED
if(property < PT_FIXED)
property = PT_FIXED;// There is only the fixed and variable groups with the variable group coming// lastif(property >= (PT_VAR + PT_GROUP))
return more;// Don't read past the end of the selected groupnextGroup = ((property / PT_GROUP) * PT_GROUP) + PT_GROUP;// Scan through the TPM properties of the requested group.
for(i = property; i < nextGroup; i++){UINT32
value;// if we have hit the end of the group, quit
if(i != property && ((i % PT_GROUP) == 0))
break;
if(TPMPropertyIsDefined((TPM_PT)i, &value)){if(propertyList->count < count){// If the list is not full, add this property
propertyList->tpmProperty[propertyList->count].property =(TPM_PT)i;
propertyList->tpmProperty[propertyList->count].value = value;
propertyList->count++;}else{// If the return list is full but there are more properties// available, set the indication and exit the loop.
more = YES;
break;}}}
return more;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 455
April 15, 2019

Trusted Platform Module Library

9.15

Part 4: Supporting Routines

Response.c

9.15.1

Description

This file contains the common code for building a response header, including setting the size of thestructure. command may be NULL if result is not TPM_RC_SUCCESS.
9.15.2
1

Includes and Defines#include "Tpm.h"

9.15.3

BuildResponseHeader()Adds the response header to the response. It will update command->parameterSize to indicate the total
size of the response.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

void
BuildResponseHeader(
COMMAND
BYTE
TPM_RC)*command,*buffer,
result

TPM_STUINT32tag;size;// IN: main control structure// OUT: the output buffer// IN: the response code{

if(result != TPM_RC_SUCCESS){
tag = TPM_ST_NO_SESSIONS;
size = 10;}
else{
tag = command->tag;// Compute the overall size of the response
size = STD_RESPONSE_HEADER + command->handleNum * sizeof(TPM_HANDLE);
size += command->parameterSize;
size += (command->tag == TPM_ST_SESSIONS) ?
command->authSize + sizeof(UINT32) : 0;}
TPM_ST_Marshal(&tag, &buffer, NULL);UINT32_Marshal(&size, &buffer, NULL);TPM_RC_Marshal(&result, &buffer, NULL);
if(result == TPM_RC_SUCCESS){
if(command->handleNum > 0)
TPM_HANDLE_Marshal(&command->handles[0], &buffer, NULL);
if(tag == TPM_ST_SESSIONS)UINT32_Marshal((UINT32 *)&command->parameterSize, &buffer, NULL);}
command->parameterSize = size;}

Page 456
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

9.16

Trusted Platform Module Library

ResponseCodeProcessing.c

9.16.1

Description

This file contains the miscellaneous functions for processing response codes.
NOTE:

9.16.2
1

Currently, there is only one.

Includes and Defines#include "Tpm.h"

9.16.3

RcSafeAddToResult()

Adds a modifier to a response code as long as the response code allows a modifier and no modifier has
already been added.
2
3
4
5
6
7
8
9
10
11
12

TPM_RCRcSafeAddToResult(
TPM_RCTPM_RC)

responseCode,modifier{if((responseCode & RC_FMT1) && !(responseCode & 0xf40))
return responseCode + modifier;else
return responseCode;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 457
April 15, 2019

Trusted Platform Module Library

9.17
9.17.1
1
2
3

Part 4: Supporting Routines

TpmFail.c
Includes, Defines, and Types#define#include#include

TPM_FAIL_C"Tpm.h"<assert.h>

On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of the
TpmTypes.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 thestructures in TpmTypes.h and only include it for the #defines of the capabilities, properties, and commandcode values.
4#include "TpmTypes.h"

9.17.2

Typedefs

These defines are used primarily for sizing of the local response buffer.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

typedef struct{
TPM_STtag;
UINT32size;
TPM_RC
code;} HEADER;
typedef struct{
BYTE
tag[sizeof(TPM_ST)];
BYTE
size[sizeof(UINT32)];
BYTE
code[sizeof(TPM_RC)];} PACKED_HEADER;
typedef struct{
BYTE
size[sizeof(UINT16)];
struct{BYTE
function[sizeof(UINT32)];
BYTE
line[sizeof(UINT32)];
BYTE
code[sizeof(UINT32)];} values;
BYTE
returnCode[sizeof(TPM_RC)];} GET_TEST_RESULT_PARAMETERS;
typedef struct{
BYTE
moreData[sizeof(TPMI_YES_NO)];
BYTE
capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES
BYTE
tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)];} GET_CAPABILITY_PARAMETERS;
typedef struct{
BYTE
header[sizeof(PACKED_HEADER)];
BYTE
getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)];} TEST_RESPONSE;
typedef struct{
BYTE
header[sizeof(PACKED_HEADER)];
BYTE
getCap[sizeof(GET_CAPABILITY_PARAMETERS)];} CAPABILITY_RESPONSE;
typedef union{

Page 458
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
46
47
48

BYTE
BYTE
} RESPONSES;

Trusted Platform Module Library

test[sizeof(TEST_RESPONSE)];cap[sizeof(CAPABILITY_RESPONSE)];

Buffer to hold the responses. This may be a little larger than required due to padding that a compiler
might add.
NOTE:

49
50
51

This is not in Global.c because of the specialized data definitions above. Since the data contained in thisstructure is not relevant outside of the execution of a single command (when the TPM is in failure mode. Thereis no compelling reason to move all the typedefs to Global.h and this structure to Global.c.

#ifndef __IGNORE_STATE__ // Don't define this value
static BYTE response[sizeof(RESPONSES)];#endif9.17.39.17.3.1

Local Functions
MarshalUint16()

Function to marshal a 16 bit value to the output buffer.
52
53
54
55
56
57
58
59
60
61

static INT32
MarshalUint16(
UINT16
BYTE)

integer,**buffer{
UINT16_TO_BYTE_ARRAY(integer, *buffer);*buffer += 2;
return 2;}

9.17.3.2

MarshalUint32()

Function to marshal a 32 bit value to the output buffer.
62
63
64
65
66
67
68
69
70
71

static INT32
MarshalUint32(
UINT32BYTE){
UINT32_TO_BYTE_ARRAY(integer, *buffer);*buffer += 4;
return 4;}

9.17.3.3
72
73
74
75
76
77
78
79
80
81
82

integer,**buffer

Unmarshal32()

static BOOL Unmarshal32(
UINT32*target,
BYTE**buffer,
INT32
*size
)
{
if((*size -= 4) < 0)return FALSE;*target = BYTE_ARRAY_TO_UINT32(*buffer);*buffer += 4;
return TRUE;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 459
April 15, 2019

Trusted Platform Module Library83}

9.17.3.4
84
85
86
87
88
89
90
91
92
93
94
95

Part 4: Supporting Routines

Unmarshal16()

static BOOL Unmarshal16(
UINT16*target,
BYTE**buffer,
INT32
*size
)
{
if((*size -= 2) < 0)return FALSE;*target = BYTE_ARRAY_TO_UINT16(*buffer);*buffer += 2;
return TRUE;}

9.17.4

Public Functions

9.17.4.1

SetForceFailureMode()This function is called by the simulator to enable failure mode testing.
96
97
98
99
100
101
102
103
104
105

#if SIMULATION

LIB_EXPORT void
SetForceFailureMode(void){
g_forceFailureMode = TRUE;
return;}#endif9.17.4.2

TpmLogFailure()

This function saves the failure values when the code will continue to operate. It if similar to TpmFail() but
returns to the caller. The assumption is that the caller will propagate a failure back up the stack.
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

void
TpmLogFailure(#if FAIL_TRACE
const char*function,
int
line,
#endifint
code){// Save the values that indicate where the error occurred.
// On a 64-bit machine, this may truncate the address of the string// of the function name where the error occurred.
#if FAIL_TRACE
s_failFunction = (UINT32)function;s_failLine = line;#else
s_failFunction = 0;s_failLine = 0;
#endifs_failCode = code;// We are in failure mode

Page 460
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
128
129
130
131

Trusted Platform Module Libraryg_inFailureMode = TRUE;
return;}9.17.4.3

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().
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

NORETURN void
TpmFail(#if FAIL_TRACE
const char*function,
int
line,
#endifint
code){// Save the values that indicate where the error occurred.
// On a 64-bit machine, this may truncate the address of the string// of the function name where the error occurred.
#if FAIL_TRACE
s_failFunction = (UINT32)function;s_failLine = line;#else
s_failFunction = (UINT32)NULL;
s_failLine = 0;
#endifs_failCode = code;// We are in failure mode
g_inFailureMode = TRUE;// if asserts are enabled, then do an assert unless the failure mode code// is being tested.
#if SIMULATION#
ifndef NDEBUG
assert(g_forceFailureMode);#
endif// Clear this flag
g_forceFailureMode = FALSE;#endif// Jump to the failure mode code.
// Note: only get here if asserts are off or if we are testing failure mode
_plat__Fail();}

9.17.4.4

TpmFailureMode

This function is called by the interface code when the platform is in failure mode.
169
170
171
172
173
174
175
176
177
178
179

void
TpmFailureMode(
unsigned int
unsigned char
unsigned int
unsigned char)inRequestSize,*inRequest,*outResponseSize,**outResponse// IN: command buffer size// IN: command buffer// OUT: response buffer size// OUT: response buffer

UINT32
UINT32HEADER

marshalSize;capability;
header;// unmarshaled command header{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 461
April 15, 2019

Trusted Platform Module Library
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

UINT32
UINT32UINT8
INT32Part 4: Supporting Routinespt;// unmarshaled property type
count; // unmarshaled property count*buffer = inRequest;
size = inRequestSize;// If there is no command buffer, then just return TPM_RC_FAILURE
if(inRequestSize == 0 || inRequest == NULL)
goto FailureModeReturn;// If the header is not correct for TPM2_GetCapability() or// TPM2_GetTestResult() then just return the in failure mode response;
if(! (Unmarshal16(&header.tag, &buffer, &size)&& Unmarshal32(&header.size, &buffer, &size)&& Unmarshal32(&header.code, &buffer, &size)))goto FailureModeReturn;if(header.tag != TPM_ST_NO_SESSIONS|| header.size < 10)goto FailureModeReturn;switch(header.code){
case TPM_CC_GetTestResult:// make sure that the command size is correctif(header.size != 10)
goto FailureModeReturn;buffer = &response[10];marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer);
marshalSize += MarshalUint32(s_failFunction, &buffer);
marshalSize += MarshalUint32(s_failLine, &buffer);
marshalSize += MarshalUint32(s_failCode, &buffer);
if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer);else
marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);
break;
case TPM_CC_GetCapability:// make sure that the size of the command is exactly the size// returned for the capability, property, and countif(header.size != (10 + (3 * sizeof(UINT32)))// also verify that this is requesting TPM properties|| !Unmarshal32(&capability, &buffer, &size)|| capability != TPM_CAP_TPM_PROPERTIES|| !Unmarshal32(&pt, &buffer, &size)|| !Unmarshal32(&count, &buffer, &size))goto FailureModeReturn;// If in failure mode because of an unrecoverable read error, and the// property is 0 and the count is 0, then this is an indication to// re-manufacture the TPM. Do the re-manufacture but stay in failure// mode until the TPM is reset.
// Note: this behavior is not required by the specification and it is// OK to leave the TPM permanently bricked due to an unrecoverable NV// error.
if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE){g_manufactured = FALSE;
TPM_Manufacture(0);}if(count > 0)
count = 1;
else if(pt > TPM_PT_FIRMWARE_VERSION_2)
count = 0;if(pt < TPM_PT_MANUFACTURER)
pt = TPM_PT_MANUFACTURER;// set up for returnbuffer = &response[10];// if the request was for a PT less than the last one// then we indicate more, otherwise, not.
if(pt < TPM_PT_FIRMWARE_VERSION_2)

Page 462
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

Trusted Platform Module Library*buffer++ = YES;
else
*buffer++ = NO;marshalSize = 1;// indicate the capability type
marshalSize += MarshalUint32(capability, &buffer);// indicate the number of values that are being returned (0 or 1)
marshalSize += MarshalUint32(count, &buffer);// indicate the property
marshalSize += MarshalUint32(pt, &buffer);#ifdefif(count > 0)
switch(pt){case TPM_PT_MANUFACTURER:// the vendor ID unique to each TPM manufacturer
MANUFACTURER
pt = *(UINT32*)MANUFACTURER;#else
pt = 0;#endif#ifdefbreak;
case TPM_PT_VENDOR_STRING_1:// the first four characters of the vendor ID string
VENDOR_STRING_1
pt = *(UINT32*)VENDOR_STRING_1;#else
pt = 0;#endif#ifdefbreak;
case TPM_PT_VENDOR_STRING_2:// the second four characters of the vendor ID string
VENDOR_STRING_2
pt = *(UINT32*)VENDOR_STRING_2;#else
pt = 0;#endif#ifdefbreak;
case TPM_PT_VENDOR_STRING_3:// the third four characters of the vendor ID string
VENDOR_STRING_3
pt = *(UINT32*)VENDOR_STRING_3;#else
pt = 0;#endif#ifdefbreak;
case TPM_PT_VENDOR_STRING_4:// the fourth four characters of the vendor ID string
VENDOR_STRING_4
pt = *(UINT32*)VENDOR_STRING_4;#else
pt = 0;#endifbreak;
case TPM_PT_VENDOR_TPM_TYPE:// vendor-defined value indicating the TPM model// We just make up a number here
pt = 1;break;
case TPM_PT_FIRMWARE_VERSION_1:// the more significant 32-bits of a vendor-specific value// indicating the version of the firmware#ifdef

FIRMWARE_V1
pt = FIRMWARE_V1;#else

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 463
April 15, 2019

Trusted Platform Module Library
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

Part 4: Supporting Routines

pt = 0;#endifbreak;
default: // TPM_PT_FIRMWARE_VERSION_2:// the less significant 32-bits of a vendor-specific value// indicating the version of the firmware#ifdef

FIRMWARE_V2
pt = FIRMWARE_V2;#else
pt = 0;#endifbreak;}
marshalSize += MarshalUint32(pt, &buffer);
break;
default: // default for switch (cc)goto FailureModeReturn;}// Now do the header
buffer = response;
marshalSize = marshalSize + 10; // Add the header size to the// stuff already marshaled
MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag
MarshalUint32(marshalSize, &buffer); // responseSize
MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code
*outResponseSize = marshalSize;*outResponse = (unsigned char *)&response;
return;FailureModeReturn:buffer = response;
marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer);
marshalSize += MarshalUint32(10, &buffer);
marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);*outResponseSize = marshalSize;*outResponse = (unsigned char *)response;
return;}9.17.4.5

UnmarshalFail()This is a stub that is used to catch an attempt to unmarshal an entry that is not defined. Don't ever expect
this to be called but...
350
351
352
353
354
355
356
357
358
359
360
361

void
UnmarshalFail(
void
BYTE
INT32
)

*type,**buffer,*size{
NOT_REFERENCED(type);
NOT_REFERENCED(buffer);
NOT_REFERENCED(size);
FAIL(FATAL_ERROR_INTERNAL);}

Page 464
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10 Cryptographic Functions
10.1

Headers

10.1.110.1.1.1

BnValues.h
Introduction

This file contains the definitions needed for defining the internal BIGNUM structure. A BIGNUM is apointer to a structure. The structure has three fields. The last field is and array (d) of crypt_uword_t. Eachword is in machine format (big- or little-endian) with the words in ascending significance (i.e. words inlittle-endian order). This is the order that seems to be used in every big number library in the worlds, so...
The first field in the structure (allocated) is the number of words in d. This is the upper limit on the size ofthe number that can be held in the structure. This differs from libraries like OpenSSL as this is notintended to deal with numbers of arbitrary size; just numbers that are needed to deal with the algorithms
that are defined in the TPM implementation.
The second field in the structure (size) is the number of significant words in n. When this number is zero,
the number is zero. The word at used-1 should never be zero. All words between d[size] and d[allocated1] should be zero.
10.1.1.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Defines#ifndef _BN_NUMBERS_H#define _BN_NUMBERS_H#if RADIX_BITS == 64# define RADIX_LOG2
6#elif RADIX_BITS == 32#define RADIX_LOG2
5#else# error "Unsupported radix"#endif#define RADIX_MOD(x)((x) & ((1 << RADIX_LOG2) - 1))#define RADIX_DIV(x)((x) >> RADIX_LOG2)#define RADIX_MASK ((((crypt_uword_t)1) << RADIX_LOG2) - 1)
#define BITS_TO_CRYPT_WORDS(bits)
RADIX_DIV((bits) + (RADIX_BITS - 1))#define BYTES_TO_CRYPT_WORDS(bytes)
BITS_TO_CRYPT_WORDS(bytes * 8)
#define SIZE_IN_CRYPT_WORDS(thing)BYTES_TO_CRYPT_WORDS(sizeof(thing))#if RADIX_BITS == 64#define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_64(x)typedef uint64_tcrypt_uword_t;
typedef int64_tcrypt_word_t;#
define TO_CRYPT_WORD_64
BIG_ENDIAN_BYTES_TO_UINT64#
define TO_CRYPT_WORD_32(a, b, c, d) TO_CRYPT_WORD_64(0, 0, 0, 0, a, b, c, d)#elif RADIX_BITS == 32#
define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_32((x))
typedef uint32_tcrypt_uword_t;
typedef int32_tcrypt_word_t;#
define TO_CRYPT_WORD_64(a, b, c, d, e, f, g, h)
BIG_ENDIAN_BYTES_TO_UINT32(e, f, g, h),
BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d)#endif#define MAX_CRYPT_UWORD (~((crypt_uword_t)0))#define MAX_CRYPT_WORD ((crypt_word_t)(MAX_CRYPT_UWORD >> 1))#define MIN_CRYPT_WORD (~MAX_CRYPT_WORD)#define LARGEST_NUMBER (MAX((ALG_RSA * MAX_RSA_KEY_BYTES),\
MAX((ALG_ECC * MAX_ECC_KEY_BYTES), MAX_DIGEST_SIZE)))#define LARGEST_NUMBER_BITS (LARGEST_NUMBER * 8)
#define MAX_ECC_PARAMETER_BYTES (MAX_ECC_KEY_BYTES * ALG_ECC)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019\\

Page 465
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

These are the basic big number formats. This is convertible to the library- specific format without to muchdifficulty. For the math performed using these numbers, the value is always positive.
37
38
39
40
41
42
43
44
45
46
47

#define BN_STRUCT_DEF(count) struct {crypt_uword_t
allocated;
crypt_uword_t
size;
crypt_uword_td[count];}
typedef BN_STRUCT_DEF(1) bignum_t;#ifndef bigNum
typedef bignum_t*bigNum;typedef const bignum_t *bigConst;#endifextern const bignum_t
BnConstZero;

\
\
\
\

The Functions to access the properties of a big number. Get number of allocated words
48#define BnGetAllocated(x)(unsigned)((x)->allocated)

Get number of words used49

#define BnGetSize(x)((x)->size)

Get a pointer to the data array50#define BnGetArray(x)((crypt_uword_t *)&((x)->d[0]))Get the nth word of a BIGNUM (zero-based)
51#define BnGetWord(x, i)(crypt_uword_t)((x)->d[i])Some things that are done often. Test to see if a bignum_t is equal to zero52

#define BnEqualZero(bn)(BnGetSize(bn) == 0)

Test to see if a bignum_t is equal to a word type
53
54

#define BnEqualWord(bn, word)\((BnGetSize(bn) == 1) && (BnGetWord(bn, 0) == (crypt_uword_t)word))

Determine if a BIGNUM is even. A zero is even. Although the indication that a number is zero is that it's
size is zero, all words of the number are 0 so this test works on zero.
55#define BnIsEven(n)((BnGetWord(n, 0) & 1) == 0)

The macros below are used to define BIGNUM values of the required size. The values are allocated on
the stack so they can be treated like simple local values. This will call the initialization function for adefined bignum_t. This sets the allocated and used fields and clears the words of n.
56
57
58

#define BN_INIT(name)(bigNum)BnInit((bigNum)&(name),
BYTES_TO_CRYPT_WORDS(sizeof(name.d)))\\In some cases, a function will need the address of the structure associated with a variable. The structure
for a BIGNUM variable of name is name_. Generally, when the structure is created, it is initialized and aparameter is created with a pointer to the structure. The pointer has the name and the structure it points
to is name_59
60#define BN_ADDRESS(name) (bigNum)&name##_#define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1)

Page 466
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

Create a structure of the correct size.
61
62#define BN_STRUCT(bits)
BN_STRUCT_DEF(BN_STRUCT_ALLOCATION(bits))\

Define a BIGNUM type with a specific allocation
63
64#define BN_TYPE(name, bits)
typedef BN_STRUCT(bits) bn_##name##_t\This creates a local BIGNUM variable of a specific size and initializes it from a TPM2B input parameter.
65
66
67
68

#define BN_INITIALIZED(name, bits, initializer)\
BN_STRUCT(bits) name##_;\bigNumname = BnFrom2B(BN_INIT(name##_),\(const TPM2B *)initializer)

Create a local variable that can hold a number with bits
69
70
71

#define BN_VAR(name, bits)
BN_STRUCT(bits) _##name;bigNumname = BN_INIT(_##name)\\Create a type that can hold the largest number defined by the implementation.
72
73
74

#define BN_MAX(name)
BN_VAR(name, LARGEST_NUMBER_BITS)#define BN_MAX_INITIALIZED(name, initializer)
BN_INITIALIZED(name, LARGEST_NUMBER_BITS, initializer)\

A word size value is useful75#define BN_WORD(name)

BN_VAR(name, RADIX_BITS)

This is used to created a word-size BIGNUM and initialize it with an input parameter to a function.
76
77
78
79

#define BN_WORD_INITIALIZED(name, initial)\
BN_STRUCT(RADIX_BITS) name##_;\bigNumname = BnInitializeWord((bigNum)&name##_,\
BN_STRUCT_ALLOCATION(RADIX_BITS), initial)

ECC-Specific Values This is the format for a point. It is always in affine format. The Z value is carried aspart of the point, primarily to simplify the interface to the support library. Rather than have the interface
layer have to create space for the point each time it is used... The x, y, and z values are pointers to
bigNum values and not in-line versions of the numbers. This is a relic of the days when there was nostandard TPM format for the numbers
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

typedef struct _bn_point_t{
bigNumx;
bigNumy;bigNumz;} bn_point_t;
typedef bn_point_t*bigPoint;
typedef const bn_point_t*pointConst;
typedef struct constant_point_t{
bigConst
x;
bigConst
y;bigConstz;} constant_point_t;#define ECC_BITS(MAX_ECC_KEY_BYTES * 8)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 467
April 15, 2019

Trusted Platform Module Library
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

Part 4: Supporting Routines

BN_TYPE(ecc, ECC_BITS);#define ECC_NUM(name)
BN_VAR(name, ECC_BITS)#define ECC_INITIALIZED(name, initializer)
BN_INITIALIZED(name, ECC_BITS, initializer)#define POINT_INSTANCE(name, bits)
BN_STRUCT (bits)
name##_x ={BITS_TO_CRYPT_WORDS ( bits ), 0,{0}};BN_STRUCT ( bits )name##_y ={BITS_TO_CRYPT_WORDS ( bits ), 0,{0}};BN_STRUCT ( bits )name##_z ={BITS_TO_CRYPT_WORDS ( bits ), 0,{0}};bn_point_t name##_#define POINT_INITIALIZER(name)
BnInitializePoint(&name##_, (bigNum)&name##_x,(bigNum)&name##_y, (bigNum)&name##_z)#define POINT_INITIALIZED(name, initValue)
POINT_INSTANCE(name, MAX_ECC_KEY_BITS);
bigPoint
name = BnPointFrom2B(
POINT_INITIALIZER(name),
initValue)#define POINT_VAR(name, bits)
POINT_INSTANCE (name, bits);
bigPoint
name = POINT_INITIALIZER(name)#define POINT(name)
POINT_VAR(name, MAX_ECC_KEY_BITS)

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Structure for the curve parameters. This is an analog to the TPMS_ALGORITHM_DETAIL_ECC
119
120
121
122
123
124
125
126
127

typedef struct{
bigConst
bigConst
bigConst
bigConst
bigConst
constant_point_t} ECC_CURVE_DATA;

prime;
order;
h;
a;
b;
base;

// a prime number// the order of the curve// cofactor// linear coefficient// constant term// base point

Access macros for the ECC_CURVE structure. The parameter C is a pointer to an ECC_CURVE_DATA
structure. In some libraries, the curve structure contains a pointer to an ECC_CURVE_DATA structure aswell as some other bits. For those cases, the AccessCurveData() macro is used in the code to first get the
pointer to the ECC_CURVE_DATA for access. In some cases, the macro does noting.
128
129
130
131
132
133
134
135

#define CurveGetPrime(C)((C)->prime)#define CurveGetOrder(C)((C)->order)#define CurveGetCofactor(C) ((C)->h)#define CurveGet_a(C)((C)->a)#define CurveGet_b(C)((C)->b)#define CurveGetG(C)((pointConst)&((C)->base))#define CurveGetGx(C)((C)->base.x)#define CurveGetGy(C)((C)->base.y)

Convert bytes in initializers according to the endianess of the system. This is used for CryptEccData.c.
136
137
138
139
140
141
142
143
144
145
146

#define#define

BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d)(((UINT32)(a) << 24)+((UINT32)(b) << 16)+((UINT32)(c) << 8)+((UINT32)(d)))
BIG_ENDIAN_BYTES_TO_UINT64(a, b, c, d, e, f, g, h)(((UINT64)(a) << 56)+((UINT64)(b) << 48)+((UINT64)(c) << 40)+((UINT64)(d) << 32)

Page 468
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\
\
\
\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
147
148
149
150
151
152
153
154
155
156
157
158
159
160

Trusted Platform Module Library+((UINT64)(e) << 24)+((UINT64)(f) << 16)+((UINT64)(g) << 8)+((UINT64)(h)))#ifndef RADIX_BYTES#
if RADIX_BITS == 32#
define RADIX_BYTES 4#
elif RADIX_BITS == 64#
define RADIX_BYTES 8#
else#
error "RADIX_BITS must either be 32 or 64"#
endif#endif\\\\

Add implementation dependent definitions for other ECC Values and for linkages.
161
162#include LIB_INCLUDE(MATH_LIB, Math)#endif // _BN_NUMBERS_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 469
April 15, 2019

Trusted Platform Module Library

10.1.2

Part 4: Supporting Routines

CryptEcc.h

10.1.2.1

Introduction

This file contains structure definitions used for ECC. The structures in this file are only used internally.
The ECC-related structures that cross the TPM interface are defined in TpmTypes.h
12#ifndef _CRYPT_ECC_H#define _CRYPT_ECC_H

10.1.2.2

Structures

This is used to define the macro that may or may not be in the data set for the curve (BnEccData.c). If
there is a mismatch, the compiler will warn that there is to much/not enough initialization data in the
curve. The macro is used because not all versions of the CryptEccData.c need the curve name.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#ifdef NAMED_CURVES#define CURVE_NAME(a) , a#define CURVE_NAME_DEF const char *name;#else# define CURVE_NAME(a)# define CURVE_NAME_DEF#endiftypedef struct ECC_CURVE{
const TPM_ECC_CURVE
curveId;
const UINT16
keySizeBits;
const TPMT_KDF_SCHEME
kdf;
const TPMT_ECC_SCHEME
sign;
const ECC_CURVE_DATA*curveData; // the address of the curve data
const BYTE*OID;
CURVE_NAME_DEF} ECC_CURVE;
extern const ECC_CURVE eccCurves[ECC_CURVE_COUNT];#endifPage 470
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.1.310.1.3.1

Trusted Platform Module Library

CryptHash.h
Introduction

This header contains the hash structure definitions used in the TPM code to define the amount of space
to be reserved for the hash state. This allows the TPM code to not have to import all of the symbols usedby the hash computations. This lets the build environment of the TPM code not to have include theheader files associated with the CryptoEngine() code.
1
2#ifndef _CRYPT_HASH_H#define _CRYPT_HASH_H

10.1.3.2
3

Hash-related Structuresunion SMAC_STATES;

These definitions add the high-level methods for processing state that may be an SMAC
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

typedef void(* SMAC_DATA_METHOD)(
union SMAC_STATES*state,UINT32
size,
const BYTE
*buffer);
typedef UINT16(* SMAC_END_METHOD)(
union SMAC_STATES*state,UINT32size,
BYTE*buffer);
typedef struct sequenceMethods {SMAC_DATA_METHOD
data;
SMAC_END_METHOD
end;} SMAC_METHODS;#define SMAC_IMPLEMENTED (CC_MAC || CC_MAC_Start)

These definitions are here because the SMAC state is in the union of hash states.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

typedef struct tpmCmacState {TPM_ALG_ID
symAlg;UINT16
keySizeBits;
INT16
bcount; // current count of bytes accumulated in IV
TPM2B_IViv;// IV buffer
TPM2B_SYM_KEY
symKey;} tpmCmacState_t;
typedef union SMAC_STATES {#if ALG_CMAC
tpmCmacState_t
cmac;#endifUINT64pad;} SMAC_STATES;
typedef struct SMAC_STATE {SMAC_METHODS
smacMethods;
SMAC_STATES
state;} SMAC_STATE;
typedef union{#if ALG_SHA1
tpmHashStateSHA1_t
Sha1;#endif#if ALG_SHA256
tpmHashStateSHA256_t
Sha256;#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 471
April 15, 2019

Trusted Platform Module Library
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#if ALG_SHA384
tpmHashStateSHA384_t#endif#if ALG_SHA512
tpmHashStateSHA512_t#endif

Part 4: Supporting Routines

Sha384;
Sha512;// Additions for symmetric block cipher MAC#if SMAC_IMPLEMENTED
SMAC_STATE
smac;#endif// to force structure alignment to be no worse than HASH_ALIGNMENT#if HASH_ALIGNMENT == 4
uint32_talign;#else
uint64_talign;#endif} ANY_HASH_STATE;
typedef ANY_HASH_STATE *PANY_HASH_STATE;
typedef const ANY_HASH_STATE*PCANY_HASH_STATE;#define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b))

MAX_HASH_STATE_SIZE will change with each implementation. It is assumed that a hash state will not
be larger than twice the block size plus some overhead (in this case, 16 bytes). The overall size needs tobe as large as any of the hash contexts. The structure needs to start on an alignment boundary and be aneven multiple of the alignment
65
66
67

#define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16)#define MAX_HASH_STATE_SIZE_ALIGNEDALIGNED_SIZE(MAX_HASH_STATE_SIZE, HASH_ALIGNMENT)\This is an aligned byte array that will hold any of the hash contexts.
68

typedef

ANY_HASH_STATE ALIGNED_HASH_STATE;

The header associated with the hash library is expected to define the methods which include the calling
sequence. When not compiling CryptHash.c, the methods are not defined so we need placeholder
functions for the structures
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

#ifndef HASH_START_METHOD_DEF#
define HASH_START_METHOD_DEF
void (HASH_START_METHOD)(void)#endif#ifndef HASH_DATA_METHOD_DEF#
define HASH_DATA_METHOD_DEF
void (HASH_DATA_METHOD)(void)#endif#ifndef HASH_END_METHOD_DEF#
define HASH_END_METHOD_DEF
void (HASH_END_METHOD)(void)#endif#ifndef HASH_STATE_COPY_METHOD_DEF#
define HASH_STATE_COPY_METHOD_DEF
void (HASH_STATE_COPY_METHOD)(void)#endif#ifndef HASH_STATE_EXPORT_METHOD_DEF#
define HASH_STATE_EXPORT_METHOD_DEF
void (HASH_STATE_EXPORT_METHOD)(void)#endif#ifndef HASH_STATE_IMPORT_METHOD_DEF#
define HASH_STATE_IMPORT_METHOD_DEF
void (HASH_STATE_IMPORT_METHOD)(void)#endifDefine the prototypical function call for each of the methods. This defines the order in which theparameters are passed to the underlying function.
87
88

typedef HASH_START_METHOD_DEF;
typedef HASH_DATA_METHOD_DEF;

Page 472
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

Trusted Platform Module Library

typedef HASH_END_METHOD_DEF;
typedef HASH_STATE_COPY_METHOD_DEF;
typedef HASH_STATE_EXPORT_METHOD_DEF;
typedef HASH_STATE_IMPORT_METHOD_DEF;
typedef struct _HASH_METHODS{HASH_START_METHOD*start;
HASH_DATA_METHOD*data;
HASH_END_METHOD*end;
HASH_STATE_COPY_METHOD*copy;
HASH_STATE_EXPORT_METHOD*copyOut;
HASH_STATE_IMPORT_METHOD*copyIn;// Copy a hash block// Copy a hash block from a hash// context// Copy a hash block to a proper hash// context} HASH_METHODS, *PHASH_METHODS;#if ALG_SHA1
TPM2B_TYPE(SHA1_DIGEST, SHA1_DIGEST_SIZE);#endif#if ALG_SHA256
TPM2B_TYPE(SHA256_DIGEST, SHA256_DIGEST_SIZE);#endif#if ALG_SHA384
TPM2B_TYPE(SHA384_DIGEST, SHA384_DIGEST_SIZE);#endif#if ALG_SHA512
TPM2B_TYPE(SHA512_DIGEST, SHA512_DIGEST_SIZE);#endif#if ALG_SM3_256
TPM2B_TYPE(SM3_256_DIGEST, SM3_256_DIGEST_SIZE);#endifWhen the TPM implements RSA, the hash-dependent OID pointers are part of the HASH_DEF. Thesemacros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE.
119
120
121
122
123
124
125

#if ALG_RSA#define PKCS1_HASH_REF#define PKCS1_OID(NAME)#else#define PKCS1_HASH_REF#define PKCS1_OID(NAME)#endifconst BYTE *PKCS1;, OID_PKCS1_##NAME

When the TPM implements ECC, the hash-dependent OID pointers are part of the HASH_DEF. Thesemacros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE.
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

#if ALG_ECDSA#define ECDSA_HASH_REF
const BYTE *ECDSA;#define ECDSA_OID(NAME) , OID_ECDSA_##NAME#else#define ECDSA_HASH_REF#define ECDSA_OID(NAME)#endiftypedef const struct HASH_DEF{
HASH_METHODS
method;uint16_t
blockSize;
uint16_t
digestSize;
uint16_t
contextSize;
uint16_t
hashAlg;
const BYTE*OID;
PKCS1_HASH_REF// PKCS1 OIDECDSA_HASH_REF// ECDSA OID} HASH_DEF, *PHASH_DEF;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 473
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

Macro to fill in the HASH_DEF for an algorithm. For SHA1, the instance would be:
HASH_DEF_TEMPLATE(Sha1, SHA1) This handles the difference in capitalization for the various pieces.
144
145
146
147
148
149
150
151
152
153
154
155
156
157

#define HASH_DEF_TEMPLATE(HASH, Hash)\
HASH_DEF
Hash##_Def= {\{(HASH_START_METHOD *)&tpmHashStart_##HASH,\(HASH_DATA_METHOD *)&tpmHashData_##HASH,\(HASH_END_METHOD *)&tpmHashEnd_##HASH,\(HASH_STATE_COPY_METHOD *)&tpmHashStateCopy_##HASH,\(HASH_STATE_EXPORT_METHOD *)&tpmHashStateExport_##HASH,\(HASH_STATE_IMPORT_METHOD *)&tpmHashStateImport_##HASH,\},\
HASH##_BLOCK_SIZE,/*block size */\HASH##_DIGEST_SIZE,/*data size */\sizeof(tpmHashState##HASH##_t),\
TPM_ALG_##HASH, OID_##HASH\
PKCS1_OID(HASH) ECDSA_OID(HASH)};

These definitions are for the types that can be in a hash state structure. These types are used in thecryptographic utilities. This is a define rather than an enum so that the size of this field can be explicit.
158
159
160
161
162
163
164

typedef BYTE
HASH_STATE_TYPE;#define HASH_STATE_EMPTY((HASH_STATE_TYPE) 0)#define HASH_STATE_HASH((HASH_STATE_TYPE) 1)#define HASH_STATE_HMAC((HASH_STATE_TYPE) 2)#if CC_MAC || CC_MAC_Start#define HASH_STATE_SMAC((HASH_STATE_TYPE) 3)#endifThis 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 anarray 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 properlyaligned structure before it is used and copy the result back. This just makes things slower.
NOTE:

165
166
167
168
169
170
171
172

This version of the state had the pointer to the update method in the state. This is to allow the SMAC functions
to use the same structure without having to replicate the entire HASH_DEF structure.

typedef struct _HASH_STATE{
HASH_STATE_TYPE
type;
TPM_ALG_ID
hashAlg;
PHASH_DEF
def;
ANY_HASH_STATE
state;} HASH_STATE, *PHASH_STATE;
typedef const HASH_STATE *PCHASH_STATE;

10.1.3.3// type of the context

HMAC State Structures

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.
173
174
175
176
177

typedef struct hmacState{
HASH_STATE
hashState;
TPM2B_HASH_BLOCK
hmacKey;} HMAC_STATE, *PHMAC_STATE;

Page 474
April 15, 2019// the hash state// the HMAC key

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module LibraryThis 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 run time check that makes sure that this i.
178
179
180
181
182
183

typedef struct{
BYTE
buffer[sizeof(HASH_STATE)];} EXPORT_HASH_STATE, *PEXPORT_HASH_STATE;
typedef const EXPORT_HASH_STATE *PCEXPORT_HASH_STATE;#endif // _CRYPT_HASH_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 475
April 15, 2019

Trusted Platform Module Library

10.1.4

Part 4: Supporting Routines

CryptRand.h10.1.4.1

Introduction

This file contains constant definition shared by CryptUtil() and the parts of the Crypto Engine.
1
2#ifndef _CRYPT_RAND_H#define _CRYPT_RAND_H

10.1.4.2

DRBG Structures and Defines

Values and structures for the random number generator. These values are defined in this header file sothat 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 DRBG based on a symmetric block cipher
is defined by three values,
the key size
the block size (the IV size)
the symmetric algorithm
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#define DRBG_KEY_SIZE_BITS
AES_MAX_KEY_SIZE_BITS#define DRBG_IV_SIZE_BITS(AES_MAX_BLOCK_SIZE * 8)
#define DRBG_ALGORITHM
TPM_ALG_AES
typedef tpmKeyScheduleAESDRBG_KEY_SCHEDULE;#define DRBG_ENCRYPT_SETUP(key, keySizeInBits, schedule)\
TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule)#define DRBG_ENCRYPT(keySchedule, in, out)\
TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out))#if((DRBG_KEY_SIZE_BITS % RADIX_BITS) != 0) \|| ((DRBG_IV_SIZE_BITS % RADIX_BITS) != 0)#error "Key size and IV for DRBG must be even multiples of the radix"#endif#if (DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0
#error "Key size for DRBG must be even multiple of the cypher block size"#endifDerived values
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#define DRBG_MAX_REQUESTS_PER_RESEED (1 << 48)#define DRBG_MAX_REQEST_SIZE (1 << 32)#define pDRBG_KEY(seed)((DRBG_KEY *)&(((BYTE *)(seed))[0]))#define pDRBG_IV(seed)((DRBG_IV *)&(((BYTE *)(seed))[DRBG_KEY_SIZE_BYTES]))#define DRBG_KEY_SIZE_WORDS(BITS_TO_CRYPT_WORDS(DRBG_KEY_SIZE_BITS))#define DRBG_KEY_SIZE_BYTES(DRBG_KEY_SIZE_WORDS * RADIX_BYTES)#define DRBG_IV_SIZE_WORDS(BITS_TO_CRYPT_WORDS(DRBG_IV_SIZE_BITS))#define DRBG_IV_SIZE_BYTES(DRBG_IV_SIZE_WORDS * RADIX_BYTES)#define DRBG_SEED_SIZE_WORDS(DRBG_KEY_SIZE_WORDS + DRBG_IV_SIZE_WORDS)#define DRBG_SEED_SIZE_BYTES(DRBG_KEY_SIZE_BYTES + DRBG_IV_SIZE_BYTES)
typedef union{
BYTE
bytes[DRBG_KEY_SIZE_BYTES];
crypt_uword_t
words[DRBG_KEY_SIZE_WORDS];} DRBG_KEY;
typedef union{
BYTE
bytes[DRBG_IV_SIZE_BYTES];
crypt_uword_t
words[DRBG_IV_SIZE_WORDS];} DRBG_IV;
typedef union{

Page 476
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

Trusted Platform Module Library

BYTE
bytes[DRBG_SEED_SIZE_BYTES];
crypt_uword_t
words[DRBG_SEED_SIZE_WORDS];} DRBG_SEED;#define CTR_DRBG_MAX_REQUESTS_PER_RESEED((UINT64)1 << 20)#define CTR_DRBG_MAX_BYTES_PER_REQUEST(1 << 16)#
define CTR_DRBG_MIN_ENTROPY_INPUT_LENGTH
DRBG_SEED_SIZE_BYTES#
define CTR_DRBG_MAX_ENTROPY_INPUT_LENGTH
DRBG_SEED_SIZE_BYTES#
define CTR_DRBG_MAX_ADDITIONAL_INPUT_LENGTH DRBG_SEED_SIZE_BYTES#defineTESTING(1 << 0)#defineENTROPY(1 << 1)
#defineTESTED(1 << 2)
#define
IsTestStateSet(BIT)((g_cryptoSelfTestState.rng & BIT) != 0)#defineSetTestStateBit(BIT)(g_cryptoSelfTestState.rng |= BIT)
#defineClearTestStateBit(BIT) (g_cryptoSelfTestState.rng &= ~BIT)#defineIsSelfTest()
IsTestStateSet(TESTING)#define
SetSelfTest()
SetTestStateBit(TESTING)#defineClearSelfTest() ClearTestStateBit(TESTING)#defineIsEntropyBad()
IsTestStateSet(ENTROPY)#define
SetEntropyBad()
SetTestStateBit(ENTROPY)#defineClearEntropyBad()
ClearTestStateBit(ENTROPY)#define
IsDrbgTested()
IsTestStateSet(TESTED)#define
SetDrbgTested()
SetTestStateBit(TESTED)#defineClearDrbgTested()
ClearTestStateBit(TESTED)
typedef struct{
UINT64reseedCounter;
UINT32
magic;
DRBG_SEED
seed; // contains the key and IV for the counter mode DRBGUINT32
lastValue[4];// used when the TPM does continuous self-test// for FIPS compliance of DRBG
} DRBG_STATE, *pDRBG_STATE;#define DRBG_MAGIC((UINT32) 0x47425244) // "DRBG" backwards so that it displays
typedef struct{
UINT64
counter;
UINT32
magic;UINT32
limit;
TPM2B*seed;
const TPM2B*label;TPM2B*context;
TPM_ALG_IDhash;
TPM_ALG_ID
kdf;
UINT16
digestSize;
TPM2B_DIGEST
residual;} KDF_STATE, *pKDR_STATE;#define KDF_MAGIC((UINT32) 0x4048444a) // "KDF " backwards

Make sure that any other structures added to this union start with a 64-bit counter and a 32-bit magic
number
86
87
88
89
90

typedef union{
DRBG_STATEKDF_STATE} RAND_STATE;

drbg;
kdf;

This is the state used when the library uses a random number generator. A special function is installed forthe library to call. That function picks up the state from this location and uses it for the generation of therandom number.
91

extern RAND_STATE*s_random;

When instrumenting RSA key sieve
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 477
April 15, 2019

Trusted Platform Module Library
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

Part 4: Supporting Routines#if RSA_INSTRUMENT#define PRIME_INDEX(x) ((x) == 512 ? 0 : (x) == 1024 ? 1 : 2)#
define INSTRUMENT_SET(a, b) ((a) = (b))#
define INSTRUMENT_ADD(a, b) (a) = (a) + (b)#define INSTRUMENT_INC(a)(a) = (a) + 1
extern UINT32 PrimeIndex;
extern UINT32 failedAtIteration[10];extern UINT32 PrimeCounts[3];extern UINT32 MillerRabinTrials[3];extern UINT32 totalFieldsSieved[3];extern UINT32 bitsInFieldAfterSieve[3];extern UINT32 emptyFieldsSieved[3];extern UINT32 noPrimeFields[3];extern UINT32 primesChecked[3];extern UINT16 lastSievePrime;#else#
define INSTRUMENT_SET(a, b)#
define INSTRUMENT_ADD(a, b)#
define INSTRUMENT_INC(a)#endif#endif // _CRYPT_RAND_H

Page 478
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.1.5

Trusted Platform Module Library

CryptRsa.h

This file contains the RSA-related structures and defines.
12#ifndef _CRYPT_RSA_H#define _CRYPT_RSA_H

These values are used in the bigNum representation of various RSA values.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

BN_TYPE(rsa, MAX_RSA_KEY_BITS);#define BN_RSA(name)
BN_VAR(name, MAX_RSA_KEY_BITS)#define BN_RSA_INITIALIZED(name, initializer)
BN_INITIALIZED(name, MAX_RSA_KEY_BITS, initializer)#define BN_PRIME(name)
BN_VAR(name, (MAX_RSA_KEY_BITS / 2))
BN_TYPE(prime, (MAX_RSA_KEY_BITS / 2));
#define BN_PRIME_INITIALIZED(name, initializer)
BN_INITIALIZED(name, MAX_RSA_KEY_BITS / 2, initializer)#if !CRT_FORMAT_RSA#
error
This verson only works with CRT formatted data
#endif // !CRT_FORMAT_RSA
typedef struct privateExponent{
bigNumP;
bigNumQ;
bigNumdP;
bigNumdQ;
bigNumqInv;
bn_prime_t
entries[5];} privateExponent;#define
NEW_PRIVATE_EXPONENT(X)
privateExponent_##X;
privateExponent*X = RsaInitializeExponent(&(_##X))#endif// _CRYPT_RSA_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\

\

\
\

Page 479
April 15, 2019

Trusted Platform Module Library

10.1.6

Part 4: Supporting Routines

CryptTest.h

This file contains constant definitions used for self-test.
1
2#ifndef _CRYPT_TEST_H#define _CRYPT_TEST_H

This is the definition of a bit array with one bit per algorithm.
NOTE:

3
4
5
6
7

Since bit numbering starts at zero, when ALG_LAST_VALUE is a multiple of 8, ALGORITHM_VECTOR willneed to have byte for the single bit in the last byte. So, for example, when ALG_LAST_VECTOR is 8,
ALGORITHM_VECTOR will need 2 bytes.

#define ALGORITHM_VECTOR_BYTES ((ALG_LAST_VALUE + 8) / 8)
typedef BYTE
ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES];#ifdef TEST_SELF_TEST
LIB_EXPORT
extern ALGORITHM_VECTOR
LibToTest;#endifThis structure is used to contain self-test tracking information for the cryptographic modules. 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.
8
9
10
11
12
13
14
15
16
17
18
19
20

typedef struct{
UINT32
rng;
UINT32
hash;
UINT32sym;#if ALG_RSAUINT32rsa;#endif#if ALG_ECCUINT32ecc;#endif} CRYPTO_SELF_TEST_STATE;#endif // _CRYPT_TEST_H

Page 480
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.1.7

Trusted Platform Module Library

HashTestData.h

Hash Test Vectors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

TPM2B_TYPE(HASH_TEST_KEY, 128); // Twice the largest digest size
TPM2B_HASH_TEST_KEY
c_hashTestKey = {{128, {0xa0,0xed,0x5c,0x9a,0xd2,0x4a,0x21,0x40,0x1a,0xd0,0x81,0x47,0x39,0x63,0xf9,0x50,
0xdc,0x59,0x47,0x11,0x40,0x13,0x99,0x92,0xc0,0x72,0xa4,0x0f,0xe2,0x33,0xe4,0x63,
0x9b,0xb6,0x76,0xc3,0x1e,0x6f,0x13,0xee,0xcc,0x99,0x71,0xa5,0xc0,0xcf,0x9a,0x40,
0xcf,0xdb,0x66,0x70,0x05,0x63,0x54,0x12,0x25,0xf4,0xe0,0x1b,0x23,0x35,0xe3,0x70,
0x7d,0x19,0x5f,0x00,0xe4,0xf1,0x61,0x73,0x05,0xd8,0x58,0x7f,0x60,0x61,0x84,0x36,
0xec,0xbe,0x96,0x1b,0x69,0x00,0xf0,0x9a,0x6e,0xe3,0x26,0x73,0x0d,0x17,0x5b,0x33,
0x41,0x44,0x9d,0x90,0xab,0xd9,0x6b,0x7d,0x48,0x99,0x25,0x93,0x29,0x14,0x2b,0xce,
0x93,0x8d,0x8c,0xaf,0x31,0x0e,0x9c,0x57,0xd8,0x5b,0x57,0x20,0x1b,0x9f,0x2d,0xa5}}};
TPM2B_TYPE(HASH_TEST_DATA, 256); // Twice the largest block size
TPM2B_HASH_TEST_DATA
c_hashTestData = {{256, {0x88,0xac,0xc3,0xe5,0x5f,0x66,0x9d,0x18,0x80,0xc9,0x7a,0x9c,0xa4,0x08,0x90,0x98,
0x0f,0x3a,0x53,0x92,0x4c,0x67,0x4e,0xb7,0x37,0xec,0x67,0x87,0xb6,0xbe,0x10,0xca,
0x11,0x5b,0x4a,0x0b,0x45,0xc3,0x32,0x68,0x48,0x69,0xce,0x25,0x1b,0xc8,0xaf,0x44,
0x79,0x22,0x83,0xc8,0xfb,0xe2,0x63,0x94,0xa2,0x3c,0x59,0x3e,0x3e,0xc6,0x64,0x2c,
0x1f,0x8c,0x11,0x93,0x24,0xa3,0x17,0xc5,0x2f,0x37,0xcf,0x95,0x97,0x8e,0x63,0x39,
0x68,0xd5,0xca,0xba,0x18,0x37,0x69,0x6e,0x4f,0x19,0xfd,0x8a,0xc0,0x8d,0x87,0x3a,
0xbc,0x31,0x42,0x04,0x05,0xef,0xb5,0x02,0xef,0x1e,0x92,0x4b,0xb7,0x73,0x2c,0x8c,
0xeb,0x23,0x13,0x81,0x34,0xb9,0xb5,0xc1,0x17,0x37,0x39,0xf8,0x3e,0xe4,0x4c,0x06,
0xa8,0x81,0x52,0x2f,0xef,0xc9,0x9c,0x69,0x89,0xbc,0x85,0x9c,0x30,0x16,0x02,0xca,
0xe3,0x61,0xd4,0x0f,0xed,0x34,0x1b,0xca,0xc1,0x1b,0xd1,0xfa,0xc1,0xa2,0xe0,0xdf,
0x52,0x2f,0x0b,0x4b,0x9f,0x0e,0x45,0x54,0xb9,0x17,0xb6,0xaf,0xd6,0xd5,0xca,0x90,
0x29,0x57,0x7b,0x70,0x50,0x94,0x5c,0x8e,0xf6,0x4e,0x21,0x8b,0xc6,0x8b,0xa6,0xbc,
0xb9,0x64,0xd4,0x4d,0xf3,0x68,0xd8,0xac,0xde,0xd8,0xd8,0xb5,0x6d,0xcd,0x93,0xeb,
0x28,0xa4,0xe2,0x5c,0x44,0xef,0xf0,0xe1,0x6f,0x38,0x1a,0x3c,0xe6,0xef,0xa2,0x9d,
0xb9,0xa8,0x05,0x2a,0x95,0xec,0x5f,0xdb,0xb0,0x25,0x67,0x9c,0x86,0x7a,0x8e,0xea,
0x51,0xcc,0xc3,0xd3,0xff,0x6e,0xf0,0xed,0xa3,0xae,0xf9,0x5d,0x33,0x70,0xf2,0x11}}};#if ALG_SHA1 == YES
TPM2B_TYPE(SHA1, 20);
TPM2B_SHA1
c_SHA1_digest = {{20, {0xee,0x2c,0xef,0x93,0x76,0xbd,0xf8,0x91,0xbc,0xe6,0xe5,0x57,0x53,0x77,0x01,0xb5,
0x70,0x95,0xe5,0x40}}};#endif#if ALG_SHA256 == YES
TPM2B_TYPE(SHA256, 32);
TPM2B_SHA256
c_SHA256_digest = {{32, {0x64,0xe8,0xe0,0xc3,0xa9,0xa4,0x51,0x49,0x10,0x55,0x8d,0x31,0x71,0xe5,0x2f,0x69,
0x3a,0xdc,0xc7,0x11,0x32,0x44,0x61,0xbd,0x34,0x39,0x57,0xb0,0xa8,0x75,0x86,0x1b}}};#endif#if ALG_SHA384 == YES
TPM2B_TYPE(SHA384, 48);
TPM2B_SHA384
c_SHA384_digest = {{48, {0x37,0x75,0x29,0xb5,0x20,0x15,0x6e,0xa3,0x7e,0xa3,0x0d,0xcd,0x80,0xa8,0xa3,0x3d,
0xeb,0xe8,0xad,0x4e,0x1c,0x77,0x94,0x5a,0xaf,0x6c,0xd0,0xc1,0xfa,0x43,0x3f,0xc7,
0xb8,0xf1,0x01,0xc0,0x60,0xbf,0xf2,0x87,0xe8,0x71,0x9e,0x51,0x97,0xa0,0x09,0x8d}}};#endif#if ALG_SHA512 == YES
TPM2B_TYPE(SHA512, 64);
TPM2B_SHA512
c_SHA512_digest = {{64, {0xe2,0x7b,0x10,0x3d,0x5e,0x48,0x58,0x44,0x67,0xac,0xa3,0x81,0x8c,0x1d,0xc5,0x71,
0x66,0x92,0x8a,0x89,0xaa,0xd4,0x35,0x51,0x60,0x37,0x31,0xd7,0xba,0xe7,0x93,0x0b,
0x16,0x4d,0xb3,0xc8,0x34,0x98,0x3c,0xd3,0x53,0xde,0x5e,0xe8,0x0c,0xbc,0xaf,0xc9,
0x24,0x2c,0xcc,0xed,0xdb,0xde,0xba,0x1f,0x14,0x14,0x5a,0x95,0x80,0xde,0x66,0xbd}}};#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 481
April 15, 2019

Trusted Platform Module Library

10.1.8

Part 4: Supporting Routines

KdfTestData.h

Hash Test Vectors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#define TEST_KDF_KEY_SIZE20
TPM2B_TYPE(KDF_TEST_KEY, TEST_KDF_KEY_SIZE);
TPM2B_KDF_TEST_KEY
c_kdfTestKeyIn = {{TEST_KDF_KEY_SIZE, {0x27, 0x1F, 0xA0, 0x8B, 0xBD, 0xC5, 0x06, 0x0E, 0xC3, 0xDF,
0xA9, 0x28, 0xFF, 0x9B, 0x73, 0x12, 0x3A, 0x12, 0xDA, 0x0C }}};TPM2B_TYPE(KDF_TEST_LABEL, 17);
TPM2B_KDF_TEST_LABEL
c_kdfTestLabel = {{17, {0x4B, 0x44, 0x46, 0x53, 0x45, 0x4C, 0x46, 0x54,
0x45, 0x53, 0x54, 0x4C, 0x41, 0x42, 0x45, 0x4C, 0x00 }}};TPM2B_TYPE(KDF_TEST_CONTEXT, 8);
TPM2B_KDF_TEST_CONTEXT c_kdfTestContextU = {{8, {0xCE, 0x24, 0x4F, 0x39, 0x5D, 0xCA, 0x73, 0x91 }}};TPM2B_KDF_TEST_CONTEXT c_kdfTestContextV = {{8, {0xDA, 0x50, 0x40, 0x31, 0xDD, 0xF1, 0x2E, 0x83 }}};
#if ALG_SHA512 == ALG_YES
TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, {0x8b, 0xe2, 0xc1, 0xb8, 0x5b, 0x78, 0x56, 0x9b, 0x9f, 0xa7,
0x59, 0xf5, 0x85, 0x7c, 0x56, 0xd6, 0x84, 0x81, 0x0f, 0xd3 }}};
#define KDF_TEST_ALG
TPM_ALG_SHA512#elif ALG_SHA384 == ALG_YES
TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, {0x1d, 0xce, 0x70, 0xc9, 0x11, 0x3e, 0xb2, 0xdb, 0xa4, 0x7b,
0xd9, 0xcf, 0xc7, 0x2b, 0xf4, 0x6f, 0x45, 0xb0, 0x93, 0x12 }}};
#define KDF_TEST_ALG
TPM_ALG_SHA384#elif ALG_SHA256 == ALG_YES
TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, {0xbb, 0x02, 0x59, 0xe1, 0xc8, 0xba, 0x60, 0x7e, 0x6a, 0x2c,
0xd7, 0x04, 0xb6, 0x9a, 0x90, 0x2e, 0x9a, 0xde, 0x84, 0xc4 }}};
#define KDF_TEST_ALG
TPM_ALG_SHA256#elif ALG_SHA1 == ALG_YES
TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, {0x55, 0xb5, 0xa7, 0x18, 0x4a, 0xa0, 0x74, 0x23, 0xc4, 0x7d,
0xae, 0x76, 0x6c, 0x26, 0xa2, 0x37, 0x7d, 0x7c, 0xf8, 0x51 }}};
#define KDF_TEST_ALG
TPM_ALG_SHA1#endifPage 482
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.1.9Trusted Platform Module Library

RsaTestData.h

RSA Test Vectors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

#define RSA_TEST_KEY_SIZE
256
typedef struct{
UINT16size;
BYTE
buffer[RSA_TEST_KEY_SIZE];} TPM2B_RSA_TEST_KEY;
typedef TPM2B_RSA_TEST_KEY TPM2B_RSA_TEST_VALUE;
typedef struct{
UINT16size;
BYTE
buffer[RSA_TEST_KEY_SIZE / 2];} TPM2B_RSA_TEST_PRIME;
const TPM2B_RSA_TEST_KEY
c_rsaPublicModulus = {256, {0x91,0x12,0xf5,0x07,0x9d,0x5f,0x6b,0x1c,0x90,0xf6,0xcc,0x87,0xde,0x3a,0x7a,0x15,
0xdc,0x54,0x07,0x6c,0x26,0x8f,0x25,0xef,0x7e,0x66,0xc0,0xe3,0x82,0x12,0x2f,0xab,
0x52,0x82,0x1e,0x85,0xbc,0x53,0xba,0x2b,0x01,0xad,0x01,0xc7,0x8d,0x46,0x4f,0x7d,
0xdd,0x7e,0xdc,0xb0,0xad,0xf6,0x0c,0xa1,0x62,0x92,0x97,0x8a,0x3e,0x6f,0x7e,0x3e,
0xf6,0x9a,0xcc,0xf9,0xa9,0x86,0x77,0xb6,0x85,0x43,0x42,0x04,0x13,0x65,0xe2,0xad,
0x36,0xc9,0xbf,0xc1,0x97,0x84,0x6f,0xee,0x7c,0xda,0x58,0xd2,0xae,0x07,0x00,0xaf,
0xc5,0x5f,0x4d,0x3a,0x98,0xb0,0xed,0x27,0x7c,0xc2,0xce,0x26,0x5d,0x87,0xe1,0xe3,
0xa9,0x69,0x88,0x4f,0x8c,0x08,0x31,0x18,0xae,0x93,0x16,0xe3,0x74,0xde,0xd3,0xf6,
0x16,0xaf,0xa3,0xac,0x37,0x91,0x8d,0x10,0xc6,0x6b,0x64,0x14,0x3a,0xd9,0xfc,0xe4,
0xa0,0xf2,0xd1,0x01,0x37,0x4f,0x4a,0xeb,0xe5,0xec,0x98,0xc5,0xd9,0x4b,0x30,0xd2,
0x80,0x2a,0x5a,0x18,0x5a,0x7d,0xd4,0x3d,0xb7,0x62,0x98,0xce,0x6d,0xa2,0x02,0x6e,
0x45,0xaa,0x95,0x73,0xe0,0xaa,0x75,0x57,0xb1,0x3d,0x1b,0x05,0x75,0x23,0x6b,0x20,
0x69,0x9e,0x14,0xb0,0x7f,0xac,0xae,0xd2,0xc7,0x48,0x3b,0xe4,0x56,0x11,0x34,0x1e,
0x05,0x1a,0x30,0x20,0xef,0x68,0x93,0x6b,0x9d,0x7e,0xdd,0xba,0x96,0x50,0xcc,0x1c,
0x81,0xb4,0x59,0xb9,0x74,0x36,0xd9,0x97,0xdc,0x8f,0x17,0x82,0x72,0xb3,0x59,0xf6,
0x23,0xfa,0x84,0xf7,0x6d,0xf2,0x05,0xff,0xf1,0xb9,0xcc,0xe9,0xa2,0x82,0x01,0xfb}};
const TPM2B_RSA_TEST_PRIME
c_rsaPrivatePrime = {RSA_TEST_KEY_SIZE / 2, {0xb7,0xa0,0x90,0xc7,0x92,0x09,0xde,0x71,0x03,0x37,0x4a,0xb5,0x2f,0xda,0x61,0xb8,
0x09,0x1b,0xba,0x99,0x70,0x45,0xc1,0x0b,0x15,0x12,0x71,0x8a,0xb3,0x2a,0x4d,0x5a,
0x41,0x9b,0x73,0x89,0x80,0x0a,0x8f,0x18,0x4c,0x8b,0xa2,0x5b,0xda,0xbd,0x43,0xbe,
0xdc,0x76,0x4d,0x71,0x0f,0xb9,0xfc,0x7a,0x09,0xfe,0x4f,0xac,0x63,0xd9,0x2e,0x50,
0x3a,0xa1,0x37,0xc6,0xf2,0xa1,0x89,0x12,0xe7,0x72,0x64,0x2b,0xba,0xc1,0x1f,0xca,
0x9d,0xb7,0xaa,0x3a,0xa9,0xd3,0xa6,0x6f,0x73,0x02,0xbb,0x85,0x5d,0x9a,0xb9,0x5c,
0x08,0x83,0x22,0x20,0x49,0x91,0x5f,0x4b,0x86,0xbc,0x3f,0x76,0x43,0x08,0x97,0xbf,
0x82,0x55,0x36,0x2d,0x8b,0x6e,0x9e,0xfb,0xc1,0x67,0x6a,0x43,0xa2,0x46,0x81,0x71}};
const BYTE
c_RsaTestValue[RSA_TEST_KEY_SIZE] = {0x2a,0x24,0x3a,0xbb,0x50,0x1d,0xd4,0x2a,0xf9,0x18,0x32,0x34,0xa2,0x0f,0xea,0x5c,
0x91,0x77,0xe9,0xe1,0x09,0x83,0xdc,0x5f,0x71,0x64,0x5b,0xeb,0x57,0x79,0xa0,0x41,
0xc9,0xe4,0x5a,0x0b,0xf4,0x9f,0xdb,0x84,0x04,0xa6,0x48,0x24,0xf6,0x3f,0x66,0x1f,
0xa8,0x04,0x5c,0xf0,0x7a,0x6b,0x4a,0x9c,0x7e,0x21,0xb6,0xda,0x6b,0x65,0x9c,0x3a,
0x68,0x50,0x13,0x1e,0xa4,0xb7,0xca,0xec,0xd3,0xcc,0xb2,0x9b,0x8c,0x87,0xa4,0x6a,
0xba,0xc2,0x06,0x3f,0x40,0x48,0x7b,0xa8,0xb8,0x2c,0x03,0x14,0x33,0xf3,0x1d,0xe9,
0xbd,0x6f,0x54,0x66,0xb4,0x69,0x5e,0xbc,0x80,0x7c,0xe9,0x6a,0x43,0x7f,0xb8,0x6a,
0xa0,0x5f,0x5d,0x7a,0x20,0xfd,0x7a,0x39,0xe1,0xea,0x0e,0x94,0x91,0x28,0x63,0x7a,
0xac,0xc9,0xa5,0x3a,0x6d,0x31,0x7b,0x7c,0x54,0x56,0x99,0x56,0xbb,0xb7,0xa1,0x2d,
0xd2,0x5c,0x91,0x5f,0x1c,0xd3,0x06,0x7f,0x34,0x53,0x2f,0x4c,0xd1,0x8b,0xd2,0x9e,
0xdc,0xc3,0x94,0x0a,0xe1,0x0f,0xa5,0x15,0x46,0x2a,0x8e,0x10,0xc2,0xfe,0xb7,0x5e,
0x2d,0x0d,0xd1,0x25,0xfc,0xe4,0xf7,0x02,0x19,0xfe,0xb6,0xe4,0x95,0x9c,0x17,0x4a,
0x9b,0xdb,0xab,0xc7,0x79,0xe3,0x5e,0x40,0xd0,0x56,0x6d,0x25,0x0a,0x72,0x65,0x80,
0x92,0x9a,0xa8,0x07,0x70,0x32,0x14,0xfb,0xfe,0x08,0xeb,0x13,0xb4,0x07,0x68,0xb4,
0x58,0x39,0xbe,0x8e,0x78,0x3a,0x59,0x3f,0x9c,0x4c,0xe9,0xa8,0x64,0x68,0xf7,0xb9,
0x6e,0x20,0xf5,0xcb,0xca,0x47,0xf2,0x17,0xaa,0x8b,0xbc,0x13,0x14,0x84,0xf6,0xab};
const TPM2B_RSA_TEST_VALUE
c_RsaepKvt = {RSA_TEST_KEY_SIZE, {0x73,0xbd,0x65,0x49,0xda,0x7b,0xb8,0x50,0x9e,0x87,0xf0,0x0a,0x8a,0x9a,0x07,0xb6,
0x00,0x82,0x10,0x14,0x60,0xd8,0x01,0xfc,0xc5,0x18,0xea,0x49,0x5f,0x13,0xcf,0x65,
0x66,0x30,0x6c,0x60,0x3f,0x24,0x3c,0xfb,0xe2,0x31,0x16,0x99,0x7e,0x31,0x98,0xab,
0x93,0xb8,0x07,0x53,0xcc,0xdb,0x7f,0x44,0xd9,0xee,0x5d,0xe8,0x5f,0x97,0x5f,0xe8,
0x1f,0x88,0x52,0x24,0x7b,0xac,0x62,0x95,0xb7,0x7d,0xf5,0xf8,0x9f,0x5a,0xa8,0x24,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 483
April 15, 2019

Trusted Platform Module Library
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

Part 4: Supporting Routines

0x9a,0x76,0x71,0x2a,0x35,0x2a,0xa1,0x08,0xbb,0x95,0xe3,0x64,0xdc,0xdb,0xc2,0x33,
0xa9,0x5f,0xbe,0x4c,0xc4,0xcc,0x28,0xc9,0x25,0xff,0xee,0x17,0x15,0x9a,0x50,0x90,
0x0e,0x15,0xb4,0xea,0x6a,0x09,0xe6,0xff,0xa4,0xee,0xc7,0x7e,0xce,0xa9,0x73,0xe4,
0xa0,0x56,0xbd,0x53,0x2a,0xe4,0xc0,0x2b,0xa8,0x9b,0x09,0x30,0x72,0x62,0x0f,0xf9,
0xf6,0xa1,0x52,0xd2,0x8a,0x37,0xee,0xa5,0xc8,0x47,0xe1,0x99,0x21,0x47,0xeb,0xdd,
0x37,0xaa,0xe4,0xbd,0x55,0x46,0x5a,0x5a,0x5d,0xfb,0x7b,0xfc,0xff,0xbf,0x26,0x71,
0xf6,0x1e,0xad,0xbc,0xbf,0x33,0xca,0xe1,0x92,0x8f,0x2a,0x89,0x6c,0x45,0x24,0xd1,
0xa6,0x52,0x56,0x24,0x5e,0x90,0x47,0xe5,0xcb,0x12,0xb0,0x32,0xf9,0xa6,0xbb,0xea,
0x37,0xa9,0xbd,0xef,0x23,0xef,0x63,0x07,0x6c,0xc4,0x4e,0x64,0x3c,0xc6,0x11,0x84,
0x7d,0x65,0xd6,0x5d,0x7a,0x17,0x58,0xa5,0xf7,0x74,0x3b,0x42,0xe3,0xd2,0xda,0x5f,
0x6f,0xe0,0x1e,0x4b,0xcf,0x46,0xe2,0xdf,0x3e,0x41,0x8e,0x0e,0xb0,0x3f,0x8b,0x65}};#defineOAEP_TEST_LABEL"OAEP Test Value"#if ALG_SHA1_VALUE == DEFAULT_TEST_HASH
const TPM2B_RSA_TEST_VALUE
c_OaepKvt = {RSA_TEST_KEY_SIZE, {0x32,0x68,0x84,0x0b,0x9c,0xc9,0x25,0x26,0xd9,0xc0,0xd0,0xb1,0xde,0x60,0x55,0xae,
0x33,0xe5,0xcf,0x6c,0x85,0xbe,0x0d,0x71,0x11,0xe1,0x45,0x60,0xbb,0x42,0x3d,0xf3,
0xb1,0x18,0x84,0x7b,0xc6,0x5d,0xce,0x1d,0x5f,0x9a,0x97,0xcf,0xb1,0x97,0x9a,0x85,
0x7c,0xa7,0xa1,0x63,0x23,0xb6,0x74,0x0f,0x1a,0xee,0x29,0x51,0xeb,0x50,0x8f,0x3c,
0x8e,0x4e,0x31,0x38,0xdc,0x11,0xfc,0x9a,0x4e,0xaf,0x93,0xc9,0x7f,0x6e,0x35,0xf3,
0xc9,0xe4,0x89,0x14,0x53,0xe2,0xc2,0x1a,0xf7,0x6b,0x9b,0xf0,0x7a,0xa4,0x69,0x52,
0xe0,0x24,0x8f,0xea,0x31,0xa7,0x5c,0x43,0xb0,0x65,0xc9,0xfe,0xba,0xfe,0x80,0x9e,
0xa5,0xc0,0xf5,0x8d,0xce,0x41,0xf9,0x83,0x0d,0x8e,0x0f,0xef,0x3d,0x1f,0x6a,0xcc,
0x8a,0x3d,0x3b,0xdf,0x22,0x38,0xd7,0x34,0x58,0x7b,0x55,0xc9,0xf6,0xbc,0x7c,0x4c,
0x3f,0xd7,0xde,0x4e,0x30,0xa9,0x69,0xf3,0x5f,0x56,0x8f,0xc2,0xe7,0x75,0x79,0xb8,
0xa5,0xc8,0x0d,0xc0,0xcd,0xb6,0xc9,0x63,0xad,0x7c,0xe4,0x8f,0x39,0x60,0x4d,0x7d,
0xdb,0x34,0x49,0x2a,0x47,0xde,0xc0,0x42,0x4a,0x19,0x94,0x2e,0x50,0x21,0x03,0x47,
0xff,0x73,0xb3,0xb7,0x89,0xcc,0x7b,0x2c,0xeb,0x03,0xa7,0x9a,0x06,0xfd,0xed,0x19,
0xbb,0x82,0xa0,0x13,0xe9,0xfa,0xac,0x06,0x5f,0xc5,0xa9,0x2b,0xda,0x88,0x23,0xa2,
0x5d,0xc2,0x7f,0xda,0xc8,0x5a,0x94,0x31,0xc1,0x21,0xd7,0x1e,0x6b,0xd7,0x89,0xb1,
0x93,0x80,0xab,0xd1,0x37,0xf2,0x6f,0x50,0xcd,0x2a,0xea,0xb1,0xc4,0xcd,0xcb,0xb5}};
const TPM2B_RSA_TEST_VALUE
c_RsaesKvt = {RSA_TEST_KEY_SIZE, {0x29,0xa4,0x2f,0xbb,0x8a,0x14,0x05,0x1e,0x3c,0x72,0x76,0x77,0x38,0xe7,0x73,0xe3,
0x6e,0x24,0x4b,0x38,0xd2,0x1a,0xcf,0x23,0x58,0x78,0x36,0x82,0x23,0x6e,0x6b,0xef,
0x2c,0x3d,0xf2,0xe8,0xd6,0xc6,0x87,0x8e,0x78,0x9b,0x27,0x39,0xc0,0xd6,0xef,0x4d,
0x0b,0xfc,0x51,0x27,0x18,0xf3,0x51,0x5e,0x4d,0x96,0x3a,0xe2,0x15,0xe2,0x7e,0x42,
0xf4,0x16,0xd5,0xc6,0x52,0x5d,0x17,0x44,0x76,0x09,0x7a,0xcf,0xe3,0x30,0xe3,0x84,
0xf6,0x6f,0x3a,0x33,0xfb,0x32,0x0d,0x1d,0xe7,0x7c,0x80,0x82,0x4f,0xed,0xda,0x87,
0x11,0x9c,0xc3,0x7e,0x85,0xbd,0x18,0x58,0x08,0x2b,0x23,0x37,0xe7,0x9d,0xd0,0xd1,
0x79,0xe2,0x05,0xbd,0xf5,0x4f,0x0e,0x0f,0xdb,0x4a,0x74,0xeb,0x09,0x01,0xb3,0xca,
0xbd,0xa6,0x7b,0x09,0xb1,0x13,0x77,0x30,0x4d,0x87,0x41,0x06,0x57,0x2e,0x5f,0x36,
0x6e,0xfc,0x35,0x69,0xfe,0x0a,0x24,0x6c,0x98,0x8c,0xda,0x97,0xf4,0xfb,0xc7,0x83,
0x2d,0x3e,0x7d,0xc0,0x5c,0x34,0xfd,0x11,0x2a,0x12,0xa7,0xae,0x4a,0xde,0xc8,0x4e,
0xcf,0xf4,0x85,0x63,0x77,0xc6,0x33,0x34,0xe0,0x27,0xe4,0x9e,0x91,0x0b,0x4b,0x85,
0xf0,0xb0,0x79,0xaa,0x7c,0xc6,0xff,0x3b,0xbc,0x04,0x73,0xb8,0x95,0xd7,0x31,0x54,
0x3b,0x56,0xec,0x52,0x15,0xd7,0x3e,0x62,0xf5,0x82,0x99,0x3e,0x2a,0xc0,0x4b,0x2e,
0x06,0x57,0x6d,0x3f,0x3e,0x77,0x1f,0x2b,0x2d,0xc5,0xb9,0x3b,0x68,0x56,0x73,0x70,
0x32,0x6b,0x6b,0x65,0x25,0x76,0x45,0x6c,0x45,0xf1,0x6c,0x59,0xfc,0x94,0xa7,0x15}};
const TPM2B_RSA_TEST_VALUE
c_RsapssKvt = {RSA_TEST_KEY_SIZE, {0x01,0xfe,0xd5,0x83,0x0b,0x15,0xba,0x90,0x2c,0xdf,0xf7,0x26,0xb7,0x8f,0xb1,0xd7,
0x0b,0xfd,0x83,0xf9,0x95,0xd5,0xd7,0xb5,0xc5,0xc5,0x4a,0xde,0xd5,0xe6,0x20,0x78,
0xca,0x73,0x77,0x3d,0x61,0x36,0x48,0xae,0x3e,0x8f,0xee,0x43,0x29,0x96,0xdf,0x3f,
0x1c,0x97,0x5a,0xbe,0xe5,0xa2,0x7e,0x5b,0xd0,0xc0,0x29,0x39,0x83,0x81,0x77,0x24,
0x43,0xdb,0x3c,0x64,0x4d,0xf0,0x23,0xe4,0xae,0x0f,0x78,0x31,0x8c,0xda,0x0c,0xec,
0xf1,0xdf,0x09,0xf2,0x14,0x6a,0x4d,0xaf,0x36,0x81,0x6e,0xbd,0xbe,0x36,0x79,0x88,
0x98,0xb6,0x6f,0x5a,0xad,0xcf,0x7c,0xee,0xe0,0xdd,0x00,0xbe,0x59,0x97,0x88,0x00,
0x34,0xc0,0x8b,0x48,0x42,0x05,0x04,0x5a,0xb7,0x85,0x38,0xa0,0x35,0xd7,0x3b,0x51,
0xb8,0x7b,0x81,0x83,0xee,0xff,0x76,0x6f,0x50,0x39,0x4d,0xab,0x89,0x63,0x07,0x6d,
0xf5,0xe5,0x01,0x10,0x56,0xfe,0x93,0x06,0x8f,0xd3,0xc9,0x41,0xab,0xc9,0xdf,0x6e,
0x59,0xa8,0xc3,0x1d,0xbf,0x96,0x4a,0x59,0x80,0x3c,0x90,0x3a,0x59,0x56,0x4c,0x6d,
0x44,0x6d,0xeb,0xdc,0x73,0xcd,0xc1,0xec,0xb8,0x41,0xbf,0x89,0x8c,0x03,0x69,0x4c,
0xaf,0x3f,0xc1,0xc5,0xc7,0xe7,0x7d,0xa7,0x83,0x39,0x70,0xa2,0x6b,0x83,0xbc,0xbe,
0xf5,0xbf,0x1c,0xee,0x6e,0xa3,0x22,0x1e,0x25,0x2f,0x16,0x68,0x69,0x5a,0x1d,0xfa,
0x2c,0x3a,0x0f,0x67,0xe1,0x77,0x12,0xe8,0x3d,0xba,0xaa,0xef,0x96,0x9c,0x1f,0x64,
0x32,0xf4,0xa7,0xb3,0x3f,0x7d,0x61,0xbb,0x9a,0x27,0xad,0xfb,0x2f,0x33,0xc4,0x70}};
const TPM2B_RSA_TEST_VALUE
c_RsassaKvt = {RSA_TEST_KEY_SIZE, {0x67,0x4e,0xdd,0xc2,0xd2,0x6d,0xe0,0x03,0xc4,0xc2,0x41,0xd3,0xd4,0x61,0x30,0xd0,

Page 484
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

Trusted Platform Module Library

0xe1,0x68,0x31,0x4a,0xda,0xd9,0xc2,0x5d,0xaa,0xa2,0x7b,0xfb,0x44,0x02,0xf5,0xd6,
0xd8,0x2e,0xcd,0x13,0x36,0xc9,0x4b,0xdb,0x1a,0x4b,0x66,0x1b,0x4f,0x9c,0xb7,0x17,
0xac,0x53,0x37,0x4f,0x21,0xbd,0x0c,0x66,0xac,0x06,0x65,0x52,0x9f,0x04,0xf6,0xa5,
0x22,0x5b,0xf7,0xe6,0x0d,0x3c,0x9f,0x41,0x19,0x09,0x88,0x7c,0x41,0x4c,0x2f,0x9c,
0x8b,0x3c,0xdd,0x7c,0x28,0x78,0x24,0xd2,0x09,0xa6,0x5b,0xf7,0x3c,0x88,0x7e,0x73,
0x5a,0x2d,0x36,0x02,0x4f,0x65,0xb0,0xcb,0xc8,0xdc,0xac,0xa2,0xda,0x8b,0x84,0x91,
0x71,0xe4,0x30,0x8b,0xb6,0x12,0xf2,0xf0,0xd0,0xa0,0x38,0xcf,0x75,0xb7,0x20,0xcb,
0x35,0x51,0x52,0x6b,0xc4,0xf4,0x21,0x95,0xc2,0xf7,0x9a,0x13,0xc1,0x1a,0x7b,0x8f,
0x77,0xda,0x19,0x48,0xbb,0x6d,0x14,0x5d,0xba,0x65,0xb4,0x9e,0x43,0x42,0x58,0x98,
0x0b,0x91,0x46,0xd8,0x4c,0xf3,0x4c,0xaf,0x2e,0x02,0xa6,0xb2,0x49,0x12,0x62,0x43,
0x4e,0xa8,0xac,0xbf,0xfd,0xfa,0x37,0x24,0xea,0x69,0x1c,0xf5,0xae,0xfa,0x08,0x82,
0x30,0xc3,0xc0,0xf8,0x9a,0x89,0x33,0xe1,0x40,0x6d,0x18,0x5c,0x7b,0x90,0x48,0xbf,
0x37,0xdb,0xea,0xfb,0x0e,0xd4,0x2e,0x11,0xfa,0xa9,0x86,0xff,0x00,0x0b,0x7b,0xca,
0x09,0x64,0x6a,0x8f,0x0c,0x0e,0x09,0x14,0x36,0x4a,0x74,0x31,0x18,0x5b,0x18,0xeb,
0xea,0x83,0xc3,0x66,0x68,0xa6,0x7d,0x43,0x06,0x0f,0x99,0x60,0xce,0x65,0x08,0xf6}};#endif // SHA1
#if ALG_SHA256_VALUE == DEFAULT_TEST_HASH
const TPM2B_RSA_TEST_VALUE
c_OaepKvt = {RSA_TEST_KEY_SIZE, {0x33,0x20,0x6e,0x21,0xc3,0xf6,0xcd,0xf8,0xd7,0x5d,0x9f,0xe9,0x05,0x14,0x8c,0x7c,
0xbb,0x69,0x24,0x9e,0x52,0x8f,0xaf,0x84,0x73,0x21,0x2c,0x85,0xa5,0x30,0x4d,0xb6,
0xb8,0xfa,0x15,0x9b,0xc7,0x8f,0xc9,0x7a,0x72,0x4b,0x85,0xa4,0x1c,0xc5,0xd8,0xe4,
0x92,0xb3,0xec,0xd9,0xa8,0xca,0x5e,0x74,0x73,0x89,0x7f,0xb4,0xac,0x7e,0x68,0x12,
0xb2,0x53,0x27,0x4b,0xbf,0xd0,0x71,0x69,0x46,0x9f,0xef,0xf4,0x70,0x60,0xf8,0xd7,
0xae,0xc7,0x5a,0x27,0x38,0x25,0x2d,0x25,0xab,0x96,0x56,0x66,0x3a,0x23,0x40,0xa8,
0xdb,0xbc,0x86,0xe8,0xf3,0xd2,0x58,0x0b,0x44,0xfc,0x94,0x1e,0xb7,0x5d,0xb4,0x57,
0xb5,0xf3,0x56,0xee,0x9b,0xcf,0x97,0x91,0x29,0x36,0xe3,0x06,0x13,0xa2,0xea,0xd6,
0xd6,0x0b,0x86,0x0b,0x1a,0x27,0xe6,0x22,0xc4,0x7b,0xff,0xde,0x0f,0xbf,0x79,0xc8,
0x1b,0xed,0xf1,0x27,0x62,0xb5,0x8b,0xf9,0xd9,0x76,0x90,0xf6,0xcc,0x83,0x0f,0xce,
0xce,0x2e,0x63,0x7a,0x9b,0xf4,0x48,0x5b,0xd7,0x81,0x2c,0x3a,0xdb,0x59,0x0d,0x4d,
0x9e,0x46,0xe9,0x9e,0x92,0x22,0x27,0x1c,0xb0,0x67,0x8a,0xe6,0x8a,0x16,0x8a,0xdf,
0x95,0x76,0x24,0x82,0xad,0xf1,0xbc,0x97,0xbf,0xd3,0x5e,0x6e,0x14,0x0c,0x5b,0x25,
0xfe,0x58,0xfa,0x64,0xe5,0x14,0x46,0xb7,0x58,0xc6,0x3f,0x7f,0x42,0xd2,0x8e,0x45,
0x13,0x41,0x85,0x12,0x2e,0x96,0x19,0xd0,0x5e,0x7d,0x34,0x06,0x32,0x2b,0xc8,0xd9,
0x0d,0x6c,0x06,0x36,0xa0,0xff,0x47,0x57,0x2c,0x25,0xbc,0x8a,0xa5,0xe2,0xc7,0xe3}};
const TPM2B_RSA_TEST_VALUE
c_RsaesKvt = {RSA_TEST_KEY_SIZE, {0x39,0xfc,0x10,0x5d,0xf4,0x45,0x3d,0x94,0x53,0x06,0x89,0x24,0xe7,0xe8,0xfd,0x03,
0xac,0xfd,0xbd,0xb2,0x28,0xd3,0x4a,0x52,0xc5,0xd4,0xdb,0x17,0xd4,0x24,0x05,0xc4,
0xeb,0x6a,0xce,0x1d,0xbb,0x37,0xcb,0x09,0xd8,0x6c,0x83,0x19,0x93,0xd4,0xe2,0x88,
0x88,0x9b,0xaf,0x92,0x16,0xc4,0x15,0xbd,0x49,0x13,0x22,0xb7,0x84,0xcf,0x23,0xf2,
0x6f,0x0c,0x3e,0x8f,0xde,0x04,0x09,0x31,0x2d,0x99,0xdf,0xe6,0x74,0x70,0x30,0xde,
0x8c,0xad,0x32,0x86,0xe2,0x7c,0x12,0x90,0x21,0xf3,0x86,0xb7,0xe2,0x64,0xca,0x98,
0xcc,0x64,0x4b,0xef,0x57,0x4f,0x5a,0x16,0x6e,0xd7,0x2f,0x5b,0xf6,0x07,0xad,0x33,
0xb4,0x8f,0x3b,0x3a,0x8b,0xd9,0x06,0x2b,0xed,0x3c,0x3c,0x76,0xf6,0x21,0x31,0xe3,
0xfb,0x2c,0x45,0x61,0x42,0xba,0xe0,0xc3,0x72,0x63,0xd0,0x6b,0x8f,0x36,0x26,0xfb,
0x9e,0x89,0x0e,0x44,0x9a,0xc1,0x84,0x5e,0x84,0x8d,0xb6,0xea,0xf1,0x0d,0x66,0xc7,
0xdb,0x44,0xbd,0x19,0x7c,0x05,0xbe,0xc4,0xab,0x88,0x32,0xbe,0xc7,0x63,0x31,0xe6,
0x38,0xd4,0xe5,0xb8,0x4b,0xf5,0x0e,0x55,0x9a,0x3a,0xe6,0x0a,0xec,0xee,0xe2,0xa8,
0x88,0x04,0xf2,0xb8,0xaa,0x5a,0xd8,0x97,0x5d,0xa0,0xa8,0x42,0xfb,0xd9,0xde,0x80,
0xae,0x4c,0xb3,0xa1,0x90,0x47,0x57,0x03,0x10,0x78,0xa6,0x8f,0x11,0xba,0x4b,0xce,
0x2d,0x56,0xa4,0xe1,0xbd,0xf8,0xa0,0xa4,0xd5,0x48,0x3c,0x63,0x20,0x00,0x38,0xa0,
0xd1,0xe6,0x12,0xe9,0x1d,0xd8,0x49,0xe3,0xd5,0x24,0xb5,0xc5,0x3a,0x1f,0xb0,0xd4}};
const TPM2B_RSA_TEST_VALUE
c_RsapssKvt = {RSA_TEST_KEY_SIZE, {0x74,0x89,0x29,0x3e,0x1b,0xac,0xc6,0x85,0xca,0xf0,0x63,0x43,0x30,0x7d,0x1c,0x9b,
0x2f,0xbd,0x4d,0x69,0x39,0x5e,0x85,0xe2,0xef,0x86,0x0a,0xc6,0x6b,0xa6,0x08,0x19,
0x6c,0x56,0x38,0x24,0x55,0x92,0x84,0x9b,0x1b,0x8b,0x04,0xcf,0x24,0x14,0x24,0x13,
0x0e,0x8b,0x82,0x6f,0x96,0xc8,0x9a,0x68,0xfc,0x4c,0x02,0xf0,0xdc,0xcd,0x36,0x25,
0x31,0xd5,0x82,0xcf,0xc9,0x69,0x72,0xf6,0x1d,0xab,0x68,0x20,0x2e,0x2d,0x19,0x49,
0xf0,0x2e,0xad,0xd2,0xda,0xaf,0xff,0xb6,0x92,0x83,0x5b,0x8a,0x06,0x2d,0x0c,0x32,
0x11,0x32,0x3b,0x77,0x17,0xf6,0x50,0xfb,0xf8,0x57,0xc9,0xc7,0x9b,0x9e,0xc6,0xd1,
0xa9,0x55,0xf0,0x22,0x35,0xda,0xca,0x3c,0x8e,0xc6,0x9a,0xd8,0x25,0xc8,0x5e,0x93,
0x0d,0xaa,0xa7,0x06,0xaf,0x11,0x29,0x99,0xe7,0x7c,0xee,0x49,0x82,0x30,0xba,0x2c,
0xe2,0x40,0x8f,0x0a,0xa6,0x7b,0x24,0x75,0xc5,0xcd,0x03,0x12,0xf4,0xb2,0x4b,0x3a,
0xd1,0x91,0x3c,0x20,0x0e,0x58,0x2b,0x31,0xf8,0x8b,0xee,0xbc,0x1f,0x95,0x35,0x58,
0x6a,0x73,0xee,0x99,0xb0,0x01,0x42,0x4f,0x66,0xc0,0x66,0xbb,0x35,0x86,0xeb,0xd9,
0x7b,0x55,0x77,0x2d,0x54,0x78,0x19,0x49,0xe8,0xcc,0xfd,0xb1,0xcb,0x49,0xc9,0xea,
0x20,0xab,0xed,0xb5,0xed,0xfe,0xb2,0xb5,0xa8,0xcf,0x05,0x06,0xd5,0x7d,0x2b,0xbb,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 485
April 15, 2019

Trusted Platform Module Library
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

Part 4: Supporting Routines

0x0b,0x65,0x6b,0x2b,0x6d,0x55,0x95,0x85,0x44,0x8b,0x12,0x05,0xf3,0x4b,0xd4,0x8e,
0x3d,0x68,0x2d,0x29,0x9c,0x05,0x79,0xd6,0xfc,0x72,0x90,0x6a,0xab,0x46,0x38,0x81}};
const TPM2B_RSA_TEST_VALUE
c_RsassaKvt = {RSA_TEST_KEY_SIZE, {0x8a,0xb1,0x0a,0xb5,0xe4,0x02,0xf7,0xdd,0x45,0x2a,0xcc,0x2b,0x6b,0x8c,0x0e,0x9a,
0x92,0x4f,0x9b,0xc5,0xe4,0x8b,0x82,0xb9,0xb0,0xd9,0x87,0x8c,0xcb,0xf0,0xb0,0x59,
0xa5,0x92,0x21,0xa0,0xa7,0x61,0x5c,0xed,0xa8,0x6e,0x22,0x29,0x46,0xc7,0x86,0x37,
0x4b,0x1b,0x1e,0x94,0x93,0xc8,0x4c,0x17,0x7a,0xae,0x59,0x91,0xf8,0x83,0x84,0xc4,
0x8c,0x38,0xc2,0x35,0x0e,0x7e,0x50,0x67,0x76,0xe7,0xd3,0xec,0x6f,0x0d,0xa0,0x5c,
0x2f,0x0a,0x80,0x28,0xd3,0xc5,0x7d,0x2d,0x1a,0x0b,0x96,0xd6,0xe5,0x98,0x05,0x8c,
0x4d,0xa0,0x1f,0x8c,0xb6,0xfb,0xb1,0xcf,0xe9,0xcb,0x38,0x27,0x60,0x64,0x17,0xca,
0xf4,0x8b,0x61,0xb7,0x1d,0xb6,0x20,0x9d,0x40,0x2a,0x1c,0xfd,0x55,0x40,0x4b,0x95,
0x39,0x52,0x18,0x3b,0xab,0x44,0xe8,0x83,0x4b,0x7c,0x47,0xfb,0xed,0x06,0x9c,0xcd,
0x4f,0xba,0x81,0xd6,0xb7,0x31,0xcf,0x5c,0x23,0xf8,0x25,0xab,0x95,0x77,0x0a,0x8f,
0x46,0xef,0xfb,0x59,0xb8,0x04,0xd7,0x1e,0xf5,0xaf,0x6a,0x1a,0x26,0x9b,0xae,0xf4,
0xf5,0x7f,0x84,0x6f,0x3c,0xed,0xf8,0x24,0x0b,0x43,0xd1,0xba,0x74,0x89,0x4e,0x39,
0xfe,0xab,0xa5,0x16,0xa5,0x28,0xee,0x96,0x84,0x3e,0x16,0x6d,0x5f,0x4e,0x0b,0x7d,
0x94,0x16,0x1b,0x8c,0xf9,0xaa,0x9b,0xc0,0x49,0x02,0x4c,0x3e,0x62,0xff,0xfe,0xa2,
0x20,0x33,0x5e,0xa6,0xdd,0xda,0x15,0x2d,0xb7,0xcd,0xda,0xff,0xb1,0x0b,0x45,0x7b,
0xd3,0xa0,0x42,0x29,0xab,0xa9,0x73,0xe9,0xa4,0xd9,0x8d,0xac,0xa1,0x88,0x2c,0x2d}};#endif // SHA256#if ALG_SHA384_VALUE == DEFAULT_TEST_HASH
const TPM2B_RSA_TEST_VALUE
c_OaepKvt = {RSA_TEST_KEY_SIZE, {0x0f,0x3c,0x42,0x4d,0x8c,0x91,0x96,0x05,0x3c,0xfd,0x59,0x3b,0x7f,0x29,0xbc,0x03,
0x67,0xc1,0xff,0x74,0xe7,0x09,0xf4,0x13,0x45,0xbe,0x13,0x1d,0xc9,0x86,0x94,0xfe,
0xed,0xa6,0xe8,0x3a,0xcb,0x89,0x4d,0xec,0x86,0x63,0x4c,0xdb,0xf1,0x95,0xee,0xc1,
0x46,0xc5,0x3b,0xd8,0xf8,0xa2,0x41,0x6a,0x60,0x8b,0x9e,0x5e,0x7f,0x20,0x16,0xe3,
0x69,0xb6,0x2d,0x92,0xfc,0x60,0xa2,0x74,0x88,0xd5,0xc7,0xa6,0xd1,0xff,0xe3,0x45,
0x02,0x51,0x39,0xd9,0xf3,0x56,0x0b,0x91,0x80,0xe0,0x6c,0xa8,0xc3,0x78,0xef,0x34,
0x22,0x8c,0xf5,0xfb,0x47,0x98,0x5d,0x57,0x8e,0x3a,0xb9,0xff,0x92,0x04,0xc7,0xc2,
0x6e,0xfa,0x14,0xc1,0xb9,0x68,0x15,0x5c,0x12,0xe8,0xa8,0xbe,0xea,0xe8,0x8d,0x9b,
0x48,0x28,0x35,0xdb,0x4b,0x52,0xc1,0x2d,0x85,0x47,0x83,0xd0,0xe9,0xae,0x90,0x6e,
0x65,0xd4,0x34,0x7f,0x81,0xce,0x69,0xf0,0x96,0x62,0xf7,0xec,0x41,0xd5,0xc2,0xe3,
0x4b,0xba,0x9c,0x8a,0x02,0xce,0xf0,0x5d,0x14,0xf7,0x09,0x42,0x8e,0x4a,0x27,0xfe,
0x3e,0x66,0x42,0x99,0x03,0xe1,0x69,0xbd,0xdb,0x7f,0x9b,0x70,0xeb,0x4e,0x9c,0xac,
0x45,0x67,0x91,0x9f,0x75,0x10,0xc6,0xfc,0x14,0xe1,0x28,0xc1,0x0e,0xe0,0x7e,0xc0,
0x5c,0x1d,0xee,0xe8,0xff,0x45,0x79,0x51,0x86,0x08,0xe6,0x39,0xac,0xb5,0xfd,0xb8,
0xf1,0xdd,0x2e,0xf4,0xb2,0x1a,0x69,0x0d,0xd9,0x98,0x8e,0xdb,0x85,0x61,0x70,0x20,
0x82,0x91,0x26,0x87,0x80,0xc4,0x6a,0xd8,0x3b,0x91,0x4d,0xd3,0x33,0x84,0xad,0xb7}};
const TPM2B_RSA_TEST_VALUE
c_RsaesKvt = {RSA_TEST_KEY_SIZE, {0x44,0xd5,0x9f,0xbc,0x48,0x03,0x3d,0x9f,0x22,0x91,0x2a,0xab,0x3c,0x31,0x71,0xab,
0x86,0x3f,0x0f,0x6f,0x59,0x5b,0x93,0x27,0xbc,0xbc,0xcd,0x29,0x38,0x43,0x2a,0x3b,
0x3b,0xd2,0xb3,0x45,0x40,0xba,0x15,0xb4,0x45,0xe3,0x56,0xab,0xff,0xb3,0x20,0x26,
0x39,0xcc,0x48,0xc5,0x5d,0x41,0x0d,0x2f,0x57,0x7f,0x9d,0x16,0x2e,0x26,0x57,0xc7,
0x6b,0xf3,0x36,0x54,0xbd,0xb6,0x1d,0x46,0x4e,0x13,0x50,0xd7,0x61,0x9d,0x8d,0x7b,
0xeb,0x21,0x9f,0x79,0xf3,0xfd,0xe0,0x1b,0xa8,0xed,0x6d,0x29,0x33,0x0d,0x65,0x94,
0x24,0x1e,0x62,0x88,0x6b,0x2b,0x4e,0x39,0xf5,0x80,0x39,0xca,0x76,0x95,0xbc,0x7c,
0x27,0x1d,0xdd,0x3a,0x11,0xf1,0x3e,0x54,0x03,0xb7,0x43,0x91,0x99,0x33,0xfe,0x9d,
0x14,0x2c,0x87,0x9a,0x95,0x18,0x1f,0x02,0x04,0x6a,0xe2,0xb7,0x81,0x14,0x13,0x45,
0x16,0xfb,0xe4,0xb7,0x8f,0xab,0x2b,0xd7,0x60,0x34,0x8a,0x55,0xbc,0x01,0x8c,0x49,
0x02,0x29,0xf1,0x9c,0x94,0x98,0x44,0xd0,0x94,0xcb,0xd4,0x85,0x4c,0x3b,0x77,0x72,
0x99,0xd5,0x4b,0xc6,0x3b,0xe4,0xd2,0xc8,0xe9,0x6a,0x23,0x18,0x3b,0x3b,0x5e,0x32,
0xec,0x70,0x84,0x5d,0xbb,0x6a,0x8f,0x0c,0x5f,0x55,0xa5,0x30,0x34,0x48,0xbb,0xc2,
0xdf,0x12,0xb9,0x81,0xad,0x36,0x3f,0xf0,0x24,0x16,0x48,0x04,0x4a,0x7f,0xfd,0x9f,
0x4c,0xea,0xfe,0x1d,0x83,0xd0,0x81,0xad,0x25,0x6c,0x5f,0x45,0x36,0x91,0xf0,0xd5,
0x8b,0x53,0x0a,0xdf,0xec,0x9f,0x04,0x58,0xc4,0x35,0xa0,0x78,0x1f,0x68,0xe0,0x22}};
const TPM2B_RSA_TEST_VALUE
c_RsapssKvt = {RSA_TEST_KEY_SIZE, {0x3f,0x3a,0x82,0x6d,0x42,0xe3,0x8b,0x4f,0x45,0x9c,0xda,0x6c,0xbe,0xbe,0xcd,0x00,
0x98,0xfb,0xbe,0x59,0x30,0xc6,0x3c,0xaa,0xb3,0x06,0x27,0xb5,0xda,0xfa,0xb2,0xc3,
0x43,0xb7,0xbd,0xe9,0xd3,0x23,0xed,0x80,0xce,0x74,0xb3,0xb8,0x77,0x8d,0xe6,0x8d,
0x3c,0xe5,0xf5,0xd7,0x80,0xcf,0x38,0x55,0x76,0xd7,0x87,0xa8,0xd6,0x3a,0xcf,0xfd,
0xd8,0x91,0x65,0xab,0x43,0x66,0x50,0xb7,0x9a,0x13,0x6b,0x45,0x80,0x76,0x86,0x22,
0x27,0x72,0xf7,0xbb,0x65,0x22,0x5c,0x55,0x60,0xd8,0x84,0x9f,0xf2,0x61,0x52,0xac,
0xf2,0x4f,0x5b,0x7b,0x21,0xe1,0xf5,0x4b,0x8f,0x01,0xf2,0x4b,0xcf,0xd3,0xfb,0x74,
0x5e,0x6e,0x96,0xb4,0xa8,0x0f,0x01,0x9b,0x26,0x54,0x0a,0x70,0x55,0x26,0xb7,0x0b,
0xe8,0x01,0x68,0x66,0x0d,0x6f,0xb5,0xfc,0x66,0xbd,0x9e,0x44,0xed,0x6a,0x1e,0x3c,
0x3b,0x61,0x5d,0xe8,0xdb,0x99,0x5b,0x67,0xbf,0x94,0xfb,0xe6,0x8c,0x4b,0x07,0xcb,

Page 486
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

Trusted Platform Module Library

0x43,0x3a,0x0d,0xb1,0x1b,0x10,0x66,0x81,0xe2,0x0d,0xe7,0xd1,0xca,0x85,0xa7,0x50,
0x82,0x2d,0xbf,0xed,0xcf,0x43,0x6d,0xdb,0x2c,0x7b,0x73,0x20,0xfe,0x73,0x3f,0x19,
0xc6,0xdb,0x69,0xb8,0xc3,0xd3,0xf4,0xe5,0x64,0xf8,0x36,0x8e,0xd5,0xd8,0x09,0x2a,
0x5f,0x26,0x70,0xa1,0xd9,0x5b,0x14,0xf8,0x22,0xe9,0x9d,0x22,0x51,0xf4,0x52,0xc1,
0x6f,0x53,0xf5,0xca,0x0d,0xda,0x39,0x8c,0x29,0x42,0xe8,0x58,0x89,0xbb,0xd1,0x2e,
0xc5,0xdb,0x86,0x8d,0xaf,0xec,0x58,0x36,0x8d,0x8d,0x57,0x23,0xd5,0xdd,0xb9,0x24}};
const TPM2B_RSA_TEST_VALUE
c_RsassaKvt = {RSA_TEST_KEY_SIZE, {0x39,0x10,0x58,0x7d,0x6d,0xa8,0xd5,0x90,0x07,0xd6,0x2b,0x13,0xe9,0xd8,0x93,0x7e,
0xf3,0x5d,0x71,0xe0,0xf0,0x33,0x3a,0x4a,0x22,0xf3,0xe6,0x95,0xd3,0x8e,0x8c,0x41,
0xe7,0xb3,0x13,0xde,0x4a,0x45,0xd3,0xd1,0xfb,0xb1,0x3f,0x9b,0x39,0xa5,0x50,0x58,
0xef,0xb6,0x3a,0x43,0xdd,0x54,0xab,0xda,0x9d,0x32,0x49,0xe4,0x57,0x96,0xe5,0x1b,
0x1d,0x8f,0x33,0x8e,0x07,0x67,0x56,0x14,0xc1,0x18,0x78,0xa2,0x52,0xe6,0x2e,0x07,
0x81,0xbe,0xd8,0xca,0x76,0x63,0x68,0xc5,0x47,0xa2,0x92,0x5e,0x4c,0xfd,0x14,0xc7,
0x46,0x14,0xbe,0xc7,0x85,0xef,0xe6,0xb8,0x46,0xcb,0x3a,0x67,0x66,0x89,0xc6,0xee,
0x9d,0x64,0xf5,0x0d,0x09,0x80,0x9a,0x6f,0x0e,0xeb,0xe4,0xb9,0xe9,0xab,0x90,0x4f,
0xe7,0x5a,0xc8,0xca,0xf6,0x16,0x0a,0x82,0xbd,0xb7,0x76,0x59,0x08,0x2d,0xd9,0x40,
0x5d,0xaa,0xa5,0xef,0xfb,0xe3,0x81,0x2c,0x2c,0x5c,0xa8,0x16,0xbd,0x63,0x20,0xc2,
0x4d,0x3b,0x51,0xaa,0x62,0x1f,0x06,0xe5,0xbb,0x78,0x44,0x04,0x0c,0x5c,0xe1,0x1b,
0x6b,0x9d,0x21,0x10,0xaf,0x48,0x48,0x98,0x97,0x77,0xc2,0x73,0xb4,0x98,0x64,0xcc,
0x94,0x2c,0x29,0x28,0x45,0x36,0xd1,0xc5,0xd0,0x2f,0x97,0x27,0x92,0x65,0x22,0xbb,
0x63,0x79,0xea,0xf5,0xff,0x77,0x0f,0x4b,0x56,0x8a,0x9f,0xad,0x1a,0x97,0x67,0x39,
0x69,0xb8,0x4c,0x6c,0xc2,0x56,0xc5,0x7a,0xa8,0x14,0x5a,0x24,0x7a,0xa4,0x6e,0x55,
0xb2,0x86,0x1d,0xf4,0x62,0x5a,0x2d,0x87,0x6d,0xde,0x99,0x78,0x2d,0xef,0xd7,0xdc}};#endif // SHA384#if ALG_SHA512_VALUE == DEFAULT_TEST_HASH
const TPM2B_RSA_TEST_VALUE
c_OaepKvt = {RSA_TEST_KEY_SIZE, {0x48,0x45,0xa7,0x70,0xb2,0x41,0xb7,0x48,0x5e,0x79,0x8c,0xdf,0x1c,0xc6,0x7e,0xbb,
0x11,0x80,0x82,0x52,0xbf,0x40,0x3d,0x90,0x03,0x6e,0x20,0x3a,0xb9,0x65,0xc8,0x51,
0x4c,0xbd,0x9c,0xa9,0x43,0x89,0xd0,0x57,0x0c,0xa3,0x69,0x22,0x7e,0x82,0x2a,0x1c,
0x1d,0x5a,0x80,0x84,0x81,0xbb,0x5e,0x5e,0xd0,0xc1,0x66,0x9a,0xac,0x00,0xba,0x14,
0xa2,0xe9,0xd0,0x3a,0x89,0x5a,0x63,0xe2,0xec,0x92,0x05,0xf4,0x47,0x66,0x12,0x7f,
0xdb,0xa7,0x3c,0x5b,0x67,0xe1,0x55,0xca,0x0a,0x27,0xbf,0x39,0x89,0x11,0x05,0xba,
0x9b,0x5a,0x9b,0x65,0x44,0xad,0x78,0xcf,0x8f,0x94,0xf6,0x9a,0xb4,0x52,0x39,0x0e,
0x00,0xba,0xbc,0xe0,0xbd,0x6f,0x81,0x2d,0x76,0x42,0x66,0x70,0x07,0x77,0xbf,0x09,
0x88,0x2a,0x0c,0xb1,0x56,0x3e,0xee,0xfd,0xdc,0xb6,0x3c,0x0d,0xc5,0xa4,0x0d,0x10,
0x32,0x80,0x3e,0x1e,0xfe,0x36,0x8f,0xb5,0x42,0xc1,0x21,0x7b,0xdf,0xdf,0x4a,0xd2,
0x68,0x0c,0x01,0x9f,0x4a,0xfd,0xd4,0xec,0xf7,0x49,0x06,0xab,0xed,0xc6,0xd5,0x1b,
0x63,0x76,0x38,0xc8,0x6c,0xc7,0x4f,0xcb,0x29,0x8a,0x0e,0x6f,0x33,0xaf,0x69,0x31,
0x8e,0xa7,0xdd,0x9a,0x36,0xde,0x9b,0xf1,0x0b,0xfb,0x20,0xa0,0x6d,0x33,0x31,0xc9,
0x9e,0xb4,0x2e,0xc5,0x40,0x0e,0x60,0x71,0x36,0x75,0x05,0xf9,0x37,0xe0,0xca,0x8e,
0x8f,0x56,0xe0,0xea,0x9b,0xeb,0x17,0xf3,0xca,0x40,0xc3,0x48,0x01,0xba,0xdc,0xc6,
0x4b,0x2b,0x5b,0x7b,0x5c,0x81,0xa6,0xbb,0xc7,0x43,0xc0,0xbe,0xc0,0x30,0x7b,0x55}};
const TPM2B_RSA_TEST_VALUE
c_RsaesKvt = {RSA_TEST_KEY_SIZE, {0x74,0x83,0xfa,0x52,0x65,0x50,0x68,0xd0,0x82,0x05,0x72,0x70,0x78,0x1c,0xac,0x10,
0x23,0xc5,0x07,0xf8,0x93,0xd2,0xeb,0x65,0x87,0xbb,0x47,0xc2,0xfb,0x30,0x9e,0x61,
0x4c,0xac,0x04,0x57,0x5a,0x7c,0xeb,0x29,0x08,0x84,0x86,0x89,0x1e,0x8f,0x07,0x32,
0xa3,0x8b,0x70,0xe7,0xa2,0x9f,0x9c,0x42,0x71,0x3d,0x23,0x59,0x82,0x5e,0x8a,0xde,
0xd6,0xfb,0xd8,0xc5,0x8b,0xc0,0xdb,0x10,0x38,0x87,0xd3,0xbf,0x04,0xb0,0x66,0xb9,
0x85,0x81,0x54,0x4c,0x69,0xdc,0xba,0x78,0xf3,0x4a,0xdb,0x25,0xa2,0xf2,0x34,0x55,
0xdd,0xaa,0xa5,0xc4,0xed,0x55,0x06,0x0e,0x2a,0x30,0x77,0xab,0x82,0x79,0xf0,0xcd,
0x9d,0x6f,0x09,0xa0,0xc8,0x82,0xc9,0xe0,0x61,0xda,0x40,0xcd,0x17,0x59,0xc0,0xef,
0x95,0x6d,0xa3,0x6d,0x1c,0x2b,0xee,0x24,0xef,0xd8,0x4a,0x55,0x6c,0xd6,0x26,0x42,
0x32,0x17,0xfd,0x6a,0xb3,0x4f,0xde,0x07,0x2f,0x10,0xd4,0xac,0x14,0xea,0x89,0x68,
0xcc,0xd3,0x07,0xb7,0xcf,0xba,0x39,0x20,0x63,0x20,0x7b,0x44,0x8b,0x48,0x60,0x5d,
0x3a,0x2a,0x0a,0xe9,0x68,0xab,0x15,0x46,0x27,0x64,0xb5,0x82,0x06,0x29,0xe7,0x25,
0xca,0x46,0x48,0x6e,0x2a,0x34,0x57,0x4b,0x81,0x75,0xae,0xb6,0xfd,0x6f,0x51,0x5f,
0x04,0x59,0xc7,0x15,0x1f,0xe0,0x68,0xf7,0x36,0x2d,0xdf,0xc8,0x9d,0x05,0x27,0x2d,
0x3f,0x2b,0x59,0x5d,0xcb,0xf3,0xc4,0x92,0x6e,0x00,0xa8,0x8d,0xd0,0x69,0xe5,0x59,
0xda,0xba,0x4f,0x38,0xf5,0xa0,0x8b,0xf1,0x73,0xe9,0x0d,0xee,0x64,0xe5,0xa2,0xd8}};
const TPM2B_RSA_TEST_VALUE
c_RsapssKvt = {RSA_TEST_KEY_SIZE, {0x1b,0xca,0x8b,0x18,0x15,0x3b,0x95,0x5b,0x0a,0x89,0x10,0x03,0x7f,0x7c,0xa0,0xc9,
0x66,0x57,0x86,0x6a,0xc9,0xeb,0x82,0x71,0xf3,0x8d,0x6f,0xa9,0xa4,0x2d,0xd0,0x22,
0xdf,0xe9,0xc6,0x71,0x5b,0xf4,0x27,0x38,0x5b,0x2c,0x8a,0x54,0xcc,0x85,0x11,0x69,
0x6d,0x6f,0x42,0xe7,0x22,0xcb,0xd6,0xad,0x1a,0xc5,0xab,0x6a,0xa5,0xfc,0xa5,0x70,
0x72,0x4a,0x62,0x25,0xd0,0xa2,0x16,0x61,0xab,0xac,0x31,0xa0,0x46,0x24,0x4f,0xdd,
0x9a,0x36,0x55,0xb6,0x00,0x9e,0x23,0x50,0x0d,0x53,0x01,0xb3,0x46,0x56,0xb2,0x1d,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 487
April 15, 2019

Trusted Platform Module Library
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

Part 4: Supporting Routines

0x33,0x5b,0xca,0x41,0x7f,0x65,0x7e,0x00,0x5c,0x12,0xff,0x0a,0x70,0x5d,0x8c,0x69,
0x4a,0x02,0xee,0x72,0x30,0xa7,0x5c,0xa4,0xbb,0xbe,0x03,0x0c,0xe4,0x5f,0x33,0xb6,
0x78,0x91,0x9d,0xd8,0xec,0x34,0x03,0x2e,0x63,0x32,0xc7,0x2a,0x36,0x50,0xd5,0x8b,
0x0e,0x7f,0x54,0x4e,0xf4,0x29,0x11,0x1b,0xcd,0x0f,0x37,0xa5,0xbc,0x61,0x83,0x50,
0xfa,0x18,0x75,0xd9,0xfe,0xa7,0xe8,0x9b,0xc1,0x4f,0x96,0x37,0x81,0x71,0xdf,0x71,
0x8b,0x89,0x81,0xf4,0x95,0xb5,0x29,0x66,0x41,0x0c,0x73,0xd7,0x0b,0x21,0xb4,0xfb,
0xf9,0x63,0x2f,0xe9,0x7b,0x38,0xaa,0x20,0xc3,0x96,0xcc,0xb7,0xb2,0x24,0xa1,0xe0,
0x59,0x9c,0x10,0x9e,0x5a,0xf7,0xe3,0x02,0xe6,0x23,0xe2,0x44,0x21,0x3f,0x6e,0x5e,
0x79,0xb2,0x93,0x7d,0xce,0xed,0xe2,0xe1,0xab,0x98,0x07,0xa7,0xbd,0xbc,0xd8,0xf7,
0x06,0xeb,0xc5,0xa6,0x37,0x18,0x11,0x88,0xf7,0x63,0x39,0xb9,0x57,0x29,0xdc,0x03}};
const TPM2B_RSA_TEST_VALUE
c_RsassaKvt = {RSA_TEST_KEY_SIZE, {0x05,0x55,0x00,0x62,0x01,0xc6,0x04,0x31,0x55,0x73,0x3f,0x2a,0xf9,0xd4,0x0f,0xc1,
0x2b,0xeb,0xd8,0xc8,0xdb,0xb2,0xab,0x6c,0x26,0xde,0x2d,0x89,0xc2,0x2d,0x36,0x62,
0xc8,0x22,0x5d,0x58,0x03,0xb1,0x46,0x14,0xa5,0xd4,0xbc,0x25,0x6b,0x7f,0x8f,0x14,
0x7e,0x03,0x2f,0x3d,0xb8,0x39,0xa5,0x79,0x13,0x7e,0x22,0x2a,0xb9,0x3e,0x8f,0xaa,
0x01,0x7c,0x03,0x12,0x21,0x6c,0x2a,0xb4,0x39,0x98,0x6d,0xff,0x08,0x6c,0x59,0x2d,
0xdc,0xc6,0xf1,0x77,0x62,0x10,0xa6,0xcc,0xe2,0x71,0x8e,0x97,0x00,0x87,0x5b,0x0e,
0x20,0x00,0x3f,0x18,0x63,0x83,0xf0,0xe4,0x0a,0x64,0x8c,0xe9,0x8c,0x91,0xe7,0x89,
0x04,0x64,0x2c,0x8b,0x41,0xc8,0xac,0xf6,0x5a,0x75,0xe6,0xa5,0x76,0x43,0xcb,0xa5,
0x33,0x8b,0x07,0xc9,0x73,0x0f,0x45,0xa4,0xc3,0xac,0xc1,0xc3,0xe6,0xe7,0x21,0x66,
0x1c,0xba,0xbf,0xea,0x3e,0x39,0xfa,0xb2,0xe2,0x8f,0xfe,0x9c,0xb4,0x85,0x89,0x33,
0x2a,0x0c,0xc8,0x5d,0x58,0xe1,0x89,0x12,0xe9,0x4d,0x42,0xb3,0x1f,0x99,0x0c,0x3e,
0xd8,0xb2,0xeb,0xf5,0x88,0xfb,0xe1,0x4b,0x8e,0xdc,0xd3,0xa8,0xda,0xbe,0x04,0x45,
0xbf,0x56,0xc6,0x54,0x70,0x00,0xb8,0x66,0x46,0x3a,0xa3,0x1e,0xb6,0xeb,0x1a,0xa0,
0x0b,0xd3,0x9a,0x9a,0x52,0xda,0x60,0x69,0xb7,0xef,0x93,0x47,0x38,0xab,0x1a,0xa0,
0x22,0x6e,0x76,0x06,0xb6,0x74,0xaf,0x74,0x8f,0x51,0xc0,0x89,0x5a,0x4b,0xbe,0x6a,
0x91,0x18,0x25,0x7d,0xa6,0x77,0xe6,0xfd,0xc2,0x62,0x36,0x07,0xc6,0xef,0x79,0xc9}};#endif // SHA512

Page 488
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.10 SymmetricTestData.h
This is a vector for testing either encrypt or decrypt. The premise for decrypt is that the IV for decryption is
the same as the IV for encryption. However, the ivOut value may be different for encryption anddecryption. We will encrypt at least two blocks. This means that the chaining value will be used for eachof the schemes (if any) and that implicitly checks that the chaining value is handled properly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#if AES_128
const BYTE key_AES128 [] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
const BYTE dataIn_AES128 [] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51};
const BYTE dataOut_AES128_ECB [] = {0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d,
0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf};
const BYTE dataOut_AES128_CBC [] = {0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee,
0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2};
const BYTE dataOut_AES128_CFB [] = {0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f,
0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b};
const BYTE dataOut_AES128_OFB [] = {0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25};
const BYTE dataOut_AES128_CTR [] = {0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff,
0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff};#endif#if AES_192
const BYTE key_AES192 [] = {0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b};
const BYTE dataIn_AES192 [] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51};
const BYTE dataOut_AES192_ECB [] = {0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f,
0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad,
0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef};
const BYTE dataOut_AES192_CBC [] = {0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a};const BYTE dataOut_AES192_CFB [] = {0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 489
April 15, 2019

Trusted Platform Module Library
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

const BYTE

const BYTEPart 4: Supporting Routines

0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21,
0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a};
dataOut_AES192_OFB [] = {0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab,
0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01};
dataOut_AES192_CTR [] = {0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2,
0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b,
0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef,
0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94};#endif#if AES_256
const BYTE key_AES256 [] = {0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4};
const BYTE dataIn_AES256 [] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51};
const BYTE dataOut_AES256_ECB [] = {0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c,
0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26,
0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70};
const BYTE dataOut_AES256_CBC [] = {0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d};
const BYTE dataOut_AES256_CFB [] = {0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b,
0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8,
0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b};
const BYTE dataOut_AES256_OFB [] = {0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b,
0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d};
const BYTE dataOut_AES256_CTR [] = {0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5,
0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28,
0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a,
0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5};#endifPage 490
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.11 SymmetricTest.h
10.1.11.1 Introduction
This file contains the structures and data definitions for the symmetric tests. This file references theheader file that contains the actual test vectors. This organization was chosen so that the program that isused to generate the test vector values does not have to also re-generate this data.
1
2
3
4
5
6

#ifndef
SELF_TEST_DATA#error "This file many only be included in AlgorithmTests.c"#endif#ifndef_SYMMETRIC_TEST_H#define_SYMMETRIC_TEST_H#include"SymmetricTestData.h"

10.1.11.2 Symmetric Test Structures
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

const SYMMETRIC_TEST_VECTOR
c_symTestValues[NUM_SYMS + 1] = {#if ALG_AES && AES_128{ALG_AES_VALUE, 128, key_AES128, 16, sizeof(dataIn_AES128), dataIn_AES128,{dataOut_AES128_CTR, dataOut_AES128_OFB, dataOut_AES128_CBC,
dataOut_AES128_CFB, dataOut_AES128_ECB}},#endif#if ALG_AES && AES_192{ALG_AES_VALUE, 192, key_AES192, 16, sizeof(dataIn_AES192), dataIn_AES192,{dataOut_AES192_CTR, dataOut_AES192_OFB, dataOut_AES192_CBC,
dataOut_AES192_CFB, dataOut_AES192_ECB}},#endif#if ALG_AES && AES_256{ALG_AES_VALUE, 256, key_AES256, 16, sizeof(dataIn_AES256), dataIn_AES256,{dataOut_AES256_CTR, dataOut_AES256_OFB, dataOut_AES256_CBC,
dataOut_AES256_CFB, dataOut_AES256_ECB}},#endif#if ALG_SM4 && SM4_128{ALG_SM4_VALUE, 128, key_SM4128, 16, sizeof(dataIn_SM4128), dataIn_SM4128,{dataOut_SM4128_CTR, dataOut_SM4128_OFB, dataOut_SM4128_CBC,
dataOut_SM4128_CFB, dataOut_AES128_ECB}},#endif{0}};#endif // _SYMMETRIC_TEST_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 491
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.1.12 EccTestData.h
This file contains the parameter data for ECC testing.
1
2
3#ifdef SELF_TEST_DATA
TPM2B_TYPE(EC_TEST, 32);
const TPM_ECC_CURVE

c_testCurve = 00003;

The static key
4
5
6
7
8
9
10
11
12

const TPM2B_EC_TEST
c_ecTestKey_ds = {{32, {0xdf,0x8d,0xa4,0xa3,0x88,0xf6,0x76,0x96,0x89,0xfc,0x2f,0x2d,0xa1,0xb4,0x39,0x7a,
0x78,0xc4,0x7f,0x71,0x8c,0xa6,0x91,0x85,0xc0,0xbf,0xf3,0x54,0x20,0x91,0x2f,0x73}}};
const TPM2B_EC_TEST
c_ecTestKey_QsX = {{32, {0x17,0xad,0x2f,0xcb,0x18,0xd4,0xdb,0x3f,0x2c,0x53,0x13,0x82,0x42,0x97,0xff,0x8d,
0x99,0x50,0x16,0x02,0x35,0xa7,0x06,0xae,0x1f,0xda,0xe2,0x9c,0x12,0x77,0xc0,0xf9}}};const TPM2B_EC_TEST
c_ecTestKey_QsY = {{32, {0xa6,0xca,0xf2,0x18,0x45,0x96,0x6e,0x58,0xe6,0x72,0x34,0x12,0x89,0xcd,0xaa,0xad,
0xcb,0x68,0xb2,0x51,0xdc,0x5e,0xd1,0x6d,0x38,0x20,0x35,0x57,0xb2,0xfd,0xc7,0x52}}};The ephemeral key
13
14
15
16
17
18
19
20
21

const TPM2B_EC_TEST
c_ecTestKey_de = {{32, {0xb6,0xb5,0x33,0x5c,0xd1,0xee,0x52,0x07,0x99,0xea,0x2e,0x8f,0x8b,0x19,0x18,0x07,
0xc1,0xf8,0xdf,0xdd,0xb8,0x77,0x00,0xc7,0xd6,0x53,0x21,0xed,0x02,0x53,0xee,0xac}}};const TPM2B_EC_TEST
c_ecTestKey_QeX = {{32, {0xa5,0x1e,0x80,0xd1,0x76,0x3e,0x8b,0x96,0xce,0xcc,0x21,0x82,0xc9,0xa2,0xa2,0xed,
0x47,0x21,0x89,0x53,0x44,0xe9,0xc7,0x92,0xe7,0x31,0x48,0x38,0xe6,0xea,0x93,0x47}}};
const TPM2B_EC_TEST
c_ecTestKey_QeY = {{32, {0x30,0xe6,0x4f,0x97,0x03,0xa1,0xcb,0x3b,0x32,0x2a,0x70,0x39,0x94,0xeb,0x4e,0xea,
0x55,0x88,0x81,0x3f,0xb5,0x00,0xb8,0x54,0x25,0xab,0xd4,0xda,0xfd,0x53,0x7a,0x18}}};ECDH test results
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

const TPM2B_EC_TEST
c_ecTestEcdh_X = {{32, {0x64,0x02,0x68,0x92,0x78,0xdb,0x33,0x52,0xed,0x3b,0xfa,0x3b,0x74,0xa3,0x3d,0x2c,
0x2f,0x9c,0x59,0x03,0x07,0xf8,0x22,0x90,0xed,0xe3,0x45,0xf8,0x2a,0x0a,0xd8,0x1d}}};const TPM2B_EC_TEST
c_ecTestEcdh_Y = {{32, {0x58,0x94,0x05,0x82,0xbe,0x5f,0x33,0x02,0x25,0x90,0x3a,0x33,0x90,0x89,0xe3,0xe5,
0x10,0x4a,0xbc,0x78,0xa5,0xc5,0x07,0x64,0xaf,0x91,0xbc,0xe6,0xff,0x85,0x11,0x40}}};TPM2B_TYPE(TEST_VALUE, 64);
const TPM2B_TEST_VALUE
c_ecTestValue = {{64, {0x78,0xd5,0xd4,0x56,0x43,0x61,0xdb,0x97,0xa4,0x32,0xc4,0x0b,0x06,0xa9,0xa8,0xa0,
0xf4,0x45,0x7f,0x13,0xd8,0x13,0x81,0x0b,0xe5,0x76,0xbe,0xaa,0xb6,0x3f,0x8d,0x4d,
0x23,0x65,0xcc,0xa7,0xc9,0x19,0x10,0xce,0x69,0xcb,0x0c,0xc7,0x11,0x8d,0xc3,0xff,
0x62,0x69,0xa2,0xbe,0x46,0x90,0xe7,0x7d,0x81,0x77,0x94,0x65,0x1c,0x3e,0xc1,0x3e}}};#if ALG_SHA1_VALUE == DEFAULT_TEST_HASH
const TPM2B_EC_TEST
c_TestEcDsa_r = {{32, {0x57,0xf3,0x36,0xb7,0xec,0xc2,0xdd,0x76,0x0e,0xe2,0x81,0x21,0x49,0xc5,0x66,0x11,
0x4b,0x8a,0x4f,0x17,0x62,0x82,0xcc,0x06,0xf6,0x64,0x78,0xef,0x6b,0x7c,0xf2,0x6c}}};const TPM2B_EC_TEST
c_TestEcDsa_s = {{32, {0x1b,0xed,0x23,0x72,0x8f,0x17,0x5f,0x47,0x2e,0xa7,0x97,0x2c,0x51,0x57,0x20,0x70,
0x6f,0x89,0x74,0x8a,0xa8,0xf4,0x26,0xf4,0x96,0xa1,0xb8,0x3e,0xe5,0x35,0xc5,0x94}}};
const TPM2B_EC_TEST
c_TestEcSchnorr_r = {{32,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x08,0x9f,0xde,
0xef,0x62,0xe3,0xf1,0x14,0xcb,0x54,0x28,0x13,0x76,0xfc,0x6d,0x69,0x22,0xb5,0x3e}}};const TPM2B_EC_TEST
c_TestEcSchnorr_s = {{32,{0xd9,0xd3,0x20,0xfb,0x4d,0x16,0xf2,0xe6,0xe2,0x45,0x07,0x45,0x1c,0x92,0x92,0x92,
0xa9,0x6b,0x48,0xf8,0xd1,0x98,0x29,0x4d,0xd3,0x8f,0x56,0xf2,0xbb,0x2e,0x22,0x3b}}};#endif // SHA1
#if ALG_SHA256_VALUE == DEFAULT_TEST_HASH
const TPM2B_EC_TEST
c_TestEcDsa_r = {{32, {0x04,0x7d,0x54,0xeb,0x04,0x6f,0x56,0xec,0xa2,0x6c,0x38,0x8c,0xeb,0x43,0x0b,0x71,

Page 492
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

Trusted Platform Module Library

0xf8,0xf2,0xf4,0xa5,0xe0,0x1d,0x3c,0xa2,0x39,0x31,0xe4,0xe7,0x36,0x3b,0xb5,0x5f}}};const TPM2B_EC_TEST
c_TestEcDsa_s = {{32, {0x8f,0xd0,0x12,0xd9,0x24,0x75,0xf6,0xc4,0x3b,0xb5,0x46,0x75,0x3a,0x41,0x8d,0x80,
0x23,0x99,0x38,0xd7,0xe2,0x40,0xca,0x9a,0x19,0x2a,0xfc,0x54,0x75,0xd3,0x4a,0x6e}}};const TPM2B_EC_TEST
c_TestEcSchnorr_r = {{32, {0xf7,0xb9,0x15,0x4c,0x34,0xf6,0x41,0x19,0xa3,0xd2,0xf1,0xbd,0xf4,0x13,0x6a,0x4f,
0x63,0xb8,0x4d,0xb5,0xc8,0xcd,0xde,0x85,0x95,0xa5,0x39,0x0a,0x14,0x49,0x3d,0x2f}}};const TPM2B_EC_TEST
c_TestEcSchnorr_s = {{32,{0xfe,0xbe,0x17,0xaa,0x31,0x22,0x9f,0xd0,0xd2,0xf5,0x25,0x04,0x92,0xb0,0xaa,0x4e,
0xcc,0x1c,0xb6,0x79,0xd6,0x42,0xb3,0x4e,0x3f,0xbb,0xfe,0x5f,0xd0,0xd0,0x8b,0xc3}}};#endif // SHA256#if ALG_SHA384_VALUE == DEFAULT_TEST_HASH
const TPM2B_EC_TEST
c_TestEcDsa_r = {{32, {0xf5,0x74,0x6d,0xd6,0xc6,0x56,0x86,0xbb,0xba,0x1c,0xba,0x75,0x65,0xee,0x64,0x31,
0xce,0x04,0xe3,0x9f,0x24,0x3f,0xbd,0xfe,0x04,0xcd,0xab,0x7e,0xfe,0xad,0xcb,0x82}}};const TPM2B_EC_TEST
c_TestEcDsa_s = {{32, {0xc2,0x4f,0x32,0xa1,0x06,0xc0,0x85,0x4f,0xc6,0xd8,0x31,0x66,0x91,0x9f,0x79,0xcd,
0x5b,0xe5,0x7b,0x94,0xa1,0x91,0x38,0xac,0xd4,0x20,0xa2,0x10,0xf0,0xd5,0x9d,0xbf}}};const TPM2B_EC_TEST
c_TestEcSchnorr_r = {{32, {0x1e,0xb8,0xe1,0xbf,0xa1,0x9e,0x39,0x1e,0x58,0xa2,0xe6,0x59,0xd0,0x1a,0x6a,0x03,
0x6a,0x1f,0x1c,0x4f,0x36,0x19,0xc1,0xec,0x30,0xa4,0x85,0x1b,0xe9,0x74,0x35,0x66}}};const TPM2B_EC_TEST
c_TestEcSchnorr_s = {{32,{0xb9,0xe6,0xe3,0x7e,0xcb,0xb9,0xea,0xf1,0xcc,0xf4,0x48,0x44,0x4a,0xda,0xc8,0xd7,
0x87,0xb4,0xba,0x40,0xfe,0x5b,0x68,0x11,0x14,0xcf,0xa0,0x0e,0x85,0x46,0x99,0x01}}};#endif // SHA384#if ALG_SHA512_VALUE == DEFAULT_TEST_HASH
const TPM2B_EC_TEST
c_TestEcDsa_r = {{32, {0xc9,0x71,0xa6,0xb4,0xaf,0x46,0x26,0x8c,0x27,0x00,0x06,0x3b,0x00,0x0f,0xa3,0x17,
0x72,0x48,0x40,0x49,0x4d,0x51,0x4f,0xa4,0xcb,0x7e,0x86,0xe9,0xe7,0xb4,0x79,0xb2}}};const TPM2B_EC_TEST
c_TestEcDsa_s = {{32,{0x87,0xbc,0xc0,0xed,0x74,0x60,0x9e,0xfa,0x4e,0xe8,0x16,0xf3,0xf9,0x6b,0x26,0x07,
0x3c,0x74,0x31,0x7e,0xf0,0x62,0x46,0xdc,0xd6,0x45,0x22,0x47,0x3e,0x0c,0xa0,0x02}}};const TPM2B_EC_TEST
c_TestEcSchnorr_r = {{32,{0xcc,0x07,0xad,0x65,0x91,0xdd,0xa0,0x10,0x23,0xae,0x53,0xec,0xdf,0xf1,0x50,0x90,
0x16,0x96,0xf4,0x45,0x09,0x73,0x9c,0x84,0xb5,0x5c,0x5f,0x08,0x51,0xcb,0x60,0x01}}};const TPM2B_EC_TEST
c_TestEcSchnorr_s = {{32,{0x55,0x20,0x21,0x54,0xe2,0x49,0x07,0x47,0x71,0xf4,0x99,0x15,0x54,0xf3,0xab,0x14,
0xdb,0x8e,0xda,0x79,0xb6,0x02,0x0e,0xe3,0x5e,0x6f,0x2c,0xb6,0x05,0xbd,0x14,0x10}}};#endif // SHA512#endif // SELF_TEST_DATA

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 493
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.1.13 CryptSym.h
10.1.13.1 Introduction
This file contains the implementation of the symmetric block cipher modes allowed for a TPM. These
functions only use the single block encryption functions of the selected symmetric cryptographic library.
10.1.13.2 Includes, Defines, and Typedefs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#ifndef CRYPT_SYM_H#define CRYPT_SYM_H
typedef union tpmCryptKeySchedule_t {#if ALG_AES
tpmKeyScheduleAES
AES;#endif#if ALG_SM4
tpmKeyScheduleSM4
SM4;#endif#if ALG_CAMELLIA
tpmKeyScheduleCAMELLIACAMELLIA;#endif#if ALG_TDES
tpmKeyScheduleTDES
TDES[3];#endif#if SYMMETRIC_ALIGNMENT == 8
uint64_talignment;#else
uint32_talignment;#endif} tpmCryptKeySchedule_t;

Each block cipher within a library is expected to conform to the same calling conventions with threeparameters (keySchedule, in, and out) in the same order. That means that all algorithms would use thesame order of the same parameters. The code is written assuming the (keySchedule, in, and out) order.
However, if the library uses a different order, the order can be changed with a SWIZZLE macro that puts
the parameters in the correct order. Note that all algorithms have to use the same order and number ofparameters because the code to build the calling list is common for each call to encrypt or decrypt withthe algorithm chosen by setting a function pointer to select the algorithm that is used.
23
24
25
26

#
#

define ENCRYPT(keySchedule, in, out)
encrypt(SWIZZLE(keySchedule, in, out))
define DECRYPT(keySchedule, in, out)
decrypt(SWIZZLE(keySchedule, in, out))\\

Note that the macros rely on encrypt as local values in the functions that use these macros. Thoseparameters are set by the macro that set the key schedule to be used for the call.
27
28
29
30
31
32
33
34
35
36
37
38

#define ENCRYPT_CASE(ALG)
case TPM_ALG_##ALG:
TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.ALG);
encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG;
break;#define DECRYPT_CASE(ALG)
case TPM_ALG_##ALG:
TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.ALG);
decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG;
break;#if ALG_AES#define ENCRYPT_CASE_AES
ENCRYPT_CASE(AES)

\
\
\
\

Page 494

Family “2.0”April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\

Level 00 Revision 01.55

Part 4: Supporting Routines
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

Trusted Platform Module Library#define DECRYPT_CASE_AES
DECRYPT_CASE(AES)#else#define ENCRYPT_CASE_AES#define DECRYPT_CASE_AES#endif#if ALG_SM4#define ENCRYPT_CASE_SM4
ENCRYPT_CASE(SM4)#define DECRYPT_CASE_SM4
DECRYPT_CASE(SM4)#else#define ENCRYPT_CASE_SM4#define DECRYPT_CASE_SM4#endif#if ALG_CAMELLIA#define ENCRYPT_CASE_CAMELLIAENCRYPT_CASE(CAMELLIA)#define DECRYPT_CASE_CAMELLIADECRYPT_CASE(CAMELLIA)#else#define ENCRYPT_CASE_CAMELLIA#define DECRYPT_CASE_CAMELLIA#endif#if ALG_TDES#define ENCRYPT_CASE_TDESENCRYPT_CASE(TDES)#define DECRYPT_CASE_TDESDECRYPT_CASE(TDES)#else#define ENCRYPT_CASE_TDES#define DECRYPT_CASE_TDES#endif

For each algorithm the case will either be defined or null.
65
66
67
68
69
70
71
72
73
74
75

#define
SELECT(direction)
switch(algorithm){
direction##_CASE_AES
direction##_CASE_SM4
direction##_CASE_CAMELLIA
direction##_CASE_TDES
default:
FAIL(FATAL_ERROR_INTERNAL);}#endif // CRYPT_SYM_H

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\
\
\
\
\
\
\
\

Page 495
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.1.14 OIDS.h
1
2#ifndef _OIDS_H_#define _OIDS_H_

All the OIDs in this file are defined as DER-encoded values with a leading tag 0x06
(ASN1_OBJECT_IDENTIFIER), followed by a single length byte. This allows the OID size to be
determined by looking at octet[1] of the OID (total size is OID[1] + 2).
3
4#define MAKE_OID(NAME)\
EXTERN const BYTE OID##NAME[] INITIALIZER({OID##NAME##_VALUE})

These macros allow OIDs to be defined (or not) depending on whether the associated hash algorithm isimplemented.
NOTE:

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

When one of these macros is used, the NAME needs '_" on each side. The exception is when the macro isused for the hash OID when only a single _ is used.

#ifndef ALG_SHA1#
define ALG_SHA1 NO#endif#if ALG_SHA1#define SHA1_OID(NAME)
MAKE_OID(NAME##SHA1)#else#define SHA1_OID(NAME)#endif#ifndef ALG_SHA256#
define ALG_SHA256 NO#endif#if ALG_SHA256#define SHA256_OID(NAME) MAKE_OID(NAME##SHA256)#else#define SHA256_OID(NAME)#endif#ifndef ALG_SHA384#
define ALG_SHA384 NO#endif#if ALG_SHA384#define SHA384_OID(NAME) MAKE_OID(NAME##SHA384)#else#define SHA#84_OID(NAME)#endif#ifndef ALG_SHA512#
define ALG_SHA512 NO#endif#if ALG_SHA512#define SHA512_OID(NAME) MAKE_OID(NAME##SHA512)#else#define SHA512_OID(NAME)#endif#ifndef ALG_SM3_256#
define ALG_SM3_256 NO#endif#if ALG_SM3_256#define SM3_256_OID(NAME) MAKE_OID(NAME##SM2_256)#else#define SM3_256_OID(NAME)#endif#ifndef ALG_SHA3_256#
define ALG_SHA3_256 NO#endif#if ALG_SHA3_256#define SHA3_256_OID(NAME) MAKE_OID(NAME##SHA3_256)

Page 496
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

Trusted Platform Module Library#else#define SHA3_256_OID(NAME)#endif#ifndef ALG_SHA3_384#
define ALG_SHA3_384 NO#endif#if ALG_SHA3_384#define SHA3_384_OID(NAME) MAKE_OID(NAME##SHA3_384)#else#define SHA3_384_OID(NAME)#endif#ifndef ALG_SHA3_512#
define ALG_SHA3_512 NO#endif#if ALG_SHA3_512#define SSHA3_512_OID(NAME) MAKE_OID(NAME##SHA3_512)#else#define SHA3_512_OID(NAME)#endif

These are encoded to take one additional byte of algorithm selector
69
70#define NIST_HASH#define NIST_SIG

0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 2
0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 3

These hash OIDs used in a lot of places.
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

#define OID_SHA1_VALUE
0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
SHA1_OID(_);// Expands to//
MAKE_OID(_SHA1)// which expands to://extern BYTEOID_SHA1[]// or//
const BYTEOID_SHA1[] = {OID_SHA1_VALUE}// which is://const BYTEOID_SHA1[] = {0x06, 0x05, 0x2B, 0x0E,//
0x03, 0x02, 0x1A}#define OID_SHA256_VALUENIST_HASH, 1
SHA256_OID(_);#define OID_SHA384_VALUENIST_HASH, 2
SHA384_OID(_);#define OID_SHA512_VALUENIST_HASH, 3
SHA512_OID(_);#define OID_SM3_256_VALUE
0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \0x83, 0x11
SM3_256_OID(_);// (1.2.156.10197.1.401)#define OID_SHA3_256_VALUENIST_HASH, 8
SHA3_256_OID(_);#define OID_SHA3_384_VALUENIST_HASH, 9
SHA3_384_OID(_);#define OID_SHA3_512_VALUENIST_HASH, 10
SHA3_512_OID(_);

These are used for RSA-PSS
96
97
98
99
100
101
102

#if ALG_RSA#define OID_MGF1_VALUE
MAKE_OID(_MGF1);#define OID_RSAPSS_VALUE

0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \0x01, 0x01, 0x08
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \0x01, 0x01, 0x0A

MAKE_OID(_RSAPSS);This is the OID to designate the public part of an RSA key.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 497
April 15, 2019

Trusted Platform Module Library
103
104
105

#define OID_PKCS1_PUB_VALUEPart 4: Supporting Routines
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \0x01, 0x01, 0x01

MAKE_OID(_PKCS1_PUB);

These are used for RSA PKCS1 signature Algorithms
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

#define OID_PKCS1_SHA1_VALUE

0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,\
0x0D, 0x01, 0x01, 0x05
SHA1_OID(_PKCS1_);// (1.2.840.113549.1.1.5)#define OID_PKCS1_SHA256_VALUE
0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,\
0x0D, 0x01, 0x01, 0x0B
SHA256_OID(_PKCS1_);// (1.2.840.113549.1.1.11)#define OID_PKCS1_SHA384_VALUE
0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,\
0x0D, 0x01, 0x01, 0x0C
SHA384_OID(_PKCS1_);// (1.2.840.113549.1.1.12)#define OID_PKCS1_SHA512_VALUE
0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,\
0x0D, 0x01, 0x01, 0x0D
SHA512_OID(_PKCS1_);//(1.2.840.113549.1.1.13)#define OID_PKCS1_SM3_256_VALUE
0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55,\
0x01, 0x83, 0x78
SM3_256_OID(_PKCS1_);// 1.2.156.10197.1.504#define OID_PKCS1_SHA3_256_VALUENIST_SIG, 14
SHA3_256_OID(_PKCS1_);#define OID_PKCS1_SHA3_384_VALUENIST_SIG, 15
SHA3_256_OID(_PKCS1_);#define OID_PKCS1_SHA3_512_VALUENIST_SIG, 16
SHA3_512_OID(_PKCS1_);#endif // ALG_RSA#if ALG_ECDSA#define OID_ECDSA_SHA1_VALUE
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x01
SHA1_OID(_ECDSA_);// (1.2.840.10045.4.1) SHA1 digest signed by an ECDSA key.
#define OID_ECDSA_SHA256_VALUE
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x03, 0x02
SHA256_OID(_ECDSA_);// (1.2.840.10045.4.3.2) SHA256 digest signed by an ECDSA key.
#define OID_ECDSA_SHA384_VALUE
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x03, 0x03
SHA384_OID(_ECDSA_);// (1.2.840.10045.4.3.3) SHA384 digest signed by an ECDSA key.
#define OID_ECDSA_SHA512_VALUE
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x03, 0x04
SHA512_OID(_ECDSA_);// (1.2.840.10045.4.3.4) SHA512 digest signed by an ECDSA key.
#define OID_ECDSA_SM3_256_VALUE
0x00
SM3_256_OID(_ECDSA_);#define OID_ECDSA_SHA3_256_VALUENIST_SIG, 10
SHA3_256_OID(_ECDSA_);#define OID_ECDSA_SHA3_384_VALUENIST_SIG, 11
SHA3_384_OID(_ECDSA_);#define OID_ECDSA_SHA3_512_VALUENIST_SIG, 12
SHA3_512_OID(_ECDSA_);#endif // ALG_ECDSA#if ALG_ECC#define OID_ECC_PUBLIC_VALUE
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, \0x01
MAKE_OID(_ECC_PUBLIC);#define OID_ECC_NIST_P192_VALUE
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \0x01, 0x01
#if ECC_NIST_P192
MAKE_OID(_ECC_NIST_P192);// (1.2.840.10045.3.1.1) 'nistP192'#endif // ECC_NIST_P192#define OID_ECC_NIST_P224_VALUE
0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x21
#if ECC_NIST_P224
MAKE_OID(_ECC_NIST_P224);// (1.3.132.0.33)'nistP224'#endif // ECC_NIST_P224#define OID_ECC_NIST_P256_VALUE
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \0x01, 0x07

Page 498
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
165
166
167
168
169
170
171
172
173
174
175

Trusted Platform Module Library#if ECC_NIST_P256
MAKE_OID(_ECC_NIST_P256);// (1.2.840.10045.3.1.7) 'nistP256'#endif // ECC_NIST_P256#define OID_ECC_NIST_P384_VALUE
0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22
#if ECC_NIST_P384
MAKE_OID(_ECC_NIST_P384);// (1.3.132.0.34)'nistP384'#endif // ECC_NIST_P384#define OID_ECC_NIST_P521_VALUE
0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23
#if ECC_NIST_P521
MAKE_OID(_ECC_NIST_P521);// (1.3.132.0.35)'nistP521'#endif // ECC_NIST_P521

No OIDs defined for these anonymous curves
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

#define OID_ECC_BN_P256_VALUE#if ECC_BN_P256
MAKE_OID(_ECC_BN_P256);#endif // ECC_BN_P256#define OID_ECC_BN_P638_VALUE#if ECC_BN_P638
MAKE_OID(_ECC_BN_P638);#endif // ECC_BN_P638#define OID_ECC_SM2_P256_VALUE

0x00

0x00

0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \0x82, 0x2D

#if ECC_SM2_P256
MAKE_OID(_ECC_SM2_P256);// Don't know where I found this OID. It needs checking#endif // ECC_SM2_P256#if ECC_BN_P256#define OID_ECC_BN_P256
NULL#endif // ECC_BN_P256#endif // ALG_ECC#undef MAKE_OID#define OID_SIZE(OID)(OID[1] + 2)
#endif // !_OIDS_H_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 499
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.1.15 TpmAsn1.h
10.1.15.1 Introduction
This file contains the macro and structure definitions for the X509 commands and functions.
12#ifndef _TPMASN1_H_#define _TPMASN1_H_

10.1.15.2 Includes
34#include "Tpm.h"#include "OIDS.h"

10.1.15.3 Defined Constants
10.1.15.3.1
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

ASN.1 Universal Types (Class 00b#define ASN1_EOC
0x00#define ASN1_BOOLEAN
0x01#define ASN1_INTEGER
0x02#define ASN1_BITSTRING
0x03#define ASN1_OCTET_STRING
0x04#define ASN1_NULL
0x05#define ASN1_OBJECT_IDENTIFIER 0x06
#define ASN1_OBJECT_DESCRIPTOR 0x07
#define ASN1_EXTERNAL
0x08#define ASN1_REAL
0x09#define ASN1_ENUMERATED
0x0A#define ASN1_EMBEDDED
0x0B#define ASN1_UTF8String
0x0C#define ASN1_RELATIVE_OID
0x0D#define ASN1_SEQUENCE
0x10// Primitive + Constructed + 0x10
#define ASN1_SET
0x11// Primitive + Constructed + 0x11
#define ASN1_NumericString
0x12#define ASN1_PrintableString
0x13#define ASN1_T61String
0x14#define ASN1_VideoString
0x15#define ASN1_IA5String
0x16#define ASN1_UTCTime
0x17#define ASN1_GeneralizeTime
0x18#define ASN1_VisibleString
0x1A#define ASN1_GeneralString
0x1B#define ASN1_UniversalString
0x1C#define ASN1_CHARACTER STRING
0x1D#define ASN1_BMPString
0x1E#define ASN1_CONSTRUCTED
0x20#define ASN1_APPLICAIION_SPECIFIC
0xA0#define ASN1_CONSTRUCTED_SEQUENCE (ASN1_SEQUENCE + ASN1_CONSTRUCTED)#define MAX_DEPTH
10 // maximum push depth for marshaling context.

10.1.15.4 Macros
10.1.15.4.1
37
38
39

Unmarshaling Macros#ifndef VERIFY#define VERIFY(_X_) {if(!(_X_)) goto Error; }#endifPage 500
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

Checks the validity of the size making sure that there is no wrap around
40
41
42
43
44

#define CHECK_SIZE(context, length)
VERIFY((((length) + (context)->offset) >= (context)->offset)&& (((length) + (context)->offset) <= (context)->size))#define NEXT_OCTET(context) ((context)->buffer[(context)->offset++])#define PEEK_NEXT(context) ((context)->buffer[(context)->offset])

10.1.15.4.2\\

Marshaling Macros

Marshaling works in reverse order. The offset is set to the top of the buffer and, as the buffer is filled,
offset counts down to zero. When the full thing is encoded it can be moved to the top of the buffer. This
happens when the last context is closed (when the45#define CHECK_SPACE(context, length)

VERIFY(context->offset > length)10.1.15.5 Structures
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

typedef struct ASN1UnmarshalContext {BYTE*buffer;// pointer to the buffer
INT16
size;
// size of the buffer (a negative number indicates// a parsing failure).
INT16
offset;// current offset into the buffer (a negative number// indicates a parsing failure). Not used
BYTE
tag;
// The last unmarshaled tag} ASN1UnmarshalContext;
typedef struct ASN1MarshalContext {BYTE*buffer;// pointer to the start of the buffer
INT16
offset;// place on the top where the last entry was added// items are added from the bottom up.
INT16
end;
// the end offset of the current value
INT16
depth;// how many pushed end values.
INT16
ends[MAX_DEPTH];} ASN1MarshalContext;#endif // _TPMASN1_H_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 501
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.1.16 X509.h
10.1.16.1 Introduction
This file contains the macro and structure definitions for the X509 commands and functions.
12#ifndef _X509_H_#define _X509_H_

10.1.16.2 Includes
34#include "Tpm.h"#include "TpmASN1.h"

10.1.16.3 Defined Constants
10.1.16.3.1
5
6
7
8X509 Application-specific types#define X509_SELECTION#define X509_ISSUER_UNIQUE_ID#define X509_SUBJECT_UNIQUE_ID#define X509_EXTENSIONS

0xA0
0xA1
0xA2
0xA3

These defines give the order in which values appear in the TBScertificate of an x.509 certificate. These
values are used to index into an array of
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

#define ENCODED_SIZE_REF
0#define VERSION_REF(ENCODED_SIZE_REF + 1)
#define SERIAL_NUMBER_REF(VERSION_REF + 1)
#define SIGNATURE_REF(SERIAL_NUMBER_REF + 1)
#define ISSUER_REF(SIGNATURE_REF + 1)
#define VALIDITY_REF(ISSUER_REF + 1)
#define SUBJECT_KEY_REF(VALIDITY_REF + 1)
#define SUBJECT_PUBLIC_KEY_REF (SUBJECT_KEY_REF + 1)
#define EXTENSIONS_REF(SUBJECT_PUBLIC_KEY_REF + 1)
#define REF_COUNT(EXTENSIONS_REF + 1)
#undef MAKE_OID#ifdef _X509_SPT_#
define MAKE_OID(NAME)\
const BYTE
OID##NAME[] = {OID##NAME##_VALUE}#else#
define MAKE_OID(NAME)\
extern const BYTE
OID##NAME[]#endif10.1.16.4 Structures
Used to access the fields of a TBSsignature some of which are in the in_CertifyX509 structure and someof which are in the out_CertifyX509 structure.
27
28
29
30
31
32
33
34

typedef struct stringRef
{
BYTE
*buf;
INT16
len;
} stringRef;
typedef union x509KeyUsageUnion {TPMA_X509_KEY_USAGE
x509;
UINT32integer;

Page 502
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
35

Trusted Platform Module Library} x509KeyUsageUnion;

10.1.16.5 Global X509 Constants
These values are instanced by X509_spt.c and referenced by other X509-related files. This is the DERencoded value for the Key Usage OID (2.5.29.15). This is the full OID, not just the numeric value
36
37#define OID_KEY_USAGE_EXTENSTION_VALUE
MAKE_OID(_KEY_USAGE_EXTENSTION);

0x06, 0x03, 0x55, 0x1D, 0x0F

This is the DER-encoded value for the TCG-defined TPMA_OBJECT OID (2.23.133.10.1.1.1)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#define OID_TCG_TPMA_OBJECT_VALUE

0x06, 0x07, 0x67, 0x81, 0x05, 0x0a, 0x01,
0x01, 0x01\

MAKE_OID(_TCG_TPMA_OBJECT);#ifdef _X509_SPT_
const x509KeyUsageUnion keyUsageSign = TPMA_X509_KEY_USAGE_INITIALIZER(/* digitalsignature */ 1, /* nonrepudiation*/ 0,/* keyencipherment */ 0, /* dataencipherment */ 0,/* keyagreement*/ 0, /* keycertsign*/ 1,/* crlsign*/ 1, /* encipheronly*/ 0,/* decipheronly*/ 0, /* bits_at_9*/ 0);
const x509KeyUsageUnion keyUsageDecrypt = TPMA_X509_KEY_USAGE_INITIALIZER(/* digitalsignature */ 0, /* nonrepudiation*/ 0,/* keyencipherment */ 1, /* dataencipherment */ 1,/* keyagreement*/ 1, /* keycertsign*/ 0,/* crlsign*/ 0, /* encipheronly*/ 1,/* decipheronly*/ 1, /* bits_at_9*/ 0);#else
extern x509KeyUsageUnion keyUsageSign;
extern x509KeyUsageUnion keyUsageDecrypt;#endif#undef MAKE_OID#endif // _X509_H_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 503
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.1.17 MinMax.h
1
2
3
4
5
6
7
8
9

#ifndef _MIN_MAX_H_#define _MIN_MAX_H_#ifndef MAX#define MAX(a, b) ((a) > (b) ? (a) : (b))#endif#ifndef MIN#define MIN(a, b) ((a) < (b) ? (a) : (b))#endif#endif // _MIN_MAX_H_

Page 504
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.18 TpmAlgorithmDefines.h
This file contains the algorithm values from the TCG Algorithm Registry.
1
2#ifndef _TPM_ALGORITHM_DEFINES_H_#define _TPM_ALGORITHM_DEFINES_H_

Table 2:3 - Definition of Base Types Base Types are in BaseTypes.h
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#define ECC_CURVES\{TPM_ECC_BN_P256,
TPM_ECC_BN_P638,
TPM_ECC_NIST_P192,
TPM_ECC_NIST_P224, TPM_ECC_NIST_P256, TPM_ECC_NIST_P384,
TPM_ECC_NIST_P521, TPM_ECC_SM2_P256}#define ECC_CURVE_COUNT\(ECC_BN_P256+ ECC_BN_P638+ ECC_NIST_P192 + ECC_NIST_P224 +ECC_NIST_P256 + ECC_NIST_P384 + ECC_NIST_P521 + ECC_SM2_P256)#define MAX_ECC_KEY_BITS\
MAX(ECC_BN_P256 * 256,
MAX(ECC_BN_P638 * 638,
MAX(ECC_NIST_P192 * 192, MAX(ECC_NIST_P224 * 224,
MAX(ECC_NIST_P256 * 256, MAX(ECC_NIST_P384 * 384,
MAX(ECC_NIST_P521 * 521, MAX(ECC_SM2_P256 * 256,0))))))))#define MAX_ECC_KEY_BYTES
BITS_TO_BYTES(MAX_ECC_KEY_BITS)

\
\
\
\
\
\
\

Table 0:6 - Defines for PLATFORM Values
17
18
19
20
21

#define PLATFORM_FAMILY#define PLATFORM_LEVEL#define PLATFORM_VERSION#define PLATFORM_YEAR#define PLATFORM_DAY_OF_YEAR

TPM_SPEC_FAMILY
TPM_SPEC_LEVELTPM_SPEC_VERSIONTPM_SPEC_YEAR
TPM_SPEC_DAY_OF_YEAR

Table 1:12 - Defines for SHA1 Hash Values
22
23#define SHA1_DIGEST_SIZE#define SHA1_BLOCK_SIZE

2064

Table 1:13 - Defines for SHA256 Hash Values
2425#define SHA256_DIGEST_SIZE#define SHA256_BLOCK_SIZE

32
64

Table 1:14 - Defines for SHA384 Hash Values
26
27#define SHA384_DIGEST_SIZE#define SHA384_BLOCK_SIZE

48
128

Table 1:15 - Defines for SHA512 Hash Values
28
29#define SHA512_DIGEST_SIZE#define SHA512_BLOCK_SIZE

64
128

Table 1:16 - Defines for SM3_256 Hash Values
30
31#define SM3_256_DIGEST_SIZE#define SM3_256_BLOCK_SIZE

32
64

Table 1:16 - Defines for SHA3_256 Hash Values
32#define SHA3_256_DIGEST_SIZEFamily “2.0”Level 00 Revision 01.55

32

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 505
April 15, 2019

Trusted Platform Module Library33#define SHA3_256_BLOCK_SIZEPart 4: Supporting Routines
136

Table 1:16 - Defines for SHA3_384 Hash Values
34
35#define SHA3_384_DIGEST_SIZE#define SHA3_384_BLOCK_SIZE

48
104

Table 1:16 - Defines for SHA3_512 Hash Values
36
37#define SHA3_512_DIGEST_SIZE#define SHA3_512_BLOCK_SIZE

64
72

Table 1:00 - Defines for RSA Asymmetric Cipher Algorithm Constants
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

#define RSA_KEY_SIZES_BITS\(1024 * RSA_1024), (2048 * RSA_2048), (3072 * RSA_3072),(4096 * RSA_4096)#if
RSA_4096#
define RSA_MAX_KEY_SIZE_BITS
4096#elif RSA_3072#
define RSA_MAX_KEY_SIZE_BITS
3072#elif RSA_2048#
define RSA_MAX_KEY_SIZE_BITS
2048#elif RSA_1024#
define RSA_MAX_KEY_SIZE_BITS
1024
#else
#
define RSA_MAX_KEY_SIZE_BITS0#endif#define MAX_RSA_KEY_BITS
RSA_MAX_KEY_SIZE_BITS#define MAX_RSA_KEY_BYTES((RSA_MAX_KEY_SIZE_BITS + 7) / 8)\

Table 1:17 - Defines for AES Symmetric Cipher Algorithm Constants
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

#define AES_KEY_SIZES_BITS\(128 * AES_128), (192 * AES_192), (256 * AES_256)#if
AES_256#
define AES_MAX_KEY_SIZE_BITS
256#elif AES_192#
define AES_MAX_KEY_SIZE_BITS
192#elif AES_128#
define AES_MAX_KEY_SIZE_BITS
128
#else
#
define AES_MAX_KEY_SIZE_BITS0#endif#define MAX_AES_KEY_BITS
AES_MAX_KEY_SIZE_BITS#define MAX_AES_KEY_BYTES((AES_MAX_KEY_SIZE_BITS + 7) / 8)
#define AES_128_BLOCK_SIZE_BYTES(AES_128 * 16)#define AES_192_BLOCK_SIZE_BYTES(AES_192 * 16)#define AES_256_BLOCK_SIZE_BYTES(AES_256 * 16)#define AES_BLOCK_SIZES\
AES_128_BLOCK_SIZE_BYTES, AES_192_BLOCK_SIZE_BYTES,
AES_256_BLOCK_SIZE_BYTES#if
ALG_AES#define AES_MAX_BLOCK_SIZE
16
#else
#
define AES_MAX_BLOCK_SIZE
0#endif#define MAX_AES_BLOCK_SIZE_BYTES
AES_MAX_BLOCK_SIZE\

Table 1:18 - Defines for SM4 Symmetric Cipher Algorithm Constants
79
80#define SM4_KEY_SIZES_BITS#if
SM4_128

Page 506
April 15, 2019(128 * SM4_128)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
81
82
83
84
85
86
87
88
89
90
91
92
93
94

Trusted Platform Module Library#define SM4_MAX_KEY_SIZE_BITS#else#define SM4_MAX_KEY_SIZE_BITS#endif#define MAX_SM4_KEY_BITS#define MAX_SM4_KEY_BYTES#define SM4_128_BLOCK_SIZE_BYTES#define SM4_BLOCK_SIZES#if
ALG_SM4#
define SM4_MAX_BLOCK_SIZE#else#define SM4_MAX_BLOCK_SIZE#endif#define MAX_SM4_BLOCK_SIZE_BYTES

128
0
SM4_MAX_KEY_SIZE_BITS((SM4_MAX_KEY_SIZE_BITS + 7) / 8)
(SM4_128 * 16)
SM4_128_BLOCK_SIZE_BYTES
160
SM4_MAX_BLOCK_SIZE

Table 1:19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

#define CAMELLIA_KEY_SIZES_BITS\(128 * CAMELLIA_128), (192 * CAMELLIA_192), (256 * CAMELLIA_256)#if
CAMELLIA_256#
define CAMELLIA_MAX_KEY_SIZE_BITS
256#elif CAMELLIA_192#
define CAMELLIA_MAX_KEY_SIZE_BITS
192#elif CAMELLIA_128#
define CAMELLIA_MAX_KEY_SIZE_BITS
128
#else
#
define CAMELLIA_MAX_KEY_SIZE_BITS0#endif#define MAX_CAMELLIA_KEY_BITS
CAMELLIA_MAX_KEY_SIZE_BITS#define MAX_CAMELLIA_KEY_BYTES((CAMELLIA_MAX_KEY_SIZE_BITS + 7) / 8)
#define CAMELLIA_128_BLOCK_SIZE_BYTES(CAMELLIA_128 * 16)#define CAMELLIA_192_BLOCK_SIZE_BYTES(CAMELLIA_192 * 16)#define CAMELLIA_256_BLOCK_SIZE_BYTES(CAMELLIA_256 * 16)#define CAMELLIA_BLOCK_SIZES\CAMELLIA_128_BLOCK_SIZE_BYTES, CAMELLIA_192_BLOCK_SIZE_BYTES,CAMELLIA_256_BLOCK_SIZE_BYTES#if
ALG_CAMELLIA#
define CAMELLIA_MAX_BLOCK_SIZE
16
#else
#
define CAMELLIA_MAX_BLOCK_SIZE
0#endif#define MAX_CAMELLIA_BLOCK_SIZE_BYTESCAMELLIA_MAX_BLOCK_SIZE\

Table 1:17 - Defines for TDES Symmetric Cipher Algorithm Constants
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

#define TDES_KEY_SIZES_BITS(128 * TDES_128), (192 * TDES_192)#if
TDES_192#
define TDES_MAX_KEY_SIZE_BITS
192#elif TDES_128#
define TDES_MAX_KEY_SIZE_BITS
128
#else
#
define TDES_MAX_KEY_SIZE_BITS0#endif#define MAX_TDES_KEY_BITS
TDES_MAX_KEY_SIZE_BITS#define MAX_TDES_KEY_BYTES((TDES_MAX_KEY_SIZE_BITS + 7) / 8)
#define TDES_128_BLOCK_SIZE_BYTES(TDES_128 * 8)
#define TDES_192_BLOCK_SIZE_BYTES(TDES_192 * 8)
#define TDES_BLOCK_SIZES\TDES_128_BLOCK_SIZE_BYTES, TDES_192_BLOCK_SIZE_BYTES#if
ALG_TDES#
define TDES_MAX_BLOCK_SIZE
8
#else
#
define TDES_MAX_BLOCK_SIZE
0#endif#define MAX_TDES_BLOCK_SIZE_BYTESTDES_MAX_BLOCK_SIZEFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 507
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

Additional values for benefit of code
140
141
142
143
144
145
146

#define TPM_CC_FIRST#define TPM_CC_LAST#if COMPRESSED_LISTS#define ADD_FILL#else#define ADD_FILL#endif0x0000011F
0x00000197
01Size the array of library commands based on whether or not the array is packed (only defined commands)
or dense (having entries for unimplemented commands)
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

#define LIBRARY_COMMAND_ARRAY_SIZE(0\+ (ADD_FILL || CC_NV_UndefineSpaceSpecial)+ (ADD_FILL || CC_EvictControl)+ (ADD_FILL || CC_HierarchyControl)+ (ADD_FILL || CC_NV_UndefineSpace)+ ADD_FILL+ (ADD_FILL || CC_ChangeEPS)+ (ADD_FILL || CC_ChangePPS)+ (ADD_FILL || CC_Clear)+ (ADD_FILL || CC_ClearControl)+ (ADD_FILL || CC_ClockSet)+ (ADD_FILL || CC_HierarchyChangeAuth)+ (ADD_FILL || CC_NV_DefineSpace)+ (ADD_FILL || CC_PCR_Allocate)+ (ADD_FILL || CC_PCR_SetAuthPolicy)+ (ADD_FILL || CC_PP_Commands)+ (ADD_FILL || CC_SetPrimaryPolicy)+ (ADD_FILL || CC_FieldUpgradeStart)+ (ADD_FILL || CC_ClockRateAdjust)+ (ADD_FILL || CC_CreatePrimary)+ (ADD_FILL || CC_NV_GlobalWriteLock)+ (ADD_FILL || CC_GetCommandAuditDigest)+ (ADD_FILL || CC_NV_Increment)+ (ADD_FILL || CC_NV_SetBits)+ (ADD_FILL || CC_NV_Extend)+ (ADD_FILL || CC_NV_Write)+ (ADD_FILL || CC_NV_WriteLock)+ (ADD_FILL || CC_DictionaryAttackLockReset)+ (ADD_FILL || CC_DictionaryAttackParameters)+ (ADD_FILL || CC_NV_ChangeAuth)+ (ADD_FILL || CC_PCR_Event)+ (ADD_FILL || CC_PCR_Reset)+ (ADD_FILL || CC_SequenceComplete)+ (ADD_FILL || CC_SetAlgorithmSet)+ (ADD_FILL || CC_SetCommandCodeAuditStatus)+ (ADD_FILL || CC_FieldUpgradeData)+ (ADD_FILL || CC_IncrementalSelfTest)+ (ADD_FILL || CC_SelfTest)+ (ADD_FILL || CC_Startup)+ (ADD_FILL || CC_Shutdown)+ (ADD_FILL || CC_StirRandom)+ (ADD_FILL || CC_ActivateCredential)+ (ADD_FILL || CC_Certify)+ (ADD_FILL || CC_PolicyNV)+ (ADD_FILL || CC_CertifyCreation)+ (ADD_FILL || CC_Duplicate)+ (ADD_FILL || CC_GetTime)+ (ADD_FILL || CC_GetSessionAuditDigest)+ (ADD_FILL || CC_NV_Read)+ (ADD_FILL || CC_NV_ReadLock)+ (ADD_FILL || CC_ObjectChangeAuth)+ (ADD_FILL || CC_PolicySecret)

Page 508
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019/* 0x0000011F *//* 0x00000120 *//* 0x00000121 *//* 0x00000122 *//* 0x00000123 *//* 0x00000124 *//* 0x00000125 *//* 0x00000126 *//* 0x00000127 *//* 0x00000128 *//* 0x00000129 *//* 0x0000012A *//* 0x0000012B *//* 0x0000012C *//* 0x0000012D *//* 0x0000012E *//* 0x0000012F *//* 0x00000130 *//* 0x00000131 *//* 0x00000132 *//* 0x00000133 *//* 0x00000134 *//* 0x00000135 *//* 0x00000136 *//* 0x00000137 *//* 0x00000138 *//* 0x00000139 *//* 0x0000013A *//* 0x0000013B *//* 0x0000013C *//* 0x0000013D *//* 0x0000013E *//* 0x0000013F *//* 0x00000140 *//* 0x00000141 *//* 0x00000142 *//* 0x00000143 *//* 0x00000144 *//* 0x00000145 *//* 0x00000146 *//* 0x00000147 *//* 0x00000148 *//* 0x00000149 *//* 0x0000014A *//* 0x0000014B *//* 0x0000014C *//* 0x0000014D *//* 0x0000014E *//* 0x0000014F *//* 0x00000150 *//* 0x00000151 */

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Trusted Platform Module Library+ (ADD_FILL || CC_Rewrap)+ (ADD_FILL || CC_Create)+ (ADD_FILL || CC_ECDH_ZGen)+ (ADD_FILL || CC_HMAC || CC_MAC)+ (ADD_FILL || CC_Import)+ (ADD_FILL || CC_Load)+ (ADD_FILL || CC_Quote)+ (ADD_FILL || CC_RSA_Decrypt)+ ADD_FILL+ (ADD_FILL || CC_HMAC_Start || CC_MAC_Start)+ (ADD_FILL || CC_SequenceUpdate)+ (ADD_FILL || CC_Sign)+ (ADD_FILL || CC_Unseal)+ ADD_FILL+ (ADD_FILL || CC_PolicySigned)+ (ADD_FILL || CC_ContextLoad)+ (ADD_FILL || CC_ContextSave)+ (ADD_FILL || CC_ECDH_KeyGen)+ (ADD_FILL || CC_EncryptDecrypt)+ (ADD_FILL || CC_FlushContext)+ ADD_FILL+ (ADD_FILL || CC_LoadExternal)+ (ADD_FILL || CC_MakeCredential)+ (ADD_FILL || CC_NV_ReadPublic)+ (ADD_FILL || CC_PolicyAuthorize)+ (ADD_FILL || CC_PolicyAuthValue)+ (ADD_FILL || CC_PolicyCommandCode)+ (ADD_FILL || CC_PolicyCounterTimer)+ (ADD_FILL || CC_PolicyCpHash)+ (ADD_FILL || CC_PolicyLocality)+ (ADD_FILL || CC_PolicyNameHash)+ (ADD_FILL || CC_PolicyOR)+ (ADD_FILL || CC_PolicyTicket)+ (ADD_FILL || CC_ReadPublic)+ (ADD_FILL || CC_RSA_Encrypt)+ ADD_FILL+ (ADD_FILL || CC_StartAuthSession)+ (ADD_FILL || CC_VerifySignature)+ (ADD_FILL || CC_ECC_Parameters)+ (ADD_FILL || CC_FirmwareRead)+ (ADD_FILL || CC_GetCapability)+ (ADD_FILL || CC_GetRandom)+ (ADD_FILL || CC_GetTestResult)+ (ADD_FILL || CC_Hash)+ (ADD_FILL || CC_PCR_Read)+ (ADD_FILL || CC_PolicyPCR)+ (ADD_FILL || CC_PolicyRestart)+ (ADD_FILL || CC_ReadClock)+ (ADD_FILL || CC_PCR_Extend)+ (ADD_FILL || CC_PCR_SetAuthValue)+ (ADD_FILL || CC_NV_Certify)+ (ADD_FILL || CC_EventSequenceComplete)+ (ADD_FILL || CC_HashSequenceStart)+ (ADD_FILL || CC_PolicyPhysicalPresence)+ (ADD_FILL || CC_PolicyDuplicationSelect)+ (ADD_FILL || CC_PolicyGetDigest)+ (ADD_FILL || CC_TestParms)+ (ADD_FILL || CC_Commit)+ (ADD_FILL || CC_PolicyPassword)+ (ADD_FILL || CC_ZGen_2Phase)+ (ADD_FILL || CC_EC_Ephemeral)+ (ADD_FILL || CC_PolicyNvWritten)+ (ADD_FILL || CC_PolicyTemplate)+ (ADD_FILL || CC_CreateLoaded)+ (ADD_FILL || CC_PolicyAuthorizeNV)+ (ADD_FILL || CC_EncryptDecrypt2)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019/* 0x00000152 *//* 0x00000153 *//* 0x00000154 *//* 0x00000155 *//* 0x00000156 *//* 0x00000157 *//* 0x00000158 *//* 0x00000159 *//* 0x0000015A *//* 0x0000015B *//* 0x0000015C *//* 0x0000015D *//* 0x0000015E *//* 0x0000015F *//* 0x00000160 *//* 0x00000161 *//* 0x00000162 *//* 0x00000163 *//* 0x00000164 *//* 0x00000165 *//* 0x00000166 *//* 0x00000167 *//* 0x00000168 *//* 0x00000169 *//* 0x0000016A *//* 0x0000016B *//* 0x0000016C *//* 0x0000016D *//* 0x0000016E *//* 0x0000016F *//* 0x00000170 *//* 0x00000171 *//* 0x00000172 *//* 0x00000173 *//* 0x00000174 *//* 0x00000175 *//* 0x00000176 *//* 0x00000177 *//* 0x00000178 *//* 0x00000179 *//* 0x0000017A *//* 0x0000017B *//* 0x0000017C *//* 0x0000017D *//* 0x0000017E *//* 0x0000017F *//* 0x00000180 *//* 0x00000181 *//* 0x00000182 *//* 0x00000183 *//* 0x00000184 *//* 0x00000185 *//* 0x00000186 *//* 0x00000187 *//* 0x00000188 *//* 0x00000189 *//* 0x0000018A *//* 0x0000018B *//* 0x0000018C *//* 0x0000018D *//* 0x0000018E *//* 0x0000018F *//* 0x00000190 *//* 0x00000191 *//* 0x00000192 *//* 0x00000193 */

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 509
April 15, 2019

Trusted Platform Module Library
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

Part 4: Supporting Routines+ (ADD_FILL || CC_AC_GetCapability)/* 0x00000194 */\+ (ADD_FILL || CC_AC_Send)/* 0x00000195 */\+ (ADD_FILL || CC_Policy_AC_SendSelect)/* 0x00000196 */\+ (ADD_FILL || CC_CertifyX509)/* 0x00000197 */\)#define VENDOR_COMMAND_ARRAY_SIZE(0 + CC_Vendor_TCG_Test)#define COMMAND_COUNT(LIBRARY_COMMAND_ARRAY_SIZE + VENDOR_COMMAND_ARRAY_SIZE)#define HASH_COUNT\(ALG_SHA1+ ALG_SHA256+ ALG_SHA384+ ALG_SHA3_256 +\ALG_SHA3_384 + ALG_SHA3_512 + ALG_SHA512+ ALG_SM3_256)#define MAX_HASH_BLOCK_SIZE \(MAX(ALG_SHA1* SHA1_BLOCK_SIZE,\
MAX(ALG_SHA256* SHA256_BLOCK_SIZE,\
MAX(ALG_SHA384* SHA384_BLOCK_SIZE,\
MAX(ALG_SHA3_256 * SHA3_256_BLOCK_SIZE,\
MAX(ALG_SHA3_384 * SHA3_384_BLOCK_SIZE,\
MAX(ALG_SHA3_512 * SHA3_512_BLOCK_SIZE,\
MAX(ALG_SHA512* SHA512_BLOCK_SIZE,\
MAX(ALG_SM3_256 * SM3_256_BLOCK_SIZE,\0)))))))))#define MAX_DIGEST_SIZE\(MAX(ALG_SHA1* SHA1_DIGEST_SIZE,\
MAX(ALG_SHA256* SHA256_DIGEST_SIZE,\
MAX(ALG_SHA384* SHA384_DIGEST_SIZE,\
MAX(ALG_SHA3_256 * SHA3_256_DIGEST_SIZE,\
MAX(ALG_SHA3_384 * SHA3_384_DIGEST_SIZE,\
MAX(ALG_SHA3_512 * SHA3_512_DIGEST_SIZE,\
MAX(ALG_SHA512* SHA512_DIGEST_SIZE,\
MAX(ALG_SM3_256 * SM3_256_DIGEST_SIZE,\0)))))))))#if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0#error "Hash data not valid"#endifDefine the 2B structure that would hold any hash block
298

TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE);

Following typedef is for some old code299

typedef TPM2B_MAX_HASH_BLOCK

TPM2B_HASH_BLOCK;

Additional symmetric constants
300
301
302
303
304
305
306
307
308
309
310
311
312

#define MAX_SYM_KEY_BITS\(MAX(AES_MAX_KEY_SIZE_BITS,
MAX(CAMELLIA_MAX_KEY_SIZE_BITS,
MAX(SM4_MAX_KEY_SIZE_BITS,
MAX(TDES_MAX_KEY_SIZE_BITS,0)))))#define MAX_SYM_KEY_BYTES((MAX_SYM_KEY_BITS + 7) / 8)
#define MAX_SYM_BLOCK_SIZE\(MAX(AES_MAX_BLOCK_SIZE,
MAX(CAMELLIA_MAX_BLOCK_SIZE,MAX(SM4_MAX_BLOCK_SIZE,
MAX(TDES_MAX_BLOCK_SIZE,0)))))#if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0#
error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK#endif#endif // _TPM_ALGORITHM_DEFINES_H_

Page 510
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

\
\

\
\

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2

Trusted Platform Module Library

Source10.2.1

AlgorithmTests.c

10.2.1.1

Introduction

This file contains the code to perform the various self-test functions.
NOTE:

10.2.1.2
1
2
3

In this implementation, large local variables are made static to minimize stack usage, which is critical for stackconstrained platforms.

Includes and Defines#include"Tpm.h"#define
SELF_TEST_DATA#if SELF_TEST

These includes pull in the data structures. They contain data definitions for the various tests.
4
5
6
7
8
9
10
11
12

#include"SelfTest.h"#include"SymmetricTest.h"#include"RsaTestData.h"#include"EccTestData.h"#include"HashTestData.h"#include"KdfTestData.h"#define TEST_DEFAULT_TEST_HASH(vector)
if(TEST_BIT(DEFAULT_TEST_HASH, g_toTest))
TestHash(DEFAULT_TEST_HASH, vector);\\

Make sure that the algorithm has been tested
13
14
15
16
17
18
19
20
21

#define CLEAR_BOTH(alg)#define SET_BOTH(alg)#define TEST_BOTH(alg){

CLEAR_BIT(alg, *toTest);
if(toTest != &g_toTest)
CLEAR_BIT(alg, g_toTest); }{SET_BIT(alg, *toTest);
if(toTest != &g_toTest)
SET_BIT(alg, g_toTest); }((toTest != &g_toTest)? TEST_BIT(alg, *toTest) || TEST_BIT(alg, g_toTest): TEST_BIT(alg, *toTest))

\
\
\
\
\
\

Can only cancel if doing a list.
22
23
24

#define CHECK_CANCELED
if(_plat__IsCanceled() && toTest != &g_toTest)
return TPM_RC_CANCELED;

10.2.1.3\\

Hash Tests

10.2.1.3.1

Description

The hash test does a known-value HMAC using the specified hash algorithm.
10.2.1.3.2

TestHash()

The hash test function.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 511
April 15, 2019

Trusted Platform Module Library

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

Part 4: Supporting Routines

static TPM_RC
TestHash(
TPM_ALG_ID
ALGORITHM_VECTOR)

hashAlg,*toTest{//static TPM2B_DIGEST
computed; // value computed
static HMAC_STATE
state;UINT16
digestSize;const TPM2B*testDigest = NULL;
TPM2B_TYPE(HMAC_BLOCK, DEFAULT_TEST_HASH_BLOCK_SIZE);

pAssert(hashAlg != ALG_NULL_VALUE);
switch(hashAlg){#if ALG_SHA1
case ALG_SHA1_VALUE:
testDigest = &c_SHA1_digest.b;
break;#endif#if ALG_SHA256
case ALG_SHA256_VALUE:
testDigest = &c_SHA256_digest.b;
break;#endif#if ALG_SHA384
case ALG_SHA384_VALUE:
testDigest = &c_SHA384_digest.b;
break;#endif#if ALG_SHA512
case ALG_SHA512_VALUE:
testDigest = &c_SHA512_digest.b;
break;#endif#if ALG_SM3_256
case ALG_SM3_256_VALUE:
testDigest = &c_SM3_256_digest.b;
break;#endifdefault:
FAIL(FATAL_ERROR_INTERNAL);}// Clear the to-test bits
CLEAR_BOTH(hashAlg);// Set the HMAC key to twice the digest size
digestSize = CryptHashGetDigestSize(hashAlg);
CryptHmacStart(&state, hashAlg, digestSize * 2,
(BYTE *)c_hashTestKey.t.buffer);
CryptDigestUpdate(&state.hashState, 2 * CryptHashGetBlockSize(hashAlg),(BYTE *)c_hashTestData.t.buffer);computed.t.size = digestSize;
CryptHmacEnd(&state, digestSize, computed.t.buffer);
if((testDigest->size != computed.t.size)|| (memcmp(testDigest->buffer, computed.t.buffer, computed.b.size) != 0))
SELF_TEST_FAILURE;
return TPM_RC_SUCCESS;}

Page 512
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.1.4

Trusted Platform Module Library

Symmetric Test Functions

10.2.1.4.1

MakeIv()

Internal function to make the appropriate IV depending on the mode.
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

static UINT32
MakeIv(
TPM_ALG_ID
UINT32
BYTE
)

mode,
size,
*iv

BYTE

i;

// IN: symmetric mode// IN: block size of the algorithm// OUT: IV to fill in{if(mode == ALG_ECB_VALUE)
return 0;
if(mode == ALG_CTR_VALUE){// The test uses an IV that has 0xff in the last byte
for(i = 1; i <= size; i++)*iv++ = 0xff - (BYTE)(size - i);}
else{
for(i = 0; i < size; i++)*iv++ = i;}return size;}

10.2.1.4.2

TestSymmetricAlgorithm()

Function to test a specific algorithm, key size, and mode.
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

static void
TestSymmetricAlgorithm(
const SYMMETRIC_TEST_VECTOR
TPM_ALG_ID)*test,
mode

//
//

{
static BYTE
static BYTE
static TPM2B_IV

encrypted[MAX_SYM_BLOCK_SIZE * 2];decrypted[MAX_SYM_BLOCK_SIZE * 2];iv;//// Get the appropriate IV
iv.t.size = (UINT16)MakeIv(mode, test->ivSize, iv.t.buffer);// Encrypt known data
CryptSymmetricEncrypt(encrypted, test->alg, test->keyBits, test->key, &iv,
mode, test->dataInOutSize, test->dataIn);// Check that it matches the expected value
if(!MemoryEqual(encrypted, test->dataOut[mode - ALG_CTR_VALUE],
test->dataInOutSize))
SELF_TEST_FAILURE;// Reinitialize the iv for decryption
MakeIv(mode, test->ivSize, iv.t.buffer);
CryptSymmetricDecrypt(decrypted, test->alg, test->keyBits, test->key, &iv,
mode, test->dataInOutSize,
test->dataOut[mode - ALG_CTR_VALUE]);// Make sure that it matches what we started withif(!MemoryEqual(decrypted, test->dataIn, test->dataInOutSize))
SELF_TEST_FAILURE;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 513
April 15, 2019

Trusted Platform Module Library
136

Part 4: Supporting Routines}

10.2.1.4.3

AllSymsAreDone()

Checks if both symmetric algorithms have been tested. This is put here so that addition of a symmetricalgorithm will be relatively easy to handle

137
138
139
140
141
142
143

Return Value

Meaning

TRUE(1)

all symmetric algorithms tested

FALSE(0)not all symmetric algorithms tested

static BOOL
AllSymsAreDone(
ALGORITHM_VECTOR)*toTest{return (!TEST_BOTH(ALG_AES_VALUE) && !TEST_BOTH(ALG_SM4_VALUE));}

10.2.1.4.4

AllModesAreDone()

Checks if all the modes have been tested

144
145
146
147
148
149
150
151
152
153
154

Return Value

Meaning

TRUE(1)

all modes tested

FALSE(0)all modes not tested

static BOOL
AllModesAreDone(
ALGORITHM_VECTOR)*toTest{
TPM_ALG_IDalg;
for(alg = TPM_SYM_MODE_FIRST; alg <= TPM_SYM_MODE_LAST; alg++)if(TEST_BOTH(alg))
return FALSE;
return TRUE;}

10.2.1.4.5

TestSymmetric()

If alg is a symmetric block cipher, then all of the modes that are selected are tested. If alg is a mode, then
all algorithms of that mode are tested.
155
156
157
158
159
160
161
162
163
164
165
166
167

static TPM_RC
TestSymmetric(
TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTestSYM_INDEX
TPM_ALG_ID

index;mode;{//
if(!TEST_BIT(alg, *toTest))
return TPM_RC_SUCCESS;
if(alg == ALG_AES_VALUE || alg == ALG_SM4_VALUE || alg == ALG_CAMELLIA_VALUE){

Page 514
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

// Will test the algorithm for all modes and key sizes
CLEAR_BOTH(alg);// A test this algorithm for all modes
for(index = 0; index < NUM_SYMS; index++){if(c_symTestValues[index].alg == alg){for(mode = TPM_SYM_MODE_FIRST;
mode <= TPM_SYM_MODE_LAST;
mode++){
if(TEST_BIT(mode, *toTest))
TestSymmetricAlgorithm(&c_symTestValues[index], mode);}}}// if all the symmetric tests are doneif(AllSymsAreDone(toTest)){// all symmetric algorithms tested so no modes should be setfor(alg = TPM_SYM_MODE_FIRST; alg <= TPM_SYM_MODE_LAST; alg++)
CLEAR_BOTH(alg);}}
else if(TPM_SYM_MODE_FIRST <= alg && alg <= TPM_SYM_MODE_LAST){// Test this mode for all key sizes and algorithms
for(index = 0; index < NUM_SYMS; index++){// The mode testing only comes into play when doing self tests// by command. When doing self tests by command, the block ciphers are// tested first. That means that all of their modes would have been// tested for all key sizes. If there is no block cipher left to// test, then clear this mode bit.
if(!TEST_BIT(ALG_AES_VALUE, *toTest)&& !TEST_BIT(ALG_SM4_VALUE, *toTest)){
CLEAR_BOTH(alg);}
else{
for(index = 0; index < NUM_SYMS; index++){if(TEST_BIT(c_symTestValues[index].alg, *toTest))
TestSymmetricAlgorithm(&c_symTestValues[index], alg);}// have tested this mode for all algorithms
CLEAR_BOTH(alg);}}if(AllModesAreDone(toTest)){
CLEAR_BOTH(ALG_AES_VALUE);
CLEAR_BOTH(ALG_SM4_VALUE);}}
else
pAssert(alg == 0 && alg != 0);
return TPM_RC_SUCCESS;}

10.2.1.5
229

Trusted Platform Module Library

RSA Tests#if ALG_RSA

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 515
April 15, 2019

Trusted Platform Module Library

10.2.1.5.1

Part 4: Supporting Routines

Introduction

The tests are for public key only operations and for private key operations. Signature verification andencryption are public key operations. They are tested by using a KVT. For signature verification, thismeans that a known good signature is checked by CryptRsaValidateSignature(). If it fails, then the TPM
enters failure mode. For encryption, the TPM encrypts known values using the selected scheme andchecks that the returned value matches the expected value.
For private key operations, a full scheme check is used. For a signing key, a known key is used to sign aknown message. Then that signature is verified. since the signature may involve use of random values,
the signature will be different each time and we can't always check that the signature matches a known
value. The same technique is used for decryption (RSADP/RSAEP).
When an operation uses the public key and the verification has not been tested, the TPM will do a KVT.
The test for the signing algorithm is built into the call for the algorithm
10.2.1.5.2

RsaKeyInitialize()

The test key is defined by a public modulus and a private prime. The TPM's RSA code computes thesecond prime and the private exponent.
230
231
232
233
234
235
236
237
238
239
240
241
242

static void
RsaKeyInitialize(
OBJECT)*testObject{
MemoryCopy2B(&testObject->publicArea.unique.rsa.b, (P2B)&c_rsaPublicModulus,
sizeof(c_rsaPublicModulus));
MemoryCopy2B(&testObject->sensitive.sensitive.rsa.b, (P2B)&c_rsaPrivatePrime,
sizeof(testObject->sensitive.sensitive.rsa.t.buffer));
testObject->publicArea.parameters.rsaDetail.keyBits = RSA_TEST_KEY_SIZE * 8;// Use the default exponent
testObject->publicArea.parameters.rsaDetail.exponent = 0;}

10.2.1.5.3

TestRsaEncryptDecrypt()

These test are for an public key encryption that uses a random value
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

static TPM_RC
TestRsaEncryptDecrypt(
TPM_ALG_ID
ALGORITHM_VECTOR)

scheme,*toTest// IN: the scheme//

static TPM2B_PUBLIC_KEY_RSA
static TPM2B_PUBLIC_KEY_RSA
static OBJECT
const TPM2B_RSA_TEST_KEY
TPM_RC
const TPM2B
TPMT_RSA_DECRYPT

testInput;
testOutput;
testObject;*kvtValue = NULL;
result = TPM_RC_SUCCESS;*testLabel = NULL;
rsaScheme;{//// Don't need to initialize much of the test object
RsaKeyInitialize(&testObject);rsaScheme.scheme = scheme;
rsaScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH;
CLEAR_BOTH(scheme);
CLEAR_BOTH(ALG_NULL_VALUE);
if(scheme == ALG_NULL_VALUE){

Page 516
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

Trusted Platform Module Library// This is an encryption scheme using the private key without any encoding.
memcpy(testInput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue));
testInput.t.size = sizeof(c_RsaTestValue);if(TPM_RC_SUCCESS != CryptRsaEncrypt(&testOutput, &testInput.b,&testObject, &rsaScheme, NULL, NULL))SELF_TEST_FAILURE;
if(!MemoryEqual(testOutput.t.buffer, c_RsaepKvt.buffer, c_RsaepKvt.size))
SELF_TEST_FAILURE;
MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer));if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b,&testObject, &rsaScheme, NULL))SELF_TEST_FAILURE;
if(!MemoryEqual(testOutput.t.buffer, c_RsaTestValue,
sizeof(c_RsaTestValue)))
SELF_TEST_FAILURE;}
else{// ALG_RSAES_VALUE:// This is an decryption scheme using padding according to// PKCS#1v2.1, 7.2. This padding uses random bits. To test a public// key encryption that uses random data, encrypt a value and then// decrypt the value and see that we get the encrypted data back.
// The hash is not used by this encryption so it can be TMP_ALG_NULL// ALG_OAEP_VALUE:// This is also an decryption scheme and it also uses a// pseudo-random// value. However, this also uses a hash algorithm. So, we may need// to test that algorithm before use.
if(scheme == ALG_OAEP_VALUE){TEST_DEFAULT_TEST_HASH(toTest);
kvtValue = &c_OaepKvt;
testLabel = OAEP_TEST_STRING;}
else if(scheme == ALG_RSAES_VALUE){
kvtValue = &c_RsaesKvt;
testLabel = NULL;}
else
SELF_TEST_FAILURE;// Only use a digest-size portion of the test value
memcpy(testInput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE);
testInput.t.size = DEFAULT_TEST_DIGEST_SIZE;// See if the encryption works
if(TPM_RC_SUCCESS != CryptRsaEncrypt(&testOutput, &testInput.b,&testObject, &rsaScheme, testLabel,
NULL))
SELF_TEST_FAILURE;
MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer));// see if we can decrypt this value and get the original data backif(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b,&testObject, &rsaScheme, testLabel))
SELF_TEST_FAILURE;// See if the results compare
if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE|| !MemoryEqual(testOutput.t.buffer, c_RsaTestValue,
DEFAULT_TEST_DIGEST_SIZE))SELF_TEST_FAILURE;// Now check that the decryption works on a known value
MemoryCopy2B(&testInput.b, (P2B)kvtValue,
sizeof(testInput.t.buffer));if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 517
April 15, 2019

Trusted Platform Module Library
331
332
333
334
335
336
337
338
339

Part 4: Supporting Routines&testObject, &rsaScheme, testLabel))
SELF_TEST_FAILURE;
if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE|| !MemoryEqual(testOutput.t.buffer, c_RsaTestValue,
DEFAULT_TEST_DIGEST_SIZE))SELF_TEST_FAILURE;}
return result;}10.2.1.5.4

TestRsaSignAndVerify()

This function does the testing of the RSA sign and verification functions. This test does a KVT.
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

static TPM_RC
TestRsaSignAndVerify(
TPM_ALG_ID
ALGORITHM_VECTOR)

scheme,*toTest{
TPM_RCstatic OBJECT
static TPM2B_DIGEST
static TPMT_SIGNATURE

result = TPM_RC_SUCCESS;
testObject;
testDigest;
testSig;// Do a sign and signature verification.
// RSASSA:// This is a signing scheme according to PKCS#1-v2.1 8.2. It does not// use random data so there is a KVT for the signing operation. On// first use of the scheme for signing, use the TPM's RSA key to// sign a portion of c_RsaTestData and compare the results to c_RsassaKvt. Then// decrypt the data to see that it matches the starting value. This verifies// the signature with a KVT// Clear the bits indicating that the function has not been checked. This is to// prevent looping
CLEAR_BOTH(scheme);
CLEAR_BOTH(ALG_NULL_VALUE);
CLEAR_BOTH(ALG_RSA_VALUE);
RsaKeyInitialize(&testObject);
memcpy(testDigest.t.buffer, (BYTE *)c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE);
testDigest.t.size = DEFAULT_TEST_DIGEST_SIZE;
testSig.sigAlg = scheme;
testSig.signature.rsapss.hash = DEFAULT_TEST_HASH;// RSAPSS:// This is a signing scheme a according to PKCS#1-v2.2 8.1 it uses// random data in the signature so there is no KVT for the signing// operation. To test signing, the TPM will use the TPM's RSA key// to sign a portion of c_RsaTestValue and then it will verify the// signature. For verification, c_RsapssKvt is verified before the// user signature blob is verified. The worst case for testing of this// algorithm is two private and one public key operation.
// The process is to sign known data. If RSASSA is being done, verify that the// signature matches the precomputed value. For both, use the signed value and// see that the verification says that it is a good signature. Then// if testing RSAPSS, do a verify of a known good signature. This ensures that// the validation function works.
if(TPM_RC_SUCCESS != CryptRsaSign(&testSig, &testObject, &testDigest, NULL))SELF_TEST_FAILURE;// For RSASSA, make sure the results is what we are looking forPage 518
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

Trusted Platform Module Libraryif(testSig.sigAlg == ALG_RSASSA_VALUE){
if(testSig.signature.rsassa.sig.t.size != RSA_TEST_KEY_SIZE|| !MemoryEqual(c_RsassaKvt.buffer,
testSig.signature.rsassa.sig.t.buffer,
RSA_TEST_KEY_SIZE))SELF_TEST_FAILURE;}// See if the TPM will validate its own signaturesif(TPM_RC_SUCCESS != CryptRsaValidateSignature(&testSig, &testObject,&testDigest))
SELF_TEST_FAILURE;// If this is RSAPSS, check the verification with known signature// Have to copy because CrytpRsaValidateSignature() eats the signature
if(ALG_RSAPSS_VALUE == scheme){
MemoryCopy2B(&testSig.signature.rsapss.sig.b, (P2B)&c_RsapssKvt,
sizeof(testSig.signature.rsapss.sig.t.buffer));if(TPM_RC_SUCCESS != CryptRsaValidateSignature(&testSig, &testObject,&testDigest))
SELF_TEST_FAILURE;}
return result;}10.2.1.5.5

TestRSA()

Function uses the provided vector to indicate which tests to run. It will clear the vector after each test is
run and also clear g_toTest
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447

static TPM_RC
TestRsa(
TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest

TPM_RC

result = TPM_RC_SUCCESS;{//
switch(alg){case ALG_NULL_VALUE:// This is the RSAEP/RSADP function. If we are processing a list, don't// need to test these now because any other test will validate// RSAEP/RSADP. Can tell this is list of test by checking to see if// 'toTest' is pointing at g_toTest. If so, this is an isolated test// an need to go ahead and do the test;
if((toTest == &g_toTest)|| (!TEST_BIT(ALG_RSASSA_VALUE, *toTest)&& !TEST_BIT(ALG_RSAES_VALUE, *toTest)&& !TEST_BIT(ALG_RSAPSS_VALUE, *toTest)&& !TEST_BIT(ALG_OAEP_VALUE, *toTest)))// Not running a list of tests or no other tests on the list// so run the test now
result = TestRsaEncryptDecrypt(alg, toTest);// if not running the test now, leave the bit on, just in case things// get interrupted
break;
case ALG_OAEP_VALUE:
case ALG_RSAES_VALUE:
result = TestRsaEncryptDecrypt(alg, toTest);
break;
case ALG_RSAPSS_VALUE:
case ALG_RSASSA_VALUE:
result = TestRsaSignAndVerify(alg, toTest);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 519
April 15, 2019

Trusted Platform Module Library
448
449
450
451
452
453
454

break;
default:
SELF_TEST_FAILURE;}
return result;}#endif // ALG_RSA

10.2.1.6
455Part 4: Supporting Routines

ECC Tests#if ALG_ECC

10.2.1.6.1

LoadEccParameter()This function is mostly for readability and type checking
456
457
458
459
460
461
462
463

static void
LoadEccParameter(
TPM2B_ECC_PARAMETER
const TPM2B_EC_TEST)// target// source{
MemoryCopy2B(&to->b, &from->b, sizeof(to->t.buffer));}

10.2.1.6.2
464
465
466
467
468
469
470
471
472
473

*to,
*from

LoadEccPoint()

static void
LoadEccPoint(
TPMS_ECC_POINT
const TPM2B_EC_TEST
const TPM2B_EC_TEST)*point,*x,*y// target// source{
MemoryCopy2B(&point->x.b, (TPM2B *)x, sizeof(point->x.t.buffer));
MemoryCopy2B(&point->y.b, (TPM2B *)y, sizeof(point->y.t.buffer));}

10.2.1.6.3

TestECDH()

This test does a KVT on a point multiply.
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

static TPM_RC
TestECDH(
TPM_ALG_ID
ALGORITHM_VECTOR)

scheme,*toTest// IN: for consistency// IN/OUT: modified after test is run{
static TPMS_ECC_POINT
static TPMS_ECC_POINT
static TPM2B_ECC_PARAMETER
TPM_RCZ;
Qe;
ds;
result = TPM_RC_SUCCESS;//NOT_REFERENCED(scheme);
CLEAR_BOTH(ALG_ECDH_VALUE);
LoadEccParameter(&ds, &c_ecTestKey_ds);
LoadEccPoint(&Qe, &c_ecTestKey_QeX, &c_ecTestKey_QeY);
if(TPM_RC_SUCCESS != CryptEccPointMultiply(&Z, c_testCurve, &Qe, &ds,
NULL, NULL))SELF_TEST_FAILURE;
if(!MemoryEqual2B(&c_ecTestEcdh_X.b, &Z.x.b)

Page 520
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
493
494
495
496

|| !MemoryEqual2B(&c_ecTestEcdh_Y.b, &Z.y.b))
SELF_TEST_FAILURE;
return result;}10.2.1.6.4
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

Trusted Platform Module Library

TestEccSignAndVerify()

static TPM_RC
TestEccSignAndVerify(
TPM_ALG_ID
ALGORITHM_VECTOR)

scheme,*toTeststatic OBJECT
static TPMT_SIGNATURE
static TPMT_ECC_SCHEME

testObject;
testSig;
eccScheme;{

testSig.sigAlg = scheme;
testSig.signature.ecdsa.hash = DEFAULT_TEST_HASH;eccScheme.scheme = scheme;
eccScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH;
CLEAR_BOTH(scheme);
CLEAR_BOTH(ALG_ECDH_VALUE);// ECC signature verification testing uses a KVT.
switch(scheme){case ALG_ECDSA_VALUE:
LoadEccParameter(&testSig.signature.ecdsa.signatureR, &c_TestEcDsa_r);
LoadEccParameter(&testSig.signature.ecdsa.signatureS, &c_TestEcDsa_s);
break;
case ALG_ECSCHNORR_VALUE:
LoadEccParameter(&testSig.signature.ecschnorr.signatureR,&c_TestEcSchnorr_r);
LoadEccParameter(&testSig.signature.ecschnorr.signatureS,&c_TestEcSchnorr_s);
break;
case ALG_SM2_VALUE:// don't have a test for SM2
return TPM_RC_SUCCESS;
default:
SELF_TEST_FAILURE;
break;}TEST_DEFAULT_TEST_HASH(toTest);// Have to copy the key. This is because the size used in the test vectors// is the size of the ECC parameter for the test key while the size of a point// is TPM dependent
MemoryCopy2B(&testObject.sensitive.sensitive.ecc.b, &c_ecTestKey_ds.b,
sizeof(testObject.sensitive.sensitive.ecc.t.buffer));
LoadEccPoint(&testObject.publicArea.unique.ecc, &c_ecTestKey_QsX,&c_ecTestKey_QsY);
testObject.publicArea.parameters.eccDetail.curveID = c_testCurve;if(TPM_RC_SUCCESS != CryptEccValidateSignature(&testSig, &testObject,(TPM2B_DIGEST *)&c_ecTestValue.b)){
SELF_TEST_FAILURE;}CHECK_CANCELED;// Now sign and verify some data

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 521
April 15, 2019

Trusted Platform Module Library
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569

if(TPM_RC_SUCCESS != CryptEccSign(&testSig, &testObject,(TPM2B_DIGEST *)&c_ecTestValue,&eccScheme, NULL))SELF_TEST_FAILURE;CHECK_CANCELED;
if(TPM_RC_SUCCESS != CryptEccValidateSignature(&testSig, &testObject,(TPM2B_DIGEST *)&c_ecTestValue))
SELF_TEST_FAILURE;CHECK_CANCELED;
return TPM_RC_SUCCESS;}

10.2.1.6.5
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

TestKDFa()

static TPM_RC
TestKDFa(
ALGORITHM_VECTOR)*toTest{static TPM2B_KDF_TEST_KEY
UINT32

keyOut;counter = 0;//
CLEAR_BOTH(ALG_KDF1_SP800_108_VALUE);
keyOut.t.size = CryptKDFa(KDF_TEST_ALG, &c_kdfTestKeyIn.b, &c_kdfTestLabel.b,&c_kdfTestContextU.b, &c_kdfTestContextV.b,
TEST_KDF_KEY_SIZE * 8, keyOut.t.buffer,&counter, FALSE);
if (keyOut.t.size != TEST_KDF_KEY_SIZE|| !MemoryEqual(keyOut.t.buffer, c_kdfTestKeyOut.t.buffer,
TEST_KDF_KEY_SIZE))SELF_TEST_FAILURE;
return TPM_RC_SUCCESS;}

10.2.1.6.6
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

Part 4: Supporting Routines

TestEcc()static TPM_RC
TestEcc(
TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest{
TPM_RC
result = TPM_RC_SUCCESS;NOT_REFERENCED(toTest);
switch(alg){case ALG_ECC_VALUE:
case ALG_ECDH_VALUE:// If this is in a loop then see if another test is going to deal with// this.
// If toTest is not a self-test list
if((toTest == &g_toTest)// or this is the only ECC test in the list|| !(TEST_BIT(ALG_ECDSA_VALUE, *toTest)|| TEST_BIT(ALG_ECSCHNORR, *toTest)|| TEST_BIT(ALG_SM2_VALUE, *toTest))){result = TestECDH(alg, toTest);

Page 522
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
613
614
615
616
617
618
619
620
621
622
623
624
625
626

Trusted Platform Module Library}
break;
case ALG_ECDSA_VALUE:
case ALG_ECSCHNORR_VALUE:
case ALG_SM2_VALUE:
result = TestEccSignAndVerify(alg, toTest);
break;
default:
SELF_TEST_FAILURE;
break;}
return result;}#endif // ALG_ECC

10.2.1.6.7

TestAlgorithm()

Dispatches to the correct test function for the algorithm or gets a list of testable algorithms.
If toTest is not NULL, then the test decisions are based on the algorithm selections in toTest. Otherwise,
g_toTest is used. When bits are clear in g_toTest they will also be cleared toTest.
If there doesn't happen to be a test for the algorithm, its associated bit is quietly cleared.
If alg is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits for which there is no test
(i.e. no tests are actually run but the vector is cleared).
NOTE:

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657

toTest will only ever have bits set for implemented algorithms but alg can be anything.

Error Returns

Meaning

TPM_RC_CANCELED

test was canceled

LIB_EXPORTTPM_RC
TestAlgorithm(
TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest

TPM_ALG_ID
TPM_ALG_ID
BOOL
TPM_RC

first = (alg == ALG_ERROR_VALUE) ? ALG_FIRST_VALUE : alg;last = (alg == ALG_ERROR_VALUE) ? ALG_LAST_VALUE : alg;
doTest = (alg != ALG_ERROR_VALUE);
result = TPM_RC_SUCCESS;{

if(toTest == NULL)
toTest = &g_toTest;// This is kind of strange. This function will either run a test of the selected// algorithm or just clear a bit if there is no test for the algorithm. So,// either this loop will be executed once for the selected algorithm or once for// each of the possible algorithms. If it is executed more than once ('alg' ==// ALG_ERROR), then no test will be run but bits will be cleared for// unimplemented algorithms. This was done this way so that there is only one// case statement with all of the algorithms. It was easier to have one case// statement than to have multiple ones to manage whenever an algorithm ID is// added.
for(alg = first; (alg <= last); alg++){// if 'alg' was TPM_ALG_ERROR, then we will be cycling through// values, some of which may not be implemented. If the bit in toTest// happens to be set, then we could either generated an assert, or just// silently CLEAR it. Decided to just clear.
if(!TEST_BIT(alg, g_implementedAlgorithms))

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 523
April 15, 2019

Trusted Platform Module Library
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

Part 4: Supporting Routines{
CLEAR_BIT(alg, *toTest);
continue;}// Process whatever is left.
// NOTE: since this switch will only be called if the algorithm is// implemented, it is not necessary to modify this list except to comment// out the algorithms for which there is no test
switch(alg){// Symmetric block ciphers#if ALG_AES
case ALG_AES_VALUE:#endif // ALG_AES#if ALG_SM4// if SM4 is implemented, its test is like other block ciphers but there// aren't any test vectors for it yet//case ALG_SM4_VALUE:#endif // ALG_SM4#if ALG_CAMELLIA// no test vectors for camellia//case ALG_CAMELLIA_VALUE:#endif// Symmetric modes#if!ALG_CFB#error
CFB is required in all TPM implementations#endif // !ALG_CFB
case ALG_CFB_VALUE:
if(doTest)
result = TestSymmetric(alg, toTest);
break;#if ALG_CTR
case ALG_CTR_VALUE:#endif // ALG_CRT#if ALG_OFB
case ALG_OFB_VALUE:#endif // ALG_OFB#if ALG_CBC
case ALG_CBC_VALUE:#endif // ALG_CBC#if ALG_ECB
case ALG_ECB_VALUE:#endifif(doTest)
result = TestSymmetric(alg, toTest);else// If doing the initialization of g_toTest vector, only need// to test one of the modes for the symmetric algorithms. If// initializing for a SelfTest(FULL_TEST), allow all the modes.
if(toTest == &g_toTest)
CLEAR_BIT(alg, *toTest);
break;#if!ALG_HMAC#
error
HMAC is required in all TPM implementations#endifcase ALG_HMAC_VALUE:// Clear the bit that indicates that HMAC is required because// HMAC is used as the basic test for all hash algorithms.
CLEAR_BOTH(alg);// Testing HMAC means test the default hashif(doTest)
TestHash(DEFAULT_TEST_HASH, toTest);else// If not testing, then indicate that the hash needs to be// tested because this uses HMAC
SET_BOTH(DEFAULT_TEST_HASH);

Page 524
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

Trusted Platform Module Library

break;
ALG_SHA1
case ALG_SHA1_VALUE:#endif // ALG_SHA1#if
ALG_SHA256
case ALG_SHA256_VALUE:#endif // ALG_SHA256#if
ALG_SHA384
case ALG_SHA384_VALUE:#endif // ALG_SHA384#if
ALG_SHA512
case ALG_SHA512_VALUE:#endif // ALG_SHA512// if SM3 is implemented its test is like any other hash, but there// aren't any test vectors yet.
#if
ALG_SM3_256//
case ALG_SM3_256_VALUE:#endif // ALG_SM3_256
if(doTest)
result = TestHash(alg, toTest);
break;// RSA-dependent#if ALG_RSA
case ALG_RSA_VALUE:
CLEAR_BOTH(alg);if(doTest)
result = TestRsa(ALG_NULL_VALUE, toTest);
else
SET_BOTH(ALG_NULL_VALUE);
break;
case ALG_RSASSA_VALUE:
case ALG_RSAES_VALUE:
case ALG_RSAPSS_VALUE:
case ALG_OAEP_VALUE:
case ALG_NULL_VALUE:// used or RSADP
if(doTest)
result = TestRsa(alg, toTest);
break;#endif // ALG_RSA#if ALG_KDF1_SP800_108
case ALG_KDF1_SP800_108_VALUE:
if(doTest)
result = TestKDFa(toTest);
break;#endif // ALG_KDF1_SP800_108#if ALG_ECC// ECC dependent but no tests//
case ALG_ECDAA_VALUE://
case ALG_ECMQV_VALUE://
case ALG_KDF1_SP800_56a_VALUE://
case ALG_KDF2_VALUE://
case ALG_MGF1_VALUE:
case ALG_ECC_VALUE:
CLEAR_BOTH(alg);if(doTest)
result = TestEcc(ALG_ECDH_VALUE, toTest);
else
SET_BOTH(ALG_ECDH_VALUE);
break;
case ALG_ECDSA_VALUE:
case ALG_ECDH_VALUE:
case ALG_ECSCHNORR_VALUE://
case ALG_SM2_VALUE:
if(doTest)
result = TestEcc(alg, toTest);
break;#if

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 525
April 15, 2019

Trusted Platform Module Library
790
791
792
793
794
795
796
797
798
799
800

Part 4: Supporting Routines#endif // ALG_ECC
default:
CLEAR_BIT(alg, *toTest);
break;}
if(result != TPM_RC_SUCCESS)
break;}
return result;}#endif // SELF_TESTS

Page 526
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.2Trusted Platform Module Library

BnConvert.c

10.2.2.1

Introduction

This file contains the basic conversion functions that will convert TPM2B to/from the internal format. Theinternal format is a bigNum,
10.2.2.2
1

Includes#include "Tpm.h"

10.2.2.3

Functions10.2.2.3.1

BnFromBytes()

This function will convert a big-endian byte array to the internal number format. If bn is NULL, then the
output is NULL. If bytes is null or the required size is 0, then the output is set to zero
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

LIB_EXPORT bigNum
BnFromBytes(
bigNumconst BYTENUMBYTES)

bn,*bytes,nBytesconst BYTE
BYTE
crypt_uword_t*pFrom; // 'p' points to the least significant bytes of source*pTo;// points to least significant bytes of destination
size;

{

//
size = (bytes != NULL) ? BYTES_TO_CRYPT_WORDS(nBytes) : 0;// If nothing in, nothing out
if(bn == NULL)
return NULL;// make sure things fit
pAssert(BnGetAllocated(bn) >= size);if(size > 0){// Clear the topmost word in case it is not filled with databn->d[size - 1] = 0;// Moving the input bytes from the end of the list (LSB) end
pFrom = bytes + nBytes - 1;// To the LS0 of the LSW of the bigNum.
pTo = (BYTE *)bn->d;for(; nBytes != 0; nBytes--)*pTo++ = *pFrom--;// For a little-endian machine, the conversion is a straight byte// reversal. For a big-endian machine, we have to put the words in// big-endian byte order#if BIG_ENDIAN_TPM{
crypt_word_tt;for(t = (crypt_word_t)size - 1; t >= 0; t--)bn->d[t] = SWAP_CRYPT_WORD(bn->d[t]);}#endif}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 527
April 15, 2019

Trusted Platform Module Library
44
45
46

Part 4: Supporting Routines

BnSetTop(bn, size);
return bn;}

10.2.2.3.2

BnFrom2B()

Convert an TPM2B to a BIG_NUM. If the input value does not exist, or the output does not exist, or the
input will not fit into the output the function returns NULL
47
48
49
50
51
52
53
54
55
56
57
58
59

LIB_EXPORT bigNum
BnFrom2B(
bigNumconst TPM2B
)

bn,
*a2B

// OUT:// IN: number to convert{
if(a2B != NULL)
return BnFromBytes(bn, a2B->buffer, a2B->size);// Make sure that the number has an initialized value rather than whatever// was there before
BnSetTop(bn, 0);// Function accepts NULL
return NULL;}

10.2.2.3.3

BnFromHex()

Convert a hex string into a bigNum. This is primarily used in debugging.
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

LIB_EXPORT bigNum
BnFromHex(
bigNumconst char){#define FromHex(a)unsigned
unsigned
const char
BYTE

bn,
*hex

// OUT:// IN:((a) - (((a) > 'a') ? ('a' + 10): ((a) > 'A') ? ('A' - 10) : '0'))i;wordCount;*p;*d = (BYTE *)&(bn->d[0]);\//pAssert(bn && hex);i = strlen(hex);
wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2);
if((i == 0) || (wordCount >= BnGetAllocated(bn)))
BnSetWord(bn, 0);else{
bn->d[wordCount - 1] = 0;p = hex + i - 1;for(;i > 1; i -= 2){
BYTE a;a = FromHex(*p);
p--;*d++ = a + (FromHex(*p) << 4);p--;}if(i == 1)*d = FromHex(*p);}#if !BIG_ENDIAN_TPM
for(i = 0; i < wordCount; i++)bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]);Page 528
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
96
97
98
99

Trusted Platform Module Library#endif // BIG_ENDIAN_TPM
BnSetTop(bn, wordCount);
return bn;}

10.2.2.3.4

BnToBytes()

This function converts a BIG_NUM to a byte array. It converts the bigNum to a big-endian byte string andsets size to the normalized value. If size is an input 0, then the receiving buffer is guaranteed to be large
enough for the result and the size will be set to the size required for bigNum (leading zeros suppressed).
The conversion for a little-endian machine simply requires that all significant bytes of the bigNum bereversed. For a big-endian machine, rather than unpack each word individually, the bigNum is converted
to little-endian words, copied, and then converted back to big-endian.
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

LIB_EXPORT BOOL
BnToBytes(
bigConst
BYTE
NUMBYTESbn,*buffer,*size// This the number of bytes that are// available in the buffer. The result// should be this big.

){
crypt_uword_t
BYTE
BYTE
crypt_uword_t

requiredSize;*pFrom;*pTo;
count;//// validate inputs
pAssert(bn && buffer && size);
requiredSize = (BnSizeInBits(bn) + 7) / 8;if(requiredSize == 0){// If the input value is 0, return a byte of zero
*size = 1;
*buffer = 0;}
else{
#if BIG_ENDIAN_TPM// Copy the constant input value into a modifiable value
BN_VAR(bnL, LARGEST_NUMBER_BITS * 2);
BnCopy(bnL, bn);// byte swap the words in the local value to make them little-endianfor(count = 0; count < bnL->size; count++)
bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]);
bn = (bigConst)bnL;#endifif(*size == 0)*size = (NUMBYTES)requiredSize;
pAssert(requiredSize <= *size);// Byte swap the number (not words but the whole value)
count = *size;// Start from the least significant word and offset to the most significant// byte which is in some high wordpFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1;
pTo = buffer;// If the number of output bytes is larger than the number bytes required// for the input number, pad with zeros
for(count = *size; count > requiredSize; count--)*pTo++ = 0;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 529
April 15, 2019

Trusted Platform Module Library
149
150
151
152
153
154
155

Part 4: Supporting Routines// Move the most significant byte at the end of the BigNum to the next most// significant byte position of the 2B and repeat for all significant bytes.
for(; requiredSize > 0; requiredSize--)*pTo++ = *pFrom--;}
return TRUE;}

10.2.2.3.5

BnTo2B()

Function to convert a BIG_NUM to TPM2B. The TPM2B size is set to the requested size which may
require padding. If size is non-zero and less than required by the value in bn then an error is returned. If
size is zero, then the TPM2B is assumed to be large enough for the data and a2b->size will be adjusted
accordingly.
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

LIB_EXPORT BOOL
BnTo2B(
bigConst
TPM2B
NUMBYTES
)

bn,
*a2B,
size

// IN:// OUT:// IN: the desired size{// Set the output size
if(bn && a2B){
a2B->size = size;
return BnToBytes(bn, a2B->buffer, &a2B->size);}
return FALSE;}#if

ALG_ECC

10.2.2.3.6

BnPointFrom2B()

Function to create a BIG_POINT structure from a 2B point. A point is going to be two ECC values in thesame buffer. The values are going to be the size of the modulus. They are in modular form.
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

LIB_EXPORT bn_point_t
BnPointFrom2B(*

bigPoint
TPMS_ECC_POINT
)

ecP,
*p

// OUT: the preallocated point structure// IN: the number to convert{
if(p == NULL)
return NULL;
if(NULL != ecP){
BnFrom2B(ecP->x, &p->x.b);
BnFrom2B(ecP->y, &p->y.b);
BnSetWord(ecP->z, 1);}
return ecP;}

10.2.2.3.7

BnPointTo2B()

This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT contains two
TPM2B_ECC_PARAMETER values. The maximum size of the parameters is dependent on the maximum

Page 530
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

EC key size used in an implementation. The presumption is that the TPMS_ECC_POINT is large enoughto hold 2 TPM2B values, each as large as a MAX_ECC_PARAMETER_BYTES
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

LIB_EXPORT BOOL
BnPointTo2B(
TPMS_ECC_POINT
bigPoint
bigCurve
)

*p,
ecP,
E

UINT16size;// OUT: the converted 2B structure// IN: the values to be converted// IN: curve descriptor for the point{//
pAssert(p && ecP && E);
pAssert(BnEqualWord(ecP->z, 1));// BnMsb is the bit number of the MSB. This is one less than the number of bits
size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E))));
BnTo2B(ecP->x, &p->x.b, size);
BnTo2B(ecP->y, &p->y.b, size);
return TRUE;}#endif // ALG_ECC

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 531
April 15, 2019

Trusted Platform Module Library

10.2.3

Part 4: Supporting Routines

BnMath.c10.2.3.1

Introduction

The simulator code uses the canonical form whenever possible in order to make the code in Part 3 moreaccessible. The canonical data formats are simple and not well suited for complex big number
computations. When operating on big numbers, the data format is changed for easier manipulation. The
format is native words in little-endian format. As the magnitude of the number decreases, the length of thearray containing the number decreases but the starting address doesn't change.
The functions in this file perform simple operations on these big numbers. Only the more complex
operations are passed to the underlying support library. Although the support library would have most ofthese functions, the interface code to convert the format for the values is greater than the size of the code
to implement the functions here. So, rather than incur the overhead of conversion, they are done here.
If an implementer would prefer, the underlying library can be used simply by making code substitutions
here.
NOTE:

There is an intention to continue to augment these functions so that there would be no need to use an external
big number library.

Many of these functions have no error returns and will always return TRUE. This is to allow them to be
used in guarded sequences. That is: OK = OK || BnSomething(s); where the BnSomething() function
should not be called if OK isn't true.
10.2.3.2
1

Includes#include "Tpm.h"

A constant value of zero as a stand in for NULL bigNum values
2

const bignum_t

10.2.3.3

BnConstZero = {1, 0, {0}};Functions10.2.3.3.1

AddSame()Adds two values that are the same size. This function allows result to be the same as either of theaddends. This is a nice function to put into assembly because handling the carry for multi-precision stuff
is not as easy in C (unless there is a REALLY smart compiler). It would be nice if there were idioms in alanguage that a compiler could recognize what is going on and optimize loops like this.

3
4
5
6
7
8
9
10
11
12

Return Value

Meaning0

no carry out

1carry out

static BOOL
AddSame(crypt_uword_t
const crypt_uword_t
const crypt_uword_t
int)*result,
*op1,
*op2,
count

{
int
int

Page 532
April 15, 2019

carry = 0;i;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Trusted Platform Module Libraryfor(i = 0; i < count; i++){crypt_uword_t
a = op1[i];crypt_uword_t
sum = a + op2[i];result[i] = sum + carry;// generate a carry if the sum is less than either of the inputs// propagate a carry if there was a carry and the sum + carry is zero// do this using bit operations rather than logical operations so that// the time is about the same.
//
propagate term
| generate term
carry = ((result[i] == 0) & carry) | (sum < a);}return carry;}

10.2.3.3.2

CarryProp()

Propagate a carry
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

static int
CarryProp(
crypt_uword_t
const crypt_uword_t
int
int
)

*result,*op,
count,
carry{
for(; count; count--)
carry = ((*result++ = *op++ + carry) == 0) & carry;
return carry;}

static void
CarryResolve(
bigNumint
int)

result,
stop,
carry

{
if(carry){pAssert((unsigned)stop < result->allocated);
result->d[stop++] = 1;}
BnSetTop(result, stop);}

10.2.3.3.3

BnAdd()

This function adds two bigNum values. This function always returns TRUE.
54
55
56
57
58
59
60
61
62
63
64
65

LIB_EXPORT BOOL
BnAdd(
bigNumbigConst
bigConst)

result,op1,
op2

crypt_uword_t
int
const bignum_t
const bignum_t

stop;
carry;*n1 = op1;
*n2 = op2;{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 533
April 15, 2019

Trusted Platform Module Library
66
67
68
69
70
71
72
73
74
75
76
77
78
79

Part 4: Supporting Routines//
if(n2->size > n1->size){
n1 = op2;
n2 = op1;}
pAssert(result->allocated >= n1->size);stop = MIN(n1->size, n2->allocated);carry = AddSame(result->d, n1->d, n2->d, stop);if(n1->size > stop)
carry = CarryProp(&result->d[stop], &n1->d[stop], n1->size - stop, carry);
CarryResolve(result, n1->size, carry);
return TRUE;}

10.2.3.3.4

BnAddWord()

This function adds a word value to a bigNum. This function always returns TRUE.
80
81
82
83
84
85
86
87
88
89
90
91
92
93

LIB_EXPORT BOOL
BnAddWord(
bigNumbigConst
crypt_uword_t)

result,
op,
word

int

carry;{//
carry = (result->d[0] = op->d[0] + word) < word;
carry = CarryProp(&result->d[1], &op->d[1], op->size - 1, carry);
CarryResolve(result, op->size, carry);
return TRUE;}

10.2.3.3.5

SubSame()This function subtracts two values that have the same size.
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

static int
SubSame(crypt_uword_t
const crypt_uword_t
const crypt_uword_t
int)*result,
*op1,
*op2,
count

{
int
borrow = 0;
int
i;for(i = 0; i < count; i++){crypt_uword_t
a = op1[i];crypt_uword_t
diff = a - op2[i];result[i] = diff - borrow;//generate|
propagateborrow = (diff > a) | ((diff == 0) & borrow);}
return borrow;}

Page 534
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.3.3.6

Trusted Platform Module Library

BorrowProp()

This propagates a borrow. If borrow is true when the end of the array is reached, then it means that op2
was larger than op1 and we don't handle that case so an assert is generated. This design choice wasmade because our only bigNum computations are on large positive numbers (primes) or on fields.
Propagate a borrow.
114
115
116
117
118
119
120
121
122
123
124
125

static int
BorrowProp(
crypt_uword_t
const crypt_uword_t
int
int
)

*result,*op,
size,
borrow{for(; size > 0; size--)borrow = ((*result++ = *op++ - borrow) == MAX_CRYPT_UWORD) && borrow;
return borrow;}

10.2.3.3.7

BnSub()

This function does subtraction of two bigNum values and returns result = op1 - op2 when op1 is greaterthan op2. If op2 is greater than op1, then a fault is generated. This function always returns TRUE.
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

LIB_EXPORT BOOL
BnSub(
bigNumbigConst
bigConst)

result,
op1,
op2

int
crypt_uword_t

borrow;
stop = MIN(op1->size, op2->allocated);{//// Make sure that op2 is not obviously larger than op1
pAssert(op1->size >= op2->size);borrow = SubSame(result->d, op1->d, op2->d, stop);
if(op1->size > stop)
borrow = BorrowProp(&result->d[stop], &op1->d[stop], op1->size - stop,
borrow);
pAssert(!borrow);
BnSetTop(result, op1->size);
return TRUE;}

10.2.3.3.8

BnSubWord()

This function subtracts a word value from a bigNum. This function always returns TRUE.
146
147
148
149
150
151
152
153
154
155
156

LIB_EXPORT BOOL
BnSubWord(
bigNumresult,bigConst
op,crypt_uword_t
word
)
{
int

borrow;//
pAssert(op->size > 1 || word <= op->d[0]);borrow = word > op->d[0];Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 535
April 15, 2019

Trusted Platform Module Library
157
158
159
160
161
162

Part 4: Supporting Routines

result->d[0] = op->d[0] - word;borrow = BorrowProp(&result->d[1], &op->d[1], op->size - 1, borrow);
pAssert(!borrow);
BnSetTop(result, op->size);
return TRUE;}

10.2.3.3.9

BnUnsignedCmp()

This function performs a comparison of op1 to op2. The compare is approximately constant time if thesize of the values used in the compare is consistent across calls (from the same line in the calling code).

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

Return Value

Meaning<0

op1 is less than op20

op1 is equal to op2>0

op1 is greater than op2

LIB_EXPORT int
BnUnsignedCmp(
bigConst
bigConst
)

op1,
op2

{
int
int
int

retVal;
diff;
i;

//
pAssert((op1 != NULL) && (op2 != NULL));
retVal = op1->size - op2->size;
if(retVal == 0){
for(i = (int)(op1->size - 1); i >= 0; i--){diff = (op1->d[i] < op2->d[i]) ? -1 : (op1->d[i] != op2->d[i]);retVal = retVal == 0 ? diff : retVal;}}
else
retVal = (retVal < 0) ? -1 : 1;
return retVal;}

10.2.3.3.10

BnUnsignedCmpWord()

Compare a bigNum to a crypt_uword_t.

187
188
189
190
191
192

Return Value

Meaning-1

op1 is less that word0

op1 is equal to word1

op1 is greater than word

LIB_EXPORT int
BnUnsignedCmpWord(
bigConst
crypt_uword_t
)

op1,
word

{

Page 536
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
193
194
195
196
197
198
199
200

Trusted Platform Module Libraryif(op1->size > 1)
return 1;
else if(op1->size == 1)
return (op1->d[0] < word) ? -1 : (op1->d[0] > word);
else // op1 is zero// equal if word is zero
return (word == 0) ? 0 : -1;}

10.2.3.3.11

BnModWord()

This function does modular division of a big number when the modulus is a word value.
201
202
203
204
205
206
207
208
209
210
211
212
213
214

LIB_EXPORT crypt_word_t
BnModWord(
bigConst
crypt_word_t)

numerator,
modulus{
BN_MAX(remainder);
BN_VAR(mod, RADIX_BITS);//
mod->d[0] = modulus;
mod->size = (modulus != 0);
BnDiv(NULL, remainder, numerator, mod);return remainder->d[0];}10.2.3.3.12

Msb()

This function returns the bit number of the most significant bit of a crypt_uword_t. The number for the
least significant bit of any bigNum value is 0. The maximum return value is RADIX_BITS - 1,

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

Return Value

Meaning-1

the word was zeron

the bit number of the most significant bit in the word

LIB_EXPORT int
Msb(
crypt_uword_t
)

word

{
int
retVal = -1;//#if RADIX_BITS == 64
if(word & 0xffffffff00000000) { retVal += 32; word >>= 32; }#endifif(word & 0xffff0000) { retVal += 16; word >>= 16; }if(word & 0x0000ff00) { retVal += 8; word >>= 8; }if(word & 0x000000f0) { retVal += 4; word >>= 4; }if(word & 0x0000000c) { retVal += 2; word >>= 2; }if(word & 0x00000002) { retVal += 1; word >>= 1; }return retVal + (int)word;}

10.2.3.3.13

BnMsb()

This function returns the number of the MSb of a bigNum value.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 537
April 15, 2019

Trusted Platform Module Library

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

Part 4: Supporting Routines

Return Value

Meaning-1

the word was zero or bn was NULLnthe bit number of the most significant bit in the word

LIB_EXPORT int
BnMsb(
bigConst)

bn{// If the value is NULL, or the size is zero then treat as zero and return -1
if(bn != NULL && bn->size > 0){
int
retVal = Msb(bn->d[bn->size - 1]);
retVal += (bn->size - 1) * RADIX_BITS;
return retVal;}
else
return -1;}

10.2.3.3.14

BnSizeInBits()

This function returns the number of bits required to hold a number. It is one greater than the Msb.
247
248
249
250
251
252
253
254
255

LIB_EXPORT unsigned
BnSizeInBits(
bigConst
)

n

{
int

bits = BnMsb(n) + 1;//
return bits < 0? 0 : (unsigned)bits;}

10.2.3.3.15

BnSetWord()

Change the value of a bignum_t to a word value.
256
257
258
259
260
261
262
263
264
265
266
267
268
269

LIB_EXPORT bigNum
BnSetWord(
bigNumcrypt_uword_t
)

n,
w

{
if(n != NULL){
pAssert(n->allocated > 1);n->d[0] = w;
BnSetTop(n, (w != 0) ? 1 : 0);}
return n;}

10.2.3.3.16

BnSetBit()

This function will SET a bit in a bigNum. Bit 0 is the least-significant bit in the 0th digit_t. The function
always return TRUE
270

LIB_EXPORT BOOL

Page 538
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

271
272
273
274
275
276
277
278
279
280
281
282
283

Trusted Platform Module Library

BnSetBit(
bigNumunsigned int)

bn,
bitNum// IN/OUT: big number to modify// IN: Bit number to SET{
crypt_uword_t
offset = bitNum / RADIX_BITS;
pAssert(bn->allocated * RADIX_BITS >= bitNum);// Grow the number if necessary to set the bit.
while(bn->size <= offset)
bn->d[bn->size++] = 0;bn->d[offset] |= (1 << RADIX_MOD(bitNum));
return TRUE;}

10.2.3.3.17

BnTestBit()

This function is used to check to see if a bit is SET in a bignum_t. The 0th bit is the LSb of d[0].

284
285
286
287
288
289
290
291
292
293
294
295
296

Return Value

Meaning

TRUE(1)the bit is set

FALSE(0)the bit is not set or the number is out of range

LIB_EXPORT BOOL
BnTestBit(
bigNumunsigned int)

bn,
bitNum// IN: number to check// IN: bit to test

crypt_uword_t

offset = RADIX_DIV(bitNum);{//if(bn->size > offset)
return ((bn->d[offset] & (((crypt_uword_t)1) << RADIX_MOD(bitNum))) != 0);
else
return FALSE;}

10.2.3.3.18

BnMaskBits()

This function is used to mask off high order bits of a big number. The returned value will have no morethan maskBit bits set.
NOTE:

297
298
299
300
301
302
303
304
305
306
307

There is a requirement that unused words of a bignum_t are set to zero.

Return Value

Meaning

TRUE(1)

result masked

FALSE(0)the input was not as large as the mask

LIB_EXPORT BOOL
BnMaskBits(
bigNumcrypt_uword_t)bn,maskBit// IN/OUT: number to mask// IN: the bit number for the mask.

crypt_uword_t
BOOL

finalSize;
retVal;{finalSize = BITS_TO_CRYPT_WORDS(maskBit);
retVal = (finalSize <= bn->allocated);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 539
April 15, 2019

Trusted Platform Module Library
308
309
310
311
312
313
314
315
316

Part 4: Supporting Routines

if(retVal && (finalSize > 0)){
crypt_uword_t
mask;
mask = ~((crypt_uword_t)0) >> RADIX_MOD(maskBit);bn->d[finalSize - 1] &= mask;}
BnSetTop(bn, finalSize);
return retVal;}

10.2.3.3.19

BnShiftRight()

This function will shift a bigNum to the right by the shiftAmount. This function always returns TRUE.
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

LIB_EXPORT BOOL
BnShiftRight(
bigNumbigConst
uint32_t)

result,toShift,
shiftAmountuint32_t
uint32_t
uint32_t
crypt_uword_t

offset = (shiftAmount >> RADIX_LOG2);i;shiftIn;
finalSize;{//
shiftAmount = shiftAmount & RADIX_MASK;
shiftIn = RADIX_BITS - shiftAmount;// The end size is toShift->size - offset less one additional// word if the shiftAmount would make the upper word == 0if(toShift->size > offset){
finalSize = toShift->size - offset;
finalSize -= (toShift->d[toShift->size - 1] >> shiftAmount) == 0 ? 1 : 0;}
else
finalSize = 0;
pAssert(finalSize <= result->allocated);
if(finalSize != 0){
for(i = 0; i < finalSize; i++){result->d[i] = (toShift->d[i + offset] >> shiftAmount)| (toShift->d[i + offset + 1] << shiftIn);}if(offset == 0)
result->d[i] = toShift->d[i] >> shiftAmount;}
BnSetTop(result, finalSize);
return TRUE;}

10.2.3.3.20

BnGetRandomBits()

This function gets random bits for use in various places. To make sure that the number is generated in a
portable format, it is created as a TPM2B and then converted to the internal format.
One consequence of the generation scheme is that, if the number of bits requested is not a multiple of 8,
then the high-order bits are set to zero. This would come into play when generating a 521-bit ECC key. A
66-byte (528-bit) value is generated an the high order 7 bits are masked off (CLEAR).
Page 540
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)success

FALSE(0)failureLIB_EXPORT BOOL
BnGetRandomBits(
bigNumsize_tRAND_STATE

n,
bits,
*rand

)
{
// Since this could be used for ECC key generation using the extra bits method,// make sure that the value is large enough
TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8);
TPM2B_LARGEST
large;//
large.b.size = (UINT16)BITS_TO_BYTES(bits);
if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size){
if(BnFrom2B(n, &large.b) != NULL){
if(BnMaskBits(n, bits))
return TRUE;}}
return FALSE;}

10.2.3.3.21

BnGenerateRandomInRange()

This function is used to generate a random number r in the range 1 <= r < limit. The function gets a
random number of bits that is the size of limit. There is some some probability that the returned number isgoing to be greater than or equal to the limit. If it is, try again. There is no more than 50% chance that thenext number is also greater, so try again. We keep trying until we get a value that meets the criteria.
Since limit is very often a number with a LOT of high order ones, this rarely would need a second try.

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

Return Value

Meaning

TRUE(1)success

FALSE(0)failure (limit is too small)

LIB_EXPORT BOOL
BnGenerateRandomInRange(
bigNumbigConst
RAND_STATE)

dest,
limit,*rand{
size_tbits = BnSizeInBits(limit);//
if(bits < 2){
BnSetWord(dest, 0);
return FALSE;}
else{
while(BnGetRandomBits(dest, bits, rand)&& (BnEqualZero(dest) || (BnUnsignedCmp(dest, limit) >= 0)));}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 541
April 15, 2019

Trusted Platform Module Library398
399

Part 4: Supporting Routines

return !g_inFailureMode;}

Page 542
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.4

Trusted Platform Module Library

BnMemory.c

10.2.4.1

Introduction

This file contains the memory setup functions used by the bigNum functions in CryptoEngine()
10.2.4.2
1

Includes#include "Tpm.h"

10.2.4.3

Functions10.2.4.3.1

BnSetTop()

This function is used when the size of a bignum_t is changed. It makes sure that the unused words are
set to zero and that any significant words of zeros are eliminated from the used size indicator.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

LIB_EXPORT bigNum
BnSetTop(
bigNumcrypt_uword_t
)

bn,
top

// IN/OUT: number to clean// IN: the new top{
if(bn != NULL){
pAssert(top <= bn->allocated);// If forcing the size to be decreased, make sure that the words being// discarded are being set to 0
while(bn->size > top)bn->d[--bn->size] = 0;bn->size = top;// Now make sure that the words that are left are 'normalized' (no high-order// words of zero.
while((bn->size > 0) && (bn->d[bn->size - 1] == 0))bn->size -= 1;}
return bn;}

10.2.4.3.2

BnClearTop()

This function will make sure that all unused words are zero.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

LIB_EXPORT bigNum
BnClearTop(
bigNum)bn{
crypt_uword_ti;//if(bn != NULL){
for(i = bn->size; i < bn->allocated; i++)bn->d[i] = 0;
while((bn->size > 0) && (bn->d[bn->size] == 0))bn->size -= 1;}
return bn;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 543
April 15, 2019

Trusted Platform Module Library

10.2.4.3.3

Part 4: Supporting Routines

BnInitializeWord()

This function is used to initialize an allocated bigNum with a word value. The bigNum does not have to beallocated with a single word.
39
40
41
42
43
44
45
46
47
48
49
50
51
52

LIB_EXPORT bigNum
BnInitializeWord(
bigNumcrypt_uword_t
crypt_uword_t)bn,allocated,
word// IN:// IN:// IN:{
bn->allocated = allocated;bn->size = (word != 0);bn->d[0] = word;while(allocated > 1)
bn->d[--allocated] = 0;
return bn;}

10.2.4.3.4

BnInit()This function initializes a stack allocated bignum_t. It initializes allocated and size and zeros the words of
d.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

LIB_EXPORT bigNum
BnInit(bigNumcrypt_uword_t)bn,allocated{
if(bn != NULL){
bn->allocated = allocated;bn->size = 0;
while(allocated != 0)
bn->d[--allocated] = 0;}
return bn;}

10.2.4.3.5

BnCopy()Function to copy a bignum_t. If the output is NULL, then nothing happens. If the input is NULL, the output
is set to zero.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

LIB_EXPORT BOOL
BnCopy(bigNumbigConst
)

out,
in

{
if(in == out)
BnSetTop(out, BnGetSize(out));else if(out != NULL){
if(in != NULL){
unsigned inti;pAssert(BnGetAllocated(out) >= BnGetSize(in));for(i = 0; i < BnGetSize(in); i++)out->d[i] = in->d[i];Page 544
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
84
85
86
87
88
89
90
91

Trusted Platform Module Library

BnSetTop(out, BnGetSize(in));}else
BnSetTop(out, 0);}
return TRUE;}#if

ALG_ECC

10.2.4.3.6

BnPointCopy()

Function to copy a bn point.
92
93
94
95
96
97
98
99
100
101

LIB_EXPORT BOOL
BnPointCopy(
bigPoint
pointConst
)

pOut,
pIn

{
return BnCopy(pOut->x, pIn->x)&& BnCopy(pOut->y, pIn->y)&& BnCopy(pOut->z, pIn->z);}

10.2.4.3.7

BnInitializePoint()

This function is used to initialize a point structure with the addresses of the coordinates.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

LIB_EXPORT bn_point_t *BnInitializePoint(
bigPoint
bigNumbigNumbigNum
)

p,
x,
y,
z

// OUT: structure to receive pointers// IN: x coordinate// IN: y coordinate// IN: x coordinate{p->x = x;p->y = y;p->z = z;
BnSetWord(z, 1);
return p;}#endif // ALG_ECC

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 545
April 15, 2019

Trusted Platform Module Library

10.2.5

Part 4: Supporting Routines

CryptCmac.c

10.2.5.1

Introduction

This file contains the implementation of the message authentication codes based on a symmetric blockcipher. These functions only use the single block encryption functions of the selected symmetric
cryptographic library.
10.2.5.2
1
2
3
4

Includes, Defines, and Typedefs#define _CRYPT_HASH_C_#include "Tpm.h"#include "CryptSym.h"#if ALG_CMAC

10.2.5.3
10.2.5.3.1

Functions
CryptCmacStart()

This is the function to start the CMAC sequence operation. It initializes the dispatch functions for the dataand end operations for CMAC and initializes the parameters that are used for the processing of data,
including the key, key size and block cipher algorithm.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

UINT16
CryptCmacStart(
SMAC_STATETPMU_PUBLIC_PARMS
TPM_ALG_ID
TPM2B*state,*keyParms,
macAlg,*key){
tpmCmacState_t*cState = &state->state.cmac;
TPMT_SYM_DEF_OBJECT *def = &keyParms->symDetail.sym;//
if(macAlg != TPM_ALG_CMAC)
return 0;// set up the encryption algorithm and parameters
cState->symAlg = def->algorithm;
cState->keySizeBits = def->keyBits.sym;
cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm,
def->keyBits.sym);
MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer));// Set up the dispatch methods for the CMAC
state->smacMethods.data = CryptCmacData;
state->smacMethods.end = CryptCmacEnd;
return cState->iv.t.size;}

10.2.5.3.2

CryptCmacData()

This function is used to add data to the CMAC sequence computation. The function will XOR new data
into the IV. If the buffer is full, and there is additional input data, the data is encrypted into the IV buffer,the new data is then XOR into the IV. When the data runs out, the function returns without encrypting
even if the buffer is full. The last data block of a sequence will not be encrypted until the call to
CryptCmacEnd(). This is to allow the proper subkey to be computed and applied before the last block is
encrypted.
Page 546
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

Trusted Platform Module Libraryvoid
CryptCmacData(
SMAC_STATESUINT32const BYTE

*state,size,*buffer){
tpmCmacState_t*cmacState = &state->cmac;
TPM_ALG_ID
algorithm = cmacState->symAlg;
BYTE*key = cmacState->symKey.t.buffer;
UINT16
keySizeInBits = cmacState->keySizeBits;
tpmCryptKeySchedule_t
keySchedule;
TpmCryptSetSymKeyCall_t encrypt;//
SELECT(ENCRYPT);
while(size > 0){if(cmacState->bcount == cmacState->iv.t.size){
ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer);
cmacState->bcount = 0;}
for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size);size--, cmacState->bcount++){
cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++;}}}

10.2.5.3.3

CryptCmacEnd()

This is the completion function for the CMAC. It does padding, if needed, and selects the subkey to be
applied before the last block is encrypted.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

UINT16
CryptCmacEnd(
SMAC_STATESUINT32
BYTE*state,outSize,*outBuffer){
tpmCmacState_t*cState = &state->cmac;// Need to set algorithm, key, and keySizeInBits in the local context so that// the SELECT and ENCRYPT macros will work here
TPM_ALG_ID
algorithm = cState->symAlg;
BYTE*key = cState->symKey.t.buffer;
UINT16
keySizeInBits = cState->keySizeBits;
tpmCryptKeySchedule_t
keySchedule;
TpmCryptSetSymKeyCall_t encrypt;
TPM2B_IV
subkey = {{0, {0}}};BOOL
xorVal;UINT16i;
subkey.t.size = cState->iv.t.size;// Encrypt a block of zero
SELECT(ENCRYPT);ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer);// shift left by 1 and XOR with 0x0...87 if the MSb was 0
xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87;
ShiftLeft(&subkey.b);subkey.t.buffer[subkey.t.size - 1] ^= xorVal;// this is a sanity check to make sure that the algorithm is working properly.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 547
April 15, 2019

Trusted Platform Module Library
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
8

Part 4: Supporting Routines// remove this check when debug is done
pAssert(cState->bcount <= cState->iv.t.size);// If the buffer is full then no need to compute subkey 2.
if(cState->bcount < cState->iv.t.size){//Pad the data
cState->iv.t.buffer[cState->bcount++] ^= 0x80;// The rest of the data is a pad of zero which would simply be XORed// with the iv value so nothing to do...
// Now compute K2
xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87;
ShiftLeft(&subkey.b);subkey.t.buffer[subkey.t.size - 1] ^= xorVal;}// XOR the subkey into the IVfor(i = 0; i < subkey.t.size; i++)cState->iv.t.buffer[i] ^= subkey.t.buffer[i];ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer);i = (UINT16)MIN(cState->iv.t.size, outSize);
MemoryCopy(outBuffer, cState->iv.t.buffer, i);return i;}#endifPage 548
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.6

Trusted Platform Module Library

CryptUtil.c

10.2.6.1

Introduction

This module contains the interfaces to the CryptoEngine() and provides miscellaneous cryptographic
functions in support of the TPM.
10.2.6.2
1

Includes#include "Tpm.h"

10.2.6.3

Hash/HMAC Functions

10.2.6.3.1

CryptHmacSign()

Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Error Returns

Meaning

TPM_RC_HASH

not a valid hashstatic TPM_RC
CryptHmacSign(
TPMT_SIGNATUREOBJECT
TPM2B_DIGEST)*signature,*signKey,*hashData// OUT: signature// IN: HMAC key sign the hash// IN: hash to be signed{
HMAC_STATEUINT32

hmacState;digestSize;

digestSize = CryptHmacStart2B(&hmacState, signature->signature.any.hashAlg,&signKey->sensitive.sensitive.bits.b);
CryptDigestUpdate2B(&hmacState.hashState, &hashData->b);
CryptHmacEnd(&hmacState, digestSize,(BYTE *)&signature->signature.hmac.digest);
return TPM_RC_SUCCESS;}

10.2.6.3.2

CryptHMACVerifySignature()

This function will verify a signature signed by a HMAC key. Note that a caller needs to prepare signature
with the signature algorithm (TPM_ALG_HMAC) and the hash algorithm to use. This function then builds
a signature of that type.

19
20
21
22
23
24
25

Error Returns

Meaning

TPM_RC_SCHEME

not the proper scheme for this key type

TPM_RC_SIGNATURE

if invalid input or signature is not genuine

static TPM_RC
CryptHMACVerifySignature(
OBJECT
TPM2B_DIGEST
TPMT_SIGNATURE)*signKey,*hashData,*signature// IN: HMAC key signed the hash// IN: digest being verified// IN: signature to be verified{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 549
April 15, 2019

Trusted Platform Module Library
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

TPMT_SIGNATURE
TPMT_KEYEDHASH_SCHEME

Part 4: Supporting Routines

test;*keyScheme =&signKey->publicArea.parameters.keyedHashDetail.scheme;//if((signature->sigAlg != ALG_HMAC_VALUE)|| (signature->signature.hmac.hashAlg == ALG_NULL_VALUE))
return TPM_RC_SCHEME;// This check is not really needed for verification purposes. However, it does// prevent someone from trying to validate a signature using a weaker hash// algorithm than otherwise allowed by the key. That is, a key with a scheme// other than TMP_ALG_NULL can only be used to validate signatures that have// a matching scheme.
if((keyScheme->scheme != ALG_NULL_VALUE)&& ((keyScheme->scheme != signature->sigAlg)|| (keyScheme->details.hmac.hashAlg!= signature->signature.any.hashAlg)))
return TPM_RC_SIGNATURE;
test.sigAlg = signature->sigAlg;
test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg;
CryptHmacSign(&test, signKey, hashData);// Compare digest
if(!MemoryEqual(&test.signature.hmac.digest,&signature->signature.hmac.digest,
CryptHashGetDigestSize(signature->signature.any.hashAlg)))
return TPM_RC_SIGNATURE;
return TPM_RC_SUCCESS;}

10.2.6.3.3

CryptGenerateKeyedHash()This function creates a keyedHash object.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

Error Returns

Meaning

TPM_RC_NO_RESULT

cannot get values from random number generator

TPM_RC_SIZE

sensitive data size is larger than allowed for the scheme

static TPM_RC
CryptGenerateKeyedHash(
TPMT_PUBLIC*publicArea,

TPMT_SENSITIVETPMS_SENSITIVE_CREATERAND_STATE)*sensitive,*sensitiveCreate,*rand

TPMT_KEYEDHASH_SCHEME
TPM_ALG_ID
UINT16
UINT16*scheme;hashAlg;
hashBlockSize;
digestSize;// IN/OUT: the public area template//
for the new key.
// OUT: sensitive area// IN: sensitive creation data// IN: "entropy" source{

scheme = &publicArea->parameters.keyedHashDetail.scheme;
if(publicArea->type != ALG_KEYEDHASH_VALUE)
return TPM_RC_FAILURE;// Pick the limiting hash algorithm
if(scheme->scheme == ALG_NULL_VALUE)
hashAlg = publicArea->nameAlg;
else if(scheme->scheme == ALG_XOR_VALUE)

Page 550
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

Trusted Platform Module Library

hashAlg = scheme->details.xor.hashAlg;
else
hashAlg = scheme->details.hmac.hashAlg;
hashBlockSize = CryptHashGetBlockSize(hashAlg);digestSize = CryptHashGetDigestSize(hashAlg);// if this is a signing or a decryption key, then the limit// for the data size is the block size of the hash. This limit// is set because larger values have lower entropy because of the// HMAC function. The lower limit is 1/2 the size of the digest////If the user provided the key, check that it is a proper size
if(sensitiveCreate->data.t.size != 0){
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)|| IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)){
if(sensitiveCreate->data.t.size > hashBlockSize)
return TPM_RC_SIZE;#if 0// May make this a FIPS-mode requirement
if(sensitiveCreate->data.t.size < (digestSize / 2))
return TPM_RC_SIZE;#endif}// If this is a data blob, then anything that will get past the unmarshaling// is OK
MemoryCopy2B(&sensitive->sensitive.bits.b, &sensitiveCreate->data.b,
sizeof(sensitive->sensitive.bits.t.buffer));}else{// The TPM is going to generate the data so set the size to be the// size of the digest of the algorithm
sensitive->sensitive.bits.t.size =DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize);if(sensitive->sensitive.bits.t.size == 0)
return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT;}
return TPM_RC_SUCCESS;}

10.2.6.3.4

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.
119
120
121
122
123
124
125

BOOL
CryptIsSchemeAnonymous(
TPM_ALG_ID)

scheme// IN: the scheme algorithm to test{
return scheme == ALG_ECDAA_VALUE;}

10.2.6.4

Symmetric Functions

10.2.6.4.1

ParmDecryptSym()

This function performs parameter decryption using symmetric block cipher.
126
127

void
ParmDecryptSym(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 551
April 15, 2019

Trusted Platform Module Library
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

TPM_ALG_ID
TPM_ALG_ID
UINT16
TPM2B
TPM2B
TPM2B
UINT32BYTE)Part 4: Supporting Routines

symAlg,// IN: the symmetric algorithm
hash,// IN: hash algorithm for KDFa
keySizeInBits, // IN: the key size in bits
*key,// IN: KDF HMAC key*nonceCaller,// IN: nonce caller*nonceTpm,// IN: nonce TPM
dataSize,// IN: size of parameter buffer*data// OUT: buffer to be decrypted{// KDF output buffer// It contains parameters for the CFB encryption// From MSB to LSB, they are the key and iv
BYTE
symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];// Symmetric key size in byte
UINT16
keySize = (keySizeInBits + 7) / 8;
TPM2B_IViv;
iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);// If there is decryption to do...
if(iv.t.size > 0){// Generate key and iv
CryptKDFa(hash, key, CFB_KEY, nonceCaller, nonceTpm,
keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
CryptSymmetricDecrypt(data, symAlg, keySizeInBits, symParmString,&iv, ALG_CFB_VALUE, dataSize, data);}
return;}10.2.6.4.2

ParmEncryptSym()

This function performs parameter encryption using symmetric block cipher.
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

void
ParmEncryptSym(
TPM_ALG_ID
TPM_ALG_ID
UINT16
TPM2B
TPM2B
TPM2B
UINT32BYTE)

symAlg,// IN: symmetric algorithm
hash,// IN: hash algorithm for KDFa
keySizeInBits, // IN: symmetric key size in bits
*key,// IN: KDF HMAC key*nonceCaller,// IN: nonce caller*nonceTpm,// IN: nonce TPM
dataSize,// IN: size of parameter buffer*data// OUT: buffer to be encrypted{// KDF output buffer// It contains parameters for the CFB encryption
BYTE
symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];// Symmetric key size in bytes
UINT16
keySize = (keySizeInBits + 7) / 8;
TPM2B_IViv;

iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);// See if there is any encryption to do
if(iv.t.size > 0){// Generate key and iv
CryptKDFa(hash, key, CFB_KEY, nonceTpm, nonceCaller,

Page 552
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
187
188
189
190
191
192
193
194

Trusted Platform Module Library

keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
CryptSymmetricEncrypt(data, symAlg, keySizeInBits, symParmString, &iv,
ALG_CFB_VALUE, dataSize, data);}
return;}10.2.6.4.3

CryptGenerateKeySymmetric()

This function generates a symmetric cipher key. The derivation process is determined by the type of theprovided rand

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236

Error Returns

Meaning

TPM_RC_NO_RESULT

cannot get a random value

TPM_RC_KEY_SIZE

key size in the public area does not match the size in the sensitive
creation area

TPM_RC_KEY

provided key value is not allowed

static TPM_RC
CryptGenerateKeySymmetric(
TPMT_PUBLIC*publicArea,

TPMT_SENSITIVETPMS_SENSITIVE_CREATERAND_STATE)*sensitive,*sensitiveCreate,*rand// IN/OUT: The public area template//
for the new key.
// OUT: sensitive area// IN: sensitive creation data// IN: the "entropy" source for{
UINT16
TPM_RC

keyBits = publicArea->parameters.symDetail.sym.keyBits.sym;
result;//// only do multiples of RADIX_BITS
if((keyBits % RADIX_BITS) != 0)
return TPM_RC_KEY_SIZE;// If this is not a new key, then the provided key data must be the right size
if(sensitiveCreate->data.t.size != 0){
result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym,(TPM2B_SYM_KEY *)&sensitiveCreate->data);
if(result == TPM_RC_SUCCESS)
MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b,
sizeof(sensitive->sensitive.sym.t.buffer));}#if ALG_TDES
else if(publicArea->parameters.symDetail.sym.algorithm == ALG_TDES_VALUE){
result = CryptGenerateKeyDes(publicArea, sensitive, rand);}#endifelse{
sensitive->sensitive.sym.t.size =DRBG_Generate(rand, sensitive->sensitive.sym.t.buffer,
BITS_TO_BYTES(keyBits));if(g_inFailureMode)
result = TPM_RC_FAILURE;
else if(sensitive->sensitive.sym.t.size == 0)
result = TPM_RC_NO_RESULT;
else
result = TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 553
April 15, 2019

Trusted Platform Module Library
237
238

Part 4: Supporting Routines

return result;}10.2.6.4.4

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.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

void
CryptXORObfuscation(
TPM_ALG_ID
TPM2B
TPM2B
TPM2B
UINT32
BYTE
)

hash,
*key,
*contextU,*contextV,
dataSize,*data// IN: hash algorithm for KDF// IN: KDF key// IN: contextU// IN: contextV// IN: size of data buffer// IN/OUT: data to be XORed in place

BYTE
BYTE
UINT32
UINT32
UINT16
UINT32
INT32

mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer*pm;
i;counter = 0;hLen = CryptHashGetDigestSize(hash);requestSize = dataSize * 8;remainBytes = (INT32)dataSize;{

pAssert((key != NULL) && (data != NULL) && (hLen != 0));// Call KDFa to generate XOR maskfor(; remainBytes > 0; remainBytes -= hLen){// Make a call to KDFa to get next iteration
CryptKDFa(hash, key, XOR_KEY, contextU, contextV,
requestSize, mask, &counter, TRUE);// XOR next piece of the datapm = mask;for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)*data++ ^= *pm++;}
return;}10.2.6.5

Initialization and shut down

10.2.6.5.1

CryptInit()

This function is called when the TPM receives a _TPM_Init() indication.
NOTE:

273
274
275

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.

Return Value

Meaning

TRUE(1)

initializations succeeded

FALSE(0)initialization failed and caller should place the TPM into Failure Mode

BOOL
CryptInit(
void

Page 554
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

Trusted Platform Module Library

)
{
BOOL
ok;
// Initialize the vector of implemented algorithms
AlgorithmGetImplementedVector(&g_implementedAlgorithms);// Indicate that all test are necessary
CryptInitializeToTest();// Do any library initializations that are necessary. If any fails,// the caller should go into failure mode;ok = SupportLibInit();ok = ok && CryptSymInit();ok = ok && CryptRandInit();ok = ok && CryptHashInit();#if ALG_RSA
ok = ok && CryptRsaInit();#endif // ALG_RSA#if ALG_ECC
ok = ok && CryptEccInit();#endif // ALG_ECC
return ok;}

10.2.6.5.2

CryptStartup()This function is called by TPM2_Startup() to initialize the functions in this cryptographic library and in theprovided CryptoLibrary(). This function and CryptUtilInit() are both provided so that the implementation
may move the initialization around to get the best interaction.

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

Return Value

Meaning

TRUE(1)startup succeeded

FALSE(0)startup failed and caller should place the TPM into Failure Mode

BOOL
CryptStartup(
STARTUP_TYPE)

type// IN: the startup type

{
BOOL
OK;
NOT_REFERENCED(type);
OK = CryptSymStartup() && CryptRandStartup() && CryptHashStartup()#if ALG_RSA&& CryptRsaStartup()#endif // ALG_RSA#if ALG_ECC&& CryptEccStartup()#endif // ALG_ECC;#if ALG_ECC// Don't directly check for SU_RESET because that is the default
if(OK && (type != SU_RESTART) && (type != SU_RESUME)){// If the shutdown was orderly, then the values recovered from NV will// be OK to use.
// Get a new random commit nonce
gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer);// Reset the counter and commit arraygr.commitCounter = 0;
MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 555
April 15, 2019

Trusted Platform Module Library
327
328
329
330

Part 4: Supporting Routines}#endif // ALG_ECC
return OK;}

10.2.6.6

Algorithm-Independent Functions

10.2.6.6.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.6.6.2

CryptIsAsymAlgorithm()

This function indicates if an algorithm is an asymmetric algorithm.

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

Return Value

Meaning

TRUE(1)

if it is an asymmetric algorithm

FALSE(0)if it is not an asymmetric algorithm

BOOL
CryptIsAsymAlgorithm(
TPM_ALG_ID
)

algID

// IN: algorithm ID{
switch(algID){#if ALG_RSA
case ALG_RSA_VALUE:#endif#if ALG_ECC
case ALG_ECC_VALUE:#endifreturn TRUE;
break;
default:
break;}
return FALSE;}

10.2.6.6.3

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().

351

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

TPM_RC

Page 556
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417

Trusted Platform Module Library

CryptSecretEncrypt(
OBJECT
const TPM2B
TPM2B_DATA
TPM2B_ENCRYPTED_SECRET)*encryptKey,*label,*data,*secret// IN: encryption key object// IN: a null-terminated string as L// OUT: secret value// OUT: secret structure

TPMT_RSA_DECRYPTTPM_RC

scheme;result = TPM_RC_SUCCESS;{//
if(data == NULL || secret == NULL)
return TPM_RC_FAILURE;// The output secret value has the size of the digest produced by the nameAlg.
data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg);// The encryption scheme is OAEP using the nameAlg of the encrypt key.
scheme.scheme = ALG_OAEP_VALUE;
scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg;
if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
return TPM_RC_ATTRIBUTES;
switch(encryptKey->publicArea.type){#if ALG_RSA
case ALG_RSA_VALUE:{// Create secret data from RNG
CryptRandomGenerate(data->t.size, data->t.buffer);// Encrypt the data by RSA OAEP into encrypted secret
result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA *)secret, &data->b,
encryptKey, &scheme, label, NULL);}
break;#endif // ALG_RSA#if ALG_ECC
case ALG_ECC_VALUE:{
TPMS_ECC_POINT
eccPublic;
TPM2B_ECC_PARAMETER eccPrivate;
TPMS_ECC_POINT
eccSecret;
BYTE*buffer = secret->t.secret;// Need to make sure that the public point of the key is on the// curve defined by the key.
if(!CryptEccIsPointOnCurve(
encryptKey->publicArea.parameters.eccDetail.curveID,&encryptKey->publicArea.unique.ecc))
result = TPM_RC_KEY;
else{// Call crypto engine to create an auxiliary ECC key// We assume crypt engine initialization should always success.
// Otherwise, TPM should go to failure mode.
CryptEccNewKeyPair(&eccPublic, &eccPrivate,
encryptKey->publicArea.parameters.eccDetail.curveID);// Marshal ECC public to secret structure. This will be used by the// recipient to decrypt the secret with their private key.
secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL);// Compute ECDH shared secret which is R = [d]Q where d is the// private part of the ephemeral key and Q is the public part of a// TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret// because the auxiliary ECC key is just created according to the

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 557
April 15, 2019

Trusted Platform Module Library
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

Part 4: Supporting Routines// parameters of input ECC encrypt key.
if(CryptEccPointMultiply(&eccSecret,encryptKey->publicArea.parameters.eccDetail.curveID,&encryptKey->publicArea.unique.ecc, &eccPrivate,
NULL, NULL)!= TPM_RC_SUCCESS)
result = TPM_RC_KEY;
else{// The secret value is computed from Z using KDFe as:// secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)// Where:// HashID the nameAlg of the decrypt key// Z
the x coordinate (Px) of the product (P) of the point//(Q) of the secret and the private x coordinate (de,V)//of the decryption key// Use a null-terminated string containing "SECRET"// PartyUInfo the x coordinate of the point in the secret//(Qe,U )// PartyVInfo the x coordinate of the public key (Qs,V )// bits
the number of bits in the digest of HashID// Retrieve seed from KDFe
CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b,
label, &eccPublic.x.b,&encryptKey->publicArea.unique.ecc.x.b,
data->t.size * 8, data->t.buffer);}}}
break;#endif // ALG_ECC
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return result;}10.2.6.6.4

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 asymmetricand symmetric decryption process

Page 558
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

Trusted Platform Module Library

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 cryptographicallybound.

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_VALUEFor RSA key, numeric value of the encrypted data is greater than themodulus, or the recovered data is larger than the output buffer. For
keyedHash or symmetric key, the secret is larger than the size of thedigest produced by the name algorithm.

TPM_RC_FAILURE

internal error

TPM_RCCryptSecretDecrypt(
OBJECT
TPM2B_NONCE*decryptKey,*nonceCaller,

const TPM2B
TPM2B_ENCRYPTED_SECRETTPM2B_DATA)*label,*secret,*data// IN: decrypt key// IN: nonceCaller. It is needed for//symmetric decryption. For//
asymmetric decryption, this//parameter is NULL// IN: a value for L// IN: input secret// OUT: decrypted secret value{
TPM_RC

result = TPM_RC_SUCCESS;// Decryption for secretswitch(decryptKey->publicArea.type){#if ALG_RSA
case ALG_RSA_VALUE:{
TPMT_RSA_DECRYPT
scheme;
TPMT_RSA_SCHEME*keyScheme= &decryptKey->publicArea.parameters.rsaDetail.scheme;
UINT16
digestSize;scheme = *(TPMT_RSA_DECRYPT *)keyScheme;// If the key scheme is ALG_NULL_VALUE, set the scheme to OAEP and// set the algorithm to the name algorithm.
if(scheme.scheme == ALG_NULL_VALUE){// Use OAEP scheme
scheme.scheme = ALG_OAEP_VALUE;
scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;}// use the digestSize as an indicator of whether or not the scheme// is using a supported hash algorithm.
// Note: depending on the scheme used for encryption, a hashAlg might// not be needed. However, the return value has to have some upper// limit on the size. In this case, it is the size of the digest of the// hash algorithm. It is checked after the decryption is done but, there// is no point in doing the decryption if the size is going to be// 'wrong' anyway.
digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg);if(scheme.scheme != ALG_OAEP_VALUE || digestSize == 0)
return TPM_RC_SCHEME;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 559
April 15, 2019

Trusted Platform Module Library
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565

Part 4: Supporting Routines// Set the output buffer capacity
data->t.size = sizeof(data->t.buffer);// Decrypt seed by RSA OAEP
result = CryptRsaDecrypt(&data->b, &secret->b,
decryptKey, &scheme, label);if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize))
result = TPM_RC_VALUE;}
break;#endif // ALG_RSA#if ALG_ECC
case ALG_ECC_VALUE:{
TPMS_ECC_POINT
TPMS_ECC_POINT
BYTE
INT32

eccPublic;
eccSecret;*buffer = secret->t.secret;size = secret->t.size;// Retrieve ECC point from secret buffer
result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);if(result == TPM_RC_SUCCESS){
result = CryptEccPointMultiply(&eccSecret,decryptKey->publicArea.parameters.eccDetail.curveID,&eccPublic, &decryptKey->sensitive.sensitive.ecc,
NULL, NULL);
if(result == TPM_RC_SUCCESS){// Set the size of the "recovered" secret value to be the size// of the digest produced by the nameAlg.
data->t.size =CryptHashGetDigestSize(decryptKey->publicArea.nameAlg);// The secret value is computed from Z using KDFe as:// secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)// Where:// HashID -- the nameAlg of the decrypt key// Z -- the x coordinate (Px) of the product (P) of the point//(Q) of the secret and the private x coordinate (de,V)//of the decryption key// Use -- a null-terminated string containing "SECRET"// PartyUInfo -- the x coordinate of the point in the secret//(Qe,U )// PartyVInfo -- the x coordinate of the public key (Qs,V )// bits -- the number of bits in the digest of HashID// Retrieve seed from KDFe
CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label,&eccPublic.x.b,&decryptKey->publicArea.unique.ecc.x.b,
data->t.size * 8, data->t.buffer);}}}
break;#endif // ALG_ECC#if!ALG_KEYEDHASH#
error"KEYEDHASH support is required"#endifcase ALG_KEYEDHASH_VALUE:// The seed size can not be bigger than the digest size of nameAlg
if(secret->t.size >CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
result = TPM_RC_VALUE;
else

Page 560
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

Trusted Platform Module Library{// Retrieve seed by XOR Obfuscation://
seed = XOR(secret, hash, key, nonceCaller, nullNonce)//
where://
secret the secret parameter from the TPM2_StartAuthHMAC//
command that contains the seed value//
hash
nameAlg of tpmKey//
key
the key or data value in the object referenced by//entityHandle in the TPM2_StartAuthHMAC command//
nonceCaller the parameter from the TPM2_StartAuthHMAC command//
nullNoncea zero-length nonce// XOR Obfuscation in place
CryptXORObfuscation(decryptKey->publicArea.nameAlg,&decryptKey->sensitive.sensitive.bits.b,&nonceCaller->b, NULL,
secret->t.size, secret->t.secret);// Copy decrypted seed
MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));}break;
case ALG_SYMCIPHER_VALUE:{TPM2B_IViv = {{0}};TPMT_SYM_DEF_OBJECT*symDef;// The seed size can not be bigger than the digest size of nameAlg
if(secret->t.size >CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
result = TPM_RC_VALUE;else{
symDef = &decryptKey->publicArea.parameters.symDetail.sym;
iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
symDef->keyBits.sym);
if(iv.t.size == 0)
return TPM_RC_FAILURE;
if(nonceCaller->t.size >= iv.t.size){
MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size);}else{
if(nonceCaller->t.size > sizeof(iv.t.buffer))
return TPM_RC_FAILURE;
MemoryCopy(iv.b.buffer, nonceCaller->t.buffer,nonceCaller->t.size);}// make sure secret will fit
if(secret->t.size > data->t.size)
return TPM_RC_FAILURE;
data->t.size = secret->t.size;// CFB decrypt, using nonceCaller as iv
CryptSymmetricDecrypt(data->t.buffer, symDef->algorithm,
symDef->keyBits.sym,
decryptKey->sensitive.sensitive.sym.t.buffer,&iv, ALG_CFB_VALUE, secret->t.size,
secret->t.secret);}}
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return result;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 561
April 15, 2019

Trusted Platform Module Library

10.2.6.6.5

Part 4: Supporting Routines

CryptParameterEncryption()

This function does in-place encryption of a response parameter.
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

void
CryptParameterEncryption(
TPM_HANDLE
TPM2B
UINT16
TPM2B_AUTH
BYTE)

handle,// IN: encrypt session handle*nonceCaller,// IN: nonce caller
leadingSizeInByte, // IN: the size of the leading size field in//
bytes*extraKey,// IN: additional key material other than//sessionAuth*buffer// IN/OUT: parameter buffer to be encrypted{
SESSION*session = SessionGet(handle); // encrypt session
TPM2B_TYPE(TEMP_KEY, (sizeof(extraKey->t.buffer)+ sizeof(session->sessionKey.t.buffer)));TPM2B_TEMP_KEY
key;// encryption key
UINT32cipherSize = 0;// size of cipher text//// Retrieve encrypted data size.
if(leadingSizeInByte == 2){// Extract the first two bytes as the size field as the data size// encrypt
cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);// advance the buffer
buffer = &buffer[2];}#ifdef
TPM4B
else if(leadingSizeInByte == 4){// use the first four bytes to indicate the number of bytes to encrypt
cipherSize = BYTE_ARRAY_TO_UINT32(buffer);//advance pointerbuffer = &buffer[4];}#endifelse{
FAIL(FATAL_ERROR_INTERNAL);}// Compute encryption key by concatenating sessionKey with extra key
MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));if(session->symmetric.algorithm == ALG_XOR_VALUE)// XOR parameter encryption formulation://
XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
CryptXORObfuscation(session->authHashAlg, &(key.b),&(session->nonceTPM.b),nonceCaller, cipherSize, buffer);
else
ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
session->symmetric.keyBits.aes, &(key.b),nonceCaller, &(session->nonceTPM.b),cipherSize, buffer);
return;}Page 562
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.6.6.6

Trusted Platform Module Library

CryptParameterDecryption()

This function does in-place decryption of a command parameter.

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744

Error Returns

Meaning

TPM_RC_SIZE

The number of bytes in the input buffer is less than the number ofbytes to be decrypted.

TPM_RCCryptParameterDecryption(
TPM_HANDLE
TPM2B
UINT32
UINT16
TPM2B_AUTH
BYTE)

handle,// IN: encrypted session handle*nonceCaller,// IN: nonce caller
bufferSize,// IN: size of parameter buffer
leadingSizeInByte, // IN: the size of the leading size field in//
byte*extraKey,// IN: the authValue*buffer// IN/OUT: parameter buffer to be decrypted{
SESSION*session = SessionGet(handle); // encrypt session// The HMAC key is going to be the concatenation of the session key and any// additional key material (like the authValue). The size of both of these// is the size of the buffer which can contain a TPMT_HA.
TPM2B_TYPE(HMAC_KEY, (sizeof(extraKey->t.buffer)+ sizeof(session->sessionKey.t.buffer)));TPM2B_HMAC_KEY
key;// decryption key
UINT32cipherSize = 0; // size of cipher text//// Retrieve encrypted data size.
if(leadingSizeInByte == 2){// The first two bytes of the buffer are the size of the// data to be decryptedcipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);buffer = &buffer[2];// advance the buffer}#ifdef TPM4B
else if(leadingSizeInByte == 4){// the leading size is four bytes so get the four byte size field
cipherSize = BYTE_ARRAY_TO_UINT32(buffer);buffer = &buffer[4];//advance pointer}#endifelse{
FAIL(FATAL_ERROR_INTERNAL);}
if(cipherSize > bufferSize)
return TPM_RC_SIZE;// Compute decryption key by concatenating sessionAuth with extra input key
MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));if(session->symmetric.algorithm == ALG_XOR_VALUE)// XOR parameter decryption formulation://
XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)// Call XOR obfuscation function
CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller,&(session->nonceTPM.b), cipherSize, buffer);else// Assume that it is one of the symmetric block ciphers.
ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 563
April 15, 2019

Trusted Platform Module Library
745
746
747
748
749
750

Part 4: Supporting Routines

session->symmetric.keyBits.sym,&key.b, nonceCaller, &session->nonceTPM.b,cipherSize, buffer);
return TPM_RC_SUCCESS;}

10.2.6.6.7

CryptComputeSymmetricUnique()This function computes the unique field in public area for symmetric objects.
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

void
CryptComputeSymmetricUnique(
TPMT_PUBLIC
TPMT_SENSITIVE
TPM2B_DIGEST)*publicArea,*sensitive,*unique// IN: the object's public area// IN: the associated sensitive area// OUT: unique buffer{// For parents (symmetric and derivation), use an HMAC to compute// the 'unique' field
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)){// Unique field is HMAC(sensitive->seedValue, sensitive->sensitive)
HMAC_STATE
hmacState;unique->b.size = CryptHmacStart2B(&hmacState, publicArea->nameAlg,&sensitive->seedValue.b);
CryptDigestUpdate2B(&hmacState.hashState,&sensitive->sensitive.any.b);
CryptHmacEnd2B(&hmacState, &unique->b);}else{
HASH_STATE hashState;// Unique := Hash(sensitive->seedValue || sensitive->sensitive)
unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg);
CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b);
CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b);
CryptHashEnd2B(&hashState, &unique->b);}
return;}10.2.6.6.8

CryptCreateObject()

This function creates an object. For an asymmetric key, it will create a key pair and, for a parent key, aseed value for child protections.
For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will create a secret
key if the caller did not provide one. It will create a random secret seed value that is hashed with thesecret value to create the public unique value.
publicArea, sensitive, and sensitiveCreate are the only required parameters and are the only ones thatare used by TPM2_Create(). The other parameters are optional and are used when the generated Object
needs to be deterministic. This is the case for both Primary Objects and Derived Objects.
When a seed value is provided, a RAND_STATE will be populated and used for all operations in theobject generation that require a random number. In the simplest case, TPM2_CreatePrimary() will use
seed, label and context with context being the hash of the template. If the Primary Object is in theEndorsement hierarchy, it will also populate proof with ehProof.

Page 564
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

For derived keys, seed will be the secret value from the parent, label and context will be set according to
the parameters of TPM2_CreateLoaded() and hashAlg will be set which causes the RAND_STATE to bea KDF generator.

782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825

Error Returns

Meaning

TPM_RC_KEY

a provided key is not an allowed value

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_NO_RESULT

unable to get random values (only in derivation)

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 keyedhash 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

TPM_RCCryptCreateObject(
OBJECT
TPMS_SENSITIVE_CREATERAND_STATE*object,*sensitiveCreate,*rand// IN: new object structure pointer// IN: sensitive creation// IN: the random number generator//
to use){
TPMT_PUBLIC
TPMT_SENSITIVE
TPM_RC*publicArea = &object->publicArea;*sensitive = &object->sensitive;
result = TPM_RC_SUCCESS;//// Set the sensitive type for the object
sensitive->sensitiveType = publicArea->type;// For all objects, copy the initial authorization data
sensitive->authValue = sensitiveCreate->userAuth;// If the TPM is the source of the data, set the size of the provided data to// zero so that there's no confusion about what to do.
if(IS_ATTRIBUTE(publicArea->objectAttributes,
TPMA_OBJECT, sensitiveDataOrigin))sensitiveCreate->data.t.size = 0;// Generate the key and unique fields for the asymmetric keys and just the// sensitive value for symmetric object
switch(publicArea->type){#if ALG_RSA// Create RSA key
case ALG_RSA_VALUE:// RSA uses full object so that it has a place to put the private// exponent
result = CryptRsaGenerateKey(publicArea, sensitive, rand);break;#endif // ALG_RSA#if ALG_ECC// Create ECC keycase ALG_ECC_VALUE:
result = CryptEccGenerateKey(publicArea, sensitive, rand);break;#endif // ALG_ECC
case ALG_SYMCIPHER_VALUE:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 565
April 15, 2019

Trusted Platform Module Library
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873

Part 4: Supporting Routines

result = CryptGenerateKeySymmetric(publicArea, sensitive,
sensitiveCreate, rand);break;
case ALG_KEYEDHASH_VALUE:
result = CryptGenerateKeyedHash(publicArea, sensitive,
sensitiveCreate, rand);break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
if(result != TPM_RC_SUCCESS)
return result;// Create the sensitive seed value// If this is a primary key in the endorsement hierarchy, stir the DRBG state// This implementation uses both shProof and ehProof to make sure that there// is no leakage of either.
if(object->attributes.primary && object->attributes.epsHierarchy){
DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b);
DRBG_AdditionalData((DRBG_STATE *)rand, &gp.ehProof.b);}// Generate a seedValue that is the size of the digest produced by nameAlg
sensitive->seedValue.t.size =DRBG_Generate(rand, sensitive->seedValue.t.buffer,
CryptHashGetDigestSize(publicArea->nameAlg));
if(g_inFailureMode)return TPM_RC_FAILURE;
else if(sensitive->seedValue.t.size == 0)
return TPM_RC_NO_RESULT;// For symmetric objects, need to compute the unique value for the public area
if(publicArea->type == ALG_SYMCIPHER_VALUE|| publicArea->type == ALG_KEYEDHASH_VALUE){
CryptComputeSymmetricUnique(publicArea, sensitive, &publicArea->unique.sym);}else{// if this is an asymmetric key and it isn't a parent, then// get rid of the seed.
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)|| !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
memset(&sensitive->seedValue, 0, sizeof(sensitive->seedValue));}// Compute the namePublicMarshalAndComputeName(publicArea, &object->name);
return result;}10.2.6.6.9

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
874
875
876
877
878
879
880
881
882
883

TPMI_ALG_HASH
CryptGetSignHashAlg(
TPMT_SIGNATURE
)

*auth

// IN: signature{if(auth->sigAlg == ALG_NULL_VALUE)
FAIL(FATAL_ERROR_INTERNAL);// Get authHash algorithm based on signing scheme
switch(auth->sigAlg)

Page 566
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

Trusted Platform Module Library{#if ALG_RSA// If RSA is supported, both RSASSA and RSAPSS are required#
if !defined ALG_RSASSA_VALUE || !defined ALG_RSAPSS_VALUE#
error "RSASSA and RSAPSS are required for RSA"#
endifcase ALG_RSASSA_VALUE:
return auth->signature.rsassa.hash;case ALG_RSAPSS_VALUE:
return auth->signature.rsapss.hash;#endif // ALG_RSA#if ALG_ECC// If ECC is defined, ECDSA is mandatory#
if !ALG_ECDSA#
error "ECDSA is requried for ECC"#
endifcase ALG_ECDSA_VALUE:// SM2 and ECSCHNORR are optional
#
#
#
#

#

#

if

ALG_SM2
case ALG_SM2_VALUE:
endif
if ALG_ECSCHNORR
case ALG_ECSCHNORR_VALUE:
endif//all ECC signatures look the same
return auth->signature.ecdsa.hash;if

ALG_ECDAA// Don't know how to verify an ECDAA signaturecase ALG_ECDAA_VALUE:
break;
endif#endif // ALG_ECC
case ALG_HMAC_VALUE:
return auth->signature.hmac.hashAlg;
default:
break;}
return ALG_NULL_VALUE;}

10.2.6.6.10

CryptIsSplitSign()

This function us used to determine if the signing operation is a split signing operation that required a
TPM2_Commit().
929
930
931
932
933
934
935
936
937
938
939
940
941

BOOL
CryptIsSplitSign(
TPM_ALG_ID)

scheme// IN: the algorithm selector{##

switch(scheme){
if ALG_ECDAA
case ALG_ECDAA_VALUE:
return TRUE;
break;
endif// ALG_ECDAA
default:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 567
April 15, 2019

Trusted Platform Module Library
942
943
944
945

Part 4: Supporting Routines

return FALSE;
break;}}

10.2.6.6.11

CryptIsAsymSignScheme()

This function indicates if a scheme algorithm is a sign algorithm.
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

BOOL
CryptIsAsymSignScheme(
TPMI_ALG_PUBLICTPMI_ALG_ASYM_SCHEME)

publicType,scheme// IN: Type of the object// IN: the scheme{
BOOL

isSignScheme = TRUE;

switch(publicType){#if ALG_RSA
case ALG_RSA_VALUE:
switch(scheme){#
if !ALG_RSASSA || !ALG_RSAPSS#
error "RSASSA and PSAPSS required if RSA used."#endifcase ALG_RSASSA_VALUE:
case ALG_RSAPSS_VALUE:
break;
default:
isSignScheme = FALSE;
break;}
break;#endif // ALG_RSA#if ALG_ECC// If ECC is implemented ECDSA is required
case ALG_ECC_VALUE:
switch(scheme){// Support for ECDSA is required for ECC
case ALG_ECDSA_VALUE:#if ALG_ECDAA // ECDAA is optionalcase ALG_ECDAA_VALUE:#endif#if ALG_ECSCHNORR // Schnorr is also optionalcase ALG_ECSCHNORR_VALUE:#endif#if ALG_SM2 // SM2 is optionalcase ALG_SM2_VALUE:#endifbreak;
default:
isSignScheme = FALSE;
break;}
break;#endif // ALG_ECC
default:
isSignScheme = FALSE;
break;}
return isSignScheme;

Page 568
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1001

Trusted Platform Module Library}

10.2.6.6.12

CryptIsAsymDecryptScheme()

This function indicate if a scheme algorithm is a decrypt algorithm.
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

BOOL
CryptIsAsymDecryptScheme(
TPMI_ALG_PUBLICTPMI_ALG_ASYM_SCHEME)

publicType,scheme// IN: Type of the object// IN: the scheme{
BOOL

isDecryptScheme = TRUE;

switch(publicType){#if ALG_RSA
case ALG_RSA_VALUE:
switch(scheme){case ALG_RSAES_VALUE:
case ALG_OAEP_VALUE:
break;
default:
isDecryptScheme = FALSE;
break;}
break;#endif // ALG_RSA#if ALG_ECC// If ECC is implemented ECDH is required
case ALG_ECC_VALUE:
switch(scheme){#if !ALG_ECDH#
error "ECDH is required for ECC"
#endifcase ALG_ECDH_VALUE:#if ALG_SM2
case ALG_SM2_VALUE:#endif#if ALG_ECMQVcase ALG_ECMQV_VALUE:#endifbreak;
default:
isDecryptScheme = FALSE;
break;}
break;#endif // ALG_ECC
default:
isDecryptScheme = FALSE;
break;}
return isDecryptScheme;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 569
April 15, 2019

Trusted Platform Module Library

10.2.6.6.13

Part 4: Supporting Routines

CryptSelectSignScheme()

This function is used by the attestation and signing commands. It implements the rules for selecting thesignature 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.
This function should not be called if 'signObject->publicArea.type' == ALG_SYMCIPHER.

1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

Return Value

Meaning

TRUE(1)scheme selected

FALSE(0)both scheme and key's default scheme are empty; or scheme isempty while key's default scheme requires explicit input scheme (split
signing); or non-empty default key scheme differs from scheme

BOOL
CryptSelectSignScheme(
OBJECT
TPMT_SIG_SCHEME)*signObject,*scheme

TPMT_SIG_SCHEME
TPMT_PUBLIC
BOOL*objectScheme;*publicArea;
OK;// IN: signing key// IN/OUT: signing scheme{// If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless// of the setting of scheme
if(signObject == NULL){
OK = TRUE;
scheme->scheme = ALG_NULL_VALUE;
scheme->details.any.hashAlg = ALG_NULL_VALUE;}
else{// assignment to save typing.
publicArea = &signObject->publicArea;// A symmetric cipher can be used to encrypt and decrypt but it can't// be used for signing
if(publicArea->type == ALG_SYMCIPHER_VALUE)
return FALSE;// Point to the scheme object
if(CryptIsAsymAlgorithm(publicArea->type))
objectScheme =(TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme;else
objectScheme =(TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme;// If the object doesn't have a default scheme, then use the// input scheme.
if(objectScheme->scheme == ALG_NULL_VALUE){// Input and default can't both be NULL
OK = (scheme->scheme != ALG_NULL_VALUE);// Assume that the scheme is compatible with the key. If not,// an error will be generated in the signing operation.
}else if(scheme->scheme == ALG_NULL_VALUE)

Page 570
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

Trusted Platform Module Library{// input scheme is NULL so use default// First, check to see if the default requires that the caller// provided scheme data
OK = !CryptIsSplitSign(objectScheme->scheme);if(OK){// The object has a scheme and the input is TPM_ALG_NULL so copy// the object scheme as the final scheme. It is better to use a// structure copy than a copy of the individual fields.
*scheme = *objectScheme;
}
}
else
{
// Both input and object have scheme selectors// If the scheme and the hash are not the same then...
// NOTE: the reason that there is no copy here is that the input// might contain extra data for a split signing scheme and that// data is not in the object so, it has to be preserved.
OK = (objectScheme->scheme == scheme->scheme)&& (objectScheme->details.any.hashAlg== scheme->details.any.hashAlg);}}
return OK;}

10.2.6.6.14

CryptSign()

Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and thegeneric TPM2_Sign() command. This function checks the key scheme and digest size. It does not checkif 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.

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

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 ofhashData does not match hash algorithm insignScheme (for an RSAkey); invalid commit status or failed to generate r value (for an ECC
key)

TPM_RCCryptSign(
OBJECT
TPMT_SIG_SCHEME
TPM2B_DIGEST
TPMT_SIGNATURE)*signKey,*signScheme,*digest,*signature// IN: signing key// IN: sign scheme.
// IN: The digest being signed// OUT: signature

TPM_RC

result = TPM_RC_SCHEME;{// Initialize signature scheme
signature->sigAlg = signScheme->scheme;// If the signature algorithm is TPM_ALG_NULL or the signing key is NULL,// then we are doneif((signature->sigAlg == ALG_NULL_VALUE) || (signKey == NULL))
return TPM_RC_SUCCESS;// Initialize signature hash

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 571
April 15, 2019

Trusted Platform Module Library
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175

Part 4: Supporting Routines// Note: need to do the check for TPM_ALG_NULL first because the null scheme// doesn't have a hashAlg member.
signature->signature.any.hashAlg = signScheme->details.any.hashAlg;// perform sign operation based on different key typeswitch(signKey->publicArea.type){#if ALG_RSA
case ALG_RSA_VALUE:
result = CryptRsaSign(signature, signKey, digest, NULL);
break;#endif // ALG_RSA#if ALG_ECC
case ALG_ECC_VALUE:// The reason that signScheme is passed to CryptEccSign but not to the// other signing methods is that the signing for ECC may be split and// need the 'r' value that is in the scheme but not in the signature.
result = CryptEccSign(signature, signKey, digest,(TPMT_ECC_SCHEME *)signScheme, NULL);
break;#endif // ALG_ECC
case ALG_KEYEDHASH_VALUE:
result = CryptHmacSign(signature, signKey, digest);
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return result;}10.2.6.6.15

CryptValidateSignature()

This function is used
TPM2_PolicySigned().

toverify a signature.

Itiscalledby TPM2_VerifySignature()

andSince this operation only requires use of a public key, no consistency checks are necessary for the key tosignature type because a caller can load any public key that they like with any scheme that they like. Thisroutine simply makes sure that the signature is correct, whatever the type.

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

Error Returns

Meaning

TPM_RC_SIGNATURE

the signature is not genuine

TPM_RC_SCHEME

the scheme is not supported

TPM_RC_HANDLEan HMAC key was selected but the private part of the key is notloadedTPM_RCCryptValidateSignature(
TPMI_DH_OBJECT
TPM2B_DIGEST
TPMT_SIGNATURE)

keyHandle,*digest,*signature// IN: The handle of sign key// IN: The digest being validated// IN: signature{// NOTE: HandleToObject will either return a pointer to a loaded object or// will assert. It will never return a non-valid value. This makes it save// to initialize 'publicArea' with the return value from HandleToObject()// without checking it first.
OBJECT*signObject = HandleToObject(keyHandle);
TPMT_PUBLIC*publicArea = &signObject->publicArea;
TPM_RC
result = TPM_RC_SCHEME;

Page 572
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

Trusted Platform Module Library// The input unmarshaling should prevent any input signature from being// a NULL signature, but just in caseif(signature->sigAlg == ALG_NULL_VALUE)
return TPM_RC_SIGNATURE;
switch(publicArea->type){#if ALG_RSA
case ALG_RSA_VALUE:{//// Call RSA code to verify signature
result = CryptRsaValidateSignature(signature, signObject, digest);
break;}#endif // ALG_RSA#if ALG_ECC
case ALG_ECC_VALUE:
result = CryptEccValidateSignature(signature, signObject, digest);
break;#endif // ALG_ECC
case ALG_KEYEDHASH_VALUE:
if(signObject->attributes.publicOnly)
result = TPM_RCS_HANDLE;
elseresult = CryptHMACVerifySignature(signObject, digest, signature);
break;
default:
break;}
return result;}10.2.6.6.16

CryptGetTestResult

This function returns the results of a self-test function.
NOTE:

1225
1226
1227
1228
1229
1230
1231
1232

the behavior in this function is NOT the correct behavior for a real TPM implementation. An artificial behavior isplaced here due to the limitation of a software simulation environment. For the correct behavior, consult the part3 specification for TPM2_GetTestResult().

TPM_RCCryptGetTestResult(
TPM2B_MAX_BUFFER)*outData// OUT: test result data{
outData->t.size = 0;
return TPM_RC_SUCCESS;}

10.2.6.6.17

CryptIsUniqueSizeValid()

This function validates that the unique values are consistent.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 573
April 15, 2019

Trusted Platform Module Library

NOTE:

1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269

Part 4: Supporting Routines

This is not a comprehensive test of the public key.

Return Value

Meaning

TRUE(1)sizes are consistent

FALSE(0)sizes are not consistent

BOOL
CryptIsUniqueSizeValid(
TPMT_PUBLIC)*publicArea// IN: the public area to check

BOOL
UINT16consistent = FALSE;
keySizeInBytes;{

switch(publicArea->type){#if ALG_RSA
case ALG_RSA_VALUE:
keySizeInBytes = BITS_TO_BYTES(
publicArea->parameters.rsaDetail.keyBits);
consistent = publicArea->unique.rsa.t.size == keySizeInBytes;
break;#endif // ALG_RSA#if ALG_ECC
case ALG_ECC_VALUE:{
keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(
publicArea->parameters.eccDetail.curveID));
consistent = keySizeInBytes > 0&& publicArea->unique.ecc.x.t.size <= keySizeInBytes&& publicArea->unique.ecc.y.t.size <= keySizeInBytes;}
break;#endif // ALG_ECC
default:// For SYMCIPHER and KEYDEDHASH objects, the unique field is the size// of the nameAlg digest.
consistent = publicArea->unique.sym.t.size== CryptHashGetDigestSize(publicArea->nameAlg);
break;}
return consistent;}

10.2.6.6.18

CryptIsSensitiveSizeValid()

This function is used by TPM2_LoadExternal() to validate that the sensitive area contains a sensitive
value that is consistent with the values in the public area.
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281

BOOL
CryptIsSensitiveSizeValid(
TPMT_PUBLIC
TPMT_SENSITIVE)*publicArea,*sensitiveArea

BOOL
UINT16consistent;
keySizeInBytes;// IN: the object's public part// IN: the object's sensitive part{switch(publicArea->type){#if ALG_RSA

Page 574
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318

Trusted Platform Module Librarycase ALG_RSA_VALUE:// sensitive prime value has to be half the size of the public modulus
keySizeInBytes = BITS_TO_BYTES(publicArea->parameters.rsaDetail.keyBits);
consistent =((sensitiveArea->sensitive.rsa.t.size * 2) == keySizeInBytes);break;#endif#if ALG_ECC
case ALG_ECC_VALUE:
keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(
publicArea->parameters.eccDetail.curveID));
consistent = (keySizeInBytes > 0)&& (sensitiveArea->sensitive.ecc.t.size == keySizeInBytes);break;#endifcase ALG_SYMCIPHER_VALUE:
keySizeInBytes =BITS_TO_BYTES(publicArea->parameters.symDetail.sym.keyBits.sym);
consistent = keySizeInBytes == sensitiveArea->sensitive.sym.t.size;
break;
case ALG_KEYEDHASH_VALUE:
keySizeInBytes = CryptHashGetBlockSize(publicArea->nameAlg);// if the block size is 0, then the algorithm is TPM_ALG_NULL and the// size of the private part is limited to 128. If the algorithm block// size is over 128 bytes, then the size is limited to 128 bytes for// interoperability reasons.
if((keySizeInBytes == 0) || (keySizeInBytes > 128))
keySizeInBytes = 128;
consistent = sensitiveArea->sensitive.bits.t.size <= keySizeInBytes;
break;
default:
consistent = TRUE;
break;}
return consistent;}

10.2.6.6.19

CryptValidateKeys()This function is used to verify that the key material of and object is valid. For a publicOnly object, the key
is verified for size and, if it is an ECC key, it is verified to be on the specified curve. For a key with asensitive area, the binding between the public and private parts of the key are verified. If the nameAlg of
the key is TPM_ALG_NULL, then the size of the sensitive area is verified but the public portion is notverified, unless the key is an RSA key. For an RSA key, the reason for loading the sensitive area is to use
it. The only way to use a private RSA key is to compute the private exponent. To compute the private
exponent, the public modulus is used.

1319
1320
1321
1322

Error Returns

Meaning

TPM_RC_BINDING

the public and private parts are not cryptographically boundTPM_RC_HASH

cannot have a publicOnly key with nameAlg of TPM_ALG_NULL

TPM_RC_KEY

the public unique is not valid

TPM_RC_KEY_SIZE

the private area key is not valid

TPM_RC_TYPE

the types of the sensitive and private parts do not match

TPM_RCCryptValidateKeys(
TPMT_PUBLIC
TPMT_SENSITIVE*publicArea,*sensitive,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 575
April 15, 2019

Trusted Platform Module Library
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388

TPM_RCTPM_RC)Part 4: Supporting Routines

blamePublic,
blameSensitive{
TPM_RCUINT16
UINT16
TPMU_PUBLIC_PARMS
TPMU_PUBLIC_ID

result;keySizeInBytes;
digestSize = CryptHashGetDigestSize(publicArea->nameAlg);*params = &publicArea->parameters;*unique = &publicArea->unique;if(sensitive != NULL){// Make sure that the types of the public and sensitive are compatible
if(publicArea->type != sensitive->sensitiveType)return TPM_RCS_TYPE + blameSensitive;// Make sure that the authValue is not bigger than allowed// If there is no name algorithm, then the size just needs to be less than// the maximum size of the buffer used for authorization. That size check// was made during unmarshaling of the sensitive areaif((sensitive->authValue.t.size) > digestSize && (digestSize > 0))
return TPM_RCS_SIZE + blameSensitive;}
switch(publicArea->type){#if ALG_RSA
case ALG_RSA_VALUE:
keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits);// Regardless of whether there is a sensitive area, the public modulus// needs to have the correct size. Otherwise, it can't be used for// any public key operation nor can it be used to compute the private// exponent.
// NOTE: This implementation only supports key sizes that are multiples// of 1024 bits which means that the MSb of the 0th byte will always be// SET in any prime and in the public modulus.
if((unique->rsa.t.size != keySizeInBytes)|| (unique->rsa.t.buffer[0] < 0x80))
return TPM_RCS_KEY + blamePublic;if(params->rsaDetail.exponent != 0&& params->rsaDetail.exponent < 7)
return TPM_RCS_VALUE + blamePublic;
if(sensitive != NULL){// If there is a sensitive area, it has to be the correct size// including having the correct high order bit SET.
if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes)|| (sensitive->sensitive.rsa.t.buffer[0] < 0x80))
return TPM_RCS_KEY_SIZE + blameSensitive;}
break;#endif#if ALG_ECC
case ALG_ECC_VALUE:{
TPMI_ECC_CURVE
curveId;
curveId = params->eccDetail.curveID;
keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId));
if(sensitive == NULL){// Validate the public key size
if(unique->ecc.x.t.size != keySizeInBytes|| unique->ecc.y.t.size != keySizeInBytes)
return TPM_RCS_KEY + blamePublic;
if(publicArea->nameAlg != ALG_NULL_VALUE){
if(!CryptEccIsPointOnCurve(curveId, &unique->ecc))

Page 576
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454

Trusted Platform Module Library
return TPM_RCS_ECC_POINT + blamePublic;

}
}
else
{
// If the nameAlg is TPM_ALG_NULL, then only verify that the// private part of the key is OK.
if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc,
curveId))
return TPM_RCS_KEY_SIZE;
if(publicArea->nameAlg != ALG_NULL_VALUE){// Full key load, verify that the public point belongs to the// private key.
TPMS_ECC_POINT
toCompare;result = CryptEccPointMultiply(&toCompare, curveId, NULL,&sensitive->sensitive.ecc,
NULL, NULL);
if(result != TPM_RC_SUCCESS)
return TPM_RCS_BINDING;
else{// Make sure that the private key generated the public key.
// The input values and the values produced by the point// multiply may not be the same size so adjust the computed// value to match the size of the input value by adding or// removing zeros.
AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size);
AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size);
if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b)|| !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b))
return TPM_RCS_BINDING;}}}
break;}#endifdefault:// Checks for SYMCIPHER and KEYEDHASH are largely the same// If public area has a nameAlg, then validate the public area size// and if there is also a sensitive area, validate the binding// For consistency, if the object is public-only just make sure that// the unique field is consistent with the name algorithm
if(sensitive == NULL){
if(unique->sym.t.size != digestSize)
return TPM_RCS_KEY + blamePublic;}else{// Make sure that the key size in the sensitive area is consistent.
if(publicArea->type == ALG_SYMCIPHER_VALUE){
result = CryptSymKeyValidate(&params->symDetail.sym,&sensitive->sensitive.sym);
if(result != TPM_RC_SUCCESS)
return result + blameSensitive;}else{// For a keyed hash object, the key has to be less than the// smaller of the block size of the hash used in the scheme or// 128 bytes. The worst case value is limited by the// unmarshaling code so the only thing left to be checked is

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 577
April 15, 2019

Trusted Platform Module Library
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504

Part 4: Supporting Routines// that it does not exceed the block size of the hash.
// by the hash algorithm of the scheme.
TPMT_KEYEDHASH_SCHEME*scheme;UINT16
maxSize;scheme = &params->keyedHashDetail.scheme;if(scheme->scheme == ALG_XOR_VALUE){
maxSize = CryptHashGetBlockSize(scheme->details.xor.hashAlg);}else if(scheme->scheme == ALG_HMAC_VALUE){
maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg);}else if(scheme->scheme == ALG_NULL_VALUE){// Not signing or xor so must be a data block
maxSize = 128;}
else
return TPM_RCS_SCHEME + blamePublic;
if(sensitive->sensitive.bits.t.size > maxSize)
return TPM_RCS_KEY_SIZE + blameSensitive;}// If there is a nameAlg, check the binding
if(publicArea->nameAlg != ALG_NULL_VALUE){TPM2B_DIGEST
compare;if(sensitive->seedValue.t.size != digestSize)
return TPM_RCS_KEY_SIZE + blameSensitive;
CryptComputeSymmetricUnique(publicArea, sensitive, &compare);if(!MemoryEqual2B(&unique->sym.b, &compare.b))
return TPM_RC_BINDING;}}
break;}// For a parent, need to check that the seedValue is the correct size for// protections. It should be at least half the size of the nameAlg
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)&& IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)&& sensitive != NULL&& publicArea->nameAlg != ALG_NULL_VALUE){
if((sensitive->seedValue.t.size < (digestSize / 2))|| (sensitive->seedValue.t.size > digestSize))
return TPM_RCS_SIZE + blameSensitive;}
return TPM_RC_SUCCESS;}

10.2.6.6.20

CryptAlgSetImplemented()

This function initializes the bit vector with one bit for each implemented algorithm. This function is calledfrom _TPM_Init(). The vector of implemented algorithms should be generated by the part 2 parser so thatthe g_implementedAlgorithms vector can be a constant. That's not how it is now
1505
1506
1507
1508
1509
1510
1511

void
CryptAlgsSetImplemented(
void){
AlgorithmGetImplementedVector(&g_implementedAlgorithms);}

Page 578
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.6.6.21

Trusted Platform Module Library

CryptSelectMac()

This function is used to set the MAC scheme based on the key parameters and the input scheme.

1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562

Error Returns

Meaning

TPM_RC_SCHEME

the scheme is not a valid mac scheme

TPM_RC_TYPE

the input key is not a type that supports a mac

TPM_RC_VALUE

the input scheme and the key scheme are not compatible

TPM_RCCryptSelectMac(
TPMT_PUBLICTPMI_ALG_MAC_SCHEME*publicArea,*inMac){
TPM_ALG_ID
macAlg = ALG_NULL_VALUE;
switch(publicArea->type){case ALG_KEYEDHASH_VALUE:{// Local value to keep lines from getting too long
TPMT_KEYEDHASH_SCHEME*scheme;scheme = &publicArea->parameters.keyedHashDetail.scheme;// Expect that the scheme is either HMAC or NULL
if(scheme->scheme != ALG_NULL_VALUE)
macAlg = scheme->details.hmac.hashAlg;
break;}
case ALG_SYMCIPHER_VALUE:{
TPMT_SYM_DEF_OBJECT*scheme;scheme = &publicArea->parameters.symDetail.sym;// Expect that the scheme is either valid symmetric cipher or NULL
if(scheme->algorithm != ALG_NULL_VALUE)
macAlg = scheme->mode.sym;
break;}
default:
return TPM_RCS_TYPE;}// If the input value is not TPM_ALG_NULL ...
if(*inMac != ALG_NULL_VALUE){// ... then either the scheme in the key must be TPM_ALG_NULL or the input// value must matchif((macAlg != ALG_NULL_VALUE) && (*inMac != macAlg))
return TPM_RCS_VALUE;}else{// Since the input value is TPM_ALG_NULL, then the key value can't be// TPM_ALG_NULL
if(macAlg == ALG_NULL_VALUE)
return TPM_RCS_VALUE;*inMac = macAlg;}
if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE))
return TPM_RCS_SCHEME;
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 579
April 15, 2019

Trusted Platform Module Library

10.2.6.6.22

Part 4: Supporting Routines

CryptMacIsValidForKey()

Check to see if the key type is compatible with the mac type
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582

BOOL
CryptMacIsValidForKey(
TPM_ALG_ID
TPM_ALG_ID
BOOL

keyType,
macAlg,flag){
switch(keyType){case ALG_KEYEDHASH_VALUE:
return CryptHashIsValidAlg(macAlg, flag);break;
case ALG_SYMCIPHER_VALUE:
return CryptSmacIsValidAlg(macAlg, flag);break;
default:
break;}
return FALSE;}

10.2.6.6.23

CryptSmacIsValidAlg()

This function is used to test if an algorithm is a supported SMAC algorithm. It needs to be updated as newalgorithms are added.
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602

BOOL
CryptSmacIsValidAlg(
TPM_ALG_ID
BOOL

alg,
FLAG

// IN: Indicates if TPM_ALG_NULL is valid){
switch (alg){#if ALG_CMAC
case ALG_CMAC_VALUE:
return TRUE;
break;#endifcase ALG_NULL_VALUE:
return FLAG;
break;
default:
return FALSE;}}

10.2.6.6.24

CryptSymModeIsValid()

Function checks to see if an algorithm ID is a valid, symmetric block cipher mode for the TPM. If flag is
SET, them TPM_ALG_NULL is a valid mode. not include the modes used for SMAC
1603
1604
1605
1606
1607
1608

BOOL
CryptSymModeIsValid(
TPM_ALG_ID
BOOL

mode,
flag

)
{

Page 580
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634

Trusted Platform Module Libraryswitch(mode){#if ALG_CTR
case ALG_CTR_VALUE:#endif // ALG_CTR#if ALG_OFB
case ALG_OFB_VALUE:#endif // ALG_OFB#if ALG_CBC
case ALG_CBC_VALUE:#endif // ALG_CBC#if ALG_CFB
case ALG_CFB_VALUE:#endif // ALG_CFB#if ALG_ECB
case ALG_ECB_VALUE:#endif // ALG_ECB
return TRUE;
case ALG_NULL_VALUE:
return flag;
break;
default:
break;}
return FALSE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 581
April 15, 2019

Trusted Platform Module Library

10.2.7

CryptSelfTest.c

10.2.7.1

Introduction

Part 4: Supporting Routines

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 bitfor each decryption algorithm that needs to be tested and g_untestedEncryptionAlgorithms has a bit foreach encryption algorithm that needs to be tested. Before an algorithm is used, the appropriate vector ischecked (indexed using the algorithm ID). If the bit is 1, then the test function should be called.
For more information, see TpmSelfTests().txt
1#include "Tpm.h"

10.2.7.2
10.2.7.2.1

Functions
RunSelfTest()

Local function to run self-test
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

static TPM_RC
CryptRunSelfTests(
ALGORITHM_VECTOR)*toTest

TPM_ALG_ID

alg;// IN: the vector of the algorithms to test{// For each of the algorithms that are in the toTestVecor, need to run a// testfor(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++){if(TEST_BIT(alg, *toTest)){
TPM_RC
result = CryptTestAlgorithm(alg, toTest);
if(result != TPM_RC_SUCCESS)
return result;}}
return TPM_RC_SUCCESS;}

10.2.7.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 arerun. 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 thiscan 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.

Page 582
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

Trusted Platform Module Library

Error Returns

Meaning

TPM_RC_CANCELED

if the command is canceled

LIB_EXPORTTPM_RCCryptSelfTest(
TPMI_YES_NO)

fullTest// IN: if full test is required{#if SIMULATION
if(g_forceFailureMode)
FAIL(FATAL_ERROR_FORCED);#endif// If the caller requested a full test, then reset the to test vector so that// all the tests will be run
if(fullTest == YES){
MemoryCopy(g_toTest,
g_implementedAlgorithms,
sizeof(g_toTest));}return CryptRunSelfTests(&g_toTest);}

10.2.7.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.

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

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

TPM_RCCryptIncrementalSelfTest(
TPML_ALG
TPML_ALG)*toTest,*toDoList// IN: list of algorithms to be tested// OUT: list of algorithms needing test

ALGORITHM_VECTOR
TPM_ALG_ID
UINT32

toTestVector = {0};
alg;
i;

{

pAssert(toTest != NULL && toDoList != NULL);
if(toTest->count > 0){// Transcribe the toTest list into the toTestVector
for(i = 0; i < toTest->count; i++){alg = toTest->algorithms[i];// make sure that the algorithm value is not out of range
if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms))

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 583
April 15, 2019

Trusted Platform Module Library
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

Part 4: Supporting Routines

return TPM_RC_VALUE;
SET_BIT(alg, toTestVector);}// Run the test
if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED)
return TPM_RC_CANCELED;}// Fill in the toDoList with the algorithms that are still untested
toDoList->count = 0;
for(alg = TPM_ALG_FIRST;
toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST;
alg++){
if(TEST_BIT(alg, g_toTest))
toDoList->algorithms[toDoList->count++] = alg;}
return TPM_RC_SUCCESS;}

10.2.7.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

void
CryptInitializeToTest(
void){// Indicate that nothing has been tested
memset(&g_cryptoSelfTestState, 0, sizeof(g_cryptoSelfTestState));// Copy the implemented algorithm vector
MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest));// Setting the algorithm to null causes the test function to just clear// out any algorithms for which there is no test.
CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest);
return;}10.2.7.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 algorithm 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 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.

99
100
101
102
103

Error Returns

Meaning

TPM_RC_CANCELED

test was canceled

LIB_EXPORTTPM_RCCryptTestAlgorithm(
TPM_ALG_ID
ALGORITHM_VECTOR

Page 584
April 15, 2019alg,
*toTestTCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

Trusted Platform Module Library){
TPM_RC
result;#if SELF_TEST
result = TestAlgorithm(alg, toTest);#else// If this is an attempt to determine the algorithms for which there is a// self test, pretend that all of them do. We do that by not clearing any// of the algorithm bits. When/if this function is called to run tests, it// will over report. This can be changed so that any call to check on which// algorithms have tests, 'toTest' can be cleared.
if(alg != TPM_ALG_ERROR){
CLEAR_BIT(alg, g_toTest);
if(toTest != NULL)
CLEAR_BIT(alg, *toTest);}
result = TPM_RC_SUCCESS;#endifreturn result;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 585
April 15, 2019

Trusted Platform Module Library

10.2.8
1
2

Part 4: Supporting Routines

CryptEccData.c#include "Tpm.h"#include "OIDS.h"

This file contains the ECC curve data. The format of the data depends on the setting of
USE_BN_ECC_DATA. If it is defined, then the TPM's BigNum() format is used. Otherwise, it is kept in
TPM2B format. The purpose of having the data in BigNum() format is so that it does not have to bereformatted before being used by the crypto library.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#if ALG_ECC#if USE_BN_ECC_DATA#
define TO_ECC_64
TO_CRYPT_WORD_64#
define TO_ECC_56(a, b, c, d, e, f, g)
TO_ECC_64(0, a, b, c, d, e, f, g)#
define TO_ECC_48(a, b, c, d, e, f)
TO_ECC_64(0, 0, a, b, c, d, e, f)#
define TO_ECC_40(a, b, c, d, e)
TO_ECC_64(0, 0, 0, a, b, c, d, e)#
if RADIX_BITS > 32#
define TO_ECC_32(a, b, c, d)
TO_ECC_64(0, 0, 0, 0, a, b, c, d)#define TO_ECC_24(a, b, c)
TO_ECC_64(0, 0, 0, 0, 0, a, b, c)#
define TO_ECC_16(a, b)
TO_ECC_64(0, 0, 0, 0, 0, 0, a, b)#
define TO_ECC_8(a)TO_ECC_64(0, 0, 0, 0, 0, 0, 0, a)#else // RADIX_BITS == 32#
define TO_ECC_32
BIG_ENDIAN_BYTES_TO_UINT32#
define TO_ECC_24(a, b, c)
TO_ECC_32(0, a, b, c)#
define TO_ECC_16(a, b)
TO_ECC_32(0, 0, a, b)#
define TO_ECC_8(a)TO_ECC_32(0, 0, 0, a)#
endif#else // TPM2B_#
define TO_ECC_64(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h#define TO_ECC_56(a, b, c, d, e, f, g)
a, b, c, d, e, f, g#
define TO_ECC_48(a, b, c, d, e, f)a, b, c, d, e, f#
define TO_ECC_40(a, b, c, d, e)a, b, c, d, e#define TO_ECC_32(a, b, c, d)a, b, c, d#define TO_ECC_24(a, b, c)a, b, c#define TO_ECC_16(a, b)
a, b#
define TO_ECC_8(a)a#endif#if USE_BN_ECC_DATA#define BN_MIN_ALLOC(bytes)(BYTES_TO_CRYPT_WORDS(bytes) == 0) ? 1 : BYTES_TO_CRYPT_WORDS(bytes)# define ECC_CONST(NAME, bytes, initializer)
const struct {crypt_uword_t
allocate, size, d[BN_MIN_ALLOC(bytes)];} NAME = {BN_MIN_ALLOC(bytes), BYTES_TO_CRYPT_WORDS(bytes),{initializer}}
ECC_CONST(ECC_ZERO, 0, 0);#else# define ECC_CONST(NAME, bytes, initializer)
const TPM2B_##bytes##_BYTE_VALUE NAME = {bytes, {initializer}}

\
\
\
\

\

Have to special case ECC_ZERO
41
42
43
44
45
46
47
48
49
50
51
52

TPM2B_BYTE_VALUE(1);TPM2B_1_BYTE_VALUE ECC_ZERO = {1, {0}};#endif
ECC_CONST(ECC_ONE, 1, 1);#if !USE_BN_ECC_DATA
TPM2B_BYTE_VALUE(24);#define TO_ECC_192(a, b, c) a, b, c
TPM2B_BYTE_VALUE(28);#define TO_ECC_224(a, b, c, d)a, b, c, d
TPM2B_BYTE_VALUE(32);#define TO_ECC_256(a, b, c, d)a, b, c, d
TPM2B_BYTE_VALUE(48);

Page 586
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

Trusted Platform Module Library#define TO_ECC_384(a, b, c, d, e, f)a, b, c, d, e, f
TPM2B_BYTE_VALUE(66);#define TO_ECC_528(a, b, c, d, e, f, g, h, i)a, b, c, d, e, f, g, h, i
TPM2B_BYTE_VALUE(80);#define TO_ECC_640(a, b, c, d, e, f, g, h, i, j)
a, b, c, d, e, f, g, h, i, j#else
#define TO_ECC_192(a, b, c) c, b, a#define TO_ECC_224(a, b, c, d)d, c, b, a#define TO_ECC_256(a, b, c, d)d, c, b, a#define TO_ECC_384(a, b, c, d, e, f)f, e, d, c, b, a#define TO_ECC_528(a, b, c, d, e, f, g, h, i)
i, h, g, f, e, d, c, b, a#define TO_ECC_640(a, b, c, d, e, f, g, h, i, j)
j, i, h, g, f, e, d, c, b, a
#endif // !USE_BN_ECC_DATA#if ECC_NIST_P192
ECC_CONST(NIST_P192_p, 24, TO_ECC_192(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P192_a, 24, TO_ECC_192(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P192_b, 24, TO_ECC_192(
TO_ECC_64(0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7),
TO_ECC_64(0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49),
TO_ECC_64(0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1)));
ECC_CONST(NIST_P192_gX, 24, TO_ECC_192(
TO_ECC_64(0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6),
TO_ECC_64(0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00),
TO_ECC_64(0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12)));
ECC_CONST(NIST_P192_gY, 24, TO_ECC_192(
TO_ECC_64(0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78),
TO_ECC_64(0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5),
TO_ECC_64(0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11)));
ECC_CONST(NIST_P192_n, 24, TO_ECC_192(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36),
TO_ECC_64(0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31)));#define NIST_P192_h
ECC_ONE#define NIST_P192_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P192 = {(bigNum)&NIST_P192_p, (bigNum)&NIST_P192_n, (bigNum)&NIST_P192_h,(bigNum)&NIST_P192_a, (bigNum)&NIST_P192_b,{(bigNum)&NIST_P192_gX, (bigNum)&NIST_P192_gY, (bigNum)&NIST_P192_gZ}};#else
const ECC_CURVE_DATA NIST_P192 = {&NIST_P192_p.b, &NIST_P192_n.b, &NIST_P192_h.b,&NIST_P192_a.b, &NIST_P192_b.b,{&NIST_P192_gX.b, &NIST_P192_gY.b, &NIST_P192_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_NIST_P192#if ECC_NIST_P224
ECC_CONST(NIST_P224_p, 28, TO_ECC_224(
TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01)));
ECC_CONST(NIST_P224_a, 28, TO_ECC_224(
TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE)));
ECC_CONST(NIST_P224_b, 28, TO_ECC_224(
TO_ECC_32(0xB4, 0x05, 0x0A, 0x85),
TO_ECC_64(0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56),

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 587
April 15, 2019

Trusted Platform Module Library
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

Part 4: Supporting Routines

TO_ECC_64(0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA),
TO_ECC_64(0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4)));
ECC_CONST(NIST_P224_gX, 28, TO_ECC_224(
TO_ECC_32(0xB7, 0x0E, 0x0C, 0xBD),
TO_ECC_64(0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9),
TO_ECC_64(0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22),
TO_ECC_64(0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21)));
ECC_CONST(NIST_P224_gY, 28, TO_ECC_224(
TO_ECC_32(0xBD, 0x37, 0x63, 0x88),
TO_ECC_64(0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6),
TO_ECC_64(0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64),
TO_ECC_64(0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34)));
ECC_CONST(NIST_P224_n, 28, TO_ECC_224(
TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E),
TO_ECC_64(0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D)));#define NIST_P224_h
ECC_ONE#define NIST_P224_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P224 = {(bigNum)&NIST_P224_p, (bigNum)&NIST_P224_n, (bigNum)&NIST_P224_h,(bigNum)&NIST_P224_a, (bigNum)&NIST_P224_b,{(bigNum)&NIST_P224_gX, (bigNum)&NIST_P224_gY, (bigNum)&NIST_P224_gZ}};#else
const ECC_CURVE_DATA NIST_P224 = {&NIST_P224_p.b, &NIST_P224_n.b, &NIST_P224_h.b,&NIST_P224_a.b, &NIST_P224_b.b,{&NIST_P224_gX.b, &NIST_P224_gY.b, &NIST_P224_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_NIST_P224#if ECC_NIST_P256
ECC_CONST(NIST_P256_p, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P256_a, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P256_b, 32, TO_ECC_256(
TO_ECC_64(0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7),
TO_ECC_64(0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC),
TO_ECC_64(0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6),
TO_ECC_64(0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B)));
ECC_CONST(NIST_P256_gX, 32, TO_ECC_256(
TO_ECC_64(0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47),
TO_ECC_64(0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2),
TO_ECC_64(0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0),
TO_ECC_64(0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96)));
ECC_CONST(NIST_P256_gY, 32, TO_ECC_256(
TO_ECC_64(0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B),
TO_ECC_64(0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16),
TO_ECC_64(0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE),
TO_ECC_64(0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5)));
ECC_CONST(NIST_P256_n, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84),
TO_ECC_64(0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51)));#define NIST_P256_h
ECC_ONE#define NIST_P256_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P256 = {Page 588
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

Trusted Platform Module Library(bigNum)&NIST_P256_p, (bigNum)&NIST_P256_n, (bigNum)&NIST_P256_h,(bigNum)&NIST_P256_a, (bigNum)&NIST_P256_b,{(bigNum)&NIST_P256_gX, (bigNum)&NIST_P256_gY, (bigNum)&NIST_P256_gZ}};#else
const ECC_CURVE_DATA NIST_P256 = {&NIST_P256_p.b, &NIST_P256_n.b, &NIST_P256_h.b,&NIST_P256_a.b, &NIST_P256_b.b,{&NIST_P256_gX.b, &NIST_P256_gY.b, &NIST_P256_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_NIST_P256#if ECC_NIST_P384
ECC_CONST(NIST_P384_p, 48, TO_ECC_384(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P384_a, 48, TO_ECC_384(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P384_b, 48, TO_ECC_384(
TO_ECC_64(0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4),
TO_ECC_64(0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19),
TO_ECC_64(0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12),
TO_ECC_64(0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A),
TO_ECC_64(0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D),
TO_ECC_64(0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF)));
ECC_CONST(NIST_P384_gX, 48, TO_ECC_384(
TO_ECC_64(0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37),
TO_ECC_64(0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74),
TO_ECC_64(0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98),
TO_ECC_64(0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38),
TO_ECC_64(0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C),
TO_ECC_64(0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7)));
ECC_CONST(NIST_P384_gY, 48, TO_ECC_384(
TO_ECC_64(0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F),
TO_ECC_64(0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29),
TO_ECC_64(0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C),
TO_ECC_64(0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0),
TO_ECC_64(0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D),
TO_ECC_64(0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F)));
ECC_CONST(NIST_P384_n, 48, TO_ECC_384(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF),
TO_ECC_64(0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A),
TO_ECC_64(0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73)));#define NIST_P384_h
ECC_ONE#define NIST_P384_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P384 = {(bigNum)&NIST_P384_p, (bigNum)&NIST_P384_n, (bigNum)&NIST_P384_h,(bigNum)&NIST_P384_a, (bigNum)&NIST_P384_b,{(bigNum)&NIST_P384_gX, (bigNum)&NIST_P384_gY, (bigNum)&NIST_P384_gZ}};#else
const ECC_CURVE_DATA NIST_P384 = {&NIST_P384_p.b, &NIST_P384_n.b, &NIST_P384_h.b,&NIST_P384_a.b, &NIST_P384_b.b,{&NIST_P384_gX.b, &NIST_P384_gY.b, &NIST_P384_gZ.b}};#endif // USE_BN_ECC_DATA

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 589
April 15, 2019

Trusted Platform Module Library
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Part 4: Supporting Routines#endif // ECC_NIST_P384#if ECC_NIST_P521
ECC_CONST(NIST_P521_p, 66, TO_ECC_528(
TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P521_a, 66, TO_ECC_528(
TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P521_b, 66, TO_ECC_528(
TO_ECC_16(0x00, 0x51),
TO_ECC_64(0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F),
TO_ECC_64(0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE),
TO_ECC_64(0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3),
TO_ECC_64(0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1),
TO_ECC_64(0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B),
TO_ECC_64(0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07),
TO_ECC_64(0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1),
TO_ECC_64(0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00)));ECC_CONST(NIST_P521_gX, 66, TO_ECC_528(
TO_ECC_16(0x00, 0xC6),
TO_ECC_64(0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD),
TO_ECC_64(0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42),
TO_ECC_64(0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21),
TO_ECC_64(0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA),
TO_ECC_64(0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28),
TO_ECC_64(0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE),
TO_ECC_64(0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B),
TO_ECC_64(0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66)));
ECC_CONST(NIST_P521_gY, 66, TO_ECC_528(
TO_ECC_16(0x01, 0x18),
TO_ECC_64(0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04),
TO_ECC_64(0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9),
TO_ECC_64(0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68),
TO_ECC_64(0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C),
TO_ECC_64(0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40),
TO_ECC_64(0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61),
TO_ECC_64(0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40),
TO_ECC_64(0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50)));ECC_CONST(NIST_P521_n, 66, TO_ECC_528(
TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA),
TO_ECC_64(0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B),
TO_ECC_64(0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0),
TO_ECC_64(0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE),
TO_ECC_64(0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09)));#define NIST_P521_h
ECC_ONE#define NIST_P521_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P521 = {Page 590
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

Trusted Platform Module Library(bigNum)&NIST_P521_p, (bigNum)&NIST_P521_n, (bigNum)&NIST_P521_h,(bigNum)&NIST_P521_a, (bigNum)&NIST_P521_b,{(bigNum)&NIST_P521_gX, (bigNum)&NIST_P521_gY, (bigNum)&NIST_P521_gZ}};#else
const ECC_CURVE_DATA NIST_P521 = {&NIST_P521_p.b, &NIST_P521_n.b, &NIST_P521_h.b,&NIST_P521_a.b, &NIST_P521_b.b,{&NIST_P521_gX.b, &NIST_P521_gY.b, &NIST_P521_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_NIST_P521#if ECC_BN_P256
ECC_CONST(BN_P256_p, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD),
TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F),
TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98, 0x0A, 0x82),
TO_ECC_64(0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13)));#define BN_P256_a
ECC_ZEROECC_CONST(BN_P256_b, 1, TO_ECC_8(3));#define BN_P256_gX
ECC_ONE
ECC_CONST(BN_P256_gY, 1, TO_ECC_8(2));
ECC_CONST(BN_P256_n, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD),
TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E),
TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A),
TO_ECC_64(0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D)));#define BN_P256_h
ECC_ONE#define BN_P256_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA BN_P256 = {(bigNum)&BN_P256_p, (bigNum)&BN_P256_n, (bigNum)&BN_P256_h,(bigNum)&BN_P256_a, (bigNum)&BN_P256_b,{(bigNum)&BN_P256_gX, (bigNum)&BN_P256_gY, (bigNum)&BN_P256_gZ}};#else
const ECC_CURVE_DATA BN_P256 = {&BN_P256_p.b, &BN_P256_n.b, &BN_P256_h.b,&BN_P256_a.b, &BN_P256_b.b,{&BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_BN_P256#if ECC_BN_P638
ECC_CONST(BN_P638_p, 80, TO_ECC_640(
TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80),
TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67)));#define BN_P638_a
ECC_ZEROECC_CONST(BN_P638_b, 2, TO_ECC_16(0x01,0x01));
ECC_CONST(BN_P638_gX, 80, TO_ECC_640(
TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80),
TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66)));
ECC_CONST(BN_P638_gY, 1, TO_ECC_8(0x10));
ECC_CONST(BN_P638_n, 80, TO_ECC_640(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 591
April 15, 2019

Trusted Platform Module Library
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

Part 4: Supporting Routines

TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0),
TO_ECC_64(0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61)));#define BN_P638_h
ECC_ONE#define BN_P638_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA BN_P638 = {(bigNum)&BN_P638_p, (bigNum)&BN_P638_n, (bigNum)&BN_P638_h,(bigNum)&BN_P638_a, (bigNum)&BN_P638_b,{(bigNum)&BN_P638_gX, (bigNum)&BN_P638_gY, (bigNum)&BN_P638_gZ}};#else
const ECC_CURVE_DATA BN_P638 = {&BN_P638_p.b, &BN_P638_n.b, &BN_P638_h.b,&BN_P638_a.b, &BN_P638_b.b,{&BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_BN_P638#if ECC_SM2_P256
ECC_CONST(SM2_P256_p, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(SM2_P256_a, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(SM2_P256_b, 32, TO_ECC_256(
TO_ECC_64(0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34),
TO_ECC_64(0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7),
TO_ECC_64(0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92),
TO_ECC_64(0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93)));
ECC_CONST(SM2_P256_gX, 32, TO_ECC_256(
TO_ECC_64(0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19),
TO_ECC_64(0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94),
TO_ECC_64(0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1),
TO_ECC_64(0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7)));
ECC_CONST(SM2_P256_gY, 32, TO_ECC_256(
TO_ECC_64(0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C),
TO_ECC_64(0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53),
TO_ECC_64(0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40),
TO_ECC_64(0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0)));ECC_CONST(SM2_P256_n, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B),
TO_ECC_64(0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23)));#define SM2_P256_h
ECC_ONE#define SM2_P256_gZ
ECC_ONE#if USE_BN_ECC_DATA
const ECC_CURVE_DATA SM2_P256 = {(bigNum)&SM2_P256_p, (bigNum)&SM2_P256_n, (bigNum)&SM2_P256_h,(bigNum)&SM2_P256_a, (bigNum)&SM2_P256_b,{(bigNum)&SM2_P256_gX, (bigNum)&SM2_P256_gY, (bigNum)&SM2_P256_gZ}};#else
const ECC_CURVE_DATA SM2_P256 = {&SM2_P256_p.b, &SM2_P256_n.b, &SM2_P256_h.b,&SM2_P256_a.b, &SM2_P256_b.b,

Page 592
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514

Trusted Platform Module Library{&SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_gZ.b}};#endif // USE_BN_ECC_DATA#endif // ECC_SM2_P256#define comma
const ECC_CURVE
eccCurves[] = {#if ECC_NIST_P192
comma{TPM_ECC_NIST_P192,
192,{ALG_KDF1_SP800_56A_VALUE, {{ALG_SHA256_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&NIST_P192,
OID_ECC_NIST_P192
CURVE_NAME("NIST_P192")}#
undef comma#
define comma ,#endif // ECC_NIST_P192#if ECC_NIST_P224
comma{TPM_ECC_NIST_P224,
224,{ALG_KDF1_SP800_56A_VALUE, {{ALG_SHA256_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&NIST_P224,
OID_ECC_NIST_P224
CURVE_NAME("NIST_P224")}#
undef comma#
define comma ,#endif // ECC_NIST_P224#if ECC_NIST_P256
comma{TPM_ECC_NIST_P256,
256,{ALG_KDF1_SP800_56A_VALUE, {{ALG_SHA256_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&NIST_P256,
OID_ECC_NIST_P256
CURVE_NAME("NIST_P256")}#
undef comma#
define comma ,#endif // ECC_NIST_P256#if ECC_NIST_P384
comma{TPM_ECC_NIST_P384,
384,{ALG_KDF1_SP800_56A_VALUE, {{ALG_SHA384_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&NIST_P384,
OID_ECC_NIST_P384
CURVE_NAME("NIST_P384")}#
undef comma#
define comma ,#endif // ECC_NIST_P384#if ECC_NIST_P521
comma{TPM_ECC_NIST_P521,
521,{ALG_KDF1_SP800_56A_VALUE, {{ALG_SHA512_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&NIST_P521,
OID_ECC_NIST_P521
CURVE_NAME("NIST_P521")}#
undef comma#
define comma ,#endif // ECC_NIST_P521#if ECC_BN_P256

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 593
April 15, 2019

Trusted Platform Module Library
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

Part 4: Supporting Routinescomma{TPM_ECC_BN_P256,
256,{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&BN_P256,
OID_ECC_BN_P256
CURVE_NAME("BN_P256")}#
undef comma#
define comma ,#endif // ECC_BN_P256#if ECC_BN_P638
comma{TPM_ECC_BN_P638,
638,{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&BN_P638,
OID_ECC_BN_P638
CURVE_NAME("BN_P638")}#
undef comma#
define comma ,#endif // ECC_BN_P638#if ECC_SM2_P256
comma{TPM_ECC_SM2_P256,
256,{ALG_KDF1_SP800_56A_VALUE, {{ALG_SM3_256_VALUE}}},{ALG_NULL_VALUE, {{ALG_NULL_VALUE}}},&SM2_P256,
OID_ECC_SM2_P256
CURVE_NAME("SM2_P256")}#
undef comma#
define comma ,#endif // ECC_SM2_P256};#endif // TPM_ALG_ECC

Page 594
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.9Trusted Platform Module Library

CryptDes.c

10.2.9.1

Introduction

This file contains the extra functions required for TDES.
10.2.9.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Includes, Defines, and Typedefs#include "Tpm.h"#if ALG_TDES#define DES_NUM_WEAK 64
const UINT64 DesWeakKeys[DES_NUM_WEAK] = {0x0101010101010101ULL, 0xFEFEFEFEFEFEFEFEULL,
0xE0E0E0E0F1F1F1F1ULL, 0x1F1F1F1F0E0E0E0EULL,
0x011F011F010E010EULL, 0x1F011F010E010E01ULL,
0x01E001E001F101F1ULL, 0xE001E001F101F101ULL,
0x01FE01FE01FE01FEULL, 0xFE01FE01FE01FE01ULL,
0x1FE01FE00EF10EF1ULL, 0xE01FE01FF10EF10EULL,
0x1FFE1FFE0EFE0EFEULL, 0xFE1FFE1FFE0EFE0EULL,
0xE0FEE0FEF1FEF1FEULL, 0xFEE0FEE0FEF1FEF1ULL,
0x01011F1F01010E0EULL, 0x1F1F01010E0E0101ULL,
0xE0E01F1FF1F10E0EULL, 0x0101E0E00101F1F1ULL,
0x1F1FE0E00E0EF1F1ULL, 0xE0E0FEFEF1F1FEFEULL,
0x0101FEFE0101FEFEULL, 0x1F1FFEFE0E0EFEFEULL,
0xE0FE011FF1FE010EULL, 0x011F1F01010E0E01ULL,
0x1FE001FE0EF101FEULL, 0xE0FE1F01F1FE0E01ULL,
0x011FE0FE010EF1FEULL, 0x1FE0E01F0EF1F10EULL,
0xE0FEFEE0F1FEFEF1ULL, 0x011FFEE0010EFEF1ULL,
0x1FE0FE010EF1FE01ULL, 0xFE0101FEFE0101FEULL,
0x01E01FFE01F10EFEULL, 0x1FFE01E00EFE01F1ULL,
0xFE011FE0FE010EF1ULL, 0xFE01E01FFE01F10EULL,
0x1FFEE0010EFEF101ULL, 0xFE1F01E0FE0E01F1ULL,
0x01E0E00101F1F101ULL, 0x1FFEFE1F0EFEFE0EULL,
0xFE1FE001FE0EF101ULL, 0x01E0FE1F01F1FE0EULL,
0xE00101E0F10101F1ULL, 0xFE1F1FFEFE0E0EFEULL,
0x01FE1FE001FE0EF1ULL, 0xE0011FFEF1010EFEULL,
0xFEE0011FFEF1010EULL, 0x01FEE01F01FEF10EULL,
0xE001FE1FF101FE0EULL, 0xFEE01F01FEF10E01ULL,
0x01FEFE0101FEFE01ULL, 0xE01F01FEF10E01FEULL,
0xFEE0E0FEFEF1F1FEULL, 0x1F01011F0E01010EULL,
0xE01F1FE0F10E0EF1ULL, 0xFEFE0101FEFE0101ULL,
0x1F01E0FE0E01F1FEULL, 0xE01FFE01F10EFE01ULL,
0xFEFE1F1FFEFE0E0EULL, 0x1F01FEE00E01FEF1ULL,
0xE0E00101F1F10101ULL, 0xFEFEE0E0FEFEF1F1ULL};

10.2.9.2.1

CryptSetOddByteParity()This function sets the per byte parity of a 64-bit value. The least-significant bit is of each byte is replacedwith the odd parity of the other 7 bits in the byte. With odd parity, no byte will ever be 0x00.
37
38
39
40
41
42
43
44
45
46
47

UINT64
CryptSetOddByteParity(
UINT64)k{#define PMASK 0x0101010101010101ULLUINT64out;k |= PMASK;// set the parity bit
out = k;k ^= k >> 4;
k ^= k >> 2;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 595
April 15, 2019

Trusted Platform Module Library
48
49
50
51
52
53

k ^= k >> 1;
k &= PMASK;out ^= k;out ^= PMASK;
return out;

Part 4: Supporting Routines// odd parity extracted// out is now even parity because parity bit was already set// out is now even parity}

10.2.9.2.2

CryptDesIsWeakKey()

Check to see if a DES key is on the list of weak, semi-weak, or possibly weak keys.

54
55
56
57
58
59
60
61
62
63
64
65
66
67

Return Value

Meaning

TRUE(1)DES key is weak

FALSE(0)DES key is not weakstatic BOOL
CryptDesIsWeakKey(
UINT64
)

k

int

i;

{
//
for(i = 0; i < DES_NUM_WEAK; i++){if(k == DesWeakKeys[i])return TRUE;}
return FALSE;}

10.2.9.2.3

CryptDesValidateKey()

Function to check to see if the input key is a valid DES key where the definition of valid is that none of theelements are on the list of weak, semi-weak, or possibly weak keys; and that for two keys, K1!=K2, andfor three keys that K1!=K2 and K2!=K3.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

BOOL
CryptDesValidateKey(
TPM2B_SYM_KEY)*desKey// IN: key to validate

UINT64
int
int
BYTE
BOOL

k[3];
i;
keys = (desKey->t.size + 7) / 8;
*pk = desKey->t.buffer;
ok;

{

//
// Note: 'keys' is the number of keys, not the maximum index for 'k'
ok = ((keys == 2) || (keys == 3)) && ((desKey->t.size % 8) == 0);
for(i = 0; ok && i < keys; pk += 8, i++){k[i] = CryptSetOddByteParity(BYTE_ARRAY_TO_UINT64(pk));
ok = !CryptDesIsWeakKey(k[i]);}ok = ok && k[0] != k[1];if(keys == 3)
ok = ok && k[1] != k[2];return ok;}

Page 596
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.9.2.4

Trusted Platform Module Library

CryptGenerateKeyDes()This function is used to create a DES key of the appropriate size. The key will have odd parity in thebytes.
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

TPM_RCCryptGenerateKeyDes(
TPMT_PUBLIC*publicArea,

TPMT_SENSITIVERAND_STATE)*sensitive,*rand// IN/OUT: The public area template//
for the new key.
// OUT: sensitive area// IN: the "entropy" source for{// Assume that the publicArea key size has been validated and is a supported// number of bits.
sensitive->sensitive.sym.t.size =BITS_TO_BYTES(publicArea->parameters.symDetail.sym.keyBits.sym);
do
{
BYTE
*pK = sensitive->sensitive.sym.t.buffer;int
i = (sensitive->sensitive.sym.t.size + 7) / 8;// Use the random number generator to generate the required number of bits
if(DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size) == 0)
return TPM_RC_NO_RESULT;
for(; i > 0; pK += 8, i--){UINT64
k = BYTE_ARRAY_TO_UINT64(pK);k = CryptSetOddByteParity(k);UINT64_TO_BYTE_ARRAY(k, pK);}
} while(!CryptDesValidateKey(&sensitive->sensitive.sym));return TPM_RC_SUCCESS;}#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 597
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.10 CryptEccKeyExchange.c
10.2.10.1 Introduction
This file contains the functions that are used for the two-phase, ECC, key-exchange protocols
12#include "Tpm.h"#if CC_ZGen_2Phase == YES

10.2.10.2 Functions
3#if ALG_ECMQV

10.2.10.2.1

avf1()

This function does the associated value computation required by MQV key exchange. Process:Convert xQ to an integer xqi using the convention specified in Appendix C.3.
Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)).
Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2) Always returns TRUE(1).
4
5
6
7
8
9
10
11
12
13
14
15
16
17

static BOOL
avf1(
bigNumbigNum)bnX,
bnN// IN/OUT: the reduced value// IN: the order of the curve{// compute f = 2^(ceil(ceil(log2(n)) / 2))int
f = (BnSizeInBits(bnN) + 1) / 2;// x' = 2^f + (x mod 2^f)
BnMaskBits(bnX, f);// This is mod 2*2^f but it doesn't matter because// the next operation will SET the extra bit anyway
BnSetBit(bnX, f);return TRUE;}

10.2.10.2.2

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.

18
19
20
21
22
23
24
25

Error Returns

Meaning

TPM_RC_NO_RESULT

the value for dsA does not give a valid point on the curve

static TPM_RC
C_2_2_MQV(
TPMS_ECC_POINT
TPM_ECC_CURVE
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPMS_ECC_POINT
TPMS_ECC_POINT

Page 598
April 15, 2019

*outZ,
curveId,
*dsA,
*deA,
*QsB,
*QeB

// OUT: the computed point// IN: the curve for the computations// IN: static private TPM key// IN: ephemeral private TPM key// IN: static public party B key// IN: ephemeral public party B key

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

Trusted Platform Module Library){
CURVE_INITIALIZED(E, curveId);
const ECC_CURVE_DATA*C;POINT(pQeA);
POINT_INITIALIZED(pQeB, QeB);
POINT_INITIALIZED(pQsB, QsB);
ECC_NUM(bnTa);
ECC_INITIALIZED(bnDeA, deA);
ECC_INITIALIZED(bnDsA, dsA);
ECC_NUM(bnN);
ECC_NUM(bnXeB);
TPM_RC
retVal;//// Parameter checks
if(E == NULL)ERROR_RETURN(TPM_RC_VALUE);
pAssert(outZ != NULL && pQeB != NULL && pQsB != NULL && deA != NULL&& dsA != NULL);
C = AccessCurveData(E);// Process:// 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
// 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
// 3. If P = O, output an error indicator.
// 4. Z=xP, where xP is the x-coordinate of P.
// Compute the public ephemeral key pQeA = [de,A]G
if((retVal = BnPointMult(pQeA, CurveGetG(C), bnDeA, NULL, NULL, E))!= TPM_RC_SUCCESS)
goto Exit;
//
//
//

1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
tA := (ds,A + de,A avf(Xe,A)) mod n(3)
Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n// Ta = avf(XeA);
BnCopy(bnTa, pQeA->x);
avf1(bnTa, bnN);// do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n
BnModMult(bnTa, bnDsA, bnTa, bnN);// now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n
BnAdd(bnTa, bnTa, bnDeA);
BnMod(bnTa, bnN);// 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
// Put this in because almost every case of h is == 1 so skip the call when// not necessary.
if(!BnEqualWord(CurveGetCofactor(C), 1))// Cofactor is not 1 so compute Ta := Ta * h mod n
BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C));// Now that 'tA' is (h * 'tA' mod n)// 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B).
// first, compute XeB = avf(XeB)
avf1(bnXeB, bnN);// QsB := [XeB]QsB
BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E);
BnEccAdd(pQeB, pQeB, pQsB, E);// QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity// If the result is not the point at infinity, return QeB
BnPointMult(pQeB, pQeB, bnTa, NULL, NULL, E);if(BnEqualZero(pQeB->z))
ERROR_RETURN(TPM_RC_NO_RESULT);// Convert BIGNUM E to TPM2B E

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 599
April 15, 2019

Trusted Platform Module Library
92
93
94
95
96
97
98

Part 4: Supporting Routines

BnPointTo2B(outZ, pQeB, E);
Exit:
CURVE_FREE(E);return retVal;}#endif // ALG_ECMQV

10.2.10.2.3

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).
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

static TPM_RC
C_2_2_ECDH(
TPMS_ECC_POINT
TPMS_ECC_POINT
TPM_ECC_CURVE
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPMS_ECC_POINT
TPMS_ECC_POINT)*outZs,*outZe,curveId,
*dsA,
*deA,
*QsB,
*QeB

// OUT: Zs// OUT: Ze// IN: the curve for the computations// IN: static private TPM key// IN: ephemeral private TPM key// IN: static public party B key// IN: ephemeral public party B key{
CURVE_INITIALIZED(E, curveId);
ECC_INITIALIZED(bnAs, dsA);
ECC_INITIALIZED(bnAe, deA);
POINT_INITIALIZED(ecBs, QsB);
POINT_INITIALIZED(ecBe, QeB);
POINT(ecZ);
TPM_RC
retVal;//// Parameter checks
if(E == NULL)ERROR_RETURN(TPM_RC_CURVE);
pAssert(outZs != NULL && dsA != NULL && deA != NULL && QsB != NULL&& QeB != NULL);// Do the point multiply for the Zs value ([dsA]QsB)
retVal = BnPointMult(ecZ, ecBs, bnAs, NULL, NULL, E);if(retVal == TPM_RC_SUCCESS){// Convert the Zs value.
BnPointTo2B(outZs, ecZ, E);// Do the point multiply for the Ze value ([deA]QeB)
retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E);if(retVal == TPM_RC_SUCCESS)
BnPointTo2B(outZe, ecZ, E);}
Exit:
CURVE_FREE(E);return retVal;}

10.2.10.2.4

CryptEcc2PhaseKeyExchange()

This function is the dispatch routine for the EC key exchange functions that use two ephemeral and two
static keys.

Page 600
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

Trusted Platform Module Library

Error Returns

Meaning

TPM_RC_SCHEME

scheme is not defined

LIB_EXPORT TPM_RC
CryptEcc2PhaseKeyExchange(
TPMS_ECC_POINT
TPMS_ECC_POINT
TPM_ECC_CURVE
TPM_ALG_ID
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPMS_ECC_POINT
TPMS_ECC_POINT)*outZ1,*outZ2,curveId,
scheme,
*dsA,
*deA,
*QsB,
*QeB

// OUT: a computed point// OUT: and optional second point// IN: the curve for the computations// IN: the key exchange scheme// IN: static private TPM key// IN: ephemeral private TPM key// IN: static public party B key// IN: ephemeral public party B key{
pAssert(outZ1 != NULL&& dsA != NULL && deA != NULL&& QsB != NULL && QeB != NULL);// Initialize the output points so that they are empty until one of the// functions decides otherwise
outZ1->x.b.size = 0;
outZ1->y.b.size = 0;if(outZ2 != NULL){
outZ2->x.b.size = 0;
outZ2->y.b.size = 0;}
switch(scheme){case ALG_ECDH_VALUE:
return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB);
break;#if
ALG_ECMQV
case ALG_ECMQV_VALUE:
return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB);
break;#endif#if
ALG_SM2
case ALG_SM2_VALUE:
return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB);
break;#endifdefault:
return TPM_RC_SCHEME;}}#if
ALG_SM2

10.2.10.2.5

ComputeWForSM2()

Compute the value for w used by SM2
184
185
186
187
188
189
190
191

static UINT32
ComputeWForSM2(
bigCurve)E{// w := ceil(ceil(log2(n)) / 2) - 1
return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 601
April 15, 2019

Trusted Platform Module Library

10.2.10.2.6

Part 4: Supporting Routines

avfSm2()This function does the associated value computation required by SM2 key exchange. This is different
from 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 withthe scheme in SM2.
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

static bigNum
avfSm2(
bigNumUINT32)bn,w// IN/OUT: the reduced value// IN: the value of w{// a)
set w := ceil(ceil(log2(n)) / 2) - 1// b)
set x' := 2^w + ( x & (2^w - 1))// This is just like the avf for MQV where x' = 2^w + (x mod 2^w)
BnMaskBits(bn, w);// as with avf1, this is too big by a factor of 2 but// it doesn't matter because we SET the extra bit// anyway

BnSetBit(bn, w);
return bn;}

10.2.10.2.7

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

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

Error Returns

Meaning

TPM_RC_NO_RESULT

the value for dsA does not give a valid point on the curve

LIB_EXPORT TPM_RC
SM2KeyExchange(
TPMS_ECC_POINT
TPM_ECC_CURVE
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPMS_ECC_POINT
TPMS_ECC_POINT)*outZ,
curveId,*dsAIn,*deAIn,*QsBIn,*QeBIn// OUT: the computed point// IN: the curve for the computations// IN: static private TPM key// IN: ephemeral private TPM key// IN: static public party B key// IN: ephemeral public party B key{
CURVE_INITIALIZED(E, curveId);
const ECC_CURVE_DATA*C;
ECC_INITIALIZED(dsA, dsAIn);
ECC_INITIALIZED(deA, deAIn);POINT_INITIALIZED(QsB, QsBIn);
POINT_INITIALIZED(QeB, QeBIn);
BN_WORD_INITIALIZED(One, 1);
POINT(QeA);
ECC_NUM(XeB);POINT(Z);ECC_NUM(Ta);UINT32w;
TPM_RC
retVal = TPM_RC_NO_RESULT;//// Parameter checks
if(E == NULL)

Page 602
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

Trusted Platform Module Library

ERROR_RETURN(TPM_RC_CURVE);
C = AccessCurveData(E);pAssert(outZ != NULL && dsA != NULL && deA != NULL &&&& QeB != NULL);

QsB != NULL// Compute the value for w
w = ComputeWForSM2(E);// Compute the public ephemeral key pQeA = [de,A]G
if(!BnEccModMult(QeA, CurveGetG(C), deA, E))
goto Exit;// tA := (ds,A + de,A avf(Xe,A)) mod n(3)// Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n// Ta = avf(XeA);// do Ta = de,A * Ta = deA * avf(XeA)
BnMult(Ta, deA, avfSm2(QeA->x, w));// now Ta = dsA + Ta = dsA + deA * avf(XeA)
BnAdd(Ta, dsA, Ta);
BnMod(Ta, CurveGetOrder(C));// outZ = [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4)// Put this in because almost every case of h is == 1 so skip the call when// not necessary.
if(!BnEqualWord(CurveGetCofactor(C), 1))// Cofactor is not 1 so compute Ta := Ta * h mod n
BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C));// Now that 'tA' is (h * 'tA' mod n)// 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)).
BnCopy(XeB, QeB->x);if(!BnEccModMult2(Z, QsB, One, QeB, avfSm2(XeB, w), E))
goto Exit;// QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
if(!BnEccModMult(Z, Z, Ta, E))
goto Exit;// Convert BIGNUM E to TPM2B E
BnPointTo2B(outZ, Z, E);
retVal = TPM_RC_SUCCESS;Exit:
CURVE_FREE(E);return retVal;}#endif#endif // CC_ZGen_2Phase

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 603
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.11 CryptEccMain.c
10.2.11.1 Includes and Defines
1
2#include "Tpm.h"#if
ALG_ECC

This version requires that the new format for ECC data be used3
4
5

#if !USE_BN_ECC_DATA#error "Need to SET USE_BN_ECC_DATA to YES in Implementaion.h"#endif10.2.11.2 Functions
6
7
8
9
10
11
12
13
14
15
16

#if SIMULATION

void
EccSimulationEnd(
void){#if SIMULATION// put things to be printed at the end of the simulation here
#endif}#endif // SIMULATION

10.2.11.2.1

CryptEccInit()

This function is called at _TPM_Init()
17
18
19
20
21
22
23

BOOL
CryptEccInit(
void){
return TRUE;}

10.2.11.2.2

CryptEccStartup()This function is called at TPM2_Startup().
24
25
26
27
28
29
30

BOOL
CryptEccStartup(
void){
return TRUE;}

10.2.11.2.3

ClearPoint2B(generic

Initialize the size values of a TPMS_ECC_POINT structure.
31
32
33

void
ClearPoint2B(
TPMS_ECC_POINT

Page 604
April 15, 2019*p// IN: the point

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
34
35
36
37
38
39
40
41

Trusted Platform Module Library){if(p != NULL){
p->x.t.size = 0;
p->y.t.size = 0;}}

10.2.11.2.4

CryptEccGetParametersByCurveId()

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. This function is in this module so that it can becalled by GetCurve() data.

42
43
44
45
46
47
48
49
50
51
52
53
54

Return Value

Meaning

NULL

curve with the indicated TPM_ECC_CURVE is not implemented!= NULL

pointer to the curve data

LIB_EXPORT const ECC_CURVE *CryptEccGetParametersByCurveId(
TPM_ECC_CURVE)

curveId// IN: the curveID

{
int
i;
for(i = 0; i < ECC_CURVE_COUNT; i++){if(eccCurves[i].curveId == curveId)
return &eccCurves[i];}return NULL;}

10.2.11.2.5

CryptEccGetKeySizeForCurve()

This function returns the key size in bits of the indicated curve.
55
56
57
58
59
60
61
62
63
64
65

LIB_EXPORT UINT16
CryptEccGetKeySizeForCurve(
TPM_ECC_CURVE)

curveId// IN: the curve{
const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
UINT16
keySizeInBits;//
keySizeInBits = (curve != NULL) ? curve->keySizeBits : 0;
return keySizeInBits;}

10.2.11.2.6

GetCurveData()

This function returns the a pointer for the parameter data associated with a curve.
66
67
68
69
70
71

const ECC_CURVE_DATA *GetCurveData(
TPM_ECC_CURVE)

curveId// IN: the curveID

const ECC_CURVE*curve = CryptEccGetParametersByCurveId(curveId);{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 605
April 15, 2019

Trusted Platform Module Library72
73

return (curve != NULL) ? curve->curveData : NULL;}

10.2.11.2.7
74
75
76
77
78
79
80
81

Part 4: Supporting Routines

CryptEccGetOID()

const BYTE *CryptEccGetOID(
TPM_ECC_CURVE

curveId){
const ECC_CURVE*curve = CryptEccGetParametersByCurveId(curveId);
return (curve != NULL) ? curve->OID : NULL;}

10.2.11.2.8

CryptEccGetCurveByIndex()

This function returns the number of the i-th implemented curve. The normal use would be to call thisfunction with i starting at 0. When the i is greater than or equal to the number of implemented curves,
TPM_ECC_NONE is returned.
82
83
84
85
86
87
88
89
90

LIB_EXPORT TPM_ECC_CURVE
CryptEccGetCurveByIndex(
UINT16)i{
if(i >= ECC_CURVE_COUNT)
return TPM_ECC_NONE;
return eccCurves[i].curveId;}

10.2.11.2.9

CryptEccGetParameter()This function returns an ECC curve parameter. The parameter is selected by a single character
designator from the set of "PNABXYH".

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

Return Value

Meaning

TRUE(1)curve exists and parameter returned

FALSE(0)curve does not exist or parameter selector

LIB_EXPORT BOOL
CryptEccGetParameter(
TPM2B_ECC_PARAMETERchar
TPM_ECC_CURVE
)

*out,
p,
curveId// OUT: place to put parameter// IN: the parameter selector// IN: the curve idconst ECC_CURVE_DATA
bigConst*curve = GetCurveData(curveId);parameter = NULL;{

if(curve != NULL){
switch(p){case 'p':
parameter = CurveGetPrime(curve);
break;
case 'n':parameter = CurveGetOrder(curve);
break;

Page 606
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

Trusted Platform Module Librarycase 'a':parameter = CurveGet_a(curve);
break;
case 'b':
parameter = CurveGet_b(curve);
break;
case 'x':
parameter = CurveGetGx(curve);
break;
case 'y':parameter = CurveGetGy(curve);
break;
case 'h':parameter = CurveGetCofactor(curve);
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}}// If not debugging and we get here with parameter still NULL, had better// not try to convert so just return FALSE instead.
return (parameter != NULL) ? BnTo2B(parameter, &out->b, 0) : 0;}

10.2.11.2.10 CryptCapGetECCCurve()
This function returns the list of implemented ECC curves.

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

Return Value

Meaning

YES

if no more ECC curve is availableNO

if there are more ECC curves not reported

TPMI_YES_NO
CryptCapGetECCCurve(
TPM_ECC_CURVEUINT32
TPML_ECC_CURVE)

curveID,
maxCount,*curveList// IN: the starting ECC curve// IN: count of returned curves// OUT: ECC curve list{
TPMI_YES_NO
UINT16
UINT32
TPM_ECC_CURVE

more = NO;i;count = ECC_CURVE_COUNT;
curve;// Initialize output property list
curveList->count = 0;// The maximum count of curves we may return is MAX_ECC_CURVES
if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES;// Scan the eccCurveValues arrayfor(i = 0; i < count; i++){curve = CryptEccGetCurveByIndex(i);// If curveID is less than the starting curveID, skip it
if(curve < curveID)
continue;if(curveList->count < maxCount){// If we have not filled up the return list, add more curves to// it

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 607
April 15, 2019

Trusted Platform Module Library
164
165
166
167
168
169
170
171
172
173
174
175
176

Part 4: Supporting Routines

curveList->eccCurves[curveList->count] = curve;
curveList->count++;}else{// If the return list is full but we still have curves// available, report this and stop iterating
more = YES;
break;}}
return more;}

10.2.11.2.11 CryptGetCurveSignScheme()
This function will return a pointer to the scheme of the curve.
177
178
179
180
181
182
183
184
185
186
187
188

const TPMT_ECC_SCHEME *CryptGetCurveSignScheme(
TPM_ECC_CURVE)

curveId// IN: The curve selector{
const ECC_CURVE*curve = CryptEccGetParametersByCurveId(curveId);if(curve != NULL)
return &(curve->sign);
else
return NULL;}

10.2.11.2.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 willvalidate 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.

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

Return Value

Meaning

TRUE(1)r value computed

FALSE(0)no r value computed

BOOL
CryptGenerateR(
TPM2B_ECC_PARAMETERUINT16
TPMI_ECC_CURVE
TPM2B_NAME*r,*c,curveID,*name// OUT: the generated random value// IN/OUT: count value.
// IN: the curve for the value// IN: optional name of a key to//associate with 'r'){// This holds the marshaled g_commitCounter.
TPM2B_TYPE(8B, 8);
TPM2B_8B
cntr = {{8,{0}}};
UINT32
iterations;
TPM2B_ECC_PARAMETERn;UINT64currentCount = gr.commitCounter;
UINT16t1;//
if(!CryptEccGetParameter(&n, 'n', curveID))

Page 608
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

Trusted Platform Module Library

return FALSE;// If this is the commit phase, use the current value of the commit counterif(c != NULL){// if the array bit is not set, can't use the value.
if(!TEST_BIT((*c & COMMIT_INDEX_MASK), gr.commitArray))return FALSE;// If it is the sign phase, figure out what the counter value was// when the commitment was made.
//// When gr.commitArray has less than 64K bits, the extra// bits of 'c' are used as a check to make sure that the// signing operation is not using an out of range count value
t1 = (UINT16)currentCount;// If the lower bits of c are greater or equal to the lower bits of t1// then the upper bits of t1 must be one more than the upper bits// of cif((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK))// Since the counter is behind, reduce the current countcurrentCount = currentCount - (COMMIT_INDEX_MASK + 1);
t1 = (UINT16)currentCount;if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK))
return FALSE;// set the counter to the value that was// present when the commitment was madecurrentCount = (currentCount & 0xffffffffffff0000) | *c;}// Marshal the count value to a TPM2B buffer for the KDF
cntr.t.size = sizeof(currentCount);
UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer);// Now can do the KDF to create the random value for the signing operation// During the creation process, we may generate an r that does not meet the// requirements of the random value.
// want to generate a new r.
r->t.size = n.t.size;for(iterations = 1; iterations < 1000000;){
inti;
CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gr.commitNonce.b, COMMIT_STRING,(TPM2B *)name, &cntr.b, n.t.size * 8, r->t.buffer,&iterations, FALSE);// "random" value must be less than the prime
if(UnsignedCompareB(r->b.size, r->b.buffer, n.t.size, n.t.buffer) >= 0)
continue;// in this implementation it is required that at least bit// in the upper half of the number be setfor(i = n.t.size / 2; i >= 0; i--)if(r->b.buffer[i] != 0)
return TRUE;}
return FALSE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 609
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.11.2.13 CryptCommit()
This function is called when the count value is committed. The gr.commitArray value associated with thecurrent count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of thecounter is returned.
267
268
269
270
271
272
273
274
275
276

UINT16
CryptCommit(
void){
UINT16
oldCount = (UINT16)gr.commitCounter;gr.commitCounter++;
SET_BIT(oldCount & COMMIT_INDEX_MASK, gr.commitArray);return oldCount;}

10.2.11.2.14 CryptEndCommit()
This function is called when the signing operation using the committed value is completed. It clears thegr.commitArray bit associated with the count value so that it can't be used again.
277
278
279
280
281
282
283

void
CryptEndCommit(
UINT16)c// IN: the counter value of the commitment{
ClearBit((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray));}

10.2.11.2.15 CryptEccGetParameters()
This function returns the ECC parameter details of the given curve.

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

Return Value

Meaning

TRUE(1)success

FALSE(0)unsupported ECC curve ID

BOOL
CryptEccGetParameters(
TPM_ECC_CURVE
TPMS_ALGORITHM_DETAIL_ECC)

curveId,*parameters// IN: ECC curve ID// OUT: ECC parametersconst ECC_CURVE
const ECC_CURVE_DATA
BOOL*curve = CryptEccGetParametersByCurveId(curveId);*data;
found = curve != NULL;{//

if(found){data = curve->curveData;
parameters->curveID = curve->curveId;
parameters->keySize = curve->keySizeBits;
parameters->kdf = curve->kdf;
parameters->sign = curve->sign;
BnTo2B(data->prime, &parameters->p.b, 0);
BnTo2B(data->prime, &parameters->p.b, parameters->p.t.size);
BnTo2B(data->a, &parameters->a.b, 0);
BnTo2B(data->b, &parameters->b.b, 0);
BnTo2B(data->base.x, &parameters->gX.b, parameters->p.t.size);

Page 610
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
306
307
308
309
310
311
312
313

//
//

Trusted Platform Module Library

BnTo2B(data->base.y, &parameters->gY.b, parameters->p.t.size);
BnTo2B(data->base.x, &parameters->gX.b, 0);
BnTo2B(data->base.y, &parameters->gY.b, 0);
BnTo2B(data->order, &parameters->n.b, 0);
BnTo2B(data->h, &parameters->h.b, 0);}
return found;}10.2.11.2.16 BnGetCurvePrime()
This function is used to get just the prime modulus associated with a curve.
314
315
316
317
318
319
320
321

const bignum_t *BnGetCurvePrime(
TPM_ECC_CURVE)

curveId{
const ECC_CURVE_DATA*C = GetCurveData(curveId);
return (C != NULL) ? CurveGetPrime(C) : NULL;}

10.2.11.2.17 BnGetCurveOrder()This function is used to get just the curve order
322
323
324
325
326
327
328
329

const bignum_t *BnGetCurveOrder(
TPM_ECC_CURVE)

curveId{
const ECC_CURVE_DATA*C = GetCurveData(curveId);
return (C != NULL) ? CurveGetOrder(C) : NULL;}

10.2.11.2.18 BnIsOnCurve()
This function checks if a point is on the curve.
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

BOOL
BnIsOnCurve(
pointConst
const ECC_CURVE_DATA
)

Q,
*C

{
BN_VAR(right, (MAX_ECC_KEY_BITS * 3));
BN_VAR(left, (MAX_ECC_KEY_BITS * 2));
bigConst
prime = CurveGetPrime(C);//// Show that point is on the curve y^2 = x^3 + ax + b;// Or y^2 = x(x^2 + a) + b// y^2
BnMult(left, Q->y, Q->y);BnMod(left, prime);// x^2
BnMult(right, Q->x, Q->x);// x^2 + a
BnAdd(right, right, CurveGet_a(C));

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 611
April 15, 2019

Trusted Platform Module Library
352
353
354
355
356
357
358
359
360
361
362
363
364

//

Part 4: Supporting Routines

BnMod(right, CurveGetPrime(C));// x(x^2 + a)
BnMult(right, right, Q->x);// x(x^2 + a) + b
BnAdd(right, right, CurveGet_b(C));
BnMod(right, prime);
if(BnUnsignedCmp(left, right) == 0)
return TRUE;
else
return FALSE;}

10.2.11.2.19 BnIsValidPrivateEcc()
Checks that 0 < x < q
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

BOOL
BnIsValidPrivateEcc(
bigConst
bigCurve)x,
E// IN: private key to check// IN: the curve to check{
BOOL
retVal;retVal = (!BnEqualZero(x)&& (BnUnsignedCmp(x, CurveGetOrder(AccessCurveData(E))) < 0));
return retVal;}

LIB_EXPORT BOOL
CryptEccIsValidPrivateKey(
TPM2B_ECC_PARAMETER
TPM_ECC_CURVE)*d,curveId{
BN_INITIALIZED(bnD, MAX_ECC_PARAMETER_BYTES * 8, d);return !BnEqualZero(bnD) && (BnUnsignedCmp(bnD, BnGetCurveOrder(curveId)) < 0);}10.2.11.2.20 BnPointMul()
This function does a point multiply of the form R = [d]S + [u]Q where the parameters are bigNum values.
If S is NULL and d is not NULL, then it computes R = [d]G + [u]Q or just R = [d]G if u and Q are NULL. If
skipChecks is TRUE, then the function will not verify that the inputs are correct for the domain. This would
be the case when the values were created by the CryptoEngine() code. It will return
TPM_RC_NO_RESULT if the resulting point is the point at infinity.

385
386
387
388
389
390
391

Error Returns

Meaning

TPM_RC_NO_RESULT

result of multiplication is a point at infinity

TPM_RC_ECC_POINT

S or Q is not on the curve

TPM_RC_VALUE

d or u is not < n

TPM_RC
BnPointMult(
bigPoint
pointConst
bigConst
pointConst
bigConst

Page 612
April 15, 2019

R,
S,
d,
Q,
u,

// OUT: computed point// IN: optional point to multiply by 'd'// IN: scalar for [d]S or [d]G// IN: optional second point// IN: optional second scalar

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

Trusted Platform Module Library

bigCurve)

E// IN: curve parameters

BOOL

OK;

{
//
TEST(TPM_ALG_ECDH);// Need one scalar
OK = (d != NULL || u != NULL);// If S is present, then d has to be present. If S is not// present, then d may or may not be present
OK = OK && (((S == NULL) == (d == NULL)) || (d != NULL));// either both u and Q have to be provided or neither can be provided (don't// know what to do if only one is provided.
OK = OK && ((u == NULL) == (Q == NULL));
OK = OK && (E != NULL);
if(!OK)
return TPM_RC_VALUE;
OK = (S == NULL) || BnIsOnCurve(S, AccessCurveData(E));
OK = OK && ((Q == NULL) || BnIsOnCurve(Q, AccessCurveData(E)));
if(!OK)
return TPM_RC_ECC_POINT;
if((d != NULL) && (S == NULL))S = CurveGetG(AccessCurveData(E));// If only one scalar, don't need Shamir's trickif((d == NULL) || (u == NULL)){
if(d == NULL)
OK = BnEccModMult(R, Q, u, E);
else
OK = BnEccModMult(R, S, d, E);}
else{
OK = BnEccModMult2(R, S, d, Q, u, E);}
return (OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT);}

10.2.11.2.21 BnEccGetPrivate()
This function gets random values that are the size of the key plus 64 bits. The value is reduced (mod (q 1)) and incremented by 1 (q is the order of the curve. This produces a value (d) such that 1 <= d < q. Thisis the method of FIPS 186-4 Section B.4.1 "Key Pair Generation Using Extra Random Bits".

435
436
437
438
439
440
441
442

Return Value

Meaning

TRUE(1)success

FALSE(0)failure generating private key

BOOL
BnEccGetPrivate(
bigNumconst ECC_CURVE_DATA

dOut,
*C,

RAND_STATE
)

*rand

// OUT: the qualified random value// IN: curve for which the private key//
needs to be appropriate// IN: state for DRBG{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 613
April 15, 2019

Trusted Platform Module Library
443
444
445
446
447
448
449
450
451
452
453
454
455

Part 4: Supporting Routines

bigConst
order = CurveGetOrder(C);BOOL
OK;
UINT32orderBits = BnSizeInBits(order);UINT32orderBytes = BITS_TO_BYTES(orderBits);
BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64);
BN_VAR(nMinus1, MAX_ECC_KEY_BITS);//
OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand);OK = OK && BnSubWord(nMinus1, order, 1);
OK = OK && BnMod(bnExtraBits, nMinus1);
OK = OK && BnAddWord(dOut, bnExtraBits, 1);
return OK && !g_inFailureMode;}

10.2.11.2.22 BnEccGenerateKeyPair()This function gets a private scalar from the source of random bits and does the point multiply to get the
public key.
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

BOOL
BnEccGenerateKeyPair(
bigNumbn_point_t
bigCurve
RAND_STATE
)

bnD,
*ecQ,
E,
*rand

// OUT: private scalar// OUT: public point// IN: curve for the point// IN: DRBG state to use{
BOOL
OK = FALSE;// Get a private scalar
OK = BnEccGetPrivate(bnD, AccessCurveData(E), rand);// Do a point multiply
OK = OK && BnEccModMult(ecQ, NULL, bnD, E);
if(!OK)
BnSetWord(ecQ->z, 0);else
BnSetWord(ecQ->z, 1);
return OK;}

10.2.11.2.23 CryptEccNewKeyPair
This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the
key will be discarded
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

LIB_EXPORT TPM_RC
CryptEccNewKeyPair(
TPMS_ECC_POINT
TPM2B_ECC_PARAMETER
TPM_ECC_CURVE)*Qout,*dOut,
curveId// OUT: the public point// OUT: the private scalar// IN: the curve for the key{
CURVE_INITIALIZED(E, curveId);
POINT(ecQ);
ECC_NUM(bnD);
BOOL
OK;
if(E == NULL)
return TPM_RC_CURVE;
TEST(TPM_ALG_ECDH);
OK = BnEccGenerateKeyPair(bnD, ecQ, E, NULL);

Page 614
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
493
494
495
496
497
498
499
500
501
502
503
504

Trusted Platform Module Libraryif(OK){
BnPointTo2B(Qout, ecQ, E);
BnTo2B(bnD, &dOut->b, Qout->x.t.size);}
else{
Qout->x.t.size = Qout->y.t.size = dOut->t.size = 0;}
CURVE_FREE(E);return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;}

10.2.11.2.24 CryptEccPointMultiply()
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 TPM_RC_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.

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531

Error Returns

Meaning

TPM_RC_ECC_POINT

the point Pin or Qin is not on the curve

TPM_RC_NO_RESULT

the product point is at infinity

TPM_RC_CURVE

bad curve

TPM_RC_VALUEdIn or uIn out of range

LIB_EXPORT TPM_RC
CryptEccPointMultiply(
TPMS_ECC_POINT*Rout,TPM_ECC_CURVE
curveId,
TPMS_ECC_POINT*Pin,
TPM2B_ECC_PARAMETER *dIn,// OUT: the product point R// IN: the curve to use// IN: first point (can be null)// IN: scalar value for [dIn]Qin//
the Pin// IN: point Q// IN: scalar value for the multiplier//of Q

TPMS_ECC_POINT*Qin,
TPM2B_ECC_PARAMETER *uIn){CURVE_INITIALIZED(E, curveId);
POINT_INITIALIZED(ecP, Pin);
ECC_INITIALIZED(bnD, dIn);
ECC_INITIALIZED(bnU, uIn);POINT_INITIALIZED(ecQ, Qin);
POINT(ecR);
TPM_RC
retVal;// If dIn is null, then bnD is null//
retVal = BnPointMult(ecR, ecP, bnD, ecQ, bnU, E);if(retVal == TPM_RC_SUCCESS)
BnPointTo2B(Rout, ecR, E);
else
ClearPoint2B(Rout);
CURVE_FREE(E);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 615
April 15, 2019

Trusted Platform Module Library
532
533

Part 4: Supporting Routines

return retVal;}

10.2.11.2.25 CryptEccIsPointOnCurve()
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).

534
535
536
537
538
539
540
541
542
543
544
545
546
547

Return Value

Meaning

TRUE(1)point is on curve

FALSE(0)point is not on curve or curve is not supported

LIB_EXPORT BOOL
CryptEccIsPointOnCurve(
TPM_ECC_CURVE
TPMS_ECC_POINT)

curveId,*Qin// IN: the curve selector// IN: the point.

{
const ECC_CURVE_DATA*C = GetCurveData(curveId);
POINT_INITIALIZED(ecQ, Qin);
BOOL
OK;
//
pAssert(Qin != NULL);
OK = (C != NULL && (BnIsOnCurve(ecQ, C)));
return OK;}

10.2.11.2.26 CryptEccGenerateKey()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.1.2 "Key Pair Generation
by Testing Candidates." 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.
It is a fatal error if Qout, dOut, is not provided (is NULL).
If the curve is not supported If seed is not provided, then a random number will be used for the key

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562

Error Returns

Meaning

TPM_RC_CURVE

curve is not supported

TPM_RC_NO_RESULT

could not verify key with signature (FIPS only)

LIB_EXPORT TPM_RC
CryptEccGenerateKey(
TPMT_PUBLIC*publicArea,

TPMT_SENSITIVE*sensitive,

RAND_STATE*rand// IN/OUT: The public area template for//the new key. The public key//
area will be replaced computed//
ECC public key// OUT: the sensitive area will be//
updated to contain the private//
ECC key and the symmetric//encryption key// IN: if not NULL, the deterministic//
RNG state){
CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID);

Page 616
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608

ECC_NUM(bnD);
POINT(ecQ);BOOL
TPM_RC

Trusted Platform Module LibraryOK;
retVal;//TEST(TPM_ALG_ECDSA); // ECDSA is used to verify each key// Validate parameters
if(E == NULL)ERROR_RETURN(TPM_RC_CURVE);
publicArea->unique.ecc.x.t.size = 0;
publicArea->unique.ecc.y.t.size = 0;
sensitive->sensitive.ecc.t.size = 0;
OK = BnEccGenerateKeyPair(bnD, ecQ, E, rand);if(OK){
BnPointTo2B(&publicArea->unique.ecc, ecQ, E);
BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size);}#if FIPS_COMPLIANT// See if PWCT is required
if(OK && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)){
ECC_NUM(bnT);
ECC_NUM(bnS);
TPM2B_DIGEST
digest;//TEST(TPM_ALG_ECDSA);
digest.t.size = MIN(sensitive->sensitive.ecc.t.size, sizeof(digest.t.buffer));// Get a random value to sign using the built in DRBG state
DRBG_Generate(NULL, digest.t.buffer, digest.t.size);if(g_inFailureMode)return TPM_RC_FAILURE;
BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL);// and make sure that we can validate the signature
OK = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest) == TPM_RC_SUCCESS;}#endifretVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;Exit:
CURVE_FREE(E);return retVal;}#endif // ALG_ECC

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 617
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.12 CryptEccSignature.c
10.2.12.1 Includes and Defines
1
2
3#include "Tpm.h"#include "CryptEccSignature_fp.h"#if
ALG_ECC

10.2.12.2 Utility Functions
10.2.12.2.1

EcdsaDigest()

Function to adjust the digest so that it is no larger than the order of the curve. This is used for ECDSA
sign and verification.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

static bigNum
EcdsaDigest(
bigNumconst TPM2B_DIGEST
bigConst

bnD,*digest,max// OUT: the adjusted digest// IN: digest to adjust// IN: value that indicates the maximum//
number of bits in the results

)
{
int
int

bitsInMax = BnSizeInBits(max);
shift;//
if(digest == NULL)
BnSetWord(bnD, 0);else{
BnFromBytes(bnD, digest->t.buffer,(NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax)));
shift = BnSizeInBits(bnD) - bitsInMax;
if(shift > 0)
BnShiftRight(bnD, bnD, shift);}return bnD;}

10.2.12.2.2

BnSchnorrSign()

This contains the Schnorr signature computation. It is used by both ECDSA and Schnorr signing. The
result is computed as: [s = k + r * d (mod n)] wheres is the signature
k is a random value
r is the value to sign
d is the private EC key
n is the order of the curve

27
28
29

Error Returns

Meaning

TPM_RC_NO_RESULT

the result of the operation was zero or r (mod n) is zerostatic TPM_RC
BnSchnorrSign(
bigNumPage 618
April 15, 2019bnS,// OUT: 's' component of the signature

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

bigConst
bigNumbigConst
bigConst)

Trusted Platform Module Library
bnK,
bnR,
bnD,
bnN

// IN: a random value// IN: the signature 'r' value// IN: the private key// IN: the order of the curve{// Need a local temp value to store the intermediate computation because product// size can be larger than will fit in bnS.
BN_VAR(bnT1, MAX_ECC_PARAMETER_BYTES * 2 * 8);//// Reduce bnR without changing the input value
BnDiv(NULL, bnT1, bnR, bnN);
if(BnEqualZero(bnT1))
return TPM_RC_NO_RESULT;// compute s = (k + r * d)(mod n)// r * d
BnMult(bnT1, bnT1, bnD);// k * r * d
BnAdd(bnT1, bnT1, bnK);// k + r * d (mod n)
BnDiv(NULL, bnS, bnT1, bnN);
return (BnEqualZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS;}

10.2.12.3 Signing Functions
10.2.12.3.1

BnSignEcdsa()

This function implements the ECDSA signing algorithm. The method is described in the comments below.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

TPM_RC
BnSignEcdsa(
bigNumbigNumbigCurve

bnR,
bnS,
E,

bigNumconst TPM2B_DIGEST
RAND_STATE)

bnD,*digest,*rand// OUT: 'r' component of the signature// OUT: 's' component of the signature// IN: the curve used in the signature//process// IN: private signing key// IN: the digest to sign// IN: used in debug of signing{
ECC_NUM(bnK);
ECC_NUM(bnIk);
BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8);
POINT(ecR);
bigConst
order = CurveGetOrder(AccessCurveData(E));
TPM_RC
retVal = TPM_RC_SUCCESS;
INT32
tries = 10;
BOOL
OK = FALSE;//
pAssert(digest != NULL);// The algorithm as described in "Suite B Implementer's Guide to FIPS// 186-3(ECDSA)"// 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a//
per-message secret number and its inverse modulo n. Since n is prime,//
the output will be invalid only if there is a failure in the RBG.
// 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar//multiplication (see [Routines]), where G is the base point included in//
the set of domain parameters.
// 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1.
// 4. Use the selected hash function to compute H = Hash(M).
// 5. Convert the bit string H to an integer e as described in Appendix B.2.
// 6. Compute s = (k^-1 * (e + d * r)) mod q. If s = 0, return to Step 1.2.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 619
April 15, 2019

Trusted Platform Module Library
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

Part 4: Supporting Routines// 7. Return (r, s).
// In the code below, q is n (that it, the order of the curve is p)
do // This implements the loop at step 6. If s is zero, start over.
{for(; tries > 0; tries--){// Step 1 and 2 -- generate an ephemeral key and the modular inverse// of the private key.
if(!BnEccGenerateKeyPair(bnK, ecR, E, rand))continue;// x coordinate is mod p. Make it mod q
BnMod(ecR->x, order);// Make sure that it is not zero;
if(BnEqualZero(ecR->x))
continue;// write the modular reduced version of r as part of the signature
BnCopy(bnR, ecR->x);// Make sure that a modular inverse exists and try again if not
OK = (BnModInverse(bnIk, bnK, order));if(OK)
break;}
if(!OK)
goto Exit;
EcdsaDigest(bnE, digest, order);// now have inverse of K (bnIk), e (bnE), r (bnR),// CurveGetOrder(E)// Compute s = k^-1 (e + r*d)(mod q)// first do s = r*d mod q
BnModMult(bnS, bnR, bnD, order);// s = e + s = e + r * d
BnAdd(bnS, bnE, bnS);// s = k^(-1)s (mod n) = k^(-1)(e + r * d)(mod n)
BnModMult(bnS, bnIk, bnS, order);d (bnD) and// If S is zero, try again} while(BnEqualZero(bnS));
Exit:
return retVal;}#if ALG_ECDAA

10.2.12.3.2

BnSignEcdaa()This function performs s = r + T * d mod q where'r is a random, or pseudo-random value created in the commit phasenonceK is a TPM-generated, random value 0 < nonceK < n
T is mod q of Hash(nonceK || digest), andd is a private key.
The signature is the tuple (nonceK, s)
Regrettably, the parameters in this function kind of collide with the parameter names used in
ECSCHNORR making for a lot of confusion.

Page 620
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

Trusted Platform Module Library

Error Returns

Meaning

TPM_RC_SCHEME

unsupported hash algorithm

TPM_RC_NO_RESULT

cannot get values from random number generator

static TPM_RC
BnSignEcdaa(
TPM2B_ECC_PARAMETER
bigNumbigCurve
bigNumconst TPM2B_DIGEST
TPMT_ECC_SCHEME*nonceK,
bnS,
E,
bnD,
*digest,*scheme,OBJECTRAND_STATE)*eccKey,*rand

TPM_RCTPM2B_ECC_PARAMETER
HASH_STATETPM2B_DIGEST
BN_MAX(bnT);

retVal;r;
state;T;// OUT: 'nonce' component of the signature// OUT: 's' component of the signature// IN: the curve used in signing// IN: the private key// IN: the value to sign (mod 'q')// IN: signing scheme (contains the//commit count value).
// IN: The signing key// IN: a random number state{//
NOT_REFERENCED(rand);if(!CryptGenerateR(&r, &scheme->details.ecdaa.count,eccKey->publicArea.parameters.eccDetail.curveID,&eccKey->name))
retVal = TPM_RC_VALUE;
else{// This allocation is here because 'r' doesn't have a value until// CrypGenerateR() is done.
ECC_INITIALIZED(bnR, &r);
do{// generate nonceK such that 0 < nonceK < n// use bnT as a temp.
if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand)){
retVal = TPM_RC_NO_RESULT;
break;}
BnTo2B(bnT, &nonceK->b, 0);
T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg);
if(T.t.size == 0){
retVal = TPM_RC_SCHEME;}
else{
CryptDigestUpdate2B(&state, &nonceK->b);
CryptDigestUpdate2B(&state, &digest->b);
CryptHashEnd2B(&state, &T.b);
BnFrom2B(bnT, &T.b);// Watch out for the name collisions in this call!!
retVal = BnSchnorrSign(bnS, bnR, bnT, bnD,
AccessCurveData(E)->order);}} while(retVal == TPM_RC_NO_RESULT);// Because the rule is that internal state is not modified if the command// fails, only end the commit if the command succeeds.
// NOTE that if the result of the Schnorr computation was zero

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 621
April 15, 2019

Trusted Platform Module Library
189
190
191
192
193
194
195
196
197
198

Part 4: Supporting Routines// it will probably not be worthwhile to run the same command again because// the result will still be zero. This means that the Commit command will// need to be run again to get a new commit value for the signature.
if(retVal == TPM_RC_SUCCESS)
CryptEndCommit(scheme->details.ecdaa.count);}
return retVal;}#endif // ALG_ECDAA#if ALG_ECSCHNORR

10.2.12.3.3

SchnorrReduce()

Function to reduce a hash result if it's magnitude is too large. The size of number is set so that it has no
more bytes of significance than reference value. If the resulting number can have more bits ofsignificance than reference.
199
200
201
202
203
204
205
206
207
208

static void
SchnorrReduce(
TPM2B
bigConst)*number,reference// IN/OUT: Value to reduce// IN: the reference value{
UINT16
maxBytes = (UINT16)BITS_TO_BYTES(BnSizeInBits(reference));if(number->size > maxBytes)
number->size = maxBytes;}

10.2.12.3.4

SchnorrEcc()

This function is used to perform a modified Schnorr signature.
This function will generate a random value k and compute(xR, yR) = [k]Gr = Hash(xR || P)(mod q)
rT = truncated r
s= k + rT * ds (mod q)
return the tuple rT, s

209
210
211
212
213
214
215
216
217
218
219
220
221
222

Error Returns

Meaning

TPM_RC_NO_RESULT

failure in the Schnorr sign process

TPM_RC_SCHEME

hashAlg can't produce zero-length digest

static TPM_RC
BnSignEcSchnorr(
bigNumbigNumbigCurve
bigNumconst TPM2B_DIGEST
TPM_ALG_ID
RAND_STATE
)

bnR,
bnS,
E,
bnD,
*digest,hashAlg,*rand// OUT: 'r' component of the signature// OUT: 's' component of the signature// IN: the curve used in signing// IN: the signing key// IN: the digest to sign// IN: signing scheme (contains a hash)// IN: non-NULL when testing{
HASH_STATE
hashState;
UINT16
digestSize = CryptHashGetDigestSize(hashAlg);
TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_KEY_BYTES));

Page 622
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

TPM2B_T
TPM2B
TPM_RC
const ECC_CURVE_DATA
bigConst
bigConst
ECC_NUM(bnK);
POINT(ecR);

Trusted Platform Module LibraryT2b;*e = &T2b.b;
retVal = TPM_RC_NO_RESULT;*C;
order;
prime;//// Parameter checks
if(E == NULL)ERROR_RETURN(TPM_RC_VALUE);
C = AccessCurveData(E);order = CurveGetOrder(C);prime = CurveGetOrder(C);// If the digest does not produce a hash, then null the signature and return// a failure.
if(digestSize == 0){
BnSetWord(bnR, 0);
BnSetWord(bnS, 0);
ERROR_RETURN(TPM_RC_SCHEME);}do{// Generate a random key pairif(!BnEccGenerateKeyPair(bnK, ecR, E, rand))break;// Convert R.x to a string
BnTo2B(ecR->x, e, (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(prime)));// f) compute r = Hash(e || P) (mod n)
CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate2B(&hashState, e);
CryptDigestUpdate2B(&hashState, &digest->b);e->size = CryptHashEnd(&hashState, digestSize, e->buffer);// Reduce the hash size if it is larger than the curve order
SchnorrReduce(e, order);// Convert hash to number
BnFrom2B(bnR, e);// Do the Schnorr computation
retVal = BnSchnorrSign(bnS, bnK, bnR, bnD, CurveGetOrder(C));} while(retVal == TPM_RC_NO_RESULT);
Exit:
return retVal;}#endif // ALG_ECSCHNORR#if ALG_SM2#ifdef _SM2_SIGN_DEBUG

10.2.12.3.5

BnHexEqual()This function compares a bignum value to a hex string.

273
274
275

Return Value

Meaning

TRUE(1)values equal

FALSE(0)values not equal

static BOOL
BnHexEqual(
bigNumbn,

Family “2.0”Level 00 Revision 01.55//IN: big number value

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 623
April 15, 2019

Trusted Platform Module Library
276
277
278
279
280
281
282
283

const char)Part 4: Supporting Routines*c//IN: character string number{
ECC_NUM(bnC);
BnFromHex(bnC, c);return (BnUnsignedCmp(bn, bnC) == 0);}#endif // _SM2_SIGN_DEBUG

10.2.12.3.6

BnSignEcSm2()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 hashedwith the message to produce a digest (e). This function signs e.

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328

Error Returns

Meaning

TPM_RC_VALUE

bad curve

static TPM_RC
BnSignEcSm2(
bigNumbigNumbigCurve
bigNumconst TPM2B_DIGEST
RAND_STATE

bnR,
bnS,
E,
bnD,
*digest,*rand// OUT: 'r' component of the signature// OUT: 's' component of the signature// IN: the curve used in signing// IN: the private key// IN: the digest to sign// IN: random number generator (mostly for//debug)){
BN_MAX_INITIALIZED(bnE, digest);// Don't know how big digest might be
ECC_NUM(bnN);
ECC_NUM(bnK);
ECC_NUM(bnT);// temp
POINT(Q1);
bigConst
order = (E != NULL)? CurveGetOrder(AccessCurveData(E)) : NULL;//#ifdef _SM2_SIGN_DEBUG
BnFromHex(bnE, "B524F552CD82B8B028476E005C377FB1""9A87E6FC682D48BB5D42E3D9B9EFFE76");
BnFromHex(bnD, "128B2FA8BD433C6C068C8D803DFF7979""2A519A55171B1B650C23661D15897263");#endif// A3: Use random number generator to generate random number 1 <= k <= n-1;// NOTE: Ax: numbers are from the SM2 standard
loop:{// Get a random number 0 < k < n
BnGenerateRandomInRange(bnK, order, rand);#ifdef _SM2_SIGN_DEBUG
BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F""C176D925DD72B727260DBAAE1FB2F96F");#endif// A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according// to details specified in 4.2.7 in Part 1 of this document, transform the// data type of x1 into an integer;
if(!BnEccModMult(Q1, NULL, bnK, E))
goto loop;// A5: Figure out 'r' = ('e' + 'x1') mod 'n',
BnAdd(bnR, bnE, Q1->x);
BnMod(bnR, order);#ifdef _SM2_SIGN_DEBUG
pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41"

Page 624
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Trusted Platform Module Library"94F79FB1EED2CAA55BACDB49C4E755D1"));#endif// if r=0 or r+k=n, return to A3;
if(BnEqualZero(bnR))
goto loop;
BnAdd(bnT, bnK, bnR);
if(BnUnsignedCmp(bnT, bnN) == 0)
goto loop;// A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n,// if s=0, return to A3;// compute t = (1+dA)^-1
BnAddWord(bnT, bnD, 1);
BnModInverse(bnT, bnT, order);#ifdef _SM2_SIGN_DEBUG
pAssert(BnHexEqual(bnT, "79BFCF3052C80DA7B939E0C6914A18CB""B2D96D8555256E83122743A7D4F5F956"));#endif// compute s = t * (k - r * dA) mod n
BnModMult(bnS, bnR, bnD, order);// k - r * dA mod n = k + n - ((r * dA) mod n)
BnSub(bnS, order, bnS);
BnAdd(bnS, bnK, bnS);
BnModMult(bnS, bnS, bnT, order);#ifdef _SM2_SIGN_DEBUG
pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6""67A457872FB09EC56327A67EC7DEEBE7"));#endifif(BnEqualZero(bnS))
goto loop;}// A7: According to details specified in 4.2.1 in Part 1 of this document,// transform the data type of r, s into bit strings, signature of message M// is (r, s).
// This is handled by the common return code
#ifdef _SM2_SIGN_DEBUG
pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41""94F79FB1EED2CAA55BACDB49C4E755D1"));pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6""67A457872FB09EC56327A67EC7DEEBE7"));#endifreturn TPM_RC_SUCCESS;}#endif // ALG_SM2

10.2.12.3.7

CryptEccSign()

This function is the dispatch function for the various ECC-based signing schemes. There is a bit ofugliness to the parameter passing. In order to test this, we sometime would like to use a deterministic
RNG so that we can get the same signatures during testing. The easiest way to do this for most schemes
is to pass in a deterministic RNG and let it return canned values during testing. There is a competingneed for a canned parameter to use in ECDAA. To accommodate both needs with minimal fuss, a special
type of RAND_STATE is defined to carry the address of the commit value. The setup and handling of thisis not very different for the caller than what was in previous versions of the code.

372
373
374
375
376

Error Returns

Meaning

TPM_RC_SCHEME

scheme is not supported

LIB_EXPORT TPM_RC
CryptEccSign(
TPMT_SIGNATUREOBJECT
const TPM2B_DIGEST

Family “2.0”Level 00 Revision 01.55*signature,*signKey,*digest,// OUT: signature// IN: ECC key to sign the hash// IN: digest to sign

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 625
April 15, 2019

Trusted Platform Module Library
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

TPMT_ECC_SCHEMERAND_STATE)Part 4: Supporting Routines*scheme,*rand// IN: signing scheme{
CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID);
ECC_INITIALIZED(bnD, &signKey->sensitive.sensitive.ecc.b);
ECC_NUM(bnR);
ECC_NUM(bnS);
const ECC_CURVE_DATA*C;
TPM_RC
retVal = TPM_RC_SCHEME;//NOT_REFERENCED(scheme);if(E == NULL)ERROR_RETURN(TPM_RC_VALUE);
C = AccessCurveData(E);signature->signature.ecdaa.signatureR.t.size= sizeof(signature->signature.ecdaa.signatureR.t.buffer);signature->signature.ecdaa.signatureS.t.size= sizeof(signature->signature.ecdaa.signatureS.t.buffer);
TEST(signature->sigAlg);
switch(signature->sigAlg){
case ALG_ECDSA_VALUE:
retVal = BnSignEcdsa(bnR, bnS, E, bnD, digest, rand);break;#if ALG_ECDAA
case ALG_ECDAA_VALUE:
retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, bnS, E,
bnD, digest, scheme, signKey, rand);bnR = NULL;
break;#endif#if ALG_ECSCHNORR
case ALG_ECSCHNORR_VALUE:
retVal = BnSignEcSchnorr(bnR, bnS, E, bnD, digest,
signature->signature.ecschnorr.hash,rand);
break;#endif#if ALG_SM2
case ALG_SM2_VALUE:
retVal = BnSignEcSm2(bnR, bnS, E, bnD, digest, rand);break;#endifdefault:
break;}// If signature generation worked, convert the results.
if(retVal == TPM_RC_SUCCESS){NUMBYTES
orderBytes =(NUMBYTES)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(C)));if(bnR != NULL)
BnTo2B(bnR, &signature->signature.ecdaa.signatureR.b, orderBytes);if(bnS != NULL)
BnTo2B(bnS, &signature->signature.ecdaa.signatureS.b, orderBytes);}
Exit:
CURVE_FREE(E);return retVal;}#if ALG_ECDSA

Page 626
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.12.3.8

Trusted Platform Module Library

BnValidateSignatureEcdsa()

This function validates an ECDSA signature. rIn and sIn should have been checked to make sure thatthey are in the range 0 < v < n

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

Error Returns

Meaning

TPM_RC_SIGNATURE

signature not valid

TPM_RC
BnValidateSignatureEcdsa(
bigNumbigNumbigCurve

bnR,
bnS,
E,

bn_point_t
const TPM2B_DIGEST)*ecQ,*digest// IN: 'r' component of the signature// IN: 's' component of the signature// IN: the curve used in the signature//process// IN: the public point of the key// IN: the digest that was signed{// Make sure that the allocation for the digest is big enough for a maximum// digest
BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8);
POINT(ecR);
ECC_NUM(bnU1);
ECC_NUM(bnU2);
ECC_NUM(bnW);
bigConst
order = CurveGetOrder(AccessCurveData(E));
TPM_RC
retVal = TPM_RC_SIGNATURE;//// Get adjusted digest
EcdsaDigest(bnE, digest, order);// 1. If r and s are not both integers in the interval [1, n - 1], output//
INVALID.
// bnR and bnS were validated by the caller// 2. Use the selected hash function to compute H0 = Hash(M0).
// This is an input parameter// 3. Convert the bit string H0 to an integer e as described in Appendix B.2.
// Done at entry// 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1.
if(!BnModInverse(bnW, bnS, order))goto Exit;// 5. Compute u1 = (e' *w) mod n, and compute u2 = (r' * w) mod n.
BnModMult(bnU1, bnE, bnW, order);
BnModMult(bnU2, bnR, bnW, order);// 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC//
scalar multiplication and EC addition (see [Routines]). If R is equal to//the point at infinity O, output INVALID.
if(BnPointMult(ecR, CurveGetG(AccessCurveData(E)), bnU1, ecQ, bnU2, E)!= TPM_RC_SUCCESS)
goto Exit;// 7. Compute v = Rx mod n.
BnMod(ecR->x, order);// 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID
if(BnUnsignedCmp(ecR->x, bnR) != 0)
goto Exit;
retVal = TPM_RC_SUCCESS;
Exit:
return retVal;}#endif// ALG_ECDSA#if ALG_SM2

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 627
April 15, 2019

Trusted Platform Module Library

10.2.12.3.9

Part 4: Supporting Routines

BnValidateSignatureEcSm2()This function is used to validate an SM2 signature.

492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

Error Returns

Meaning

TPM_RC_SIGNATURE

signature not valid

static TPM_RC
BnValidateSignatureEcSm2(
bigNumbigNumbigCurve

bnR,
bnS,
E,

bigPoint
const TPM2B_DIGEST)

ecQ,*digest// IN: 'r' component of the signature// IN: 's' component of the signature// IN: the curve used in the signature//process// IN: the public point of the key// IN: the digest that was signed{
POINT(P);ECC_NUM(bnRp);
ECC_NUM(bnT);
BN_MAX_INITIALIZED(bnE, digest);
BOOL
OK;
bigConst
order = CurveGetOrder(AccessCurveData(E));#ifdef _SM2_SIGN_DEBUG// Make sure that the input signature is the test signature
pAssert(BnHexEqual(bnR,"40F1EC59F793D9F49E09DCEF49130D41""94F79FB1EED2CAA55BACDB49C4E755D1"));pAssert(BnHexEqual(bnS,"6FC6DAC32C5D5CF10C77DFB20F7C2EB6""67A457872FB09EC56327A67EC7DEEBE7"));#endif// b)compute t := (r + s) mod n
BnAdd(bnT, bnR, bnS);
BnMod(bnT, order);#ifdef _SM2_SIGN_DEBUG
pAssert(BnHexEqual(bnT,"2B75F07ED7ECE7CCC1C8986B991F441A""D324D6D619FE06DD63ED32E0C997C801"));#endif// c)
verify that t > 0
OK = !BnEqualZero(bnT);
if(!OK)// set T to a value that should allow rest of the computations to run// without trouble
BnCopy(bnT, bnS);// d)compute (x, y) := [s]G + [t]Q
OK = BnEccModMult2(P, NULL, bnS, ecQ, bnT, E);#ifdef _SM2_SIGN_DEBUG
pAssert(OK && BnHexEqual(P->x,"110FCDA57615705D5E7B9324AC4B856D""23E6D9188B2AE47759514657CE25D112"));#endif// e)compute r' := (e + x) mod n (the x coordinate is in bnT)
OK = OK && BnAdd(bnRp, bnE, P->x);
OK = OK && BnMod(bnRp, order);// f)verify that r' = r
OK = OK && (BnUnsignedCmp(bnR, bnRp) == 0);
if(!OK)
return TPM_RC_SIGNATURE;
else

Page 628
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
549
550
551
552

Trusted Platform Module Library

return TPM_RC_SUCCESS;}#endif // ALG_SM2#if ALG_ECSCHNORR

10.2.12.3.10 BnValidateSignatureEcSchnorr()
This function is used to validate an EC Schnorr signature.

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

Error Returns

Meaning

TPM_RC_SIGNATURE

signature not valid

static TPM_RC
BnValidateSignatureEcSchnorr(
bigNumbigNumTPM_ALG_ID
bigCurve

bnR,
bnS,
hashAlg,E,

bigPoint
const TPM2B_DIGEST)

ecQ,*digest// IN: 'r' component of the signature// IN: 's' component of the signature// IN: hash algorithm of the signature// IN: the curve used in the signature//process// IN: the public point of the key// IN: the digest that was signed{
BN_MAX(bnRn);
POINT(ecE);
BN_MAX(bnEx);
const ECC_CURVE_DATA*C = AccessCurveData(E);bigConst
order = CurveGetOrder(C);UINT16
digestSize = CryptHashGetDigestSize(hashAlg);
HASH_STATE
hashState;
TPM2B_TYPE(BUFFER, MAX(MAX_ECC_PARAMETER_BYTES, MAX_DIGEST_SIZE));
TPM2B_BUFFER
Ex2 = {{sizeof(Ex2.t.buffer),{ 0 }}};
BOOL
OK;
//
// E = [s]G - [r]Q
BnMod(bnR, order);// Make -r = n - r
BnSub(bnRn, order, bnR);// E = [s]G + [-r]Q
OK = BnPointMult(ecE, CurveGetG(C), bnS, ecQ, bnRn, E) == TPM_RC_SUCCESS;//// reduce the x portion of E mod q//
OK = OK && BnMod(ecE->x, order);// Convert to byte string
OK = OK && BnTo2B(ecE->x, &Ex2.b,(NUMBYTES)(BITS_TO_BYTES(BnSizeInBits(order))));
if(OK){// Ex = h(pE.x || digest)
CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate(&hashState, Ex2.t.size, Ex2.t.buffer);
CryptDigestUpdate(&hashState, digest->t.size, digest->t.buffer);
Ex2.t.size = CryptHashEnd(&hashState, digestSize, Ex2.t.buffer);
SchnorrReduce(&Ex2.b, order);
BnFrom2B(bnEx, &Ex2.b);// see if Ex matches R
OK = BnUnsignedCmp(bnEx, bnR) == 0;}
return (OK) ? TPM_RC_SUCCESS : TPM_RC_SIGNATURE;}#endif // ALG_ECSCHNORRFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 629
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.12.3.11 CryptEccValidateSignature()
This function validates an EcDsa() or EcSchnorr() signature. The point Qin needs to have been validated
to be on the curve of curveId.

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

Error Returns

Meaning

TPM_RC_SIGNATURE

not a valid signature

LIB_EXPORT TPM_RC
CryptEccValidateSignature(
TPMT_SIGNATUREOBJECT
const TPM2B_DIGEST)*signature,*signKey,*digest// IN: signature to be verified// IN: ECC key signed the hash// IN: digest that was signed{
CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID);
ECC_NUM(bnR);
ECC_NUM(bnS);
POINT_INITIALIZED(ecQ, &signKey->publicArea.unique.ecc);
bigConst
order;
TPM_RC
retVal;if(E == NULL)ERROR_RETURN(TPM_RC_VALUE);
order = CurveGetOrder(AccessCurveData(E));//// Make sure that the scheme is valid
switch(signature->sigAlg){
case ALG_ECDSA_VALUE:#if ALG_ECSCHNORR
case ALG_ECSCHNORR_VALUE:#endif#if ALG_SM2
case ALG_SM2_VALUE:#endifbreak;
default:
ERROR_RETURN(TPM_RC_SCHEME);
break;}// Can convert r and s after determining that the scheme is an ECC scheme. If// this conversion doesn't work, it means that the unmarshaling code for// an ECC signature is broken.
BnFrom2B(bnR, &signature->signature.ecdsa.signatureR.b);
BnFrom2B(bnS, &signature->signature.ecdsa.signatureS.b);// r and s have to be greater than 0 but less than the curve orderif(BnEqualZero(bnR) || BnEqualZero(bnS))
ERROR_RETURN(TPM_RC_SIGNATURE);
if((BnUnsignedCmp(bnS, order) >= 0)|| (BnUnsignedCmp(bnR, order) >= 0))
ERROR_RETURN(TPM_RC_SIGNATURE);
switch(signature->sigAlg){
case ALG_ECDSA_VALUE:
retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest);
break;#if ALG_ECSCHNORR
case ALG_ECSCHNORR_VALUE:
retVal = BnValidateSignatureEcSchnorr(bnR, bnS,

Page 630
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672

Trusted Platform Module Librarysignature->signature.any.hashAlg,
E, ecQ, digest);

break;#endif#if ALG_SM2
case ALG_SM2_VALUE:
retVal = BnValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest);
break;#endifdefault:
FAIL(FATAL_ERROR_INTERNAL);}
Exit:
CURVE_FREE(E);return retVal;}

10.2.12.3.12 CryptEccCommitCompute()
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.
It is a fatal error if r is NULL. If B is not NULL, then it is a fatal error if d is NULL or if K and L are both
NULL. If M is not NULL, then it is a fatal error if E is NULL.

673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704

Error Returns

Meaning

TPM_RC_NO_RESULT

if K, L or E was computed to be the point at infinity

TPM_RC_CANCELED

a cancel indication was asserted during this function

LIB_EXPORT TPM_RC
CryptEccCommitCompute(
TPMS_ECC_POINT
TPMS_ECC_POINT
TPMS_ECC_POINT
TPM_ECC_CURVE
TPMS_ECC_POINT
TPMS_ECC_POINT
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
)

*K,
*L,
*E,
curveId,
*M,
*B,
*d,
*r

// OUT: [d]B or [r]Q// OUT: [r]B// OUT: [r]M// IN: the curve for the computations// IN: M (optional)// IN: B (optional)// IN: d (optional)// IN: the computed r value (required)

CURVE_INITIALIZED(curve, curveId);// Normally initialize E as the curve, but// E means something else in this function{
ECC_INITIALIZED(bnR, r);
TPM_RC
retVal = TPM_RC_SUCCESS;//// Validate that the required parameters are provided.
// Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do// E := [r]Q if both M and B are NULL.
pAssert(r != NULL && E != NULL);// Initialize the output points in case they are not computed
ClearPoint2B(K);
ClearPoint2B(L);
ClearPoint2B(E);// Sizes of the r parameter may not be zero
pAssert(r->t.size > 0);// If B is provided, compute K=[d]B and L=[r]B
if(B != NULL)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 631
April 15, 2019

Trusted Platform Module Library
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

Part 4: Supporting Routines{
ECC_INITIALIZED(bnD, d);
POINT_INITIALIZED(pB, B);
POINT(pK);
POINT(pL);//
pAssert(d != NULL && K != NULL && L != NULL);
if(!BnIsOnCurve(pB, AccessCurveData(curve)))
ERROR_RETURN(TPM_RC_VALUE);// do the math for K = [d]B
if((retVal = BnPointMult(pK, pB, bnD, NULL, NULL, curve)) != TPM_RC_SUCCESS)
goto Exit;// Convert BN K to TPM2B K
BnPointTo2B(K, pK, curve);// compute L= [r]B after checking for cancel
if(_plat__IsCanceled())
ERROR_RETURN(TPM_RC_CANCELED);// compute L = [r]Bif(!BnIsValidPrivateEcc(bnR, curve))
ERROR_RETURN(TPM_RC_VALUE);
if((retVal = BnPointMult(pL, pB, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS)
goto Exit;// Convert BN L to TPM2B L
BnPointTo2B(L, pL, curve);}if((M != NULL) || (B == NULL)){
POINT_INITIALIZED(pM, M);
POINT(pE);//// Make sure that a place was provided for the result
pAssert(E != NULL);// if this is the third point multiply, check for cancel firstif((B != NULL) && _plat__IsCanceled())
ERROR_RETURN(TPM_RC_CANCELED);// If M provided, then pM will not be NULL and will compute E = [r]M.
// However, if M was not provided, then pM will be NULL and E = [r]G// will be computedif((retVal = BnPointMult(pE, pM, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS)
goto Exit;// Convert E to 2B format
BnPointTo2B(E, pE, curve);}
Exit:
CURVE_FREE(curve);
return retVal;}#endif // ALG_ECC

Page 632
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.13 CryptHash.c
10.2.13.1 Description
This file contains implementation of cryptographic functions for hashing.
10.2.13.2 Includes, Defines, and Types
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#define _CRYPT_HASH_C_#include "Tpm.h"#include "CryptHash_fp.h"#include "CryptHash.h"#include "OIDS.h"#define HASH_TABLE_SIZE(HASH_COUNT + 1)
#if
ALG_SHA1
HASH_DEF_TEMPLATE(SHA1, Sha1);#endif#if
ALG_SHA256
HASH_DEF_TEMPLATE(SHA256, Sha256);#endif#if
ALG_SHA384
HASH_DEF_TEMPLATE(SHA384, Sha384);#endif#if
ALG_SHA512
HASH_DEF_TEMPLATE(SHA512, Sha512);#endif#if ALG_SM3_256
HASH_DEF_TEMPLATE(SM3_256, Sm3_256);#endif
HASH_DEF NULL_Def = {{0}};PHASH_DEF
HashDefArray[] = {#if ALG_SHA1&Sha1_Def,#endif#if ALG_SHA256&Sha256_Def,#endif#if ALG_SHA384&Sha384_Def,#endif#if ALG_SHA512&Sha512_Def,#endif#if ALG_SM3_256&Sm3_256_Def,#endif&NULL_Def};10.2.13.3 Obligatory Initialization Functions
10.2.13.3.1

CryptHashInit()

This function is called by _TPM_Init() do perform the initialization operations for the library.
41
42
43
44
45

BOOL
CryptHashInit(
void
)
{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 633
April 15, 2019

Trusted Platform Module Library
46
47
48

Part 4: Supporting Routines

LibHashInit();return TRUE;}

10.2.13.3.2

CryptHashStartup()This function is called by TPM2_Startup() in case there is work to do at startup. Currently, this is aplaceholder.
49
50
51
52
53
54
55
56

BOOL
CryptHashStartup(
void
)
{
int
i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1;
return (i == HASH_COUNT);}

10.2.13.4 Hash Information Access Functions
10.2.13.4.1

Introduction

These functions provide access to the hash algorithm description information.
10.2.13.4.2

CryptGetHashDef()

This function accesses the hash descriptor associated with a hash a algorithm. The function returns apointer to a null descriptor if hashAlg is TPM_ALG_NULL or not a defined algorithm.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

PHASH_DEF
CryptGetHashDef(
TPM_ALG_ID)

hashAlg{
INT16i;#define HASHES (sizeof(HashDefArray) / sizeof(PHASH_DEF))
for(i = 0; i < HASHES; i++){
PHASH_DEF p = HashDefArray[i];if(p->hashAlg == hashAlg)
return p;}
return &NULL_Def;}10.2.13.4.3

CryptHashIsValidAlg()

This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then TPM_ALG_NULL
is a valid hash.

72
73
74

Return Value

Meaning

TRUE(1)

hashAlg is a valid, implemented hash on this TPM

FALSE(0)hashAlg is not valid for this TPM

BOOLCryptHashIsValidAlg(
TPM_ALG_ID

Page 634
April 15, 2019

hashAlg,// IN: the algorithm to check

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
75
76
77
78
79
80
81
82

BOOL

Trusted Platform Module Libraryflag// IN: TRUE if TPM_ALG_NULL is to be treated//as a valid hash){if(hashAlg == TPM_ALG_NULL)
return flag;
return CryptGetHashDef(hashAlg) != &NULL_Def;}10.2.13.4.4

CryptHashGetAlgByIndex()

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 of 2 will return the last. All other index values will return
TPM_ALG_NULL.

83
84
85
86
87
88
89
90
91
92
93
94

Return Value

Meaning

TPM_ALG_xxx

a hash algorithm

TPM_ALG_NULL

this can be used as a stop value

LIB_EXPORT TPM_ALG_ID
CryptHashGetAlgByIndex(
UINT32)index// IN: the index{
TPM_ALG_ID
hashAlg;
if(index >= HASH_COUNT)hashAlg = TPM_ALG_NULL;
else
hashAlg = HashDefArray[index]->hashAlg;
return hashAlg;}

10.2.13.4.5

CryptHashGetDigestSize()

Returns the size of the digest produced by the hash. If hashAlg is not a hash algorithm, the TPM will
FAIL.

95
96
97
98
99
100
101

Return Value

Meaning0

TPM_ALG_NULL>0

the digest size

LIB_EXPORT UINT16
CryptHashGetDigestSize(
TPM_ALG_ID)

hashAlg// IN: hash algorithm to look up{
return CryptGetHashDef(hashAlg)->digestSize;}

10.2.13.4.6

CryptHashGetBlockSize()

Returns the size of the block used by the hash. If hashAlg is not a hash algorithm, the TPM will FAIL.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 635
April 15, 2019

Trusted Platform Module Library

102
103
104
105
106
107
108

Part 4: Supporting Routines

Return Value

Meaning0

TPM_ALG_NULL>0

the digest size

LIB_EXPORT UINT16
CryptHashGetBlockSize(
TPM_ALG_ID)

hashAlg// IN: hash algorithm to look up{
return CryptGetHashDef(hashAlg)->blockSize;}

10.2.13.4.7

CryptHashGetOid()

This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs are full OID values
including the Tag (0x06) and length byte.
109
110
111
112
113
114
115

LIB_EXPORT const BYTE *CryptHashGetOid(
TPM_ALG_ID

hashAlg){
return CryptGetHashDef(hashAlg)->OID;}

10.2.13.4.8

CryptHashGetContextAlg()

This function returns the hash algorithm associated with a hash context.
116
117
118
119
120
121
122

TPM_ALG_ID
CryptHashGetContextAlg(
PHASH_STATE
)

state

// IN: the context to check{
return state->hashAlg;}

10.2.13.5 State Import and Export
10.2.13.5.1

CryptHashCopyState

This function is used to clone a HASH_STATE.
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

LIB_EXPORT void
CryptHashCopyState(
HASH_STATE
const HASH_STATE
)

*out,
*in

// OUT: destination of the state// IN: source of the state{
pAssert(out->type == in->type);out->hashAlg = in->hashAlg;
out->def = in->def;
if(in->hashAlg != TPM_ALG_NULL){
HASH_STATE_COPY(out, in);}
if(in->type == HASH_STATE_HMAC){

Page 636
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
138
139
140
141
142
143

Trusted Platform Module Library

const HMAC_STATE*hIn = (HMAC_STATE *)in;
HMAC_STATE*hOut = (HMAC_STATE *)out;
hOut->hmacKey = hIn->hmacKey;}
return;}10.2.13.5.2

CryptHashExportState()

This function is used to export a hash or HMAC hash state. This function would be called when preparing
to context save a sequence object.
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

void
CryptHashExportState(
PCHASH_STATEinternalFmt,

PEXPORT_HASH_STATE)

externalFmt// IN: the hash state formatted for use by//library// OUT: the exported hash state{
BYTE*outBuf = (BYTE *)externalFmt;//
cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE));// the following #define is used to move data from an aligned internal data// structure to a byte buffer (external format data.
#define CopyToOffset(value)\
memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value,\
sizeof(internalFmt->value))// Copy the hashAlg
CopyToOffset(hashAlg);
CopyToOffset(type);#ifdef HASH_STATE_SMAC
if(internalFmt->type == HASH_STATE_SMAC){
memcpy(outBuf, internalFmt, sizeof(HASH_STATE));
return;}#endifif(internalFmt->type == HASH_STATE_HMAC){
HMAC_STATE*from = (HMAC_STATE *)internalFmt;
memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey,
sizeof(from->hmacKey));}if(internalFmt->hashAlg != TPM_ALG_NULL)
HASH_STATE_EXPORT(externalFmt, internalFmt);}

10.2.13.5.3

CryptHashImportState()

This function is used to import the hash state. This function would be called to import a hash state when
the context of a sequence object was being loaded.
179
180
181
182
183
184
185
186
187

void
CryptHashImportState(
PHASH_STATEinternalFmt,

PCEXPORT_HASH_STATE)

externalFmt// OUT: the hash state formatted for use by//
the library// IN: the exported hash state{
BYTE*inBuf = (BYTE *)externalFmt;

Family “2.0”

TCG PUBLIC REVIEW//

Level 00 Revision 01.55

Copyright © TCG 2006-2019

Page 637
April 15, 2019

Trusted Platform Module Library
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

Part 4: Supporting Routines#define CopyFromOffset(value)
memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)],sizeof(internalFmt->value))\\// Copy the hashAlg of the byte-aligned input structure to the structure-aligned// internal structure.
CopyFromOffset(hashAlg);
CopyFromOffset(type);if(internalFmt->hashAlg != TPM_ALG_NULL){#ifdef HASH_STATE_SMAC
if(internalFmt->type == HASH_STATE_SMAC){
memcpy(internalFmt, inBuf, sizeof(HASH_STATE));
return;}#endifinternalFmt->def = CryptGetHashDef(internalFmt->hashAlg);
HASH_STATE_IMPORT(internalFmt, inBuf);
if(internalFmt->type == HASH_STATE_HMAC){
HMAC_STATE*to = (HMAC_STATE *)internalFmt;
memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)],
sizeof(to->hmacKey));}}}

10.2.13.6 State Modification Functions
10.2.13.6.1

HashEnd()

Local function to complete a hash that uses the hashDef instead of an algorithm ID. This function is used
to complete the hash and only return a partial digest. The return value is the size of the data copied.
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

static UINT16
HashEnd(
PHASH_STATEUINT32PBYTE)

hashState,
dOutSize,
dOut// IN: the hash state// IN: the size of receive buffer// OUT: the receive buffer{
BYTE
temp[MAX_DIGEST_SIZE];
if((hashState->hashAlg == TPM_ALG_NULL)|| (hashState->type != HASH_STATE_HASH))
dOutSize = 0;if(dOutSize > 0){
hashState->def = CryptGetHashDef(hashState->hashAlg);// Set the final size
dOutSize = MIN(dOutSize, hashState->def->digestSize);// Complete into the temp buffer and then copy
HASH_END(hashState, temp);// Don't want any other functions calling the HASH_END method// directly.
#undef HASH_END
memcpy(dOut, &temp, dOutSize);}
hashState->type = HASH_STATE_EMPTY;
return (UINT16)dOutSize;}

Page 638
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.13.6.2

Trusted Platform Module Library

CryptHashStart()

Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, the value ofstateSize 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 notsupported.
This function does not use the sequence parameter. If it is necessary to import or export context, this will
start the sequence in a local state and export the state to the input buffer. Will need to add a flag to thestate structure to indicate that it needs to be imported before it can be used. (BLEH).

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Return Value

Meaning0

hash is TPM_ALG_NULL>0digest size

LIB_EXPORT UINT16
CryptHashStart(
PHASH_STATETPM_ALG_ID)

hashState,hashAlg// OUT: the running hash state// IN: hash algorithm{
UINT16

retVal;TEST(hashAlg);
hashState->hashAlg = hashAlg;
if(hashAlg == TPM_ALG_NULL){
retVal = 0;}
else{
hashState->def = CryptGetHashDef(hashAlg);
HASH_START(hashState);
retVal = hashState->def->digestSize;}#undef HASH_START
hashState->type = HASH_STATE_HASH;
return retVal;}

10.2.13.6.3

CryptDigestUpdate()

Add data to a hash or HMAC, SMAC stack.
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

void
CryptDigestUpdate(
PHASH_STATEUINT32const BYTE)

hashState,
dataSize,*data// IN: the hash context information// IN: the size of data to be added// IN: data to be hashed{if(hashState->hashAlg != TPM_ALG_NULL){
if((hashState->type == HASH_STATE_HASH)|| (hashState->type == HASH_STATE_HMAC))
HASH_DATA(hashState, dataSize, (BYTE *)data);#if SMAC_IMPLEMENTED
else if(hashState->type == HASH_STATE_SMAC)(hashState->state.smac.smacMethods.data)(&hashState->state.smac.state,
dataSize, data);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 639
April 15, 2019

Trusted Platform Module Library
282
283
284
285
286
287

Part 4: Supporting Routines#endif // SMAC_IMPLEMENTED
else
FAIL(FATAL_ERROR_INTERNAL);}
return;}10.2.13.6.4

CryptHashEnd()

Complete a hash or HMAC computation. This function will place the smaller of digestSize or the size ofthe digest in dOut. The number of bytes in the placed in the buffer is returned. If there is a failure, thereturned value is <= 0.

288
289
290
291
292
293
294
295
296
297

Return Value

Meaning0

no data returned>0

the number of bytes in the digest or dOutSize, whichever is smaller

LIB_EXPORT UINT16
CryptHashEnd(
PHASH_STATEUINT32BYTE)

hashState,
dOutSize,*dOut// IN: the state of hash stack// IN: size of digest buffer// OUT: hash digest{
pAssert(hashState->type == HASH_STATE_HASH);
return HashEnd(hashState, dOutSize, dOut);}10.2.13.6.5

CryptHashBlock()

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.

298
299
300
301
302
303
304
305
306
307
308
309
310
311

Return Value

Meaning>= 0

number of bytes placed in dOut

LIB_EXPORT UINT16
CryptHashBlock(
TPM_ALG_ID
UINT32const BYTEUINT32BYTE)

hashAlg,
dataSize,*data,
dOutSize,*dOut// IN: The hash algorithm// IN: size of buffer to hash// IN: the buffer to hash// IN: size of the digest buffer// OUT: digest buffer{
HASH_STATE
state;
CryptHashStart(&state, hashAlg);
CryptDigestUpdate(&state, dataSize, data);
return HashEnd(&state, dOutSize, dOut);}10.2.13.6.6

CryptDigestUpdate2B()

This function updates a digest (hash or HMAC) with a TPM2B.

Page 640
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module LibraryThis function can be used for both HMAC and hash functions so the digestState is void so that either
state type can be passed.
312
313
314
315
316
317
318
319
320
321
322
323
324
325

LIB_EXPORT void
CryptDigestUpdate2B(
PHASH_STATE
const TPM2B)

state,*bIn// IN: the digest state// IN: 2B containing the data{// Only compute the digest if a pointer to the 2B is provided.
// In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change// to the digest occurs. This function should not provide a buffer if bIn is// not provided.
pAssert(bIn != NULL);
CryptDigestUpdate(state, bIn->size, bIn->buffer);
return;}10.2.13.6.7

CryptHashEnd2B()

This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the mostcommon use and this is provided for specification clarity. digest.size should be set to indicate the numberof bytes to place in the buffer

326
327
328
329
330
331
332
333
334

Return Value

Meaning>=0

the number of bytes placed in digest.buffer

LIB_EXPORT UINT16
CryptHashEnd2B(
PHASH_STATE
P2B

state,
digest// IN: the hash state// IN: the size of the buffer Out: requested//
number of bytes){
return CryptHashEnd(state, digest->size, digest->buffer);}

10.2.13.6.8

CryptDigestUpdateInt()

This function is used to include an integer value to a hash stack. The function marshals the integer into its
canonical form before calling CryptDigestUpdate().
335
336
337
338
339
340
341
342
343
344
345
346

LIB_EXPORT void
CryptDigestUpdateInt(
void
UINT32
UINT64)*state,intSize,
intValue// IN: the state of hash stack// IN: the size of 'intValue' in bytes// IN: integer value to be hashed{#if LITTLE_ENDIAN_TPM
intValue = REVERSE_ENDIAN_64(intValue);#endifCryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 641
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.13.7 HMAC Functions
10.2.13.7.1

CryptHmacStart()

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.

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

Return Value

Meaning>= 0

number of bytes in digest produced by hashAlg (may be zero)

LIB_EXPORT UINT16
CryptHmacStart(
PHMAC_STATETPM_ALG_ID
UINT16const BYTE)

state,
hashAlg,
keySize,*key// IN/OUT: the state buffer// IN: the algorithm to use// IN: the size of the HMAC key// IN: the HMAC key{
PHASH_DEF
BYTE *UINT32

hashDef;pb;i;//hashDef = CryptGetHashDef(hashAlg);if(hashDef->digestSize != 0){// If the HMAC key is larger than the hash block size, it has to be reduced// to fit. The reduction is a digest of the hashKey.
if(keySize > hashDef->blockSize){// if the key is too big, reduce it to a digest of itself
state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key,
hashDef->digestSize,state->hmacKey.t.buffer);}
else{
memcpy(state->hmacKey.t.buffer, key, keySize);state->hmacKey.t.size = keySize;}// XOR the key with iPad (0x36)
pb = state->hmacKey.t.buffer;for(i = state->hmacKey.t.size; i > 0; i--)*pb++ ^= 0x36;// if the keySize is smaller than a block, fill the rest with 0x36
for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--)*pb++ = 0x36;// Increase the oPadSize to a full blockstate->hmacKey.t.size = hashDef->blockSize;// Start a new hash with the HMAC key// This will go in the caller's state structure and may be a sequence or not
CryptHashStart((PHASH_STATE)state, hashAlg);
CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size,state->hmacKey.t.buffer);// XOR the key block with 0x5c ^ 0x36
for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--)*pb++ ^= (0x5c ^ 0x36);}// Set the hash algorithm

Page 642
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
398
399
400
401
402
403

Trusted Platform Module Librarystate->hashState.hashAlg = hashAlg;// Set the hash state typestate->hashState.type = HASH_STATE_HMAC;
return hashDef->digestSize;}

10.2.13.7.2

CryptHmacEnd()

This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It willthen add the oPadKey and the completed digest and return the results in dOut. It will not return more thandOutSize bytes.

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

Return Value

Meaning>= 0

number of bytes in dOut (may be zero)

LIB_EXPORT UINT16
CryptHmacEnd(
PHMAC_STATEUINT32
BYTE)

state,
dOutSize,*dOut// IN: the hash state buffer// IN: size of digest buffer// OUT: hash digest{
BYTE
PHASH_STATE

temp[MAX_DIGEST_SIZE];hState = (PHASH_STATE)&state->hashState;#if SMAC_IMPLEMENTED
if(hState->type == HASH_STATE_SMAC)
return (state->hashState.state.smac.smacMethods.end)(&state->hashState.state.smac.state,
dOutSize,
dOut);#endifpAssert(hState->type == HASH_STATE_HMAC);
hState->def = CryptGetHashDef(hState->hashAlg);// Change the state type for completion processing
hState->type = HASH_STATE_HASH;
if(hState->hashAlg == TPM_ALG_NULL)
dOutSize = 0;else{// Complete the current hash
HashEnd(hState, hState->def->digestSize, temp);// Do another hash starting with the oPad
CryptHashStart(hState, hState->hashAlg);
CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer);
CryptDigestUpdate(hState, hState->def->digestSize, temp);}
return HashEnd(hState, dOutSize, dOut);}10.2.13.7.3

CryptHmacStart2B()

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.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 643
April 15, 2019

Trusted Platform Module Library

439
440
441
442
443
444
445
446
447
448

Part 4: Supporting Routines

Return Value

Meaning>0

the digest size of the algorithm=0

the hashAlg was TPM_ALG_NULL

LIB_EXPORT UINT16
CryptHmacStart2B(
PHMAC_STATE

hmacState,

TPMI_ALG_HASH
P2B)

hashAlg,
key// OUT: the state of HMAC stack. It will be used//in HMAC update and completion// IN: hash algorithm// IN: HMAC key{
return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer);}

10.2.13.7.4

CryptHmacEnd2B()

This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is themost common use.

449
450
451
452
453
454
455
456

Return Value

Meaning>=0

the number of bytes placed in digest

LIB_EXPORT UINT16
CryptHmacEnd2B(
PHMAC_STATE
P2B)

hmacState,digest// IN: the state of HMAC stack// OUT: HMAC{
return CryptHmacEnd(hmacState, digest->size, digest->buffer);}

10.2.13.8 Mask and Key Generation Functions
10.2.13.8.1

CryptMGF1()

This function performs MGF1 using the selected hash. MGF1 is T(n) = T(n-1) || H(seed || counter). Thisfunction returns the length of the mask produced which could be zero if the digest algorithm is notsupported

457
458
459
460
461
462
463
464
465
466
467
468

Return Value

Meaning0

hash algorithm was TPM_ALG_NULL>0should be the same as mSize

LIB_EXPORT UINT16
CryptMGF1(
UINT32BYTE
TPM_ALG_ID
UINT32BYTE)

mSize,*mask,
hashAlg,
seedSize,*seed// IN: length of the mask to be produced// OUT: buffer to receive the mask// IN: hash to use// IN: size of the seed// IN: seed size{
HASH_STATEPHASH_DEF
UINT32

Page 644
April 15, 2019

hashState;hDef = CryptGetHashDef(hashAlg);remaining;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497

UINT32BYTE

Trusted Platform Module Librarycounter = 0;
swappedCounter[4];// If there is no digest to compute returnif((hashAlg == TPM_ALG_NULL) || (mSize == 0))
return 0;
for(remaining = mSize; ; remaining -= hDef->digestSize){// Because the system may be either Endian...
UINT32_TO_BYTE_ARRAY(counter, swappedCounter);// Start the hash and include the seed and counter
CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate(&hashState, seedSize, seed);
CryptDigestUpdate(&hashState, 4, swappedCounter);// Handling the completion depends on how much space remains in the mask// buffer. If it can hold the entire digest, put it there. If not// put the digest in a temp buffer and only copy the amount that// will fit into the mask buffer.
HashEnd(&hashState, remaining, mask);
if(remaining <= hDef->digestSize)
break;
mask = &mask[hDef->digestSize];counter++;}
return (UINT16)mSize;}

10.2.13.8.2

CryptKDFa()

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.

498
499
500
501
502
503
504
505
506
507
508

Return Value

Meaning0

hash algorithm is not supported or is TPM_ALG_NULL>0

the number of bytes in the keyStream buffer

LIB_EXPORT UINT16
CryptKDFa(
TPM_ALG_ID
const TPM2B
const TPM2B
const TPM2B
const TPM2B
UINT32BYTE
UINT32

hashAlg,*key,*label,*contextU,*contextV,
sizeInBits,*keyStream,*counterInOut,

Family “2.0”Level 00 Revision 01.55// IN: hash algorithm used in HMAC// IN: HMAC key// IN: a label for the KDF// IN: context U// IN: context V// IN: size of generated key in bits// OUT: key buffer// IN/OUT: caller may provide the iteration//
counter for incremental operations to

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 645
April 15, 2019

Trusted Platform Module Library
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

UINT16

Part 4: Supporting Routines//
avoid large intermediate buffers.
// IN: If non-zero, this is the maximum number//of blocks to be returned, regardless//of sizeInBits

blocks){UINT32
INT16
UINT16BYTE
HMAC_STATEUINT16

counter = 0;// counter value
bytes;// number of bytes to produce
generated;// number of bytes generated*stream = keyStream;hState;digestSize = CryptHashGetDigestSize(hashAlg);

pAssert(key != NULL && keyStream != NULL);TEST(TPM_ALG_KDF1_SP800_108);
if(digestSize == 0)
return 0;if(counterInOut != NULL)
counter = *counterInOut;// If the size of the request is larger than the numbers will handle,// it is a fatal error.
pAssert(((sizeInBits + 7) / 8) <= INT16_MAX);// The number of bytes to be generated is the smaller of the sizeInBits bytes or// the number of requested blocks. The number of blocks is the smaller of the// number requested or the number allowed by sizeInBits. A partial block is// a full block.
bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits);
generated = bytes;// Generate required bytesfor(; bytes > 0; bytes -= digestSize){counter++;// Start HMAC
if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0)
return 0;// Adding counter
CryptDigestUpdateInt(&hState.hashState, 4, counter);// Adding label
if(label != NULL)
HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer);// Add a null. SP108 is not very clear about when the 0 is needed but to// make this like the previous version that did not add an 0x00 after// a null-terminated string, this version will only add a null byte// if the label parameter did not end in a null byte, or if no label// is present.
if((label == NULL)|| (label->size == 0)|| (label->buffer[label->size - 1] != 0))
CryptDigestUpdateInt(&hState.hashState, 1, 0);// Adding contextU
if(contextU != NULL)
HASH_DATA(&hState.hashState, contextU->size, contextU->buffer);// Adding contextV
if(contextV != NULL)
HASH_DATA(&hState.hashState, contextV->size, contextV->buffer);// Adding size in bits
CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits);// Complete and put the data in the buffer

Page 646
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
575
576
577
578
579
580
581
582
583
584

Trusted Platform Module Library

CryptHmacEnd(&hState, bytes, stream);
stream = &stream[digestSize];}// Masking in the KDF is disabled. If the calling function wants something// less than even number of bytes, then the caller should do the masking// because there is no universal way to do it here
if(counterInOut != NULL)*counterInOut = counter;
return generated;}

10.2.13.8.3

CryptKDFe()

This function implements 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 processingof this command is considered fatal.

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

Return Value

Meaning0

hash algorithm is not supported or is TPM_ALG_NULL>0

the number of bytes in the keyStream buffer

LIB_EXPORT UINT16
CryptKDFe(
TPM_ALG_ID
TPM2B
const TPM2B
TPM2B
TPM2B
UINT32BYTE)

hashAlg,*Z,*label,*partyUInfo,*partyVInfo,
sizeInBits,*keyStream// IN: hash algorithm used in HMAC// IN: Z// IN: a label value for the KDF// IN: PartyUInfo// IN: PartyVInfo// IN: size of generated key in bits// OUT: key buffer

HASH_STATEPHASH_DEF

hashState;hashDef = CryptGetHashDef(hashAlg);UINT32
UINT16BYTE
INT16

counter = 0;// counter value
hLen;*stream = keyStream;
bytes;// number of bytes to generate{

pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX);//
hLen = hashDef->digestSize;
bytes = (INT16)((sizeInBits + 7) / 8);if(hashAlg == TPM_ALG_NULL || bytes == 0)
return 0;// Generate required bytes//The inner loop of that KDF uses:// Hash[i] := H(counter | Z | OtherInfo) (5)// Where:// Hash[i]the hash generated on the i-th iteration of the loop.
// H()
an approved hash function// countera 32-bit counter that is initialized to 1 and incremented//
on each iteration// Z
the X coordinate of the product of a public ECC key and a//different private ECC key.
// OtherInfo
a collection of qualifying data for the KDF defined below.
// In this specification, OtherInfo will be constructed by:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 647
April 15, 2019

Trusted Platform Module Library
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

Part 4: Supporting Routines//
OtherInfo := Use | PartyUInfo | PartyVInfo
for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen){
if(bytes < hLen)
hLen = bytes;
counter++;// Do the hash
CryptHashStart(&hashState, hashAlg);// Add counter
CryptDigestUpdateInt(&hashState, 4, counter);// Add Z
if(Z != NULL)
CryptDigestUpdate2B(&hashState, Z);// Add label
if(label != NULL)
CryptDigestUpdate2B(&hashState, label);// Add a null. SP108 is not very clear about when the 0 is needed but to// make this like the previous version that did not add an 0x00 after// a null-terminated string, this version will only add a null byte// if the label parameter did not end in a null byte, or if no label// is present.
if((label == NULL)|| (label->size == 0)|| (label->buffer[label->size - 1] != 0))
CryptDigestUpdateInt(&hashState, 1, 0);// Add PartyUInfo
if(partyUInfo != NULL)
CryptDigestUpdate2B(&hashState, partyUInfo);// Add PartyVInfo
if(partyVInfo != NULL)
CryptDigestUpdate2B(&hashState, partyVInfo);// Compute Hash. hLen was changed to be the smaller of bytes or hLen// at the start of each iteration.
CryptHashEnd(&hashState, hLen, stream);}// Mask off bits if the required bits is not a multiple of byte sizeif((sizeInBits % 8) != 0)
keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
return (UINT16)((sizeInBits + 7) / 8);}

Page 648
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.14 CryptPrime.c
10.2.14.1 Introduction
This file contains the code for prime validation.
1
2
3
4
5
6
7
8
9
10

#include "Tpm.h"#include "CryptPrime_fp.h"//#define CPRI_PRIME//#include "PrimeTable.h"#include "CryptPrimeSieve_fp.h"
extern const uint32_t
s_LastPrimeInTable;
extern const uint32_t
s_PrimeTableSize;extern const uint32_t
s_PrimesInTable;
extern const unsigned char s_PrimeTable[];extern bigConsts_CompositeOfSmallPrimes;

10.2.14.2 Functions
10.2.14.2.1

Root2()

This finds ceil(sqrt(n)) to use as a stopping point for searching the prime table.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

static uint32_t
Root2(
uint32_t)nint32_tint32_tint32_tint32_tlast = (int32_t)(n >> 2);next = (int32_t)(n >> 1);
diff;stop = 10;{//// get a starting point
for(; next != 0; last >>= 1, next >>= 2);
last++;
do{next = (last + (n / last)) >> 1;
diff = next - last;
last = next;
if(stop-- == 0)
FAIL(FATAL_ERROR_INTERNAL);} while(diff < -1 || diff > 1);if((n / next) > (unsigned)next)
next++;
pAssert(next != 0);
pAssert(((n / next) <= (unsigned)next) && (n / (next + 1) < (unsigned)next));
return next;}

10.2.14.2.2

IsPrimeInt()

This will do a test of a word of up to 32-bits in size.
38
39
40
41
42

BOOL
IsPrimeInt(
uint32_t)n{Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 649
April 15, 2019

Trusted Platform Module Library
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

Part 4: Supporting Routines

uint32_ti;uint32_t
stop;
if(n < 3 || ((n & 1) == 0))
return (n == 2);
if(n <= s_LastPrimeInTable){n >>= 1;
return ((s_PrimeTable[n >> 3] >> (n & 7)) & 1);}// Need to searchstop = Root2(n) >> 1;// starting at 1 is equivalent to staring at (1 << 1) + 1 = 3
for(i = 1; i < stop; i++){if((s_PrimeTable[i >> 3] >> (i & 7)) & 1)// see if this prime evenly divides the number
if((n % ((i << 1) + 1)) == 0)
return FALSE;}
return TRUE;}

10.2.14.2.3

BnIsProbablyPrime()

This function is used when the key sieve is not implemented. This function Will try to eliminate some ofthe obvious things before going on to perform MillerRabin() as a final verification of primeness.
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

BOOL
BnIsProbablyPrime(
bigNumRAND_STATE

prime,*rand// IN:// IN: the random state just//in case Miller-Rabin is required){#if RADIX_BITS > 32
if(BnUnsignedCmpWord(prime, UINT32_MAX) <= 0)#else
if(BnGetSize(prime) == 1)#endifreturn IsPrimeInt(prime->d[0]);if(BnIsEven(prime))
return FALSE;
if(BnUnsignedCmpWord(prime, s_LastPrimeInTable) <= 0){crypt_uword_t
temp = prime->d[0] >> 1;
return ((s_PrimeTable[temp >> 3] >> (temp & 7)) & 1);}{
BN_VAR(n, LARGEST_NUMBER_BITS);
BnGcd(n, prime, s_CompositeOfSmallPrimes);if(!BnEqualWord(n, 1))
return FALSE;}
return MillerRabin(prime, rand);}10.2.14.2.4MillerRabinRounds()

Function returns the number of Miller-Rabin rounds necessary to give an error probability equal to thesecurity strength of the prime. These values are from FIPS 186-3.
93

UINT32

Page 650
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

94
95
96
97
98
99
100
101

Trusted Platform Module Library

MillerRabinRounds(
UINT32)bits// IN: Number of bits in the RSA prime{
if(bits < 511) return 8;if(bits < 1536) return 5;
return 4;// don't really expect this// for 512 and 1K primes// for 3K public modulus and greater}

10.2.14.2.5

MillerRabin()This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the number. In all
likelihood, if the number is not prime, the first test fails.

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

Return Value

Meaning

TRUE(1)probably prime

FALSE(0)composite

BOOL
MillerRabin(
bigNumRAND_STATE
)

bnW,
*rand

{
BN_MAX(bnWm1);
BN_PRIME(bnM);
BN_PRIME(bnB);
BN_PRIME(bnZ);
BOOL
unsigned int
unsigned int
int
int
int

ret = FALSE;// Assumed composite for easy exit
a;
j;
wLen;
i;
iterations = MillerRabinRounds(BnSizeInBits(bnW));//
INSTRUMENT_INC(MillerRabinTrials[PrimeIndex]);pAssert(bnW->size > 1);// Let a be the largest integer such that 2^a divides w1.
BnSubWord(bnWm1, bnW, 1);pAssert(bnWm1->size != 0);// Since w is odd (w-1) is even so start at bit number 1 rather than 0// Get the number of bits in bnWm1 so that it doesn't have to be recomputed// on each iteration.
i = bnWm1->size * RADIX_BITS;// Now find the largest power of 2 that divides w1for(a = 1;
(a < (bnWm1->size * RADIX_BITS)) &&(BnTestBit(bnWm1, a) == 0);a++);// 2. m = (w1) / 2^a
BnShiftRight(bnM, bnWm1, a);// 3. wlen = len (w).
wLen = BnSizeInBits(bnW);// 4. For i = 1 to iterations dofor(i = 0; i < iterations; i++){// 4.1 Obtain a string b of wlen bits from an RBG.
// Ensure that 1 < b < w1.
// 4.2 If ((b <= 1) or (b >= w1)), then go to step 4.1.
while(BnGetRandomBits(bnB, wLen, rand) && ((BnUnsignedCmpWord(bnB, 1) <= 0)Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 651
April 15, 2019

Trusted Platform Module Library
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

Part 4: Supporting Routines|| (BnUnsignedCmp(bnB, bnWm1) >= 0)));if(g_inFailureMode)return FALSE;// 4.3 z = b^m mod w.
// if ModExp fails, then say this is not// prime and bail out.
BnModExp(bnZ, bnB, bnM, bnW);// 4.4 If ((z == 1) or (z = w == 1)), then go to step 4.7.
if((BnUnsignedCmpWord(bnZ, 1) == 0)|| (BnUnsignedCmp(bnZ, bnWm1) == 0))
goto step4point7;// 4.5 For j = 1 to a 1 do.
for(j = 1; j < a; j++){// 4.5.1 z = z^2 mod w.
BnModMult(bnZ, bnZ, bnZ, bnW);// 4.5.2 If (z = w1), then go to step 4.7.
if(BnUnsignedCmp(bnZ, bnWm1) == 0)
goto step4point7;// 4.5.3 If (z = 1), then go to step 4.6.
if(BnEqualWord(bnZ, 1))
goto step4point6;}// 4.6 Return COMPOSITE.
step4point6:
INSTRUMENT_INC(failedAtIteration[i]);goto end;// 4.7 Continue. Comment: Increment i for the do-loop in step 4.
step4point7:
continue;}// 5. Return PROBABLY PRIME
ret = TRUE;
end:
return ret;}#if
ALG_RSA

10.2.14.2.6

RsaCheckPrime()

This will check to see if a number is prime and appropriate for an RSA prime.
This has different functionality based on whether we are using key sieving or not. If not, the number
checked to see if it is divisible by the public exponent, then the number is adjusted either up or down inorder to make it a better candidate. It is then checked for being probably prime.
If sieving is used, the number is used to root a sieving process.
185
186
187
188
189
190
191
192
193
194
195
196
197
198

TPM_RC
RsaCheckPrime(
bigNumUINT32
RAND_STATE){#if !RSA_KEY_SIEVE
TPM_RCUINT32prime,
exponent,*rand

retVal = TPM_RC_SUCCESS;
modE = BnModWord(prime, exponent);

NOT_REFERENCED(rand);if(modE == 0)Page 652
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

Trusted Platform Module Library// evenly divisible so add two keeping the number odd
BnAddWord(prime, prime, 2);// want 0 != (p - 1) mod e// which is 1 != p mod eelse if(modE == 1)// subtract 2 keeping number odd and insuring that// 0 != (p - 1) mod e
BnSubWord(prime, prime, 2);if(BnIsProbablyPrime(prime, rand) == 0)
ERROR_RETURN(g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_VALUE);
Exit:
return retVal;#else
return PrimeSelectWithSieve(prime, exponent, rand);#endif}10.2.14.2.7

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 thisroutine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 which is, in fixed point,
0.7071075439453125 or an error of 0.000108%. Just setting the upper two bits would give a value > 0.75
which is an error of > 6%. 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 code maps the most significant crypt_uword_t in prime so that a 32-/64-bit value of 0 to 0xB5050...0
and a value of 0xff...f to 0xff...f. It also sets the LSb of prime to make sure that the number is odd.
This code has been fixed so that it will work with a RADIX_SIZE == 64.
The function also puts the number on a field boundary.
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

LIB_EXPORT void
RsaAdjustPrimeCandidate(
bigNum)prime{
crypt_uword_t
msw = prime->d[prime->size - 1];
crypt_uword_t
adjusted;#if RADIX_BITS == 64#
define ADD_CONST ((crypt_uword_t)0xB505000000000000ULL)#else#
define ADD_CONST ((crypt_uword_t)0xB5050000UL)#endif// Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0
adjusted = (crypt_uword_t)(msw >> 16) * (crypt_uword_t)0x4AFB;
adjusted += ((msw & 0xFFFF) * (crypt_uword_t)0x4AFB) >> 16;
adjusted += ADD_CONST;
prime->d[prime->size - 1] = adjusted;// make sure the number is odd
prime->d[0] |= 1;}

10.2.14.2.8

BnGeneratePrimeForRSA()

Function to generate a prime of the desired size with the proper attributes for an RSA prime.
236
237
238

TPM_RC
BnGeneratePrimeForRSA(
bigNumprime,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 653
April 15, 2019

Trusted Platform Module Library
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

Part 4: Supporting RoutinesUINT32
UINT32
RAND_STATE)

bits,
exponent,
*rand

BOOL

found = FALSE;{//// Make sure that the prime is large enoughpAssert(prime->allocated >= BITS_TO_CRYPT_WORDS(bits));// Only try to handle specific sizes of keys in order to save overhead
pAssert((bits % 32) == 0);prime->size = BITS_TO_CRYPT_WORDS(bits);
while(!found){
DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));if(g_inFailureMode)return TPM_RC_FAILURE;
RsaAdjustPrimeCandidate(prime);
found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS;}
return TPM_RC_SUCCESS;}#endif // ALG_RSA

Page 654
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.15 CryptPrimeSieve.c
10.2.15.1 Includes and defines
1
2
3#include "Tpm.h"#if RSA_KEY_SIEVE#include "CryptPrimeSieve_fp.h"

This determines the number of bits in the largest sieve field.
4
5
6
7
8

#define MAX_FIELD_SIZE 2048
extern const uint32_t
s_LastPrimeInTable;
extern const uint32_t
s_PrimeTableSize;extern const uint32_t
s_PrimesInTable;
extern const unsigned char s_PrimeTable[];This table is set of prime markers. Each entry is the prime value for the ((n + 1) * 1024) prime. That is, theentry in s_PrimeMarkers[1] is the value for the 2,048th prime. This is used in the PrimeSieve() to adjust
the limit for the prime search. When processing smaller prime candidates, fewer primes are checked
directly before going to Miller-Rabin. As the prime grows, it is worth spending more time eliminating
primes as, a) the density is lower, and b) the cost of Miller-Rabin is higher.
9
10
11
12

const uint32_t
s_PrimeMarkersCount = 6;
const uint32_t
s_PrimeMarkers[] = {8167, 17881, 28183, 38891, 49871, 60961 };uint32_tprimeLimit;

10.2.15.2 Functions
10.2.15.2.1

RsaAdjustPrimeLimit()

This used during the sieve process. The iterator for getting the next prime (RsaNextPrime()) will return
primes until it hits the limit (primeLimit) set up by this function. This causes the sieve process to stop
when an appropriate number of primes have been sieved.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

LIB_EXPORT void
RsaAdjustPrimeLimit(
uint32_t)

requestedPrimes{
if(requestedPrimes == 0 || requestedPrimes > s_PrimesInTable)
requestedPrimes = s_PrimesInTable;
requestedPrimes = (requestedPrimes - 1) / 1024;
if(requestedPrimes < s_PrimeMarkersCount)primeLimit = s_PrimeMarkers[requestedPrimes];
else
primeLimit = s_LastPrimeInTable;
primeLimit >>= 1;}

10.2.15.2.2

RsaNextPrime()

This the iterator used during the sieve process. The input is the last prime returned (or any starting point)
and the output is the next higher prime. The function returns 0 when the primeLimit is reached.
28
29

LIB_EXPORT uint32_t
RsaNextPrime(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 655
April 15, 2019

Trusted Platform Module Library
30
31
32
33
34
35
36
37
38
39
40
41
42

uint32_t)

Part 4: Supporting Routines

lastPrime{
if(lastPrime == 0)
return 0;
lastPrime >>= 1;for(lastPrime += 1; lastPrime <= primeLimit; lastPrime++){if(((s_PrimeTable[lastPrime >> 3] >> (lastPrime & 0x7)) & 1) == 1)
return ((lastPrime << 1) + 1);}
return 0;}

This table contains a previously sieved table. It has the bits for 3, 5, and 7 removed. Because of thefactors, it needs to be aligned to 105 and has a repeat of 105.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

const BYTE
seedValues[] = {0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c,
0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96,
0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d, 0x99,
0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96, 0x69,
0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6,
0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb,
0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c,
0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9, 0x34,
0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c, 0x1b,
0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45,
0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6,
0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2,
0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6, 0x29,0xd1};#define USE_NIBBLE#ifndef USE_NIBBLE
static const BYTE bitsInByte[256] = {0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,

Page 656
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
91
92
93
94
95
96
97
98
99
100
101
102

Trusted Platform Module Library

0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08};
#define BitsInByte(x)bitsInByte[(unsigned char)x]#else
const BYTE bitsInNibble[16] = {0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04};#define BitsInByte(x)(bitsInNibble[(unsigned char)(x) & 0xf]+
bitsInNibble[((unsigned char)(x) >> 4) & 0xf])#endif10.2.15.2.3\\

BitsInArry()

This function counts the number of bits set in an array of bytes.
103
104
105
106
107
108
109
110
111
112
113

static int
BitsInArray(
const unsigned char
unsigned int
)

*a,
aSize

// IN: A pointer to an array of bytes// IN: the number of bytes to sum{
int
j = 0;
for(; aSize; a++, aSize--)j += BitsInByte(*a);
return j;}

10.2.15.2.4

FindNthSetBit()

This function finds the nth SET bit in a bit array. The n parameter is between 1 and the number of bits inthe array (always a multiple of 8). If called when the array does not have n bits set, it will return -1

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

Return Value

Meaning<0

no bit is set or no bit with the requested number is set>=0

the number of the bit in the array that is the nth set

LIB_EXPORT int
FindNthSetBit(
const UINT16
const BYTE
const UINT32)

aSize,*a,n// IN: the size of the array to check// IN: the array to check// IN, the number of the SET bit{
UINT16
int
UINT32
BYTE

i;
retValue;sum = 0;sel;//find the bitfor(i = 0; (i < (int)aSize) && (sum < n); i++)sum += BitsInByte(a[i]);i--;// The chosen bit is in the byte that was just accessed// Compute the offset to the start of that byte
retValue = i * 8 - 1;
sel = a[i];// Subtract the bits in the last byte added.
sum -= BitsInByte(sel);// Now process the byte, one bit at a time.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 657
April 15, 2019

Trusted Platform Module Library
137
138
139
140
141
142
143
144
145
146
147

Part 4: Supporting Routinesfor(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1)
sum += (sel & 1) != 0;
return (sum == n) ? retValue : -1;}
typedef struct{
UINT16prime;UINT16
count;} SIEVE_MARKS;
const SIEVE_MARKS sieveMarks[5] = {{31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}};10.2.15.2.5

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 precomputed field with the bits associated with 3, 5 and 7 alreadyturned off, the value of pnN may need to be adjusted by a few counts to allow the precomputed field to be
used without modification.
To get better performance, one could address the issue of developing the composite numbers. When thesize of the prime gets large, the time for doing the divisions goes up, noticeably. It could be better todevelop larger composite numbers even if they need to be bigNum's themselves. The object would be to
reduce the number of times that the large prime is divided into a few large divides and then use smaller
divides to get to the final 16 bit (or smaller) remainders.
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

LIB_EXPORT UINT32
PrimeSieve(
bigNumUINT32
BYTE)

bnN,// IN/OUT: number to sieve
fieldSize, // IN: size of the field area in bytes*field// IN: field

INT32
UINT32
UINT32
UINT32
BYTE
INT32
UINT32
UINT32
UINT32
UINT32
UINT32
UINT32
UINT32i;j;fieldBits = fieldSize * 8;r;
*pField;iter;
adjust;mark = 0;
count = sieveMarks[0].count;stop = sieveMarks[0].prime;
composite;
pList[8];next;{

pAssert(field != NULL && bnN != NULL);// If the remainder is odd, then subtracting the value will give an even number,// but we want an odd number, so subtract the 105+rem. Otherwise, just subtract// the even remainder.
adjust = BnModWord(bnN, 105);if(adjust & 1)
adjust += 105;//// Adjust the input number so that it points to the first number in a// aligned field.
BnSubWord(bnN, bnN, adjust);
pAssert(BnModWord(bnN, 105) == 0);
pField = field;for(i = fieldSize; i >= sizeof(seedValues);
pField += sizeof(seedValues), i -= sizeof(seedValues)){

Page 658
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

Trusted Platform Module Library

memcpy(pField, seedValues, sizeof(seedValues));}if(i != 0)
memcpy(pField, seedValues, i);// Cycle through the primes, clearing bits// Have already done 3, 5, and 7
iter = 7;#define NEXT_PRIME(iter)(iter = RsaNextPrime(iter))// Get the next N primes where N is determined by the mark in the sieveMarks
while((composite = NEXT_PRIME(iter)) != 0){
next = 0;i = count;
pList[i--] = composite;for(; i > 0; i--){next = NEXT_PRIME(iter);pList[i] = next;
if(next != 0)
composite *= next;}// Get the remainder when dividing the base field address// by the composite
composite = BnModWord(bnN, composite);// 'composite' is divisible by the composite components. for each of the// composite components, divide 'composite'. That remainder (r) is used to// pick a starting point for clearing the array. The stride is equal to the// composite component. Note, the field only contains odd numbers. If the// field were expanded to contain all numbers, then half of the bits would// have already been cleared. We can save the trouble of clearing them a// second time by having a stride of 2*next. Or we can take all of the even// numbers out of the field and use a stride of 'next'
for(i = count; i > 0; i--){next = pList[i];if(next == 0)
goto done;r = composite % next;// these computations deal with the fact that the field starts at some// arbitrary offset within the number space. If the field were all numbers,// then we would have gone through some number of bit clearings before we// got to the start of this range. We don't know how many there were before,// but we can tell from the remainder whether we are on an even or odd// stride when we hit the beginning of the table. If we are on an odd stride// (r & 1), we would start half a stride in (next - r)/2. If we are on an// even stride, we need 1.5 strides (next + r/2) because the table only has// odd numbers. If the remainder happens to be zero, then the start of the// table is on stride so no adjustment is necessary.
if(r & 1)
j = (next - r) / 2;
else if(r == 0)
j = 0;else
j = next - r / 2;for(; j < fieldBits; j += next)
ClearBit(j, field, fieldSize);}if(next >= stop){
mark++;
count = sieveMarks[mark].count;stop = sieveMarks[mark].prime;
}
}
done:
INSTRUMENT_INC(totalFieldsSieved[PrimeIndex]);i = BitsInArray(field, fieldSize);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 659
April 15, 2019

Trusted Platform Module Library
252
253
254
255
256
257

Part 4: Supporting Routines

INSTRUMENT_ADD(bitsInFieldAfterSieve[PrimeIndex], i);
INSTRUMENT_ADD(emptyFieldsSieved[PrimeIndex], (i == 0));
return i;}#ifdef SIEVE_DEBUG
static uint32_t fieldSize = 210;10.2.15.2.6

SetFieldSize()

Function to set the field size used for prime generation. Used for tuning.
258
259
260
261
262
263
264
265
266
267
268
269

LIB_EXPORT uint32_t
SetFieldSize(uint32_t)

newFieldSize{
if(newFieldSize == 0 || newFieldSize > MAX_FIELD_SIZE)
fieldSize = MAX_FIELD_SIZE;
elsefieldSize = newFieldSize;
return fieldSize;}#endif // SIEVE_DEBUG

10.2.15.2.7

PrimeSelectWithSieve()

This function will sieve the field around the input prime candidate. If the sieve field is not empty, one ofthe one bits in the field is chosen for testing with Miller-Rabin. If the value is prime, pnP is updated withthis 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 thefield have been checked and none is prime, the function returns FALSE and a new random value needs
to be chosen.

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

Error Returns

Meaning

TPM_RC_FAILURE

TPM in failure mode, probably due to entropy source

TPM_RC_SUCCESS

candidate is probably prime

TPM_RC_NO_RESULT

candidate is not prime and couldn't find and alternative in the field

LIB_EXPORT TPM_RC
PrimeSelectWithSieve(
bigNumUINT32
RAND_STATE)

candidate,
e,
*rand

// IN/OUT: The candidate to filter// IN: the exponent// IN: the random number generator state{
BYTE
field[MAX_FIELD_SIZE];UINT32first;UINT32
ones;
INT32
chosen;BN_PRIME(test);
UINT32modE;#ifndef SIEVE_DEBUG
UINT32fieldSize = MAX_FIELD_SIZE;#endifUINT32primeSize;//// Adjust the field size and prime table list to fit the size of the prime// being tested. This is done to try to optimize the trade-off between the// dividing done for sieving and the time for Miller-Rabin. When the size

Page 660
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

Trusted Platform Module Library// of the prime is large, the cost of Miller-Rabin is fairly high, as is the// cost of the sieving. However, the time for Miller-Rabin goes up considerably// faster than the cost of dividing by a number of primes.
primeSize = BnSizeInBits(candidate);if(primeSize <= 512){
RsaAdjustPrimeLimit(1024); // Use just the first 1024 primes}
else if(primeSize <= 1024){
RsaAdjustPrimeLimit(4096); // Use just the first 4K primes}
else{
RsaAdjustPrimeLimit(0);// Use all available}// Save the low-order word to use as a search generator and make sure that// it has some interesting range to it
first = candidate->d[0] | 0x80000000;// Sieve the fieldones = PrimeSieve(candidate, fieldSize, field);
pAssert(ones > 0 && ones < (fieldSize * 8));for(; ones > 0; ones--){// Decide which bit to look at and find its offset
chosen = FindNthSetBit((UINT16)fieldSize, field, ((first % ones) + 1));if((chosen < 0) || (chosen >= (INT32)(fieldSize * 8)))FAIL(FATAL_ERROR_INTERNAL);// Set this as the trial prime
BnAddWord(test, candidate, (crypt_uword_t)(chosen * 2));// The exponent might not have been one of the tested primes so// make sure that it isn't divisible and make sure that 0 != (p-1) mod e// Note: This is the same as 1 != p mod e
modE = BnModWord(test, e);if((modE != 0) && (modE != 1) && MillerRabin(test, rand)){
BnCopy(candidate, test);
return TPM_RC_SUCCESS;}// Clear the bit just tested
ClearBit(chosen, field, fieldSize);}// Ran out of bits and couldn't find a prime in this field
INSTRUMENT_INC(noPrimeFields[PrimeIndex]);return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT);}#if RSA_INSTRUMENT
static chara[256];

char *
PrintTuple(
UINT32)*i{sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]);return a;}#define CLEAR_VALUE(x)memset(x, 0, sizeof(x))

void

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 661
April 15, 2019

Trusted Platform Module Library
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

Part 4: Supporting Routines

RsaSimulationEnd(
void
)
{
int
i;
UINT32
averages[3];UINT32
nonFirst = 0;if((PrimeCounts[0] + PrimeCounts[1] + PrimeCounts[2]) != 0){
printf("Primes generated = %s\n", PrintTuple(PrimeCounts));
printf("Fields sieved = %s\n", PrintTuple(totalFieldsSieved));printf("Fields with no primes = %s\n", PrintTuple(noPrimeFields));
printf("Primes checked with Miller-Rabin = %s\n",PrintTuple(MillerRabinTrials));for(i = 0; i < 3; i++)averages[i] = (totalFieldsSieved[i]!= 0 ? bitsInFieldAfterSieve[i] / totalFieldsSieved[i]: 0);printf("Average candidates in field %s\n", PrintTuple(averages));for(i = 1; i < (sizeof(failedAtIteration) / sizeof(failedAtIteration[0]));i++)
nonFirst += failedAtIteration[i];printf("Miller-Rabin failures not in first round = %d\n", nonFirst);}
CLEAR_VALUE(PrimeCounts);
CLEAR_VALUE(totalFieldsSieved);
CLEAR_VALUE(noPrimeFields);
CLEAR_VALUE(MillerRabinTrials);
CLEAR_VALUE(bitsInFieldAfterSieve);}
LIB_EXPORT void
GetSieveStats(uint32_t*trials,
uint32_t*emptyFields,
uint32_t*averageBits){
uint32_t
totalBits;
uint32_tfields;*trials = MillerRabinTrials[0] + MillerRabinTrials[1] + MillerRabinTrials[2];*emptyFields = noPrimeFields[0] + noPrimeFields[1] + noPrimeFields[2];fields = totalFieldsSieved[0] + totalFieldsSieved[1]+ totalFieldsSieved[2];totalBits = bitsInFieldAfterSieve[0] + bitsInFieldAfterSieve[1]+ bitsInFieldAfterSieve[2];if(fields != 0)*averageBits = totalBits / fields;
else*averageBits = 0;
CLEAR_VALUE(PrimeCounts);
CLEAR_VALUE(totalFieldsSieved);
CLEAR_VALUE(noPrimeFields);
CLEAR_VALUE(MillerRabinTrials);
CLEAR_VALUE(bitsInFieldAfterSieve);}#endif#endif // RSA_KEY_SIEVE#if !RSA_INSTRUMENT
void
RsaSimulationEnd(
voidPage 662
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
423
424
425
426

Trusted Platform Module Library){}#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 663
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.16 CryptRand.c
10.2.16.1 Introduction
This file implements a DRBG with a behavior according to SP800-90A using a block cypher. This is also
compliant to ISO/IEC 18031:2011(E) C.3.2.
A state structure is created for use by TPM.lib and functions within the CryptoEngine() my use their own
state structures when they need to have deterministic values.
A debug mode is available that allows the random numbers generated for TPM.lib to be repeated during
runs of the simulator. The switch for it is in TpmBuildSwitches.h. It is USE_DEBUG_RNG.
This is the implementation layer of CTR DRGB mechanism as defined in SP800-90A and the functions
are organized as closely as practical to the organization in SP800-90A. It is intended to be compiled as aseparate module that is linked with a secure application so that both reside inside the same boundary [SP
800-90A 8.5]. The secure application in particular manages the accesses protected storage for the stateof the DRBG instantiations, and supplies the implementation functions here with a valid pointer to theworking state of the given instantiations (as a DRBG_STATE structure).
This DRBG mechanism implementation does not support prediction resistance. Thus
prediction_resistance_flag is omitted from Instantiate_function(), Reseed_function(), Generate_function()argument lists [SP 800-90A 9.1, 9.2, 9.3], as well as from the working state data structure DRBG_STATE[SP 800-90A 9.1].
This DRBG mechanism implementation always uses the highest security strength of available in the blockciphers. Thus requested_security_strength parameter is omitted from Instantiate_function() and
Generate_function() argument lists [SP 800-90A 9.1, 9.2, 9.3], as well as from the working state data
structure DRBG_STATE [SP 800-90A 9.1].
Internal functions (ones without Crypt prefix) expect validated arguments and therefore use assertions
instead of runtime parameter checks and mostly return void instead of a status value.
1#include "Tpm.h"

Pull in the test vector definitions and define the space
2
3
4
5
6
7
8

#include"PRNG_TestVectors.h"
const BYTE DRBG_NistTestVector_Entropy[] = {DRBG_TEST_INITIATE_ENTROPY};
const BYTE DRBG_NistTestVector_GeneratedInterm[] ={DRBG_TEST_GENERATED_INTERM};
const BYTE DRBG_NistTestVector_EntropyReseed[] ={DRBG_TEST_RESEED_ENTROPY};
const BYTE DRBG_NistTestVector_Generated[] = {DRBG_TEST_GENERATED};

10.2.16.2 Derivation Functions
10.2.16.2.1

Description

The functions in this section are used to reduce the personalization input values to make them usable as
input for reseeding and instantiation. The overall behavior is intended to produce the same results as
described in SP800-90A, section 10.4.2 "Derivation Function Using a Block Cipher Algorithm(Block_Cipher_df)." The code is broken into several subroutines to deal with the fact that the data used
for personalization may come in several separate blocks such as a Template hash and a proof value anda primary seed.

Page 664
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.16.2.2
9
10
11
12
13
14
15
16
17
18
19
20

Trusted Platform Module Library

Derivation Function Defines and Structures#define
DF_COUNT (DRBG_KEY_SIZE_WORDS / DRBG_IV_SIZE_WORDS + 1)
#if DRBG_KEY_SIZE_BITS != 128 && DRBG_KEY_SIZE_BITS != 256#
error "CryptRand.c only written for AES with 128- or 256-bit keys."#endiftypedef struct{
DRBG_KEY_SCHEDULE
keySchedule;
DRBG_IV
iv[DF_COUNT];DRBG_IV
out1;
DRBG_IVbuf;
int
contents;} DF_STATE, *PDF_STATE;

10.2.16.2.3

DfCompute()

This function does the incremental update of the derivation function state. It encrypts the iv value and
XOR's the results into each of the blocks of the output. This is equivalent to processing all of input data
for each output block.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

static void
DfCompute(
PDF_STATE)

dfStateint
int
crypt_uword_t
crypt_uword_t

i;
iv;
*pIv;
temp[DRBG_IV_SIZE_WORDS] = {0};{//for(iv = 0; iv < DF_COUNT; iv++){
pIv = (crypt_uword_t *)&dfState->iv[iv].words[0];for(i = 0; i < DRBG_IV_SIZE_WORDS; i++){temp[i] ^= pIv[i] ^ dfState->buf.words[i];}DRBG_ENCRYPT(&dfState->keySchedule, &temp, pIv);}
for(i = 0; i < DRBG_IV_SIZE_WORDS; i++)dfState->buf.words[i] = 0;
dfState->contents = 0;}

10.2.16.2.4

DfStart()This initializes the output blocks with an encrypted counter value and initializes the key schedule.
44
45
46
47
48
49
50
51
52
53
54
55
56

static void
DfStart(
PDF_STATE
uint32_t)

dfState,inputLength

BYTE
int
UINT32

init[8];i;drbgSeedSize = sizeof(DRBG_SEED);{

const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 665
April 15, 2019

Trusted Platform Module Library
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

Part 4: Supporting Routines#if DRBG_KEY_SIZE_BYTES > 16
,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
#endif};memset(dfState, 0, sizeof(DF_STATE));DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule);// Create the first chaining values
for(i = 0; i < DF_COUNT; i++)((BYTE *)&dfState->iv[i])[3] = (BYTE)i;
DfCompute(dfState);// initialize the first 64 bits of the IV in a way that doesn't depend// on the size of the words used.
UINT32_TO_BYTE_ARRAY(inputLength, init);
UINT32_TO_BYTE_ARRAY(drbgSeedSize, &init[4]);memcpy(&dfState->iv[0], init, 8);
dfState->contents = 4;}

10.2.16.2.5

DfUpdate()

This updates the state with the input data. A byte at a time is moved into the state buffer until it is full andthen that block is encrypted by DfCompute().
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

static void
DfUpdate(
PDF_STATE
int
const BYTE)

dfState,
size,
*data

{
while(size > 0){int
toFill = DRBG_IV_SIZE_BYTES - dfState->contents;
if(size < toFill)toFill = size;// Copy as many bytes as there are or until the state buffer is full
memcpy(&dfState->buf.bytes[dfState->contents], data, toFill);// Reduce the size left by the amount copied
size -= toFill;// Advance the data pointer by the amount copied
data += toFill;// increase the buffer contents count by the amount copied
dfState->contents += toFill;pAssert(dfState->contents <= DRBG_IV_SIZE_BYTES);// If we have a full buffer, do a computation pass.
if(dfState->contents == DRBG_IV_SIZE_BYTES)
DfCompute(dfState);}}

10.2.16.2.6

DfEnd()

This function is called to get the result of the derivation function computation. If the buffer is not full, it ispadded with zeros. The output buffer is structured to be the same as a DRBG_SEED value so that thefunction can return a pointer to the DRBG_SEED value in the DF_STATE structure.
101
102
103
104
105

static DRBG_SEED *DfEnd(PDF_STATE)

dfState{Page 666
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
106
107
108
109
110
111
112
113
114
115

Trusted Platform Module Library// Since DfCompute is always called when a buffer is full, there is always// space in the buffer for the terminator
dfState->buf.bytes[dfState->contents++] = 0x80;// If the buffer is not full, pad with zeros
while(dfState->contents < DRBG_IV_SIZE_BYTES)
dfState->buf.bytes[dfState->contents++] = 0;// Do a final state update
DfCompute(dfState);
return (DRBG_SEED *)&dfState->iv;}

10.2.16.2.7

DfBuffer()

Function to take an input buffer and do the derivation function to produce a DRBG_SEED value that canbe used in DRBG_Reseed();
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

static DRBG_SEED *DfBuffer(
DRBG_SEED
int
BYTE
)

*output,
size,
*buf

// OUT: receives the result// IN: size of the buffer to add// IN: address of the buffer{
DF_STATE
dfState;if(size == 0 || buf == NULL)
return NULL;// Initialize the derivation function
DfStart(&dfState, size);
DfUpdate(&dfState, size, buf);
DfEnd(&dfState);
memcpy(output, &dfState.iv[0], sizeof(DRBG_SEED));return output;}

10.2.16.2.8

DRBG_GetEntropy()

Even though this implementation never fails, it may get blocked indefinitely long in the call to get entropy
from the platform (DRBG_GetEntropy32()). This function is only used during instantiation of the DRBG for
manufacturing and on each start-up after an non-orderly shutdown.

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

Return Value

Meaning

TRUE(1)

requested entropy returned

FALSE(0)entropy Failure

BOOL
DRBG_GetEntropy(
UINT32requiredEntropy,

BYTE)*entropy// IN: requested number of bytes of full//
entropy// OUT: buffer to return collected entropy{#if !USE_DEBUG_RNG
UINT32
INT32

obtainedEntropy;
returnedEntropy;// If in debug mode, always use the self-test values for initialization
if(IsSelfTest()){#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 667
April 15, 2019

Trusted Platform Module Library
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

Part 4: Supporting Routines// If doing simulated DRBG, then check to see if the// entropyFailure condition is being tested
if(!IsEntropyBad()){// In self-test, the caller should be asking for exactly the seed// size of entropy.
pAssert(requiredEntropy == sizeof(DRBG_NistTestVector_Entropy));
memcpy(entropy, DRBG_NistTestVector_Entropy,
sizeof(DRBG_NistTestVector_Entropy));}#if !USE_DEBUG_RNG}
else if(!IsEntropyBad()){// Collect entropy// Note: In debug mode, the only "entropy" value ever returned// is the value of the self-test vector.
for(returnedEntropy = 1, obtainedEntropy = 0;
obtainedEntropy < requiredEntropy && !IsEntropyBad();obtainedEntropy += returnedEntropy){
returnedEntropy = _plat__GetEntropy(&entropy[obtainedEntropy],
requiredEntropy - obtainedEntropy);
if(returnedEntropy <= 0)
SetEntropyBad();}}#endifreturn !IsEntropyBad();}10.2.16.2.9

IncrementIv()

This function increments the IV value by 1. It is used by EncryptDRBG().
179
180
181
182
183
184
185
186

void
IncrementIv(
DRBG_IV
)

*iv

{
BYTE
*ivP = ((BYTE *)iv) + DRBG_IV_SIZE_BYTES;
while((--ivP >= (BYTE *)iv) && ((*ivP = ((*ivP + 1) & 0xFF)) == 0));}10.2.16.2.10 EncryptDRBG()
This does the encryption operation for the DRBG. It will encrypt the input state counter (IV) using thestate key. Into the output buffer for as many times as it takes to generate the required number of bytes.
187
188
189
190
191
192
193
194
195
196
197
198
199
200

static BOOL
EncryptDRBG(
BYTE
UINT32
DRBG_KEY_SCHEDULE
DRBG_IVUINT32)*dOut,
dOutBytes,*keySchedule,*iv,*lastValue// Points to the last output value{#if FIPS_COMPLIANT// For FIPS compliance, the DRBG has to do a continuous self-test to make sure that// no two consecutive values are the same. This overhead is not incurred if the TPM// is not required to be FIPS compliant//

Page 668
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

UINT32int
BYTE

Trusted Platform Module Librarytemp[DRBG_IV_SIZE_BYTES / sizeof(UINT32)];i;*p;for(; dOutBytes > 0;){// Increment the IV before each encryption (this is what makes this// different from normal counter-mode encryption
IncrementIv(iv);
DRBG_ENCRYPT(keySchedule, iv, temp);// Expect a 16 byte block#if DRBG_IV_SIZE_BITS != 128#error "Unsuppored IV size in DRBG"#endifif((lastValue[0] == temp[0])&& (lastValue[1] == temp[1])&& (lastValue[2] == temp[2])&& (lastValue[3] == temp[3])){LOG_FAILURE(FATAL_ERROR_ENTROPY);
return FALSE;}
lastValue[0] = temp[0];lastValue[1] = temp[1];lastValue[2] = temp[2];lastValue[3] = temp[3];i = MIN(dOutBytes, DRBG_IV_SIZE_BYTES);
dOutBytes -= i;for(p = (BYTE *)temp; i > 0; i--)*dOut++ = *p++;}#else // version without continuous self-test
NOT_REFERENCED(lastValue);for(; dOutBytes >= DRBG_IV_SIZE_BYTES;
dOut = &dOut[DRBG_IV_SIZE_BYTES], dOutBytes -= DRBG_IV_SIZE_BYTES){// Increment the IV
IncrementIv(iv);
DRBG_ENCRYPT(keySchedule, iv, dOut);}// If there is a partial, generate into a block-sized// temp buffer and copy to the output.
if(dOutBytes != 0){
BYTE
temp[DRBG_IV_SIZE_BYTES];// Increment the IV
IncrementIv(iv);
DRBG_ENCRYPT(keySchedule, iv, temp);
memcpy(dOut, temp, dOutBytes);}#endifreturn TRUE;}

10.2.16.2.11 DRBG_Update()
This function performs the state update function. According to SP800-90A, a temp value is created bydoing CTR mode encryption of providedData and replacing the key and IV with these values. The one
difference is that, with counter mode, the IV is incremented after each block is encrypted and in thisoperation, the counter is incremented before each block is encrypted. This function implements an
optimized version of the algorithm in that it does the update of the drbgState->seed in place and thenprovidedData is XORed into drbgState->seed to complete the encryption of providedData. This works
because the IV is the last thing that gets encrypted.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 669
April 15, 2019

Trusted Platform Module Library

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

Part 4: Supporting Routines

static BOOLDRBG_Update(
DRBG_STATEDRBG_KEY_SCHEDULE
DRBG_SEED)*drbgState,*keySchedule,*providedData// IN:OUT state to update// IN: the key schedule (optional)// IN: additional data

UINT32
BYTE
DRBG_KEY
DRBG_IV
DRBG_KEY_SCHEDULE

i;*temp = (BYTE *)&drbgState->seed;*key = pDRBG_KEY(&drbgState->seed);*iv = pDRBG_IV(&drbgState->seed);
localKeySchedule;{//
pAssert(drbgState->magic == DRBG_MAGIC);// If an key schedule was not provided, make oneif(keySchedule == NULL){
if(DRBG_ENCRYPT_SETUP((BYTE *)key,
DRBG_KEY_SIZE_BITS, &localKeySchedule) != 0){
LOG_FAILURE(FATAL_ERROR_INTERNAL);
return FALSE;}
keySchedule = &localKeySchedule;}// Encrypt the temp value
EncryptDRBG(temp, sizeof(DRBG_SEED), keySchedule, iv,
drbgState->lastValue);if(providedData != NULL){
BYTE*pP = (BYTE *)providedData;for(i = DRBG_SEED_SIZE_BYTES; i != 0; i--)*temp++ ^= *pP++;}// Since temp points to the input key and IV, we are done and// don't need to copy the resulting 'temp' to drbgState->seed
return TRUE;}

10.2.16.2.12 DRBG_Reseed()
This function is used when reseeding of the DRBG is required. If entropy is provided, it is used in lieu ofusing hardware entropy.
NOTE:

295
296
297
298
299
300
301
302
303

the provided entropy must be the required size.

Return Value

Meaning

TRUE(1)reseed succeeded

FALSE(0)reseed failed, probably due to the entropy generation

BOOL
DRBG_Reseed(
DRBG_STATEDRBG_SEEDDRBG_SEED)*drbgState,*providedEntropy,*additionalData

DRBG_SEED

seed;// IN: the state to update// IN: entropy// IN:{

Page 670
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

Trusted Platform Module LibrarypAssert((drbgState != NULL) && (drbgState->magic == DRBG_MAGIC));if(providedEntropy == NULL){
providedEntropy = &seed;if(!DRBG_GetEntropy(sizeof(DRBG_SEED), (BYTE *)providedEntropy))
return FALSE;}
if(additionalData != NULL){
unsigned inti;// XOR the provided data into the provided entropyfor(i = 0; i < sizeof(DRBG_SEED); i++)((BYTE *)providedEntropy)[i] ^= ((BYTE *)additionalData)[i];}DRBG_Update(drbgState, NULL, providedEntropy);
drbgState->reseedCounter = 1;
return TRUE;}

10.2.16.2.13 DRBG_SelfTest()
This is run when the DRBG is instantiated and at startup

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

Return Value

Meaning

TRUE(1)

test OKFALSE(0)test failed

BOOL
DRBG_SelfTest(
void
)
{
BYTE
DRBG_SEEDUINT32
BYTE
DRBG_STATEbuf[sizeof(DRBG_NistTestVector_Generated)];
seed;
i;
*p;
testState;//pAssert(!IsSelfTest());
SetSelfTest();
SetDrbgTested();// Do an instantiateif(!DRBG_Instantiate(&testState, 0, NULL))
return FALSE;#if DRBG_DEBUG_PRINT
dbgDumpMemBlock(pDRBG_KEY(&testState), DRBG_KEY_SIZE_BYTES,"Key after Instantiate");dbgDumpMemBlock(pDRBG_IV(&testState), DRBG_IV_SIZE_BYTES,"Value after Instantiate");#endifif(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0)
return FALSE;#if DRBG_DEBUG_PRINT
dbgDumpMemBlock(pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES,"Key after 1st Generate");dbgDumpMemBlock(pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,"Value after 1st Generate");Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 671
April 15, 2019

Trusted Platform Module Library
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

Part 4: Supporting Routines#endifif(memcmp(buf, DRBG_NistTestVector_GeneratedInterm, sizeof(buf)) != 0)
return FALSE;
memcpy(seed.bytes, DRBG_NistTestVector_EntropyReseed, sizeof(seed));
DRBG_Reseed(&testState, &seed, NULL);#if DRBG_DEBUG_PRINT
dbgDumpMemBlock((BYTE *)pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES,"Key after 2nd Generate");dbgDumpMemBlock((BYTE *)pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,"Value after 2nd Generate");dbgDumpMemBlock(buf, sizeof(buf), "2nd Generated");#endifif(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0)
return FALSE;
if(memcmp(buf, DRBG_NistTestVector_Generated, sizeof(buf)) != 0)
return FALSE;
ClearSelfTest();DRBG_Uninstantiate(&testState);for(p = (BYTE *)&testState, i = 0; i < sizeof(DRBG_STATE); i++){if(*p++)
return FALSE;}// Simulate hardware failure to make sure that we get an error when// trying to instantiate
SetEntropyBad();if(DRBG_Instantiate(&testState, 0, NULL))
return FALSE;
ClearEntropyBad();return TRUE;}

10.2.16.3 Public Interface
10.2.16.3.1

Description

The functions in this section are the interface to the RNG. These are the functions that are used by
TPM.lib. Other functions are only visible to programs in the LtcCryptoEngine().
10.2.16.3.2

CryptRandomStir()

This function is used to cause a reseed. A DRBG_SEED amount of entropy is collected from the
hardware and then additional data is added.

390
391
392
393
394
395
396
397
398
399
400
401

Error Returns

Meaning

TPM_RC_NO_RESULT

failure of the entropy generator

LIB_EXPORT TPM_RC
CryptRandomStir(UINT16
BYTE)

additionalDataSize,*additionalData{#if !USE_DEBUG_RNG
DRBG_SEED
tmpBuf;
DRBG_SEED
dfResult;//// All reseed with outside data starts with a buffer full of entropy
if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE *)&tmpBuf))

Page 672
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

Trusted Platform Module Library

return TPM_RC_NO_RESULT;DRBG_Reseed(&drbgDefault, &tmpBuf,
DfBuffer(&dfResult, additionalDataSize, additionalData));
drbgDefault.reseedCounter = 1;
return TPM_RC_SUCCESS;#else// If doing debug, use the input data as the initial setting for the RNG state// so that the test can be reset at any time.
// Note: If this is called with a data size of 0 or less, nothing happens. The// presumption is that, in a debug environment, the caller will have specific// values for initialization, so this check is just a simple way to prevent// inadvertent programming errors from screwing things up. This doesn't use an// pAssert() because the non-debug version of this function will accept these// parameters as meaning that there is no additionalData and only hardware// entropy is used.
if((additionalDataSize > 0) && (additionalData != NULL)){
memset(drbgDefault.seed.bytes, 0, sizeof(drbgDefault.seed.bytes));
memcpy(drbgDefault.seed.bytes, additionalData,
MIN(additionalDataSize, sizeof(drbgDefault.seed.bytes)));}drbgDefault.reseedCounter = 1;
return TPM_RC_SUCCESS;#endif}10.2.16.3.3

CryptRandomGenerate()

Generate a randomSize number or random bytes.
431
432
433
434
435
436
437
438
439
440

LIB_EXPORT UINT16
CryptRandomGenerate(
INT32
BYTE
)

randomSize,*buffer{if(randomSize > UINT16_MAX)
randomSize = UINT16_MAX;
return DRBG_Generate((RAND_STATE *)&drbgDefault, buffer, (UINT16)randomSize);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 673
April 15, 2019

Trusted Platform Module Library

10.2.16.3.3.1

Part 4: Supporting Routines

DRBG_InstantiateSeededKdf()

This function is used to instantiate a KDF-based RNG. This is used for derivations. This function always
returns TRUE.
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

LIB_EXPORT BOOLDRBG_InstantiateSeededKdf(
KDF_STATETPM_ALG_ID
TPM_ALG_ID
TPM2B
const TPM2B
TPM2B
UINT32)*state,hashAlg,
kdf,*seed,*label,*context,limit// OUT: buffer to hold the state// IN: hash algorithm// IN: the KDF to use// IN: the seed to use// IN: a label for the generation process.
// IN: the context value// IN: Maximum number of bits from the KDF{
state->magic = KDF_MAGIC;
state->limit = limit;
state->seed = seed;state->hash = hashAlg;
state->kdf = kdf;
state->label = label;state->context = context;
state->digestSize = CryptHashGetDigestSize(hashAlg);
state->counter = 0;state->residual.t.size = 0;
return TRUE;}

Page 674
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.16.3.3.2

Trusted Platform Module Library

DRBG_AdditionalData()

Function to reseed the DRBG with additional entropy. This is normally called before computing theprotection value of a primary key in the Endorsement hierarchy.
464
465
466
467
468
469
470
471
472
473
474
475
476

LIB_EXPORT void
DRBG_AdditionalData(
DRBG_STATE
TPM2B)*drbgState,// IN:OUT state to update*additionalData // IN: value to incorporate{
DRBG_SEED
dfResult;
if(drbgState->magic == DRBG_MAGIC){
DfBuffer(&dfResult, additionalData->size, additionalData->buffer);
DRBG_Reseed(drbgState, &dfResult, NULL);}}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 675
April 15, 2019

Trusted Platform Module Library

10.2.16.3.3.3

Part 4: Supporting Routines

DRBG_InstantiateSeeded()This function is used to instantiate a random number generator from seed values. The nominal use of thisgenerator is to create sequences of pseudo-random numbers from a seed value. This function always
returns TRUE.
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

LIB_EXPORT TPM_RC
DRBG_InstantiateSeeded(
DRBG_STATE
const TPM2B
const TPM2B
const TPM2B
const TPM2B)*drbgState,*seed,*purpose,*name,*additional// IN/OUT: buffer to hold the state// IN: the seed to use// IN: a label for the generation process.
// IN: name of the object// IN: additional data{
DF_STATE
dfState;int
totalInputSize;// DRBG should have been tested, but...
if(!IsDrbgTested() && !DRBG_SelfTest()){
LOG_FAILURE(FATAL_ERROR_SELF_TEST);
return TPM_RC_FAILURE;}// Initialize the DRBG state
memset(drbgState, 0, sizeof(DRBG_STATE));
drbgState->magic = DRBG_MAGIC;// Size all of the values
totalInputSize = (seed != NULL) ? seed->size : 0;
totalInputSize += (purpose != NULL) ? purpose->size : 0;
totalInputSize += (name != NULL) ? name->size : 0;
totalInputSize += (additional != NULL) ? additional->size : 0;// Initialize the derivation
DfStart(&dfState, totalInputSize);// Run all the input strings through the derivation function
if(seed != NULL)
DfUpdate(&dfState, seed->size, seed->buffer);
if(purpose != NULL)
DfUpdate(&dfState, purpose->size, purpose->buffer);
if(name != NULL)
DfUpdate(&dfState, name->size, name->buffer);if(additional != NULL)
DfUpdate(&dfState, additional->size, additional->buffer);// Used the derivation function output as the "entropy" input. This is not// how it is described in SP800-90A but this is the equivalent function
DRBG_Reseed(((DRBG_STATE *)drbgState), DfEnd(&dfState), NULL);
return TPM_RC_SUCCESS;}

Page 676
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.16.3.3.4

Trusted Platform Module Library

CryptRandStartup()This function is called when TPM_Startup is executed. This function always returns TRUE.
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

LIB_EXPORT BOOL
CryptRandStartup(void){#if ! _DRBG_STATE_SAVE// If not saved in NV, re-instantiate on each startup
DRBG_Instantiate(&drbgDefault, 0, NULL);#else// If the running state is saved in NV, NV has to be loaded before it can// be updated
if(go.drbgState.magic == DRBG_MAGIC)DRBG_Reseed(&go.drbgState, NULL, NULL);else
DRBG_Instantiate(&go.drbgState, 0, NULL);#endifreturn TRUE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 677
April 15, 2019

Trusted Platform Module Library

10.2.16.3.3.5

Part 4: Supporting Routines

CryptRandInit()

This function is called when _TPM_Init() is being processed.

541
542
543
544
545
546
547
548
549
550

Return Value

Meaning

TRUE(1)success

FALSE(0)failureLIB_EXPORT BOOL
CryptRandInit(void){#if !USE_DEBUG_RNG_plat__GetEntropy(NULL, 0);#endifreturn DRBG_SelfTest();}10.2.16.3.4

DRBG_Generate()

This function generates a random sequence according SP800-90A. If random is not NULL, thenrandomSize bytes of random values are generated. If random is NULL or randomSize is zero, then thefunction returns TRUE without generating any bits or updating the reseed counter. This function returns 0
if a reseed is required. Otherwise, it returns the number of bytes produced which could be less than thenumber requested if the request is too large.
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

LIB_EXPORT UINT16
DRBG_Generate(
RAND_STATEBYTE
UINT16)*state,*random,
randomSize// OUT: buffer to receive the random values// IN: the number of bytes to generate{if(state == NULL)
state = (RAND_STATE *)&drbgDefault;// If the caller used a KDF state, generate a sequence from the KDF not to// exceed the limit.
if(state->kdf.magic == KDF_MAGIC){KDF_STATE*kdf = (KDF_STATE *)state;
UINT32
counter = (UINT32)kdf->counter;
INT32
bytesLeft = randomSize;if(random == NULL)
return 0;// If the number of bytes to be returned would put the generator// over the limit, then return 0if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit)
return 0;// Process partial and full blocks until all requested bytes provided
while(bytesLeft > 0){// If there is any residual data in the buffer, copy it to the output// bufferif(kdf->residual.t.size > 0)
{
INT32
size;
//

Page 678
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649

Trusted Platform Module Library// Don't use more of the residual than will fit or more than are// available
size = MIN(kdf->residual.t.size, bytesLeft);// Copy some or all of the residual to the output. The residual is// at the end of the buffer. The residual might be a full buffer.
MemoryCopy(random,&kdf->residual.t.buffer[kdf->digestSize - kdf->residual.t.size], size);// Advance the buffer pointerrandom += size;// Reduce the number of bytes left to get
bytesLeft -= size;// And reduce the residual size appropriately
kdf->residual.t.size -= (UINT16)size;}
else{
UINT16blocks = (UINT16)(bytesLeft / kdf->digestSize);//// Get the number of required full blocks
if(blocks > 0){
UINT16size = blocks * kdf->digestSize;// Get some number of full blocks and put them in the return buffer
CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL,
kdf->limit, random, &counter, blocks);// reduce the size remaining to be moved and advance the pointerbytesLeft -= size;
random += size;}else{// Fill the residual buffer with a full block and then loop to// top to get part of it copied to the output.
kdf->residual.t.size = CryptKDFa(kdf->hash, kdf->seed,kdf->label, kdf->context, NULL,
kdf->limit,
kdf->residual.t.buffer,&counter, 1);}}}
kdf->counter = counter;
return randomSize;}else if(state->drbg.magic == DRBG_MAGIC){DRBG_STATE*drbgState = (DRBG_STATE *)state;
DRBG_KEY_SCHEDULE
keySchedule;
DRBG_SEED*seed = &drbgState->seed;if(drbgState->reseedCounter >= CTR_DRBG_MAX_REQUESTS_PER_RESEED){
if(drbgState == &drbgDefault){
DRBG_Reseed(drbgState, NULL, NULL);
if(IsEntropyBad() && !IsSelfTest())
return 0;}
else{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 679
April 15, 2019

Trusted Platform Module Library
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684

Part 4: Supporting Routines// If this is a PRNG then the only way to get// here is if the SW has run away.
LOG_FAILURE(FATAL_ERROR_INTERNAL);
return 0;}}// if the allowed number of bytes in a request is larger than the// less than the number of bytes that can be requested, then check#if UINT16_MAX >= CTR_DRBG_MAX_BYTES_PER_REQUEST
if(randomSize > CTR_DRBG_MAX_BYTES_PER_REQUEST)
randomSize = CTR_DRBG_MAX_BYTES_PER_REQUEST;#endif// Create encryption scheduleif(DRBG_ENCRYPT_SETUP((BYTE *)pDRBG_KEY(seed),
DRBG_KEY_SIZE_BITS, &keySchedule) != 0){
LOG_FAILURE(FATAL_ERROR_INTERNAL);
return 0;}// Generate the random data
EncryptDRBG(random, randomSize, &keySchedule, pDRBG_IV(seed),
drbgState->lastValue);// Do a key update
DRBG_Update(drbgState, &keySchedule, NULL);// Increment the reseed counter
drbgState->reseedCounter += 1;}else{
LOG_FAILURE(FATAL_ERROR_INTERNAL);
return FALSE;}
return randomSize;}

10.2.16.3.5

DRBG_Instantiate()

This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1]. This is called when a the TPM
DRBG is to be instantiated. This is called to instantiate a DRBG used by the TPM for normal operations.

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701

Return Value

Meaning

TRUE(1)

instantiation succeeded

FALSE(0)instantiation failed

LIB_EXPORT BOOLDRBG_Instantiate(
DRBG_STATEUINT16
BYTE)*drbgState,
pSize,*personalization

DRBG_SEEDDRBG_SEED

seed;
dfResult;// OUT: the instantiated value// IN: Size of personalization string// IN: The personalization string{//
pAssert((pSize == 0) || (pSize <= sizeof(seed)) || (personalization != NULL));// If the DRBG has not been tested, test when doing an instantiation. Since// Instantiation is called during self test, make sure we don't get stuck in a// loop.
if(!IsDrbgTested() && !IsSelfTest() && !DRBG_SelfTest())
return FALSE;// If doing a self test, DRBG_GetEntropy will return the NIST

Page 680
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
702
703
704
705
706
707
708
709
710
711
712
713
714
715

Trusted Platform Module Library// test vector value.
if(!DRBG_GetEntropy(sizeof(seed), (BYTE *)&seed))
return FALSE;// set everything to zeromemset(drbgState, 0, sizeof(DRBG_STATE));
drbgState->magic = DRBG_MAGIC;// Steps 1, 2, 3, 6, 7 of SP 800-90A 10.2.1.3.1 are exactly what// reseeding does. So, do a reduction on the personalization value (if any)// and do a reseed.
DRBG_Reseed(drbgState, &seed, DfBuffer(&dfResult, pSize, personalization));return TRUE;}

10.2.16.3.6

DRBG_Uninstantiate()

This is Uninstantiate_function() from [SP 800-90A 9.4].

716
717
718
719
720
721
722
723
724
725

Error Returns

Meaning

TPM_RC_VALUE

not a valid state

LIB_EXPORT TPM_RC
DRBG_Uninstantiate(
DRBG_STATE)*drbgState// IN/OUT: working state to erase{
if((drbgState == NULL) || (drbgState->magic != DRBG_MAGIC))
return TPM_RC_VALUE;
memset(drbgState, 0, sizeof(DRBG_STATE));
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 681
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.17 CryptRsa.c
10.2.17.1 Introduction
This file contains implementation of cryptographic primitives for RSA. Vendors may replace theimplementation in this file with their own library functions.
10.2.17.2 Includes
Need this define to get the private defines for this function
1
2
3#define CRYPT_RSA_C#include "Tpm.h"#if
ALG_RSA

10.2.17.3 Obligatory Initialization Functions
10.2.17.3.1

CryptRsaInit()

Function called at _TPM_Init().
4
5
6
7
8
9
10

BOOL
CryptRsaInit(
void){
return TRUE;}

10.2.17.3.2

CryptRsaStartup()

Function called at TPM2_Startup()
11
12
13
14
15
16
17

BOOL
CryptRsaStartup(
void){
return TRUE;}

10.2.17.4 Internal Functions
10.2.17.4.1

RsaInitializeExponent()

This function initializes the bignum data structure that holds the private exponent. This function returns
the pointer to the private exponent value so that it can be used in an initializer for a data declaration.
18
19
20
21
22
23
24
25

static privateExponent *RsaInitializeExponent(
privateExponent)*Z{
bigNumint*bn = (bigNum *)&Z->P;
i;//

Page 682
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
26
27
28
29
30
31
32

Trusted Platform Module Libraryfor(i = 0; i < 5; i++){bn[i] = (bigNum)&Z->entries[i];BnInit(bn[i], BYTES_TO_CRYPT_WORDS(sizeof(Z->entries[0].d)));}return Z;}

10.2.17.4.2

MakePgreaterThanQ()

This function swaps the pointers for P and Q if Q happens to be larger than Q.
33
34
35
36
37
38
39
40
41
42
43
44

static void
MakePgreaterThanQ(privateExponent*Z){
if(BnUnsignedCmp(Z->P, Z->Q) < 0){
bigNumbnT = Z->P;
Z->P = Z->Q;
Z->Q = bnT;}}

10.2.17.4.3

PackExponent()

This function takes the bignum private exponent and converts it into TPM2B form. In this form, the size
field contains the overall size of the packed data. The buffer contains 5, equal sized values in P, Q, dP,
dQ, qInv order. For example, if a key has a 2Kb public key, then the packed private key will contain 5,
1Kb values. This form makes it relatively easy to load and save the values without changing the normal
unmarshaling to do anything more than allow a larger TPM2B for the private key. Also, when exporting
the value, all that is needed is to change the size field of the private key in order to save just the P value.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

Return Value

Meaning

TRUE(1)success

FALSE(0)failure // The data is too big to fit

static BOOL
PackExponent(
TPM2B_PRIVATE_KEY_RSA
privateExponent*packed,*Z

int
UINT16
UINT16i;primeSize = (UINT16)BITS_TO_BYTES(BnMsb(Z->P));pS = primeSize;){//
pAssert((primeSize * 5) <= sizeof(packed->t.buffer));packed->t.size = (primeSize * 5) + RSA_prime_flag;for(i = 0; i < 5; i++)if(!BnToBytes((bigNum)&Z->entries[i], &packed->t.buffer[primeSize * i], &pS))
return FALSE;
if(pS != primeSize)
return FALSE;
return TRUE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 683
April 15, 2019

Trusted Platform Module Library

10.2.17.4.4

Part 4: Supporting Routines

UnpackExponent()

This function unpacks the private exponent from its TPM2B form into its bignum form.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

Return Value

Meaning

TRUE(1)success

FALSE(0)TPM2B is not the correct size

static BOOL
UnpackExponent(
TPM2B_PRIVATE_KEY_RSA
privateExponent

*b,
*Z

)
{
UINT16int
bigNumprimeSize = b->t.size & ~RSA_prime_flag;i;*bn = &Z->P;//
VERIFY(b->t.size & RSA_prime_flag);
RsaInitializeExponent(Z);VERIFY((primeSize % 5) == 0);primeSize /= 5;for(i = 0; i < 5; i++)VERIFY(BnFromBytes(bn[i], &b->t.buffer[primeSize * i], primeSize)!= NULL);
MakePgreaterThanQ(Z);return TRUE;
Error:
return FALSE;}

10.2.17.4.5

ComputePrivateExponent()

This function computes the private exponent from the primes.

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Return Value

Meaning

TRUE(1)success

FALSE(0)failurestatic BOOL
ComputePrivateExponent(
bigNumprivateExponent

pubExp,*Z// IN: the public exponent// IN/OUT: on input, has primes P and Q. On//
output, has P, Q, dP, dQ, and pInv

)
{
BOOL
BOOL
BN_PRIME(pT);

pOK;
qOK;

//
// make p the larger value so that m2 is always less than p
MakePgreaterThanQ(Z);//dP = (1/e) mod (p-1)
pOK = BnSubWord(pT, Z->P, 1);
pOK = pOK && BnModInverse(Z->dP, pubExp, pT);//dQ = (1/e) mod (q-1)
qOK = BnSubWord(pT, Z->Q, 1);
qOK = qOK && BnModInverse(Z->dQ, pubExp, pT);// qInv = (1/q) mod p

Page 684
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
107
108
109
110
111
112
113
114

Trusted Platform Module Libraryif(pOK && qOK)
pOK = qOK = BnModInverse(Z->qInv, Z->Q, Z->P);if(!pOK)
BnSetWord(Z->P, 0);if(!qOK)
BnSetWord(Z->Q, 0);
return pOK && qOK;}

10.2.17.4.6

RsaPrivateKeyOp()

This function is called to do the exponentiation with the private key. Compile options allow use of thesimple (but slow) private exponent, or the more complex but faster CRT method.

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

Return Value

Meaning

TRUE(1)success

FALSE(0)failurestatic BOOL
RsaPrivateKeyOp(
bigNumprivateExponent)

inOut, // IN/OUT: number to be exponentiated*Z{
BN_RSA(M1);
BN_RSA(M2);
BN_RSA(M);
BN_RSA(H);//
MakePgreaterThanQ(Z);// m1 = cdP mod p
VERIFY(BnModExp(M1, inOut, Z->dP, Z->P));// m2 = cdQ mod q
VERIFY(BnModExp(M2, inOut, Z->dQ, Z->Q));// h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P// so m2 < P
VERIFY(BnSub(H, Z->P, M2));
VERIFY(BnAdd(H, H, M1));
VERIFY(BnModMult(H, H, Z->qInv, Z->P));// m = m2 + h * q
VERIFY(BnMult(M, H, Z->Q));VERIFY(BnAdd(inOut, M2, M));
return TRUE;
Error:
return FALSE;}

10.2.17.4.7

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).

143
144
145
146

Error Returns

Meaning

TPM_RC_VALUE

number to exponentiate is larger than the modulus

static TPM_RC
RSAEP(TPM2B*dInOut,

Family “2.0”Level 00 Revision 01.55// IN: size of the encrypted block and the size of//the encrypted value. It must be the size of

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 685
April 15, 2019

Trusted Platform Module Library
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

OBJECT)

Part 4: Supporting Routines//
the modulus.
// OUT: the encrypted data. Will receive the//decrypted value// IN: the key to use*key{
TPM2B_TYPE(4BYTES, 4);
TPM2B_4BYTES
e2B;
UINT32e = key->publicArea.parameters.rsaDetail.exponent;//
if(e == 0)e = RSA_DEFAULT_PUBLIC_EXPONENT;UINT32_TO_BYTE_ARRAY(e, e2B.t.buffer);
e2B.t.size = 4;
return ModExpB(dInOut->size, dInOut->buffer, dInOut->size, dInOut->buffer,
e2B.t.size, e2B.t.buffer, key->publicArea.unique.rsa.t.size,key->publicArea.unique.rsa.t.buffer);}

10.2.17.4.8

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.
This function also checks the size of the private key. If the size indicates that only a prime value ispresent, the key is converted to being a private exponent.

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

Error Returns

Meaning

TPM_RC_SIZE

the value to decrypt is larger than the modulus

static TPM_RC
RSADP(TPM2B
OBJECT)*inOut,*key// IN/OUT: the value to encrypt// IN: the key{
BN_RSA_INITIALIZED(bnM, inOut);
NEW_PRIVATE_EXPONENT(Z);
if(UnsignedCompareB(inOut->size, inOut->buffer,
key->publicArea.unique.rsa.t.size,key->publicArea.unique.rsa.t.buffer) >= 0)
return TPM_RC_SIZE;// private key operation requires that private exponent be loaded// During self-test, this might not be the case so load it up if it hasn't// already done// been doneif((key->sensitive.sensitive.rsa.t.size & RSA_prime_flag) == 0){if(CryptRsaLoadPrivateExponent(&key->publicArea, &key->sensitive)!= TPM_RC_SUCCESS)
return TPM_RC_BINDING;}VERIFY(UnpackExponent(&key->sensitive.sensitive.rsa, Z));VERIFY(RsaPrivateKeyOp(bnM, Z));VERIFY(BnTo2B(bnM, inOut, inOut->size));
return TPM_RC_SUCCESS;
Error:
return TPM_RC_FAILURE;}

Page 686
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.17.4.9

Trusted Platform Module Library

OaepEncode()This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must
equal the size of the modulus

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

Error Returns

Meaning

TPM_RC_VALUE

hashAlg is not valid or message size is too large

static TPM_RC
OaepEncode(
TPM2B*padded,
TPM_ALG_ID
hashAlg,
const TPM2B *label,
TPM2B*message,
RAND_STATE *rand)// OUT: the pad data// IN: algorithm to use for padding// IN: null-terminated string (may be NULL)// IN: the message being padded// IN: the random number generator to use

{
INT32
INT32
INT32
BYTE
BYTE
INT32
BYTE
BYTE
BYTE
TPM_RC

padLen;dbSize;i;
mySeed[MAX_DIGEST_SIZE];*seed = mySeed;hLen = CryptHashGetDigestSize(hashAlg);mask[MAX_RSA_KEY_BYTES];
*pp;
*pm;
retVal = TPM_RC_SUCCESS;

pAssert(padded != NULL && message != NULL);// A value of zero is not allowed because the KDF can't produce a result// if the digest size is zero.
if(hLen <= 0)
return TPM_RC_VALUE;// Basic size checks// make sure digest isn't too big for key size
if(padded->size < (2 * hLen) + 2)
ERROR_RETURN(TPM_RC_HASH);// and that message will fit messageSize <= k - 2hLen - 2
if(message->size > (padded->size - (2 * hLen) - 2))
ERROR_RETURN(TPM_RC_VALUE);// Hash L even if it is null// Offset into padded leaving room for masked seed and byte of zeropp = &padded->buffer[hLen + 1];
if(CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer,
hLen, pp) != hLen)
ERROR_RETURN(TPM_RC_FAILURE);// concatenate PS of k mLen 2hLen 2
padLen = padded->size - message->size - (2 * hLen) - 2;
MemorySet(&pp[hLen], 0, padLen);pp[hLen + padLen] = 0x01;
padLen += 1;
memcpy(&pp[hLen + padLen], message->buffer, message->size);// The total size of db = hLen + pad + mSize;
dbSize = hLen + padLen + message->size;// If testing, then use the provided seed. Otherwise, use values// from the RNG
CryptRandomGenerate(hLen, mySeed);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 687
April 15, 2019

Trusted Platform Module Library
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

Part 4: Supporting Routines

DRBG_Generate(rand, mySeed, (UINT16)hLen);if(g_inFailureMode)
ERROR_RETURN(TPM_RC_FAILURE);// mask = MGF1 (seed, nSize hLen 1)
CryptMGF1(dbSize, mask, hashAlg, hLen, seed);// Create the masked db
pm = mask;for(i = dbSize; i > 0; i--)*pp++ ^= *pm++;
pp = &padded->buffer[hLen + 1];// Run the masked data through MGF1
if(CryptMGF1(hLen, &padded->buffer[1], hashAlg, dbSize, pp) != (unsigned)hLen)
ERROR_RETURN(TPM_RC_VALUE);// Now XOR the seed to create masked seedpp = &padded->buffer[1];pm = seed;
for(i = hLen; i > 0; i--)*pp++ ^= *pm++;// Set the first byte to zero
padded->buffer[0] = 0x00;
Exit:
return retVal;}

10.2.17.4.10 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 TPM_RC_VALUE.
The dSize parameter is used as an input to indicate the size available in the buffer. If insufficient space isavailable, the size is not changed and the return code is TPM_RC_VALUE.

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

Error Returns

Meaning

TPM_RC_VALUE

the value to decode was larger than the modulus, or the padding iswrong or the buffer to receive the results is too small

static TPM_RC
OaepDecode(
TPM2B
TPM_ALG_ID
const TPM2B
TPM2B)*dataOut,
hashAlg,*label,*padded// OUT: the recovered data// IN: algorithm to use for padding// IN: null-terminated string (may be NULL)// IN: the padded data{
UINT32BYTE
UINT32i;seedMask[MAX_DIGEST_SIZE];hLen = CryptHashGetDigestSize(hashAlg);

BYTE
BYTE
BYTE
TPM_RCmask[MAX_RSA_KEY_BYTES];
*pp;
*pm;
retVal = TPM_RC_SUCCESS;// Strange size (anything smaller can't be an OAEP padded block)// Also check for no leading 0
if((padded->size < (unsigned)((2 * hLen) + 2)) || (padded->buffer[0] != 0))
ERROR_RETURN(TPM_RC_VALUE);// Use the hash size to determine what to put through MGF1 in order// to recover the seedMask
CryptMGF1(hLen, seedMask, hashAlg, padded->size - hLen - 1,
&padded->buffer[hLen + 1]);Page 688
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348

Trusted Platform Module Library// Recover the seed into seedMask
pAssert(hLen <= sizeof(seedMask));
pp = &padded->buffer[1];pm = seedMask;
for(i = hLen; i > 0; i--)*pm++ ^= *pp++;// Use the seed to generate the data mask
CryptMGF1(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask);// Use the mask generated from seed to recover the padded data
pp = &padded->buffer[hLen + 1];
pm = mask;for(i = (padded->size - hLen - 1); i > 0; i--)*pm++ ^= *pp++;// Make sure that the recovered data has the hash of the label// Put trial value in the seed maskif((CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer,
hLen, seedMask)) != hLen)
FAIL(FATAL_ERROR_INTERNAL);
if(memcmp(seedMask, mask, hLen) != 0)
ERROR_RETURN(TPM_RC_VALUE);// find the start of the datapm = &mask[hLen];for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--){if(*pm++ != 0)
break;}// If we ran out of data or didn't end with 0x01, then return an error
if(i == 0 || pm[-1] != 0x01)
ERROR_RETURN(TPM_RC_VALUE);// pm should be pointing at the first part of the data// and i is one greater than the number of bytes to movei--;
if(i > dataOut->size)// Special exit to preserve the size of the output buffer
return TPM_RC_VALUE;
memcpy(dataOut->buffer, pm, i);dataOut->size = (UINT16)i;Exit:
if(retVal != TPM_RC_SUCCESS)
dataOut->size = 0;
return retVal;}

10.2.17.4.11 PKCS1v1_5Encode()This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1

349
350
351
352
353
354

Error Returns

Meaning

TPM_RC_VALUE

message size is too large

static TPM_RC
RSAES_PKCS1v1_5Encode(
TPM2B
TPM2B
RAND_STATE)*padded,*message,*rand

Family “2.0”Level 00 Revision 01.55// OUT: the pad data// IN: the message being padded

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 689
April 15, 2019

Trusted Platform Module Library
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

Part 4: Supporting Routines{UINT32

ps = padded->size - message->size - 3;//if(message->size > padded->size - 11)
return TPM_RC_VALUE;// move the message to the end of the buffer
memcpy(&padded->buffer[padded->size - message->size], message->buffer,message->size);// Set the first byte to 0x00 and the second to 0x02
padded->buffer[0] = 0;
padded->buffer[1] = 2;// Fill with random bytes
DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps);if(g_inFailureMode)return TPM_RC_FAILURE;// Set the delimiter for the random field to 0
padded->buffer[2 + ps] = 0;// Now, the only messy part. Make sure that all the 'ps' bytes are non-zero// In this implementation, use the value of the current index
for(ps++; ps > 1; ps--){if(padded->buffer[ps] == 0)
padded->buffer[ps] = 0x55; // In the < 0.5% of the cases that the// random value is 0, just pick a value to// put into the spot.
}
return TPM_RC_SUCCESS;}

10.2.17.4.12 RSAES_Decode()This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

Error Returns

Meaning

TPM_RC_FAIL

decoding error or results would no fit into provided buffer

static TPM_RC
RSAES_Decode(
TPM2B
TPM2B
)

*message,*codedBOOL
UINT16

fail = FALSE;
pSize;// OUT: the recovered message// IN: the encoded message{

fail = (coded->size < 11);
fail = (coded->buffer[0] != 0x00) | fail;fail = (coded->buffer[1] != 0x02) | fail;for(pSize = 2; pSize < coded->size; pSize++){if(coded->buffer[pSize] == 0)
break;}
pSize++;// Make sure that pSize has not gone over the end and that there are at least 8// bytes of pad data.
fail = (pSize > coded->size) | fail;fail = ((pSize - 2) < 8) | fail;if((message->size < (UINT16)(coded->size - pSize)) || fail)Page 690
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
410
411
412
413
414

Trusted Platform Module Library

return TPM_RC_VALUE;
message->size = coded->size - pSize;
memcpy(message->buffer, &coded->buffer[pSize], coded->size - pSize);
return TPM_RC_SUCCESS;}

10.2.17.4.13 CryptRsaPssSaltSize()This function computes the salt size used in PSS. It is broken out so that the X509 code can get the samevalue that is used by the encoding function in this module.
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

INT16
CryptRsaPssSaltSize(
INT16
INT16

hashSize,
outSize

INT16

saltSize;){//// (Mask Length) = (outSize - hashSize - 1);// Max saltSize is (Mask Length) - 1
saltSize = (outSize - hashSize - 1) - 1;// Use the maximum salt size allowed by FIPS 186-4
if(saltSize > hashSize)
saltSize = hashSize;else if(saltSize < 0)saltSize = 0;
return saltSize;}

10.2.17.4.14 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.
Returns TPM_RC_SUCCESS or goes into failure mode.
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458

static TPM_RC
PssEncode(
TPM2B
TPM_ALG_ID
TPM2B
RAND_STATE)*out,
hashAlg,*digest,*rand// OUT: the encoded buffer// IN: hash algorithm for the encoding// IN: the digest// IN: random number source{
UINT32BYTE
UINT16BYTE
BYTE
UINT16
HASH_STATE

hLen = CryptHashGetDigestSize(hashAlg);salt[MAX_RSA_KEY_BYTES - 1];
saltSize;*ps = salt;*pOut;mLen;
hashState;// These are fatal errors indicating bad TPM firmware
pAssert(out != NULL && hLen > 0 && digest != NULL);// Get the size of the mask
mLen = (UINT16)(out->size - hLen - 1);// Set the salt size
saltSize = CryptRsaPssSaltSize((INT16)hLen, (INT16)out->size);//using eOut for scratch space

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 691
April 15, 2019

Trusted Platform Module Library
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496

Part 4: Supporting Routines// Set the first 8 bytes to zero
pOut = out->buffer;memset(pOut, 0, 8);// Get set the salt
DRBG_Generate(rand, salt, saltSize);if(g_inFailureMode)return TPM_RC_FAILURE;// Create the hash of the pad || input hash || salt
CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate(&hashState, 8, pOut);
CryptDigestUpdate2B(&hashState, digest);
CryptDigestUpdate(&hashState, saltSize, salt);
CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]);// Create a maskif(CryptMGF1(mLen, pOut, hashAlg, hLen, &pOut[mLen]) != mLen)
FAIL(FATAL_ERROR_INTERNAL);// Since this implementation uses key sizes that are all even multiples of// 8, just need to make sure that the most significant bit is CLEAR*pOut &= 0x7f;// Before we mess up the pOut value, set the last byte to 0xbc
pOut[out->size - 1] = 0xbc;// XOR a byte of 0x01 at the position just before where the salt will be XOR'ed
pOut = &pOut[mLen - saltSize - 1];*pOut++ ^= 0x01;// XOR the salt data into the bufferfor(; saltSize > 0; saltSize--)*pOut++ ^= *ps++;// and we are done
return TPM_RC_SUCCESS;}

10.2.17.4.15 PssDecode()This function checks that the PSS encoded block was built from the provided digest. If the check is
successful, TPM_RC_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 ofvalues. Those assumptions are enforce by this implementation. This implementation does allow for avariable size salt value to have been used by the creator of the signature.

497
498
499
500
501
502
503
504
505

Error Returns

Meaning

TPM_RC_SCHEME

hashAlg is not a supported hash algorithm

TPM_RC_VALUE

decode operation failed

static TPM_RC
PssDecode(
TPM_ALG_ID
TPM2B
TPM2B
)

hashAlg,
*dIn,
*eIn

// IN: hash algorithm to use for the encoding// In: the digest to compare// IN: the encoded data{
UINT32BYTE

Page 692
April 15, 2019

hLen = CryptHashGetDigestSize(hashAlg);mask[MAX_RSA_KEY_BYTES];TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

BYTE
BYTE
BYTE
UINT32
UINT32BYTE
TPM_RC
HASH_STATE

Trusted Platform Module Library*pm = mask;*pe;
pad[8] = {0};
i;
mLen;
fail;
retVal = TPM_RC_SUCCESS;
hashState;// These errors are indicative of failures due to programmer error
pAssert(dIn != NULL && eIn != NULL);
pe = eIn->buffer;// check the hash scheme
if(hLen == 0)
ERROR_RETURN(TPM_RC_SCHEME);// most significant bit must be zero
fail = pe[0] & 0x80;// last byte must be 0xbc
fail |= pe[eIn->size - 1] ^ 0xbc;// Use the hLen bytes at the end of the buffer to generate a mask// Doesn't start at the end which is a flag byte
mLen = eIn->size - hLen - 1;
CryptMGF1(mLen, mask, hashAlg, hLen, &pe[mLen]);// Clear the MSO of the mask to make it consistent with the encoding.
mask[0] &= 0x7F;
pAssert(mLen <= sizeof(mask));// XOR the data into the mask to recover the salt. This sequence// advances eIn so that it will end up pointing to the seed data// which is the hash of the signature datafor(i = mLen; i > 0; i--)*pm++ ^= *pe++;// Find the first byte of 0x01 after a string of all 0x00
for(pm = mask, i = mLen; i > 0; i--){if(*pm == 0x01)
break;
else
fail |= *pm++;}// i should not be zero
fail |= (i == 0);// if we have failed, will continue using the entire mask as the salt value so// that the timing attacks will not disclose anything (I don't think that this// is a problem for TPM applications but, usually, we don't fail so this// doesn't cost anything).
if(fail){
i = mLen;pm = mask;
}
else
{
pm++;
i--;
}
// i contains the salt size and pm points to the salt. Going to use the input// hash and the seed to recreate the hash in the lower portion of eIn.
CryptHashStart(&hashState, hashAlg);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 693
April 15, 2019

Trusted Platform Module Library
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

Part 4: Supporting Routines// add the pad of 8 zeros
CryptDigestUpdate(&hashState, 8, pad);// add the provided digest value
CryptDigestUpdate(&hashState, dIn->size, dIn->buffer);// and the salt
CryptDigestUpdate(&hashState, i, pm);// get the result
fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen);// Compare all bytes
for(pm = mask; hLen > 0; hLen--)// don't use fail = because that could skip the increment and compare// operations after the first failure and that gives away timing// information.
fail |= *pm++ ^ *pe++;retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS;
Exit:
return retVal;}

10.2.17.4.16 MakeDerTag()
Construct the DER value that is used in RSASSA

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

Return Value

Meaning>0

size of value<= 0

no hash exists

INT16
MakeDerTag(
TPM_ALG_ID
INT16
BYTE
)
{
//
//
//
//
//
//

hashAlg,
sizeOfBuffer,*buffer

0x30, 0x31,// SEQUENCE (2 elements) 1st
0x30, 0x0D,// SEQUENCE (2 elements)
0x06, 0x09,// HASH OID
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00, // NULL
0x04, 0x20 // OCTET STRING
HASH_DEF*info = CryptGetHashDef(hashAlg);
INT16
oidSize;// If no OID, can't do encode
VERIFY(info != NULL);
oidSize = 2 + (info->OID)[1];// make sure this fits in the buffer
VERIFY(sizeOfBuffer >= (oidSize + 8));*buffer++ = 0x30; // 1st SEQUENCE// Size of the 1st SEQUENCE is 6 bytes + size of the hash OID + size of the// digest size
*buffer++ = (BYTE)(6 + oidSize + info->digestSize);//*buffer++ = 0x30; // 2nd SEQUENCE// size is 4 bytes of overhead plus the side of the OID*buffer++ = (BYTE)(2 + oidSize);
MemoryCopy(buffer, info->OID, oidSize);buffer += oidSize;

Page 694
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
625
626
627
628
629
630
631
632
633
634

*buffer++ = 0x05;*buffer++ = 0x00;

Trusted Platform Module Library// Add a NULL

*buffer++ = 0x04;*buffer++ = (BYTE)(info->digestSize);
return oidSize + 8;
Error:
return 0;}

10.2.17.4.17 RSASSA_Encode()
Encode a message using PKCS1v1.5 method.

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676

Error Returns

Meaning

TPM_RC_SCHEME

hashAlg is not a supported hash algorithm

TPM_RC_SIZE

eOutSize is not large enough

TPM_RC_VALUE

hInSize does not match the digest size of hashAlg

static TPM_RC
RSASSA_Encode(
TPM2B*pOut,TPM_ALG_ID
TPM2B)

hashAlg,*hIn// IN:OUT on in, the size of the public key//
on out, the encoded area// IN: hash algorithm for PKCS1v1_5// IN: digest value to encode

{
BYTE
BYTE
INT32
BYTE
INT32
TPM_RCDER[20];*der = DER;
derSize = MakeDerTag(hashAlg, sizeof(DER), DER);*eOut;
fillSize;
retVal = TPM_RC_SUCCESS;// Can't use this scheme if the algorithm doesn't have a DER string defined.
if(derSize == 0)
ERROR_RETURN(TPM_RC_SCHEME);// If the digest size of 'hashAl' doesn't match the input digest size, then// the DER will misidentify the digest so return an error
if(CryptHashGetDigestSize(hashAlg) != hIn->size)
ERROR_RETURN(TPM_RC_VALUE);
fillSize = pOut->size - derSize - hIn->size - 3;
eOut = pOut->buffer;// Make sure that this combination will fit in the provided space
if(fillSize < 8)
ERROR_RETURN(TPM_RC_SIZE);// Start filling*eOut++ = 0; // initial byte of zero
*eOut++ = 1; // byte of 0x01
for(; fillSize > 0; fillSize--)*eOut++ = 0xff; // bunch of 0xff
*eOut++ = 0; // another 0for(; derSize > 0; derSize--)*eOut++ = *der++;// copy the DER
der = hIn->buffer;for(fillSize = hIn->size; fillSize > 0; fillSize--)*eOut++ = *der++;// copy the hash
Exit:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 695
April 15, 2019

Trusted Platform Module Library
677
678

Part 4: Supporting Routines

return retVal;}

10.2.17.4.18 RSASSA_Decode()This function performs the RSASSA decoding of a signature.

679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727

Error Returns

Meaning

TPM_RC_VALUE

decode unsuccessful

TPM_RC_SCHEME

haslAlg is not supported

static TPM_RC
RSASSA_Decode(
TPM_ALG_ID
TPM2B
TPM2B
)

hashAlg,
*hIn,
*eIn

// IN: hash algorithm to use for the encoding// In: the digest to compare// IN: the encoded data

BYTE
BYTE
BYTE
INT32
BYTE
INT32
INT32
TPM_RCBYTE
UINT16fail;DER[20];*der = DER;
derSize = MakeDerTag(hashAlg, sizeof(DER), DER);*pe;hashSize = CryptHashGetDigestSize(hashAlg);
fillSize;
retVal;*digest;digestSize;{

pAssert(hIn != NULL && eIn != NULL);
pe = eIn->buffer;// Can't use this scheme if the algorithm doesn't have a DER string// defined or if the provided hash isn't the right size
if(derSize == 0 || (unsigned)hashSize != hIn->size)
ERROR_RETURN(TPM_RC_SCHEME);// Make sure that this combination will fit in the provided space// Since no data movement takes place, can just walk though this// and accept nearly random values. This can only be called from// CryptValidateSignature() so eInSize is known to be in range.
fillSize = eIn->size - derSize - hashSize - 3;// Start checking (fail will become non-zero if any of the bytes do not have// the expected value.
fail = *pe++;// initial byte of zero
fail |= *pe++ ^ 1;// byte of 0x01
for(; fillSize > 0; fillSize--)fail |= *pe++ ^ 0xff;// bunch of 0xff
fail |= *pe++;// another 0for(; derSize > 0; derSize--)fail |= *pe++ ^ *der++;// match the DER
digestSize = hIn->size;
digest = hIn->buffer;for(; digestSize > 0; digestSize--)fail |= *pe++ ^ *digest++; // match the hashretVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS;
Exit:
return retVal;}

Page 696
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.17.5 Externally Accessible Functions
10.2.17.5.1

CryptRsaSelectScheme()

This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select ascheme 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
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.
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

TPMT_RSA_DECRYPT*
CryptRsaSelectScheme(
TPMI_DH_OBJECT
TPMT_RSA_DECRYPT)

rsaHandle,*schemeOBJECT
TPMT_ASYM_SCHEME
TPMT_RSA_DECRYPT*rsaObject;*keyScheme;*retVal = NULL;// IN: handle of an RSA key// IN: a sign or decrypt scheme{// Get sign object pointerrsaObject = HandleToObject(rsaHandle);
keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme;// if the default scheme of the object is TPM_ALG_NULL, then select the// input scheme
if(keyScheme->scheme == TPM_ALG_NULL){
retVal = scheme;}// if the object scheme is not TPM_ALG_NULL and the input scheme is// TPM_ALG_NULL, then select the default scheme of the object.
else if(scheme->scheme == TPM_ALG_NULL){// if input scheme is NULL
retVal = (TPMT_RSA_DECRYPT *)keyScheme;}// get here if both the object scheme and the input scheme are// not TPM_ALG_NULL. Need to insure that they are the same.
// IMPLEMENTATION NOTE: This could cause problems if future versions have// schemes that have more values than just a hash algorithm. A new function// (IsSchemeSame()) might be needed then.
else if(keyScheme->scheme == scheme->scheme&& keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg){
retVal = scheme;}// two different, incompatible schemes specified will return NULL
return retVal;}

10.2.17.5.2

CryptRsaLoadPrivateExponent()

This function is called to generate the private exponent of an RSA key.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 697
April 15, 2019

Trusted Platform Module Library

768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812

Part 4: Supporting Routines

Error Returns

Meaning

TPM_RC_BINDING

public and private parts of rsaKey are not matched

TPM_RCCryptRsaLoadPrivateExponent(
TPMT_PUBLIC
TPMT_SENSITIVE)*publicArea,*sensitive{//if((sensitive->sensitive.rsa.t.size & RSA_prime_flag) == 0){if((sensitive->sensitive.rsa.t.size * 2) == publicArea->unique.rsa.t.size){
NEW_PRIVATE_EXPONENT(Z);
BN_RSA_INITIALIZED(bnN, &publicArea->unique.rsa);
BN_RSA(bnQr);
BN_VAR(bnE, RADIX_BITS);TEST(ALG_NULL_VALUE);
VERIFY((sensitive->sensitive.rsa.t.size * 2)== publicArea->unique.rsa.t.size);// Initialize the exponent
BnSetWord(bnE, publicArea->parameters.rsaDetail.exponent);
if(BnEqualZero(bnE))
BnSetWord(bnE, RSA_DEFAULT_PUBLIC_EXPONENT);// Convert first prime to 2B
VERIFY(BnFrom2B(Z->P, &sensitive->sensitive.rsa.b) != NULL);// Find the second prime by division. This uses 'bQ' rather than Z->Q// because the division could make the quotient larger than a prime during// some intermediate step.
VERIFY(BnDiv(Z->Q, bnQr, bnN, Z->P));VERIFY(BnEqualZero(bnQr));// Compute the private exponent and return it if found
VERIFY(ComputePrivateExponent(bnE, Z));VERIFY(PackExponent(&sensitive->sensitive.rsa, Z));}else
VERIFY(((sensitive->sensitive.rsa.t.size / 5) * 2)== publicArea->unique.rsa.t.size);sensitive->sensitive.rsa.t.size |= RSA_prime_flag;}
return TPM_RC_SUCCESS;
Error:
return TPM_RC_BINDING;}

10.2.17.5.3

CryptRsaEncrypt()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 treated as a number. It must be lower in value than the key
modulus.

Page 698
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

NOTE:

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866

Trusted Platform Module Library

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 forthe call to RSAEP. This is because the high order bytes of dIn might have a numeric value that is greater thanthe value of the key modulus. If this had low-order zeros added, it would have a numeric value larger than themodulus even though it started out with a lower numeric value.

Error Returns

Meaning

TPM_RC_VALUE

cOutSize is too small (must be the size of the modulus)

TPM_RC_SCHEME

padType is not a supported scheme

LIB_EXPORT TPM_RC
CryptRsaEncrypt(
TPM2B_PUBLIC_KEY_RSA
TPM2B
OBJECT
TPMT_RSA_DECRYPT*cOut,*dIn,*key,*scheme,const TPM2B
RAND_STATE*label,*rand// OUT: the encrypted data// IN: the data to encrypt// IN: the key used for encryption// IN: the type of padding and hash//if needed// IN: in case it is needed// IN: random number generator//
state (mostly for testing)){
TPM_RCTPM2B_PUBLIC_KEY_RSA

retVal = TPM_RC_SUCCESS;
dataIn;//// if the input and output buffers are the same, copy the input to a scratch// buffer so that things don't get messed up.
if(dIn == &cOut->b){
MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer));dIn = &dataIn.b;}// All encryption schemes return the same size of data
cOut->t.size = key->publicArea.unique.rsa.t.size;
TEST(scheme->scheme);
switch(scheme->scheme){case ALG_NULL_VALUE: // 'raw' encryption
{
INT32
i;
INT32
dSize = dIn->size;// dIn can have more bytes than cOut as long as the extra bytes// are zero. Note: the more significant bytes of a number in a byte// buffer are the bytes at the start of the array.
for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++);dSize -= i;if(dSize > cOut->t.size)
ERROR_RETURN(TPM_RC_VALUE);// Pad cOut with zeros if dIn is smaller
memset(cOut->t.buffer, 0, cOut->t.size - dSize);// And copy the rest of the value
memcpy(&cOut->t.buffer[cOut->t.size - dSize], &dIn->buffer[i], dSize);// If the size of dIn is the same as cOut dIn could be larger than// the modulus. If it is, then RSAEP() will catch it.
}
break;
case ALG_RSAES_VALUE:
retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand);break;
case ALG_OAEP_VALUE:
retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn,rand);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 699
April 15, 2019

Trusted Platform Module Library
867
868
869
870
871
872
873
874
875
876
877
878
879

Part 4: Supporting Routines

break;
default:
ERROR_RETURN(TPM_RC_SCHEME);
break;}// All the schemes that do padding will come here for the encryption step// Check that the Encoding worked
if(retVal == TPM_RC_SUCCESS)// Padding OK so do the encryption
retVal = RSAEP(&cOut->b, key);
Exit:
return retVal;}

10.2.17.5.4

CryptRsaDecrypt()This is the entry point for decryption using RSA. Decryption is use of the private exponent. The padTypeparameter determines what padding was used.

880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916

Error Returns

Meaning

TPM_RC_SIZE

cInSize is not the same as the size of the public modulus of key; ornumeric value of the encrypted data is greater than the modulus

TPM_RC_VALUE

dOutSize is not large enough for the result

TPM_RC_SCHEME

padType is not supported

LIB_EXPORT TPM_RC
CryptRsaDecrypt(
TPM2B
TPM2B
OBJECT
TPMT_RSA_DECRYPT
const TPM2B)*dOut,*cIn,*key,*scheme,*label// OUT: the decrypted data// IN: the data to decrypt// IN: the key to use for decryption// IN: the padding scheme// IN: in case it is needed for the scheme{
TPM_RC

retVal;// Make sure that the necessary parameters are provided
pAssert(cIn != NULL && dOut != NULL && key != NULL);// Size is checked to make sure that the encrypted value is the right size
if(cIn->size != key->publicArea.unique.rsa.t.size)
ERROR_RETURN(TPM_RC_SIZE);TEST(scheme->scheme);// For others that do padding, do the decryption in place and then// go handle the decoding.
retVal = RSADP(cIn, key);if(retVal == TPM_RC_SUCCESS){// Remove padding
switch(scheme->scheme){case ALG_NULL_VALUE:
if(dOut->size < cIn->size)
return TPM_RC_VALUE;
MemoryCopy2B(dOut, cIn, dOut->size);break;
case ALG_RSAES_VALUE:
retVal = RSAES_Decode(dOut, cIn);
break;
case ALG_OAEP_VALUE:

Page 700
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
917
918
919
920
921
922
923
924
925
926

Trusted Platform Module Library

retVal = OaepDecode(dOut, scheme->details.oaep.hashAlg, label, cIn);
break;
default:
retVal = TPM_RC_SCHEME;
break;}}
Exit:
return retVal;}

10.2.17.5.5

CryptRsaSign()

This function is used to generate an RSA signature of the type indicated in scheme.

927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969

Error Returns

Meaning

TPM_RC_SCHEME

scheme or hashAlg are not supported

TPM_RC_VALUE

hInSize does not match hashAlg (for RSASSA)LIB_EXPORT TPM_RC
CryptRsaSign(
TPMT_SIGNATUREOBJECT
TPM2B_DIGEST
RAND_STATE*sigOut,
*key,
*hIn,
*rand

// IN: key to use// IN: the digest to sign// IN: the random number generator//
to use (mostly for testing)){
TPM_RCUINT16

retVal = TPM_RC_SUCCESS;
modSize;// parameter checks
pAssert(sigOut != NULL && key != NULL && hIn != NULL);
modSize = key->publicArea.unique.rsa.t.size;// for all non-null signatures, the size is the size of the key modulus
sigOut->signature.rsapss.sig.t.size = modSize;
TEST(sigOut->sigAlg);
switch(sigOut->sigAlg){
case ALG_NULL_VALUE:
sigOut->signature.rsapss.sig.t.size = 0;
return TPM_RC_SUCCESS;
case ALG_RSAPSS_VALUE:
retVal = PssEncode(&sigOut->signature.rsapss.sig.b,
sigOut->signature.rsapss.hash, &hIn->b, rand);break;
case ALG_RSASSA_VALUE:
retVal = RSASSA_Encode(&sigOut->signature.rsassa.sig.b,
sigOut->signature.rsassa.hash, &hIn->b);
break;
default:
retVal = TPM_RC_SCHEME;}
if(retVal == TPM_RC_SUCCESS){// Do the encryption using the private key
retVal = RSADP(&sigOut->signature.rsapss.sig.b, key);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 701
April 15, 2019

Trusted Platform Module Library
970
971

Part 4: Supporting Routines

return retVal;}

10.2.17.5.6

CryptRsaValidateSignature()

This function is used to validate an RSA signature. If the signature is valid TPM_RC_SUCCESS isreturned. If the signature is not valid, TPM_RC_SIGNATURE is returned. Other return codes indicate
either parameter problems or fatal errors.

972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020

Error Returns

Meaning

TPM_RC_SIGNATURE

the signature does not check

TPM_RC_SCHEME

unsupported scheme or hash algorithm

LIB_EXPORT TPM_RC
CryptRsaValidateSignature(
TPMT_SIGNATUREOBJECT
TPM2B_DIGEST
)

*sig,
*key,
*digest

TPM_RC

retVal;// IN: signature// IN: public modulus// IN: The digest being validated{//// Fatal programming errors
pAssert(key != NULL && sig != NULL && digest != NULL);
switch(sig->sigAlg){
case ALG_RSAPSS_VALUE:
case ALG_RSASSA_VALUE:
break;
default:
return TPM_RC_SCHEME;}// Errors that might be caused by calling parametersif(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size)
ERROR_RETURN(TPM_RC_SIGNATURE);
TEST(sig->sigAlg);// Decrypt the block
retVal = RSAEP(&sig->signature.rsassa.sig.b, key);if(retVal == TPM_RC_SUCCESS){
switch(sig->sigAlg){
case ALG_RSAPSS_VALUE:
retVal = PssDecode(sig->signature.any.hashAlg, &digest->b,&sig->signature.rsassa.sig.b);break;
case ALG_RSASSA_VALUE:
retVal = RSASSA_Decode(sig->signature.any.hashAlg, &digest->b,&sig->signature.rsassa.sig.b);break;
default:
return TPM_RC_SCHEME;
}
}
Exit:
return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS;}#if SIMULATION && USE_RSA_KEY_CACHE
extern int s_rsaKeyCacheEnabled;

Page 702
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1021
1022
1023
1024
1025
1026
1027

Trusted Platform Module Library

int GetCachedRsaKey(TPMT_PUBLIC *publicArea, TPMT_SENSITIVE *sensitive,
RAND_STATE *rand);#define GET_CACHED_KEY(publicArea, sensitive, rand)\(s_rsaKeyCacheEnabled && GetCachedRsaKey(publicArea, sensitive, rand))#else#define GET_CACHED_KEY(key, rand)#endif10.2.17.5.7

CryptRsaGenerateKey()

Generate an RSA key from a provided seed

1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072

Error Returns

Meaning

TPM_RC_CANCELED

operation was canceled

TPM_RC_RANGE

public exponent is not supported

TPM_RC_VALUE

could not find a prime using the provided parameters

LIB_EXPORT TPM_RC
CryptRsaGenerateKey(
TPMT_PUBLIC
TPMT_SENSITIVERAND_STATE*publicArea,*sensitive,*rand// IN: if not NULL, the deterministic//
RNG state){
UINT32i;
BN_RSA(bnD);
BN_RSA(bnN);
BN_WORD(bnPubExp);UINT32e = publicArea->parameters.rsaDetail.exponent;
int
keySizeInBits;
TPM_RC
retVal = TPM_RC_NO_RESULT;
NEW_PRIVATE_EXPONENT(Z);//// Need to make sure that the caller did not specify an exponent that is// not supported
e = publicArea->parameters.rsaDetail.exponent;
if(e == 0)e = RSA_DEFAULT_PUBLIC_EXPONENT;
else{
if(e < 65537)
ERROR_RETURN(TPM_RC_RANGE);// Check that e is prime
if(!IsPrimeInt(e))
ERROR_RETURN(TPM_RC_RANGE);}
BnSetWord(bnPubExp, e);// check for supported key size.
keySizeInBits = publicArea->parameters.rsaDetail.keyBits;if(((keySizeInBits % 1024) != 0)|| (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but...
|| (keySizeInBits == 0))
ERROR_RETURN(TPM_RC_VALUE);// Set the prime size for instrumentation purposes
INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2));
#if SIMULATION && USE_RSA_KEY_CACHE
if(GET_CACHED_KEY(publicArea, sensitive, rand))Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 703
April 15, 2019

Trusted Platform Module Library
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138

Part 4: Supporting Routines

return TPM_RC_SUCCESS;#endif// Make sure that key generation has been tested
TEST(ALG_NULL_VALUE);// The prime is computed in P. When a new prime is found, Q is checked to// see if it is zero. If so, P is copied to Q and a new P is found.
// When both P and Q are non-zero, the modulus and// private exponent are computed and a trial encryption/decryption is// performed. If the encrypt/decrypt fails, assume that at least one of the// primes is composite. Since we don't know which one, set Q to zero and start// over and find a new pair of primes.
for(i = 1; (retVal == TPM_RC_NO_RESULT) && (i != 100); i++){if(_plat__IsCanceled())
ERROR_RETURN(TPM_RC_CANCELED);
if(BnGeneratePrimeForRSA(Z->P, keySizeInBits / 2, e, rand) == TPM_RC_FAILURE){
retVal = TPM_RC_FAILURE;
goto Exit;}
INSTRUMENT_INC(PrimeCounts[PrimeIndex]);// If this is the second prime, make sure that it differs from the// first prime by at least 2^100
if(BnEqualZero(Z->Q)){// copy p to q and compute another prime in p
BnCopy(Z->Q, Z->P);
continue;}// Make sure that the difference is at least 100 bits. Need to do it this// way because the big numbers are only positive values
if(BnUnsignedCmp(Z->P, Z->Q) < 0)
BnSub(bnD, Z->Q, Z->P);else
BnSub(bnD, Z->P, Z->Q);
if(BnMsb(bnD) < 100)
continue;//Form the public modulus and set the unique value
BnMult(bnN, Z->P, Z->Q);
BnTo2B(bnN, &publicArea->unique.rsa.b,(NUMBYTES)BITS_TO_BYTES(keySizeInBits));// Make sure everything came out right. The MSb of the values must be oneif(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0)|| (publicArea->unique.rsa.t.size!= (NUMBYTES)BITS_TO_BYTES(keySizeInBits)))
FAIL(FATAL_ERROR_INTERNAL);// Make sure that we can form the private exponent values
if(ComputePrivateExponent(bnPubExp, Z) != TRUE){// If ComputePrivateExponent could not find an inverse for// Q, then copy P and recompute P. This might// cause both to be recomputed if P is also zero
if(BnEqualZero(Z->Q))
BnCopy(Z->Q, Z->P);
continue;}// Pack the private exponent into the sensitive area

Page 704
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170

Trusted Platform Module Library

PackExponent(&sensitive->sensitive.rsa, Z);// Make sure everything came out right. The MSb of the values must be oneif(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0)|| ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0))
FAIL(FATAL_ERROR_INTERNAL);
retVal = TPM_RC_SUCCESS;// Do a trial encryption decryption if this is a signing key
if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)){
BN_RSA(temp1);
BN_RSA(temp2);
BnGenerateRandomInRange(temp1, bnN, rand);// Encrypt with public exponent...
BnModExp(temp2, temp1, bnPubExp, bnN);// ... then decrypt with private exponent
RsaPrivateKeyOp(temp2, Z);// If the starting and ending values are not the same,// start over )-;if(BnUnsignedCmp(temp2, temp1) != 0){
BnSetWord(Z->Q, 0);
retVal = TPM_RC_NO_RESULT;
}
}
}
Exit:
return retVal;}#endif // ALG_RSA

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 705
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.18 CryptSmac.c
10.2.18.1 Introduction
This file contains the implementation of the message authentication codes based on a symmetric blockcipher. These functions only use the single block encryption functions of the selected symmetric
cryptographic library.
10.2.18.2 Includes, Defines, and Typedefs
1
2
3#define _CRYPT_HASH_C_#include "Tpm.h"#if SMAC_IMPLEMENTED

10.2.18.2.1

CryptSmacStart()

Function to start an SMAC.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

UINT16
CryptSmacStart(
HASH_STATETPMU_PUBLIC_PARMS
TPM_ALG_ID
TPM2B*state,*keyParameters,
macAlg,*key

UINT16

retVal = 0;// IN: the type of MAC){//// Make sure that the key size is correct. This should have been checked// at key load, but...
if(BITS_TO_BYTES(keyParameters->symDetail.sym.keyBits.sym) == key->size){
switch(macAlg){#if
ALG_CMAC
case ALG_CMAC_VALUE:
retVal = CryptCmacStart(&state->state.smac, keyParameters,
macAlg, key);break;#endifdefault:
break;}}
state->type = (retVal != 0) ? HASH_STATE_SMAC : HASH_STATE_EMPTY;
return retVal;}

10.2.18.2.2

CryptMacStart()

Function to start either an HMAC or an SMAC. Cannot reuse the CryptHmacStart() function because of
the difference in number of parameters.
33
34
35
36
37
38

UINT16
CryptMacStart(
HMAC_STATETPMU_PUBLIC_PARMS
TPM_ALG_ID
TPM2BPage 706
April 15, 2019*state,*keyParameters,
macAlg,*key// IN: the type of MAC

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Trusted Platform Module Library){
MemorySet(state, 0, sizeof(HMAC_STATE));
if(CryptHashIsValidAlg(macAlg, FALSE)){
return CryptHmacStart(state, macAlg, key->size, key->buffer);}
else if(CryptSmacIsValidAlg(macAlg, FALSE)){
return CryptSmacStart(&state->hashState, keyParameters, macAlg, key);}else
return 0;}

10.2.18.2.3

CryptMacEnd()

Dispatch to the MAC end function using a size and buffer pointer.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

UINT16
CryptMacEnd(
HMAC_STATEUINT32
BYTE*state,size,*buffer){
UINT16
retVal = 0;if(state->hashState.type == HASH_STATE_SMAC)
retVal = (state->hashState.state.smac.smacMethods.end)(&state->hashState.state.smac.state, size, buffer);
else if(state->hashState.type == HASH_STATE_HMAC)
retVal = CryptHmacEnd(state, size, buffer);state->hashState.type = HASH_STATE_EMPTY;
return retVal;}

10.2.18.2.4

CryptMacEnd2B()

Dispatch to the MAC end function using a 2B.
69
70
71
72
73
74
75
76
77

UINT16
CryptMacEnd2B (HMAC_STATE
TPM2B*state,*data){
return CryptMacEnd(state, data->size, data->buffer);}#endif // SMAC_IMPLEMENTED

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 707
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.19 CryptSym.c
10.2.19.1 Introduction
This file contains the implementation of the symmetric block cipher modes allowed for a TPM. These
functions only use the single block encryption functions of the selected symmetric crypto library.
10.2.19.2 Includes, Defines, and Typedefs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include "Tpm.h"#include "CryptSym.h"#defineKEY_BLOCK_SIZES(ALG, alg)
static const INT16
alg##KeyBlockSizes[] = {ALG##_KEY_SIZES_BITS, -1, ALG##_BLOCK_SIZES };#if ALG_AES
KEY_BLOCK_SIZES(AES, aes);#endif // ALG_AES#if ALG_SM4
KEY_BLOCK_SIZES(SM4, sm4);#endif#if ALG_CAMELLIA
KEY_BLOCK_SIZES(CAMELLIA, camellia);#endif#if ALG_TDES
KEY_BLOCK_SIZES(TDES, tdes);#endif\\10.2.19.3 Initialization and Data Access Functions
10.2.19.3.1

CryptSymInit()

This function is called to do _TPM_Init() processing
18
19
20
21
22
23
24

BOOL
CryptSymInit(
void){
return TRUE;}

10.2.19.3.2

CryptSymStartup()This function is called to do TPM2_Startup() processing
25
26
27
28
29
30
31

BOOL
CryptSymStartup(
void){
return TRUE;}

10.2.19.3.3

CryptGetSymmetricBlockSize()This function returns the block size of the algorithm. The table of bit sizes has an entry for each allowed
key size. The entry for a key size is 0 if the TPM does not implement that key size. The key size table isPage 708
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Librarydelimited with a negative number (-1). After the delimiter is a list of block sizes with each entry
corresponding to the key bit size. For most symmetric algorithms, the block size is the same regardless of
the key size but this arrangement allows them to be different.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

Return Value

Meaning<= 0

cipher not supported>0

the cipher block size in bytes

LIB_EXPORT INT16
CryptGetSymmetricBlockSize(
TPM_ALG_ID
UINT16)symmetricAlg,
keySizeInBits// IN: the symmetric algorithm// IN: the key size{
const INT16*sizes;INT16i;#define ALG_CASE(SYM, sym) case ALG_##SYM##_VALUE: sizes = sym##KeyBlockSizes; breakswitch(symmetricAlg){#if ALG_AES
ALG_CASE(AES, aes);#endif#if ALG_SM4
ALG_CASE(SM4, sm4);#endif#if ALG_CAMELLIA
ALG_CASE(CAMELLIA, camellia);#endif#if ALG_TDES
ALG_CASE(TDES, tdes);#endifdefault:
return 0;}// Find the index of the indicated keySizeInBits
for(i = 0; *sizes >= 0; i++, sizes++){if(*sizes == keySizeInBits)
break;}// If sizes is pointing at the end of the list of key sizes, then the desired// key size was not found so set the block size to zero.
if(*sizes++ < 0)return 0;// Advance until the end of the list is foundwhile(*sizes++ >= 0);// sizes is pointing to the first entry in the list of block sizes. Use the// ith index to find the block size for the corresponding key size.
return sizes[i];}10.2.19.4 Symmetric Encryption
This function performs symmetric encryption based on the mode.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 709
April 15, 2019

Trusted Platform Module Library

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

Part 4: Supporting Routines

Error Returns

Meaning

TPM_RC_SIZE

dSize is not a multiple of the block size for an algorithm that requiresit

TPM_RC_FAILURE

Fatal error

LIB_EXPORT TPM_RC
CryptSymmetricEncrypt(
BYTE
TPM_ALG_ID
UINT16const BYTE

*dOut,// OUT:algorithm,// IN: the symmetric algorithm
keySizeInBits, // IN: key size in bits
*key,// IN: key buffer. The size of this buffer//
in bytes is (keySizeInBits + 7) / 8*ivInOut,// IN/OUT: IV for decryption.
mode,// IN: Mode to use
dSize,// IN: data size (may need to be a//multiple of the blockSize)*dIn// IN: data buffer

TPM2B_IV
TPM_ALG_ID
INT32
const BYTE
)
{

BYTE
*pIv;
int
i;
BYTE
tmp[MAX_SYM_BLOCK_SIZE];
BYTE
*pT;
tpmCryptKeySchedule_t
keySchedule;
INT16
blockSize;
TpmCryptSetSymKeyCall_t
encrypt;
BYTE
*iv;
BYTE
defaultIv[MAX_SYM_BLOCK_SIZE] = {0};//pAssert(dOut != NULL && key != NULL && dIn != NULL);
if(dSize == 0)
return TPM_RC_SUCCESS;TEST(algorithm);
blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
if(blockSize == 0)
return TPM_RC_FAILURE;// If the iv is provided, then it is expected to be block sized. In some cases,// the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]// with no knowledge of the actual block size. This function will set it.
if((ivInOut != NULL) && (mode != ALG_ECB_VALUE)){
ivInOut->t.size = blockSize;iv = ivInOut->t.buffer;}else
iv = defaultIv;
pIv = iv;// Create encrypt key schedule and set the encryption function pointer.
SELECT(ENCRYPT);
switch(mode){#if
ALG_CTRcase ALG_CTR_VALUE:
for(; dSize > 0; dSize -= blockSize){// Encrypt the current value of the IV(counter)
ENCRYPT(&keySchedule, iv, tmp);//increment the counter (counter is big-endian so start at end)

Page 710
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

Trusted Platform Module Libraryfor(i = blockSize - 1; i >= 0; i--)if((iv[i] += 1) != 0)
break;// XOR the encrypted counter value with input and put into output
pT = tmp;for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)*dOut++ = *dIn++ ^ *pT++;}
break;#endif#if ALG_OFB
case ALG_OFB_VALUE:// This is written so that dIn and dOut may be the samefor(; dSize > 0; dSize -= blockSize){// Encrypt the current value of the "IV"ENCRYPT(&keySchedule, iv, iv);// XOR the encrypted IV into dIn to create the cipher text (dOut)
pIv = iv;
for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)*dOut++ = (*pIv++ ^ *dIn++);}break;#endif#if ALG_CBC
case ALG_CBC_VALUE:// For CBC the data size must be an even multiple of the// cipher block sizeif((dSize % blockSize) != 0)
return TPM_RC_SIZE;// XOR the data block into the IV, encrypt the IV into the IV// and then copy the IV to the output
for(; dSize > 0; dSize -= blockSize){
pIv = iv;
for(i = blockSize; i > 0; i--)*pIv++ ^= *dIn++;ENCRYPT(&keySchedule, iv, iv);
pIv = iv;
for(i = blockSize; i > 0; i--)*dOut++ = *pIv++;}
break;#endif// CFB is not optionalcase ALG_CFB_VALUE:// Encrypt the IV into the IV, XOR in the data, and copy to output
for(; dSize > 0; dSize -= blockSize){// Encrypt the current value of the IV
ENCRYPT(&keySchedule, iv, iv);
pIv = iv;
for(i = (int)(dSize < blockSize) ? dSize : blockSize; i > 0; i--)// XOR the data into the IV to create the cipher text// and put into the output*dOut++ = *pIv++ ^= *dIn++;}// If the inner loop (i loop) was smaller than blockSize, then dSize// would have been smaller than blockSize and it is now negative. If// it is negative, then it indicates how many bytes are needed to pad// out the IV for the next round.
for(; dSize < 0; dSize++)*pIv++ = 0;
break;#if ALG_ECB

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 711
April 15, 2019

Trusted Platform Module Library
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

Part 4: Supporting Routinescase ALG_ECB_VALUE:// For ECB the data size must be an even multiple of the// cipher block sizeif((dSize % blockSize) != 0)
return TPM_RC_SIZE;// Encrypt the input block to the output blockfor(; dSize > 0; dSize -= blockSize){
ENCRYPT(&keySchedule, dIn, dOut);dIn = &dIn[blockSize];
dOut = &dOut[blockSize];}break;#endifdefault:
return TPM_RC_FAILURE;}
return TPM_RC_SUCCESS;}

10.2.19.4.1

CryptSymmetricDecrypt()This function performs symmetric decryption based on the mode.

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

Error Returns

Meaning

TPM_RC_FAILURE

A fatal error

TPM_RCS_SIZE

dSize is not a multiple of the block size for an algorithm that requiresit

LIB_EXPORT TPM_RC
CryptSymmetricDecrypt(
BYTE
TPM_ALG_ID
UINT16const BYTE
TPM2B_IV
TPM_ALG_ID
INT32
const BYTE)

*dOut,// OUT: decrypted data
algorithm,// IN: the symmetric algorithm
keySizeInBits, // IN: key size in bits
*key,// IN: key buffer. The size of this buffer//
in bytes is (keySizeInBits + 7) / 8*ivInOut,// IN/OUT: IV for decryption.
mode,// IN: Mode to use
dSize,// IN: data size (may need to be a//multiple of the blockSize)*dIn// IN: data buffer

{
BYTE
*pIv;
int
i;
BYTE
tmp[MAX_SYM_BLOCK_SIZE];
BYTE
*pT;
tpmCryptKeySchedule_t
keySchedule;
INT16
blockSize;
BYTE
*iv;
TpmCryptSetSymKeyCall_t
encrypt;
TpmCryptSetSymKeyCall_t
decrypt;
BYTE
defaultIv[MAX_SYM_BLOCK_SIZE] = {0};// These are used but the compiler can't tell because they are initialized// in case statements and it can't tell if they are always initialized// when needed, so... Comment these out if the compiler can tell or doesn't// care that these are initialized before use.
encrypt = NULL;
decrypt = NULL;
pAssert(dOut != NULL && key != NULL && dIn != NULL);

Page 712
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

Trusted Platform Module Libraryif(dSize == 0)
return TPM_RC_SUCCESS;TEST(algorithm);
blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
if(blockSize == 0)
return TPM_RC_FAILURE;// If the iv is provided, then it is expected to be block sized. In some cases,// the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]// with no knowledge of the actual block size. This function will set it.
if((ivInOut != NULL) && (mode != ALG_ECB_VALUE)){
ivInOut->t.size = blockSize;iv = ivInOut->t.buffer;}else
iv = defaultIv;
pIv = iv;// Use the mode to select the key schedule to create. Encrypt always uses the// encryption schedule. Depending on the mode, decryption might use either// the decryption or encryption schedule.
switch(mode){#if ALG_CBC || ALG_ECB
case ALG_CBC_VALUE: // decrypt = decrypt
case ALG_ECB_VALUE:// For ECB and CBC, the data size must be an even multiple of the// cipher block sizeif((dSize % blockSize) != 0)
return TPM_RC_SIZE;
SELECT(DECRYPT);
break;#endifdefault:// For the remaining stream ciphers, use encryption to decrypt
SELECT(ENCRYPT);
break;}// Now do the mode-dependent decryption
switch(mode){#if ALG_CBC
case ALG_CBC_VALUE:// Copy the input data to a temp buffer, decrypt the buffer into the// output, XOR in the IV, and copy the temp buffer to the IV and repeat.
for(; dSize > 0; dSize -= blockSize){
pT = tmp;for(i = blockSize; i > 0; i--)*pT++ = *dIn++;DECRYPT(&keySchedule, tmp, dOut);
pIv = iv;
pT = tmp;for(i = blockSize; i > 0; i--){*dOut++ ^= *pIv;*pIv++ = *pT++;}}
break;#endifcase ALG_CFB_VALUE:
for(; dSize > 0; dSize -= blockSize){// Encrypt the IV into the temp buffer

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 713
April 15, 2019

Trusted Platform Module Library
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

Part 4: Supporting Routines

ENCRYPT(&keySchedule, iv, tmp);
pT = tmp;
pIv = iv;
for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)// Copy the current cipher text to IV, XOR// with the temp buffer and put into the output*dOut++ = *pT++ ^ (*pIv++ = *dIn++);}// If the inner loop (i loop) was smaller than blockSize, then dSize// would have been smaller than blockSize and it is now negative// If it is negative, then it indicates how may fill bytes// are needed to pad out the IV for the next round.
for(; dSize < 0; dSize++)*pIv++ = 0;
break;#if ALG_CTR
case ALG_CTR_VALUE:
for(; dSize > 0; dSize -= blockSize){// Encrypt the current value of the IV(counter)
ENCRYPT(&keySchedule, iv, tmp);//increment the counter (counter is big-endian so start at end)
for(i = blockSize - 1; i >= 0; i--)if((iv[i] += 1) != 0)
break;// XOR the encrypted counter value with input and put into output
pT = tmp;for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)*dOut++ = *dIn++ ^ *pT++;}
break;#endif#if ALG_ECB
case ALG_ECB_VALUE:
for(; dSize > 0; dSize -= blockSize){
DECRYPT(&keySchedule, dIn, dOut);dIn = &dIn[blockSize];
dOut = &dOut[blockSize];}break;#endif#if ALG_OFB
case ALG_OFB_VALUE:// This is written so that dIn and dOut may be the samefor(; dSize > 0; dSize -= blockSize){// Encrypt the current value of the "IV"ENCRYPT(&keySchedule, iv, iv);// XOR the encrypted IV into dIn to create the cipher text (dOut)
pIv = iv;
for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)*dOut++ = (*pIv++ ^ *dIn++);}break;#endifdefault:
return TPM_RC_FAILURE;}
return TPM_RC_SUCCESS;}

Page 714
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

10.2.19.4.2

Trusted Platform Module Library

CryptSymKeyValidate()

Validate that a provided symmetric key meets the requirements of the TPM

380
381
382
383
384
385
386
387
388
389
390
391
392
393

Error Returns

Meaning

TPM_RC_KEY_SIZE

Key size specifiers do not match

TPM_RC_KEY

Key is not allowed

TPM_RCCryptSymKeyValidate(
TPMT_SYM_DEF_OBJECT *symDef,
TPM2B_SYM_KEY*key){if(key->t.size != BITS_TO_BYTES(symDef->keyBits.sym))
return TPM_RCS_KEY_SIZE;#if ALG_TDES
if(symDef->algorithm == TPM_ALG_TDES && !CryptDesValidateKey(key))
return TPM_RCS_KEY;#endif // ALG_TDES
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 715
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.20 PrimeData.c1#include "Tpm.h"

This table is the product of all of the primes up to 1000. Checking to see if there is a GCD between aprime candidate and this number will eliminate many prime candidates from consideration before running
Miller-Rabin on the result.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

const BN_STRUCT(43 * RADIX_BITS) s_CompositeOfSmallPrimes_ ={44, 44,{ 0x2ED42696, 0x2BBFA177, 0x4820594F, 0xF73F4841,
0xBFAC313A, 0xCAC3EB81, 0xF6F26BF8, 0x7FAB5061,
0x59746FB7, 0xF71377F6, 0x3B19855B, 0xCBD03132,
0xBB92EF1B, 0x3AC3152C, 0xE87C8273, 0xC0AE0E69,
0x74A9E295, 0x448CCE86, 0x63CA1907, 0x8A0BF944,
0xF8CC3BE0, 0xC26F0AF5, 0xC501C02F, 0x6579441A,
0xD1099CDA, 0x6BC76A00, 0xC81A3228, 0xBFB1AB25,
0x70FA3841, 0x51B3D076, 0xCC2359ED, 0xD9EE0769,
0x75E47AF0, 0xD45FF31E, 0x52CCE4F6, 0x04DBC891,
0x96658ED2, 0x1753EFE5, 0x3AE4A5A6, 0x8FD4A97F,
0x8B15E7EB, 0x0243C3E1, 0xE0F0C31D, 0x0000000B }};bigConst
s_CompositeOfSmallPrimes = (const bigNum)&s_CompositeOfSmallPrimes_;

This table contains a bit for each of the odd values between 1 and 2^16 + 1. This table allows fast
checking of the primes in that range. Don't change the size of this table unless you are prepared to do
redo IsPrimeInt().
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

const uint32_t
s_LastPrimeInTable = 65537;
const uint32_t
s_PrimeTableSize = 4097;
const uint32_t
s_PrimesInTable = 6542;
const unsigned char s_PrimeTable[] = {0x6e, 0xcb, 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x81, 0x32, 0x4c, 0x4a, 0x86,
0x0d, 0x82, 0x96, 0x21, 0xc9, 0x34, 0x04, 0x5a, 0x20, 0x61, 0x89, 0xa4,
0x44, 0x11, 0x86, 0x29, 0xd1, 0x82, 0x28, 0x4a, 0x30, 0x40, 0x42, 0x32,
0x21, 0x99, 0x34, 0x08, 0x4b, 0x06, 0x25, 0x42, 0x84, 0x48, 0x8a, 0x14,
0x05, 0x42, 0x30, 0x6c, 0x08, 0xb4, 0x40, 0x0b, 0xa0, 0x08, 0x51, 0x12,
0x28, 0x89, 0x04, 0x65, 0x98, 0x30, 0x4c, 0x80, 0x96, 0x44, 0x12, 0x80,
0x21, 0x42, 0x12, 0x41, 0xc9, 0x04, 0x21, 0xc0, 0x32, 0x2d, 0x98, 0x00,
0x00, 0x49, 0x04, 0x08, 0x81, 0x96, 0x68, 0x82, 0xb0, 0x25, 0x08, 0x22,
0x48, 0x89, 0xa2, 0x40, 0x59, 0x26, 0x04, 0x90, 0x06, 0x40, 0x43, 0x30,
0x44, 0x92, 0x00, 0x69, 0x10, 0x82, 0x08, 0x08, 0xa4, 0x0d, 0x41, 0x12,
0x60, 0xc0, 0x00, 0x24, 0xd2, 0x22, 0x61, 0x08, 0x84, 0x04, 0x1b, 0x82,
0x01, 0xd3, 0x10, 0x01, 0x02, 0xa0, 0x44, 0xc0, 0x22, 0x60, 0x91, 0x14,
0x0c, 0x40, 0xa6, 0x04, 0xd2, 0x94, 0x20, 0x09, 0x94, 0x20, 0x52, 0x00,
0x08, 0x10, 0xa2, 0x4c, 0x00, 0x82, 0x01, 0x51, 0x10, 0x08, 0x8b, 0xa4,
0x25, 0x9a, 0x30, 0x44, 0x81, 0x10, 0x4c, 0x03, 0x02, 0x25, 0x52, 0x80,
0x08, 0x49, 0x84, 0x20, 0x50, 0x32, 0x00, 0x18, 0xa2, 0x40, 0x11, 0x24,
0x28, 0x01, 0x84, 0x01, 0x01, 0xa0, 0x41, 0x0a, 0x12, 0x45, 0x00, 0x36,
0x08, 0x00, 0x26, 0x29, 0x83, 0x82, 0x61, 0xc0, 0x80, 0x04, 0x10, 0x10,
0x6d, 0x00, 0x22, 0x48, 0x58, 0x26, 0x0c, 0xc2, 0x10, 0x48, 0x89, 0x24,
0x20, 0x58, 0x20, 0x45, 0x88, 0x24, 0x00, 0x19, 0x02, 0x25, 0xc0, 0x10,
0x68, 0x08, 0x14, 0x01, 0xca, 0x32, 0x28, 0x80, 0x00, 0x04, 0x4b, 0x26,
0x00, 0x13, 0x90, 0x60, 0x82, 0x80, 0x25, 0xd0, 0x00, 0x01, 0x10, 0x32,
0x0c, 0x43, 0x86, 0x21, 0x11, 0x00, 0x08, 0x43, 0x24, 0x04, 0x48, 0x10,
0x0c, 0x90, 0x92, 0x00, 0x43, 0x20, 0x2d, 0x00, 0x06, 0x09, 0x88, 0x24,
0x40, 0xc0, 0x32, 0x09, 0x09, 0x82, 0x00, 0x53, 0x80, 0x08, 0x80, 0x96,
0x41, 0x81, 0x00, 0x40, 0x48, 0x10, 0x48, 0x08, 0x96, 0x48, 0x58, 0x20,
0x29, 0xc3, 0x80, 0x20, 0x02, 0x94, 0x60, 0x92, 0x00, 0x20, 0x81, 0x22,
0x44, 0x10, 0xa0, 0x05, 0x40, 0x90, 0x01, 0x49, 0x20, 0x04, 0x0a, 0x00,
0x24, 0x89, 0x34, 0x48, 0x13, 0x80, 0x2c, 0xc0, 0x82, 0x29, 0x00, 0x24,
0x45, 0x08, 0x00, 0x08, 0x98, 0x36, 0x04, 0x52, 0x84, 0x04, 0xd0, 0x04,
0x00, 0x8a, 0x90, 0x44, 0x82, 0x32, 0x65, 0x18, 0x90, 0x00, 0x0a, 0x02,

Page 716
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

Trusted Platform Module Library

0x01, 0x40, 0x02, 0x28, 0x40, 0xa4, 0x04, 0x92, 0x30, 0x04, 0x11, 0x86,
0x08, 0x42, 0x00, 0x2c, 0x52, 0x04, 0x08, 0xc9, 0x84, 0x60, 0x48, 0x12,
0x09, 0x99, 0x24, 0x44, 0x00, 0x24, 0x00, 0x03, 0x14, 0x21, 0x00, 0x10,
0x01, 0x1a, 0x32, 0x05, 0x88, 0x20, 0x40, 0x40, 0x06, 0x09, 0xc3, 0x84,
0x40, 0x01, 0x30, 0x60, 0x18, 0x02, 0x68, 0x11, 0x90, 0x0c, 0x02, 0xa2,
0x04, 0x00, 0x86, 0x29, 0x89, 0x14, 0x24, 0x82, 0x02, 0x41, 0x08, 0x80,
0x04, 0x19, 0x80, 0x08, 0x10, 0x12, 0x68, 0x42, 0xa4, 0x04, 0x00, 0x02,
0x61, 0x10, 0x06, 0x0c, 0x10, 0x00, 0x01, 0x12, 0x10, 0x20, 0x03, 0x94,
0x21, 0x42, 0x12, 0x65, 0x18, 0x94, 0x0c, 0x0a, 0x04, 0x28, 0x01, 0x14,
0x29, 0x0a, 0xa4, 0x40, 0xd0, 0x00, 0x40, 0x01, 0x90, 0x04, 0x41, 0x20,
0x2d, 0x40, 0x82, 0x48, 0xc1, 0x20, 0x00, 0x10, 0x30, 0x01, 0x08, 0x24,
0x04, 0x59, 0x84, 0x24, 0x00, 0x02, 0x29, 0x82, 0x00, 0x61, 0x58, 0x02,
0x48, 0x81, 0x16, 0x48, 0x10, 0x00, 0x21, 0x11, 0x06, 0x00, 0xca, 0xa0,
0x40, 0x02, 0x00, 0x04, 0x91, 0xb0, 0x00, 0x42, 0x04, 0x0c, 0x81, 0x06,
0x09, 0x48, 0x14, 0x25, 0x92, 0x20, 0x25, 0x11, 0xa0, 0x00, 0x0a, 0x86,
0x0c, 0xc1, 0x02, 0x48, 0x00, 0x20, 0x45, 0x08, 0x32, 0x00, 0x98, 0x06,
0x04, 0x13, 0x22, 0x00, 0x82, 0x04, 0x48, 0x81, 0x14, 0x44, 0x82, 0x12,
0x24, 0x18, 0x10, 0x40, 0x43, 0x80, 0x28, 0xd0, 0x04, 0x20, 0x81, 0x24,
0x64, 0xd8, 0x00, 0x2c, 0x09, 0x12, 0x08, 0x41, 0xa2, 0x00, 0x00, 0x02,
0x41, 0xca, 0x20, 0x41, 0xc0, 0x10, 0x01, 0x18, 0xa4, 0x04, 0x18, 0xa4,
0x20, 0x12, 0x94, 0x20, 0x83, 0xa0, 0x40, 0x02, 0x32, 0x44, 0x80, 0x04,
0x00, 0x18, 0x00, 0x0c, 0x40, 0x86, 0x60, 0x8a, 0x00, 0x64, 0x88, 0x12,
0x05, 0x01, 0x82, 0x00, 0x4a, 0xa2, 0x01, 0xc1, 0x10, 0x61, 0x09, 0x04,
0x01, 0x88, 0x00, 0x60, 0x01, 0xb4, 0x40, 0x08, 0x06, 0x01, 0x03, 0x80,
0x08, 0x40, 0x94, 0x04, 0x8a, 0x20, 0x29, 0x80, 0x02, 0x0c, 0x52, 0x02,
0x01, 0x42, 0x84, 0x00, 0x80, 0x84, 0x64, 0x02, 0x32, 0x48, 0x00, 0x30,
0x44, 0x40, 0x22, 0x21, 0x00, 0x02, 0x08, 0xc3, 0xa0, 0x04, 0xd0, 0x20,
0x40, 0x18, 0x16, 0x40, 0x40, 0x00, 0x28, 0x52, 0x90, 0x08, 0x82, 0x14,
0x01, 0x18, 0x10, 0x08, 0x09, 0x82, 0x40, 0x0a, 0xa0, 0x20, 0x93, 0x80,
0x08, 0xc0, 0x00, 0x20, 0x52, 0x00, 0x05, 0x01, 0x10, 0x40, 0x11, 0x06,
0x0c, 0x82, 0x00, 0x00, 0x4b, 0x90, 0x44, 0x9a, 0x00, 0x28, 0x80, 0x90,
0x04, 0x4a, 0x06, 0x09, 0x43, 0x02, 0x28, 0x00, 0x34, 0x01, 0x18, 0x00,
0x65, 0x09, 0x80, 0x44, 0x03, 0x00, 0x24, 0x02, 0x82, 0x61, 0x48, 0x14,
0x41, 0x00, 0x12, 0x28, 0x00, 0x34, 0x08, 0x51, 0x04, 0x05, 0x12, 0x90,
0x28, 0x89, 0x84, 0x60, 0x12, 0x10, 0x49, 0x10, 0x26, 0x40, 0x49, 0x82,
0x00, 0x91, 0x10, 0x01, 0x0a, 0x24, 0x40, 0x88, 0x10, 0x4c, 0x10, 0x04,
0x00, 0x50, 0xa2, 0x2c, 0x40, 0x90, 0x48, 0x0a, 0xb0, 0x01, 0x50, 0x12,
0x08, 0x00, 0xa4, 0x04, 0x09, 0xa0, 0x28, 0x92, 0x02, 0x00, 0x43, 0x10,
0x21, 0x02, 0x20, 0x41, 0x81, 0x32, 0x00, 0x08, 0x04, 0x0c, 0x52, 0x00,
0x21, 0x49, 0x84, 0x20, 0x10, 0x02, 0x01, 0x81, 0x10, 0x48, 0x40, 0x22,
0x01, 0x01, 0x84, 0x69, 0xc1, 0x30, 0x01, 0xc8, 0x02, 0x44, 0x88, 0x00,
0x0c, 0x01, 0x02, 0x2d, 0xc0, 0x12, 0x61, 0x00, 0xa0, 0x00, 0xc0, 0x30,
0x40, 0x01, 0x12, 0x08, 0x0b, 0x20, 0x00, 0x80, 0x94, 0x40, 0x01, 0x84,
0x40, 0x00, 0x32, 0x00, 0x10, 0x84, 0x00, 0x0b, 0x24, 0x00, 0x01, 0x06,
0x29, 0x8a, 0x84, 0x41, 0x80, 0x10, 0x08, 0x08, 0x94, 0x4c, 0x03, 0x80,
0x01, 0x40, 0x96, 0x40, 0x41, 0x20, 0x20, 0x50, 0x22, 0x25, 0x89, 0xa2,
0x40, 0x40, 0xa4, 0x20, 0x02, 0x86, 0x28, 0x01, 0x20, 0x21, 0x4a, 0x10,
0x08, 0x00, 0x14, 0x08, 0x40, 0x04, 0x25, 0x42, 0x02, 0x21, 0x43, 0x10,
0x04, 0x92, 0x00, 0x21, 0x11, 0xa0, 0x4c, 0x18, 0x22, 0x09, 0x03, 0x84,
0x41, 0x89, 0x10, 0x04, 0x82, 0x22, 0x24, 0x01, 0x14, 0x08, 0x08, 0x84,
0x08, 0xc1, 0x00, 0x09, 0x42, 0xb0, 0x41, 0x8a, 0x02, 0x00, 0x80, 0x36,
0x04, 0x49, 0xa0, 0x24, 0x91, 0x00, 0x00, 0x02, 0x94, 0x41, 0x92, 0x02,
0x01, 0x08, 0x06, 0x08, 0x09, 0x00, 0x01, 0xd0, 0x16, 0x28, 0x89, 0x80,
0x60, 0x00, 0x00, 0x68, 0x01, 0x90, 0x0c, 0x50, 0x20, 0x01, 0x40, 0x80,
0x40, 0x42, 0x30, 0x41, 0x00, 0x20, 0x25, 0x81, 0x06, 0x40, 0x49, 0x00,
0x08, 0x01, 0x12, 0x49, 0x00, 0xa0, 0x20, 0x18, 0x30, 0x05, 0x01, 0xa6,
0x00, 0x10, 0x24, 0x28, 0x00, 0x02, 0x20, 0xc8, 0x20, 0x00, 0x88, 0x12,
0x0c, 0x90, 0x92, 0x00, 0x02, 0x26, 0x01, 0x42, 0x16, 0x49, 0x00, 0x04,
0x24, 0x42, 0x02, 0x01, 0x88, 0x80, 0x0c, 0x1a, 0x80, 0x08, 0x10, 0x00,
0x60, 0x02, 0x94, 0x44, 0x88, 0x00, 0x69, 0x11, 0x30, 0x08, 0x12, 0xa0,
0x24, 0x13, 0x84, 0x00, 0x82, 0x00, 0x65, 0xc0, 0x10, 0x28, 0x00, 0x30,
0x04, 0x03, 0x20, 0x01, 0x11, 0x06, 0x01, 0xc8, 0x80, 0x00, 0xc2, 0x20,
0x08, 0x10, 0x82, 0x0c, 0x13, 0x02, 0x0c, 0x52, 0x06, 0x40, 0x00, 0xb0,
0x61, 0x40, 0x10, 0x01, 0x98, 0x86, 0x04, 0x10, 0x84, 0x08, 0x92, 0x14,
0x60, 0x41, 0x80, 0x41, 0x1a, 0x10, 0x04, 0x81, 0x22, 0x40, 0x41, 0x20,
0x29, 0x52, 0x00, 0x41, 0x08, 0x34, 0x60, 0x10, 0x00, 0x28, 0x01, 0x10,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 717
April 15, 2019

Trusted Platform Module Library
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

Part 4: Supporting Routines

0x40, 0x00, 0x84, 0x08, 0x42, 0x90, 0x20, 0x48, 0x04, 0x04, 0x52, 0x02,
0x00, 0x08, 0x20, 0x04, 0x00, 0x82, 0x0d, 0x00, 0x82, 0x40, 0x02, 0x10,
0x05, 0x48, 0x20, 0x40, 0x99, 0x00, 0x00, 0x01, 0x06, 0x24, 0xc0, 0x00,
0x68, 0x82, 0x04, 0x21, 0x12, 0x10, 0x44, 0x08, 0x04, 0x00, 0x40, 0xa6,
0x20, 0xd0, 0x16, 0x09, 0xc9, 0x24, 0x41, 0x02, 0x20, 0x0c, 0x09, 0x92,
0x40, 0x12, 0x00, 0x00, 0x40, 0x00, 0x09, 0x43, 0x84, 0x20, 0x98, 0x02,
0x01, 0x11, 0x24, 0x00, 0x43, 0x24, 0x00, 0x03, 0x90, 0x08, 0x41, 0x30,
0x24, 0x58, 0x20, 0x4c, 0x80, 0x82, 0x08, 0x10, 0x24, 0x25, 0x81, 0x06,
0x41, 0x09, 0x10, 0x20, 0x18, 0x10, 0x44, 0x80, 0x10, 0x00, 0x4a, 0x24,
0x0d, 0x01, 0x94, 0x28, 0x80, 0x30, 0x00, 0xc0, 0x02, 0x60, 0x10, 0x84,
0x0c, 0x02, 0x00, 0x09, 0x02, 0x82, 0x01, 0x08, 0x10, 0x04, 0xc2, 0x20,
0x68, 0x09, 0x06, 0x04, 0x18, 0x00, 0x00, 0x11, 0x90, 0x08, 0x0b, 0x10,
0x21, 0x82, 0x02, 0x0c, 0x10, 0xb6, 0x08, 0x00, 0x26, 0x00, 0x41, 0x02,
0x01, 0x4a, 0x24, 0x21, 0x1a, 0x20, 0x24, 0x80, 0x00, 0x44, 0x02, 0x00,
0x2d, 0x40, 0x02, 0x00, 0x8b, 0x94, 0x20, 0x10, 0x00, 0x20, 0x90, 0xa6,
0x40, 0x13, 0x00, 0x2c, 0x11, 0x86, 0x61, 0x01, 0x80, 0x41, 0x10, 0x02,
0x04, 0x81, 0x30, 0x48, 0x48, 0x20, 0x28, 0x50, 0x80, 0x21, 0x8a, 0x10,
0x04, 0x08, 0x10, 0x09, 0x10, 0x10, 0x48, 0x42, 0xa0, 0x0c, 0x82, 0x92,
0x60, 0xc0, 0x20, 0x05, 0xd2, 0x20, 0x40, 0x01, 0x00, 0x04, 0x08, 0x82,
0x2d, 0x82, 0x02, 0x00, 0x48, 0x80, 0x41, 0x48, 0x10, 0x00, 0x91, 0x04,
0x04, 0x03, 0x84, 0x00, 0xc2, 0x04, 0x68, 0x00, 0x00, 0x64, 0xc0, 0x22,
0x40, 0x08, 0x32, 0x44, 0x09, 0x86, 0x00, 0x91, 0x02, 0x28, 0x01, 0x00,
0x64, 0x48, 0x00, 0x24, 0x10, 0x90, 0x00, 0x43, 0x00, 0x21, 0x52, 0x86,
0x41, 0x8b, 0x90, 0x20, 0x40, 0x20, 0x08, 0x88, 0x04, 0x44, 0x13, 0x20,
0x00, 0x02, 0x84, 0x60, 0x81, 0x90, 0x24, 0x40, 0x30, 0x00, 0x08, 0x10,
0x08, 0x08, 0x02, 0x01, 0x10, 0x04, 0x20, 0x43, 0xb4, 0x40, 0x90, 0x12,
0x68, 0x01, 0x80, 0x4c, 0x18, 0x00, 0x08, 0xc0, 0x12, 0x49, 0x40, 0x10,
0x24, 0x1a, 0x00, 0x41, 0x89, 0x24, 0x4c, 0x10, 0x00, 0x04, 0x52, 0x10,
0x09, 0x4a, 0x20, 0x41, 0x48, 0x22, 0x69, 0x11, 0x14, 0x08, 0x10, 0x06,
0x24, 0x80, 0x84, 0x28, 0x00, 0x10, 0x00, 0x40, 0x10, 0x01, 0x08, 0x26,
0x08, 0x48, 0x06, 0x28, 0x00, 0x14, 0x01, 0x42, 0x84, 0x04, 0x0a, 0x20,
0x00, 0x01, 0x82, 0x08, 0x00, 0x82, 0x24, 0x12, 0x04, 0x40, 0x40, 0xa0,
0x40, 0x90, 0x10, 0x04, 0x90, 0x22, 0x40, 0x10, 0x20, 0x2c, 0x80, 0x10,
0x28, 0x43, 0x00, 0x04, 0x58, 0x00, 0x01, 0x81, 0x10, 0x48, 0x09, 0x20,
0x21, 0x83, 0x04, 0x00, 0x42, 0xa4, 0x44, 0x00, 0x00, 0x6c, 0x10, 0xa0,
0x44, 0x48, 0x80, 0x00, 0x83, 0x80, 0x48, 0xc9, 0x00, 0x00, 0x00, 0x02,
0x05, 0x10, 0xb0, 0x04, 0x13, 0x04, 0x29, 0x10, 0x92, 0x40, 0x08, 0x04,
0x44, 0x82, 0x22, 0x00, 0x19, 0x20, 0x00, 0x19, 0x20, 0x01, 0x81, 0x90,
0x60, 0x8a, 0x00, 0x41, 0xc0, 0x02, 0x45, 0x10, 0x04, 0x00, 0x02, 0xa2,
0x09, 0x40, 0x10, 0x21, 0x49, 0x20, 0x01, 0x42, 0x30, 0x2c, 0x00, 0x14,
0x44, 0x01, 0x22, 0x04, 0x02, 0x92, 0x08, 0x89, 0x04, 0x21, 0x80, 0x10,
0x05, 0x01, 0x20, 0x40, 0x41, 0x80, 0x04, 0x00, 0x12, 0x09, 0x40, 0xb0,
0x64, 0x58, 0x32, 0x01, 0x08, 0x90, 0x00, 0x41, 0x04, 0x09, 0xc1, 0x80,
0x61, 0x08, 0x90, 0x00, 0x9a, 0x00, 0x24, 0x01, 0x12, 0x08, 0x02, 0x26,
0x05, 0x82, 0x06, 0x08, 0x08, 0x00, 0x20, 0x48, 0x20, 0x00, 0x18, 0x24,
0x48, 0x03, 0x02, 0x00, 0x11, 0x00, 0x09, 0x00, 0x84, 0x01, 0x4a, 0x10,
0x01, 0x98, 0x00, 0x04, 0x18, 0x86, 0x00, 0xc0, 0x00, 0x20, 0x81, 0x80,
0x04, 0x10, 0x30, 0x05, 0x00, 0xb4, 0x0c, 0x4a, 0x82, 0x29, 0x91, 0x02,
0x28, 0x00, 0x20, 0x44, 0xc0, 0x00, 0x2c, 0x91, 0x80, 0x40, 0x01, 0xa2,
0x00, 0x12, 0x04, 0x09, 0xc3, 0x20, 0x00, 0x08, 0x02, 0x0c, 0x10, 0x22,
0x04, 0x00, 0x00, 0x2c, 0x11, 0x86, 0x00, 0xc0, 0x00, 0x00, 0x12, 0x32,
0x40, 0x89, 0x80, 0x40, 0x40, 0x02, 0x05, 0x50, 0x86, 0x60, 0x82, 0xa4,
0x60, 0x0a, 0x12, 0x4d, 0x80, 0x90, 0x08, 0x12, 0x80, 0x09, 0x02, 0x14,
0x48, 0x01, 0x24, 0x20, 0x8a, 0x00, 0x44, 0x90, 0x04, 0x04, 0x01, 0x02,
0x00, 0xd1, 0x12, 0x00, 0x0a, 0x04, 0x40, 0x00, 0x32, 0x21, 0x81, 0x24,
0x08, 0x19, 0x84, 0x20, 0x02, 0x04, 0x08, 0x89, 0x80, 0x24, 0x02, 0x02,
0x68, 0x18, 0x82, 0x44, 0x42, 0x00, 0x21, 0x40, 0x00, 0x28, 0x01, 0x80,
0x45, 0x82, 0x20, 0x40, 0x11, 0x80, 0x0c, 0x02, 0x00, 0x24, 0x40, 0x90,
0x01, 0x40, 0x20, 0x20, 0x50, 0x20, 0x28, 0x19, 0x00, 0x40, 0x09, 0x20,
0x08, 0x80, 0x04, 0x60, 0x40, 0x80, 0x20, 0x08, 0x30, 0x49, 0x09, 0x34,
0x00, 0x11, 0x24, 0x24, 0x82, 0x00, 0x41, 0xc2, 0x00, 0x04, 0x92, 0x02,
0x24, 0x80, 0x00, 0x0c, 0x02, 0xa0, 0x00, 0x01, 0x06, 0x60, 0x41, 0x04,
0x21, 0xd0, 0x00, 0x01, 0x01, 0x00, 0x48, 0x12, 0x84, 0x04, 0x91, 0x12,
0x08, 0x00, 0x24, 0x44, 0x00, 0x12, 0x41, 0x18, 0x26, 0x0c, 0x41, 0x80,
0x00, 0x52, 0x04, 0x20, 0x09, 0x00, 0x24, 0x90, 0x20, 0x48, 0x18, 0x02,
0x00, 0x03, 0xa2, 0x09, 0xd0, 0x14, 0x00, 0x8a, 0x84, 0x25, 0x4a, 0x00,

Page 718
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

Trusted Platform Module Library

0x20, 0x98, 0x14, 0x40, 0x00, 0xa2, 0x05, 0x00, 0x00, 0x00, 0x40, 0x14,
0x01, 0x58, 0x20, 0x2c, 0x80, 0x84, 0x00, 0x09, 0x20, 0x20, 0x91, 0x02,
0x08, 0x02, 0xb0, 0x41, 0x08, 0x30, 0x00, 0x09, 0x10, 0x00, 0x18, 0x02,
0x21, 0x02, 0x02, 0x00, 0x00, 0x24, 0x44, 0x08, 0x12, 0x60, 0x00, 0xb2,
0x44, 0x12, 0x02, 0x0c, 0xc0, 0x80, 0x40, 0xc8, 0x20, 0x04, 0x50, 0x20,
0x05, 0x00, 0xb0, 0x04, 0x0b, 0x04, 0x29, 0x53, 0x00, 0x61, 0x48, 0x30,
0x00, 0x82, 0x20, 0x29, 0x00, 0x16, 0x00, 0x53, 0x22, 0x20, 0x43, 0x10,
0x48, 0x00, 0x80, 0x04, 0xd2, 0x00, 0x40, 0x00, 0xa2, 0x44, 0x03, 0x80,
0x29, 0x00, 0x04, 0x08, 0xc0, 0x04, 0x64, 0x40, 0x30, 0x28, 0x09, 0x84,
0x44, 0x50, 0x80, 0x21, 0x02, 0x92, 0x00, 0xc0, 0x10, 0x60, 0x88, 0x22,
0x08, 0x80, 0x00, 0x00, 0x18, 0x84, 0x04, 0x83, 0x96, 0x00, 0x81, 0x20,
0x05, 0x02, 0x00, 0x45, 0x88, 0x84, 0x00, 0x51, 0x20, 0x20, 0x51, 0x86,
0x41, 0x4b, 0x94, 0x00, 0x80, 0x00, 0x08, 0x11, 0x20, 0x4c, 0x58, 0x80,
0x04, 0x03, 0x06, 0x20, 0x89, 0x00, 0x05, 0x08, 0x22, 0x05, 0x90, 0x00,
0x40, 0x00, 0x82, 0x09, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x41, 0xc2, 0x20,
0x08, 0x00, 0x16, 0x08, 0x40, 0x26, 0x21, 0xd0, 0x90, 0x08, 0x81, 0x90,
0x41, 0x00, 0x02, 0x44, 0x08, 0x10, 0x0c, 0x0a, 0x86, 0x09, 0x90, 0x04,
0x00, 0xc8, 0xa0, 0x04, 0x08, 0x30, 0x20, 0x89, 0x84, 0x00, 0x11, 0x22,
0x2c, 0x40, 0x00, 0x08, 0x02, 0xb0, 0x01, 0x48, 0x02, 0x01, 0x09, 0x20,
0x04, 0x03, 0x04, 0x00, 0x80, 0x02, 0x60, 0x42, 0x30, 0x21, 0x4a, 0x10,
0x44, 0x09, 0x02, 0x00, 0x01, 0x24, 0x00, 0x12, 0x82, 0x21, 0x80, 0xa4,
0x20, 0x10, 0x02, 0x04, 0x91, 0xa0, 0x40, 0x18, 0x04, 0x00, 0x02, 0x06,
0x69, 0x09, 0x00, 0x05, 0x58, 0x02, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00,
0x00, 0x03, 0x92, 0x20, 0x00, 0x34, 0x01, 0xc8, 0x20, 0x48, 0x08, 0x30,
0x08, 0x42, 0x80, 0x20, 0x91, 0x90, 0x68, 0x01, 0x04, 0x40, 0x12, 0x02,
0x61, 0x00, 0x12, 0x08, 0x01, 0xa0, 0x00, 0x11, 0x04, 0x21, 0x48, 0x04,
0x24, 0x92, 0x00, 0x0c, 0x01, 0x84, 0x04, 0x00, 0x00, 0x01, 0x12, 0x96,
0x40, 0x01, 0xa0, 0x41, 0x88, 0x22, 0x28, 0x88, 0x00, 0x44, 0x42, 0x80,
0x24, 0x12, 0x14, 0x01, 0x42, 0x90, 0x60, 0x1a, 0x10, 0x04, 0x81, 0x10,
0x48, 0x08, 0x06, 0x29, 0x83, 0x02, 0x40, 0x02, 0x24, 0x64, 0x80, 0x10,
0x05, 0x80, 0x10, 0x40, 0x02, 0x02, 0x08, 0x42, 0x84, 0x01, 0x09, 0x20,
0x04, 0x50, 0x00, 0x60, 0x11, 0x30, 0x40, 0x13, 0x02, 0x04, 0x81, 0x00,
0x09, 0x08, 0x20, 0x45, 0x4a, 0x10, 0x61, 0x90, 0x26, 0x0c, 0x08, 0x02,
0x21, 0x91, 0x00, 0x60, 0x02, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x08, 0x06,
0x08, 0x48, 0x84, 0x08, 0x11, 0x02, 0x00, 0x80, 0xa4, 0x00, 0x5a, 0x20,
0x00, 0x88, 0x04, 0x04, 0x02, 0x00, 0x09, 0x00, 0x14, 0x08, 0x49, 0x14,
0x20, 0xc8, 0x00, 0x04, 0x91, 0xa0, 0x40, 0x59, 0x80, 0x00, 0x12, 0x10,
0x00, 0x80, 0x80, 0x65, 0x00, 0x00, 0x04, 0x00, 0x80, 0x40, 0x19, 0x00,
0x21, 0x03, 0x84, 0x60, 0xc0, 0x04, 0x24, 0x1a, 0x12, 0x61, 0x80, 0x80,
0x08, 0x02, 0x04, 0x09, 0x42, 0x12, 0x20, 0x08, 0x34, 0x04, 0x90, 0x20,
0x01, 0x01, 0xa0, 0x00, 0x0b, 0x00, 0x08, 0x91, 0x92, 0x40, 0x02, 0x34,
0x40, 0x88, 0x10, 0x61, 0x19, 0x02, 0x00, 0x40, 0x04, 0x25, 0xc0, 0x80,
0x68, 0x08, 0x04, 0x21, 0x80, 0x22, 0x04, 0x00, 0xa0, 0x0c, 0x01, 0x84,
0x20, 0x41, 0x00, 0x08, 0x8a, 0x00, 0x20, 0x8a, 0x00, 0x48, 0x88, 0x04,
0x04, 0x11, 0x82, 0x08, 0x40, 0x86, 0x09, 0x49, 0xa4, 0x40, 0x00, 0x10,
0x01, 0x01, 0xa2, 0x04, 0x50, 0x80, 0x0c, 0x80, 0x00, 0x48, 0x82, 0xa0,
0x01, 0x18, 0x12, 0x41, 0x01, 0x04, 0x48, 0x41, 0x00, 0x24, 0x01, 0x00,
0x00, 0x88, 0x14, 0x00, 0x02, 0x00, 0x68, 0x01, 0x20, 0x08, 0x4a, 0x22,
0x08, 0x83, 0x80, 0x00, 0x89, 0x04, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x34,
0x04, 0x00, 0x82, 0x28, 0x02, 0x02, 0x41, 0x4a, 0x90, 0x05, 0x82, 0x02,
0x09, 0x80, 0x24, 0x04, 0x41, 0x00, 0x01, 0x92, 0x80, 0x28, 0x01, 0x14,
0x00, 0x50, 0x20, 0x4c, 0x10, 0xb0, 0x04, 0x43, 0xa4, 0x21, 0x90, 0x04,
0x01, 0x02, 0x00, 0x44, 0x48, 0x00, 0x64, 0x08, 0x06, 0x00, 0x42, 0x20,
0x08, 0x02, 0x92, 0x01, 0x4a, 0x00, 0x20, 0x50, 0x32, 0x25, 0x90, 0x22,
0x04, 0x09, 0x00, 0x08, 0x11, 0x80, 0x21, 0x01, 0x10, 0x05, 0x00, 0x32,
0x08, 0x88, 0x94, 0x08, 0x08, 0x24, 0x0d, 0xc1, 0x80, 0x40, 0x0b, 0x20,
0x40, 0x18, 0x12, 0x04, 0x00, 0x22, 0x40, 0x10, 0x26, 0x05, 0xc1, 0x82,
0x00, 0x01, 0x30, 0x24, 0x02, 0x22, 0x41, 0x08, 0x24, 0x48, 0x1a, 0x00,
0x25, 0xd2, 0x12, 0x28, 0x42, 0x00, 0x04, 0x40, 0x30, 0x41, 0x00, 0x02,
0x00, 0x13, 0x20, 0x24, 0xd1, 0x84, 0x08, 0x89, 0x80, 0x04, 0x52, 0x00,
0x44, 0x18, 0xa4, 0x00, 0x00, 0x06, 0x20, 0x91, 0x10, 0x09, 0x42, 0x20,
0x24, 0x40, 0x30, 0x28, 0x00, 0x84, 0x40, 0x40, 0x80, 0x08, 0x10, 0x04,
0x09, 0x08, 0x04, 0x40, 0x08, 0x22, 0x00, 0x19, 0x02, 0x00, 0x00, 0x80,
0x2c, 0x02, 0x02, 0x21, 0x01, 0x90, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x34,
0x48, 0x58, 0x20, 0x01, 0x43, 0x04, 0x20, 0x80, 0x14, 0x00, 0x90, 0x00,
0x6d, 0x11, 0x00, 0x00, 0x40, 0x20, 0x00, 0x03, 0x10, 0x40, 0x88, 0x30,

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 719
April 15, 2019

Trusted Platform Module Library
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

Part 4: Supporting Routines

0x05, 0x4a, 0x00, 0x65, 0x10, 0x24, 0x08, 0x18, 0x84, 0x28, 0x03, 0x80,
0x20, 0x42, 0xb0, 0x40, 0x00, 0x10, 0x69, 0x19, 0x04, 0x00, 0x00, 0x80,
0x04, 0xc2, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x22, 0x25, 0x08, 0x96,
0x04, 0x02, 0x22, 0x00, 0xd0, 0x10, 0x29, 0x01, 0xa0, 0x60, 0x08, 0x10,
0x04, 0x01, 0x16, 0x44, 0x10, 0x02, 0x28, 0x02, 0x82, 0x48, 0x40, 0x84,
0x20, 0x90, 0x22, 0x28, 0x80, 0x04, 0x00, 0x40, 0x04, 0x24, 0x00, 0x80,
0x29, 0x03, 0x10, 0x60, 0x48, 0x00, 0x00, 0x81, 0xa0, 0x00, 0x51, 0x20,
0x0c, 0xd1, 0x00, 0x01, 0x41, 0x20, 0x04, 0x92, 0x00, 0x00, 0x10, 0x92,
0x00, 0x42, 0x04, 0x05, 0x01, 0x86, 0x40, 0x80, 0x10, 0x20, 0x52, 0x20,
0x21, 0x00, 0x10, 0x48, 0x0a, 0x02, 0x00, 0xd0, 0x12, 0x41, 0x48, 0x80,
0x04, 0x00, 0x00, 0x48, 0x09, 0x22, 0x04, 0x00, 0x24, 0x00, 0x43, 0x10,
0x60, 0x0a, 0x00, 0x44, 0x12, 0x20, 0x2c, 0x08, 0x20, 0x44, 0x00, 0x84,
0x09, 0x40, 0x06, 0x08, 0xc1, 0x00, 0x40, 0x80, 0x20, 0x00, 0x98, 0x12,
0x48, 0x10, 0xa2, 0x20, 0x00, 0x84, 0x48, 0xc0, 0x10, 0x20, 0x90, 0x12,
0x08, 0x98, 0x82, 0x00, 0x0a, 0xa0, 0x04, 0x03, 0x00, 0x28, 0xc3, 0x00,
0x44, 0x42, 0x10, 0x04, 0x08, 0x04, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00,
0x21, 0x03, 0x80, 0x04, 0x88, 0x12, 0x69, 0x10, 0x00, 0x04, 0x08, 0x04,
0x04, 0x02, 0x84, 0x48, 0x49, 0x04, 0x20, 0x18, 0x02, 0x64, 0x80, 0x30,
0x08, 0x01, 0x02, 0x00, 0x52, 0x12, 0x49, 0x08, 0x20, 0x41, 0x88, 0x10,
0x48, 0x08, 0x34, 0x00, 0x01, 0x86, 0x05, 0xd0, 0x00, 0x00, 0x83, 0x84,
0x21, 0x40, 0x02, 0x41, 0x10, 0x80, 0x48, 0x40, 0xa2, 0x20, 0x51, 0x00,
0x00, 0x49, 0x00, 0x01, 0x90, 0x20, 0x40, 0x18, 0x02, 0x40, 0x02, 0x22,
0x05, 0x40, 0x80, 0x08, 0x82, 0x10, 0x20, 0x18, 0x00, 0x05, 0x01, 0x82,
0x40, 0x58, 0x00, 0x04, 0x81, 0x90, 0x29, 0x01, 0xa0, 0x64, 0x00, 0x22,
0x40, 0x01, 0xa2, 0x00, 0x18, 0x04, 0x0d, 0x00, 0x00, 0x60, 0x80, 0x94,
0x60, 0x82, 0x10, 0x0d, 0x80, 0x30, 0x0c, 0x12, 0x20, 0x00, 0x00, 0x12,
0x40, 0xc0, 0x20, 0x21, 0x58, 0x02, 0x41, 0x10, 0x80, 0x44, 0x03, 0x02,
0x04, 0x13, 0x90, 0x29, 0x08, 0x00, 0x44, 0xc0, 0x00, 0x21, 0x00, 0x26,
0x00, 0x1a, 0x80, 0x01, 0x13, 0x14, 0x20, 0x0a, 0x14, 0x20, 0x00, 0x32,
0x61, 0x08, 0x00, 0x40, 0x42, 0x20, 0x09, 0x80, 0x06, 0x01, 0x81, 0x80,
0x60, 0x42, 0x00, 0x68, 0x90, 0x82, 0x08, 0x42, 0x80, 0x04, 0x02, 0x80,
0x09, 0x0b, 0x04, 0x00, 0x98, 0x00, 0x0c, 0x81, 0x06, 0x44, 0x48, 0x84,
0x28, 0x03, 0x92, 0x00, 0x01, 0x80, 0x40, 0x0a, 0x00, 0x0c, 0x81, 0x02,
0x08, 0x51, 0x04, 0x28, 0x90, 0x02, 0x20, 0x09, 0x10, 0x60, 0x00, 0x00,
0x09, 0x81, 0xa0, 0x0c, 0x00, 0xa4, 0x09, 0x00, 0x02, 0x28, 0x80, 0x20,
0x00, 0x02, 0x02, 0x04, 0x81, 0x14, 0x04, 0x00, 0x04, 0x09, 0x11, 0x12,
0x60, 0x40, 0x20, 0x01, 0x48, 0x30, 0x40, 0x11, 0x00, 0x08, 0x0a, 0x86,
0x00, 0x00, 0x04, 0x60, 0x81, 0x04, 0x01, 0xd0, 0x02, 0x41, 0x18, 0x90,
0x00, 0x0a, 0x20, 0x00, 0xc1, 0x06, 0x01, 0x08, 0x80, 0x64, 0xca, 0x10,
0x04, 0x99, 0x80, 0x48, 0x01, 0x82, 0x20, 0x50, 0x90, 0x48, 0x80, 0x84,
0x20, 0x90, 0x22, 0x00, 0x19, 0x00, 0x04, 0x18, 0x20, 0x24, 0x10, 0x86,
0x40, 0xc2, 0x00, 0x24, 0x12, 0x10, 0x44, 0x00, 0x16, 0x08, 0x10, 0x24,
0x00, 0x12, 0x06, 0x01, 0x08, 0x90, 0x00, 0x12, 0x02, 0x4d, 0x10, 0x80,
0x40, 0x50, 0x22, 0x00, 0x43, 0x10, 0x01, 0x00, 0x30, 0x21, 0x0a, 0x00,
0x00, 0x01, 0x14, 0x00, 0x10, 0x84, 0x04, 0xc1, 0x10, 0x29, 0x0a, 0x00,
0x01, 0x8a, 0x00, 0x20, 0x01, 0x12, 0x0c, 0x49, 0x20, 0x04, 0x81, 0x00,
0x48, 0x01, 0x04, 0x60, 0x80, 0x12, 0x0c, 0x08, 0x10, 0x48, 0x4a, 0x04,
0x28, 0x10, 0x00, 0x28, 0x40, 0x84, 0x45, 0x50, 0x10, 0x60, 0x10, 0x06,
0x44, 0x01, 0x80, 0x09, 0x00, 0x86, 0x01, 0x42, 0xa0, 0x00, 0x90, 0x00,
0x05, 0x90, 0x22, 0x40, 0x41, 0x00, 0x08, 0x80, 0x02, 0x08, 0xc0, 0x00,
0x01, 0x58, 0x30, 0x49, 0x09, 0x14, 0x00, 0x41, 0x02, 0x0c, 0x02, 0x80,
0x40, 0x89, 0x00, 0x24, 0x08, 0x10, 0x05, 0x90, 0x32, 0x40, 0x0a, 0x82,
0x08, 0x00, 0x12, 0x61, 0x00, 0x04, 0x21, 0x00, 0x22, 0x04, 0x10, 0x24,
0x08, 0x0a, 0x04, 0x01, 0x10, 0x00, 0x20, 0x40, 0x84, 0x04, 0x88, 0x22,
0x20, 0x90, 0x12, 0x00, 0x53, 0x06, 0x24, 0x01, 0x04, 0x40, 0x0b, 0x14,
0x60, 0x82, 0x02, 0x0d, 0x10, 0x90, 0x0c, 0x08, 0x20, 0x09, 0x00, 0x14,
0x09, 0x80, 0x80, 0x24, 0x82, 0x00, 0x40, 0x01, 0x02, 0x44, 0x01, 0x20,
0x0c, 0x40, 0x84, 0x40, 0x0a, 0x10, 0x41, 0x00, 0x30, 0x05, 0x09, 0x80,
0x44, 0x08, 0x20, 0x20, 0x02, 0x00, 0x49, 0x43, 0x20, 0x21, 0x00, 0x20,
0x00, 0x01, 0xb6, 0x08, 0x40, 0x04, 0x08, 0x02, 0x80, 0x01, 0x41, 0x80,
0x40, 0x08, 0x10, 0x24, 0x00, 0x20, 0x04, 0x12, 0x86, 0x09, 0xc0, 0x12,
0x21, 0x81, 0x14, 0x04, 0x00, 0x02, 0x20, 0x89, 0xb4, 0x44, 0x12, 0x80,
0x00, 0xd1, 0x00, 0x69, 0x40, 0x80, 0x00, 0x42, 0x12, 0x00, 0x18, 0x04,
0x00, 0x49, 0x06, 0x21, 0x02, 0x04, 0x28, 0x02, 0x84, 0x01, 0xc0, 0x10,
0x68, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, 0x91, 0x10, 0x01, 0x81, 0x24,
0x04, 0xd2, 0x10, 0x4c, 0x88, 0x86, 0x00, 0x10, 0x80, 0x0c, 0x02, 0x14,

Page 720
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

Trusted Platform Module Library

0x00, 0x8a, 0x90, 0x40, 0x18, 0x20, 0x21, 0x80, 0xa4, 0x00, 0x58, 0x24,
0x20, 0x10, 0x10, 0x60, 0xc1, 0x30, 0x41, 0x48, 0x02, 0x48, 0x09, 0x00,
0x40, 0x09, 0x02, 0x05, 0x11, 0x82, 0x20, 0x4a, 0x20, 0x24, 0x18, 0x02,
0x0c, 0x10, 0x22, 0x0c, 0x0a, 0x04, 0x00, 0x03, 0x06, 0x48, 0x48, 0x04,
0x04, 0x02, 0x00, 0x21, 0x80, 0x84, 0x00, 0x18, 0x00, 0x0c, 0x02, 0x12,
0x01, 0x00, 0x14, 0x05, 0x82, 0x10, 0x41, 0x89, 0x12, 0x08, 0x40, 0xa4,
0x21, 0x01, 0x84, 0x48, 0x02, 0x10, 0x60, 0x40, 0x02, 0x28, 0x00, 0x14,
0x08, 0x40, 0xa0, 0x20, 0x51, 0x12, 0x00, 0xc2, 0x00, 0x01, 0x1a, 0x30,
0x40, 0x89, 0x12, 0x4c, 0x02, 0x80, 0x00, 0x00, 0x14, 0x01, 0x01, 0xa0,
0x21, 0x18, 0x22, 0x21, 0x18, 0x06, 0x40, 0x01, 0x80, 0x00, 0x90, 0x04,
0x48, 0x02, 0x30, 0x04, 0x08, 0x00, 0x05, 0x88, 0x24, 0x08, 0x48, 0x04,
0x24, 0x02, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x65, 0x11, 0x90,
0x00, 0x0a, 0x82, 0x04, 0xc3, 0x04, 0x60, 0x48, 0x24, 0x04, 0x92, 0x02,
0x44, 0x88, 0x80, 0x40, 0x18, 0x06, 0x29, 0x80, 0x10, 0x01, 0x00, 0x00,
0x44, 0xc8, 0x10, 0x21, 0x89, 0x30, 0x00, 0x4b, 0xa0, 0x01, 0x10, 0x14,
0x00, 0x02, 0x94, 0x40, 0x00, 0x20, 0x65, 0x00, 0xa2, 0x0c, 0x40, 0x22,
0x20, 0x81, 0x12, 0x20, 0x82, 0x04, 0x01, 0x10, 0x00, 0x08, 0x88, 0x00,
0x00, 0x11, 0x80, 0x04, 0x42, 0x80, 0x40, 0x41, 0x14, 0x00, 0x40, 0x32,
0x2c, 0x80, 0x24, 0x04, 0x19, 0x00, 0x00, 0x91, 0x00, 0x20, 0x83, 0x00,
0x05, 0x40, 0x20, 0x09, 0x01, 0x84, 0x40, 0x40, 0x20, 0x20, 0x11, 0x00,
0x40, 0x41, 0x90, 0x20, 0x00, 0x00, 0x40, 0x90, 0x92, 0x48, 0x18, 0x06,
0x08, 0x81, 0x80, 0x48, 0x01, 0x34, 0x24, 0x10, 0x20, 0x04, 0x00, 0x20,
0x04, 0x18, 0x06, 0x2d, 0x90, 0x10, 0x01, 0x00, 0x90, 0x00, 0x0a, 0x22,
0x01, 0x00, 0x22, 0x00, 0x11, 0x84, 0x01, 0x01, 0x00, 0x20, 0x88, 0x00,
0x44, 0x00, 0x22, 0x01, 0x00, 0xa6, 0x40, 0x02, 0x06, 0x20, 0x11, 0x00,
0x01, 0xc8, 0xa0, 0x04, 0x8a, 0x00, 0x28, 0x19, 0x80, 0x00, 0x52, 0xa0,
0x24, 0x12, 0x12, 0x09, 0x08, 0x24, 0x01, 0x48, 0x00, 0x04, 0x00, 0x24,
0x40, 0x02, 0x84, 0x08, 0x00, 0x04, 0x48, 0x40, 0x90, 0x60, 0x0a, 0x22,
0x01, 0x88, 0x14, 0x08, 0x01, 0x02, 0x08, 0xd3, 0x00, 0x20, 0xc0, 0x90,
0x24, 0x10, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x0a, 0xa0, 0x00, 0x80, 0x00,
0x01, 0x09, 0x00, 0x20, 0x52, 0x02, 0x25, 0x00, 0x24, 0x04, 0x02, 0x84,
0x24, 0x10, 0x92, 0x40, 0x02, 0xa0, 0x40, 0x00, 0x22, 0x08, 0x11, 0x04,
0x08, 0x01, 0x22, 0x00, 0x42, 0x14, 0x00, 0x09, 0x90, 0x21, 0x00, 0x30,
0x6c, 0x00, 0x00, 0x0c, 0x00, 0x22, 0x09, 0x90, 0x10, 0x28, 0x40, 0x00,
0x20, 0xc0, 0x20, 0x00, 0x90, 0x00, 0x40, 0x01, 0x82, 0x05, 0x12, 0x12,
0x09, 0xc1, 0x04, 0x61, 0x80, 0x02, 0x28, 0x81, 0x24, 0x00, 0x49, 0x04,
0x08, 0x10, 0x86, 0x29, 0x41, 0x80, 0x21, 0x0a, 0x30, 0x49, 0x88, 0x90,
0x00, 0x41, 0x04, 0x29, 0x81, 0x80, 0x41, 0x09, 0x00, 0x40, 0x12, 0x10,
0x40, 0x00, 0x10, 0x40, 0x48, 0x02, 0x05, 0x80, 0x02, 0x21, 0x40, 0x20,
0x00, 0x58, 0x20, 0x60, 0x00, 0x90, 0x48, 0x00, 0x80, 0x28, 0xc0, 0x80,
0x48, 0x00, 0x00, 0x44, 0x80, 0x02, 0x00, 0x09, 0x06, 0x00, 0x12, 0x02,
0x01, 0x00, 0x10, 0x08, 0x83, 0x10, 0x45, 0x12, 0x00, 0x2c, 0x08, 0x04,
0x44, 0x00, 0x20, 0x20, 0xc0, 0x10, 0x20, 0x01, 0x00, 0x05, 0xc8, 0x20,
0x04, 0x98, 0x10, 0x08, 0x10, 0x00, 0x24, 0x02, 0x16, 0x40, 0x88, 0x00,
0x61, 0x88, 0x12, 0x24, 0x80, 0xa6, 0x00, 0x42, 0x00, 0x08, 0x10, 0x06,
0x48, 0x40, 0xa0, 0x00, 0x50, 0x20, 0x04, 0x81, 0xa4, 0x40, 0x18, 0x00,
0x08, 0x10, 0x80, 0x01, 0x01};#if RSA_KEY_SIEVE && SIMULATION && RSA_INSTRUMENTUINT32 PrimeIndex = 0;
UINT32 failedAtIteration[10] = {0};UINT32 PrimeCounts[3] = {0};UINT32 MillerRabinTrials[3] = {0};UINT32 totalFieldsSieved[3] = {0};UINT32 bitsInFieldAfterSieve[3] = {0};UINT32 emptyFieldsSieved[3] = {0};UINT32 noPrimeFields[3] = {0};UINT32 primesChecked[3] = {0};UINT16 lastSievePrime = 0;
#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 721
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.21 RsaKeyCache.c
10.2.21.1 Introduction
This file contains the functions to implement the RSA key cache that can be used to speed up simulation.
Only one key is created for each supported key size and it is returned whenever a key of that size isrequested.
If desired, the key cache can be populated from a file. This allows multiple TPM to run with the same RSA
keys. Also, when doing simulation, the DRBG will use preset sequences so it is not too hard to repeat
sequences for debug or profile or stress.
When the key cache is enabled, a call to CryptRsaGenerateKey() will call the GetCachedRsaKey(). If thecache is enabled and populated, then the cached key of the requested size is returned. If a key of therequested size is not available, the no key is loaded and the requested key will need to be generated. If
the cache is not populated, the TPM will open a file that has the appropriate name for the type of keys
required (CRT or no-CRT). If the file is the right size, it is used. If the file doesn't exist or the file does nothave the correct size, the TMP will populate the cache with new keys of the required size and write thecache data to the file so that they will be available the next time.
Currently, if two simulations are being run with TPM's that have different RSA key sizes (e.g,, one with
1024 and 2048 and another with 2048 and 3072, then the files will not match for the both of them andthey will both try to overwrite the other's cache file. I may try to do something about this if necessary.
10.2.21.2 Includes, Types, Locals, and Defines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include "Tpm.h"#if USE_RSA_KEY_CACHE#include <stdio.h>#include "Platform_fp.h"#include "RsaKeyCache_fp.h"#if CRT_FORMAT_RSA == YES#define CACHE_FILE_NAME "RsaKeyCacheCrt.data"#else#define CACHE_FILE_NAME "RsaKeyCacheNoCrt.data"#endiftypedef struct _RSA_KEY_CACHE_{TPM2B_PUBLIC_KEY_RSA
publicModulus;
TPM2B_PRIVATE_KEY_RSA
privateExponent;} RSA_KEY_CACHE;

Determine the number of RSA key sizes for the cache
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

TPMI_RSA_KEY_BITS
SupportedRsaKeySizes[] = {#if RSA_1024
1024,#endif#if RSA_2048
2048,#endif#if RSA_3072
3072,#endif#if RSA_4096
4096,#endif0};#define RSA_KEY_CACHE_ENTRIES (RSA_1024 + RSA_2048 + RSA_3072 + RSA_4096)

Page 722
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

The key cache holds one entry for each of the supported key sizes
32

RSA_KEY_CACHE

s_rsaKeyCache[RSA_KEY_CACHE_ENTRIES];

Indicates if the key cache is loaded. It can be loaded and enabled or disabled.
33

BOOL

s_keyCacheLoaded = 0;

Indicates if the key cache is enabled34

int

s_rsaKeyCacheEnabled = FALSE;

10.2.21.2.1

RsaKeyCacheControl()

Used to enable and disable the RSA key cache.
35
36
37
38
39
40
41

LIB_EXPORT void
RsaKeyCacheControl(
int

state

)
{
s_rsaKeyCacheEnabled = state;}

10.2.21.2.2

InitializeKeyCache()This will initialize the key cache and attempt to write it to a file for later use.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

Return Value

Meaning

TRUE(1)success

FALSE(0)failurestatic BOOL
InitializeKeyCache(
TPMT_PUBLIC
TPMT_SENSITIVERAND_STATE*publicArea,*sensitive,
*rand

int
TPM_KEY_BITS
BOOL

index;
keySave = publicArea->parameters.rsaDetail.keyBits;
OK = TRUE;// IN: if not NULL, the deterministic//
RNG state){//s_rsaKeyCacheEnabled = FALSE;
for(index = 0; OK && index < RSA_KEY_CACHE_ENTRIES; index++){publicArea->parameters.rsaDetail.keyBits= SupportedRsaKeySizes[index];OK = (CryptRsaGenerateKey(publicArea, sensitive, rand) == TPM_RC_SUCCESS);
if(OK){
s_rsaKeyCache[index].publicModulus = publicArea->unique.rsa;
s_rsaKeyCache[index].privateExponent = sensitive->sensitive.rsa;}}
publicArea->parameters.rsaDetail.keyBits = keySave;s_keyCacheLoaded = OK;#if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 723
April 15, 2019

Trusted Platform Module Library
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

Part 4: Supporting Routines

if(OK){
FILE
const char*cacheFile;*fn = CACHE_FILE_NAME;#if defined _MSC_VER
if(fopen_s(&cacheFile, fn, "w+b") != 0)#else
cacheFile = fopen(fn, "w+b");if(NULL == cacheFile)#endif{printf("Can't open %s for write.\n", fn);}else{
fseek(cacheFile, 0, SEEK_SET);
if(fwrite(s_rsaKeyCache, 1, sizeof(s_rsaKeyCache), cacheFile)!= sizeof(s_rsaKeyCache)){printf("Error writing cache to %s.", fn);}}
if(cacheFile)fclose(cacheFile);}#endifreturn s_keyCacheLoaded;}

10.2.21.2.3

KeyCacheLoaded()

Checks that key cache is loaded.

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

Return Value

Meaning

TRUE(1)cache loaded

FALSE(0)cache not loaded

static BOOL
KeyCacheLoaded(
TPMT_PUBLIC
TPMT_SENSITIVERAND_STATE*publicArea,*sensitive,*rand// IN: if not NULL, the deterministic//
RNG state){#if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE
if(!s_keyCacheLoaded){FILE*cacheFile;const char *fn = CACHE_FILE_NAME;#if defined _MSC_VER && 1
if(fopen_s(&cacheFile, fn, "r+b") == 0)#else
cacheFile = fopen(fn, "r+b");if(NULL != cacheFile)#endif{fseek(cacheFile, 0L, SEEK_END);
if(ftell(cacheFile) == sizeof(s_rsaKeyCache)){fseek(cacheFile, 0L, SEEK_SET);

Page 724
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
122
123
124
125
126
127
128
129
130
131
132
133

s_keyCacheLoaded = (fread(&s_rsaKeyCache, 1, sizeof(s_rsaKeyCache), cacheFile)== sizeof(s_rsaKeyCache));}fclose(cacheFile);}}#endifif(!s_keyCacheLoaded)s_rsaKeyCacheEnabled = InitializeKeyCache(publicArea, sensitive, rand);return s_keyCacheLoaded;}

10.2.21.2.4

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

Trusted Platform Module Library

GetCachedRsaKey()

Return Value

Meaning

TRUE(1)

key loaded

FALSE(0)key not loaded

BOOL
GetCachedRsaKey(
TPMT_PUBLIC
TPMT_SENSITIVERAND_STATE*publicArea,*sensitive,*rand// IN: if not NULL, the deterministic//
RNG state

)
{
int
int

keyBits = publicArea->parameters.rsaDetail.keyBits;
index;//
if(KeyCacheLoaded(publicArea, sensitive, rand)){for(index = 0; index < RSA_KEY_CACHE_ENTRIES; index++){if((s_rsaKeyCache[index].publicModulus.t.size * 8) == keyBits){publicArea->unique.rsa = s_rsaKeyCache[index].publicModulus;
sensitive->sensitive.rsa = s_rsaKeyCache[index].privateExponent;
return TRUE;}}
return FALSE;}
return s_keyCacheLoaded;}#endif// defined SIMULATION && defined USE_RSA_KEY_CACHE

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 725
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.22 Ticket.c
10.2.22.1 Introduction
This clause contains the functions used for ticket computations.
10.2.22.2 Includes
1#include "Tpm.h"

10.2.22.3 Functions
10.2.22.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

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Return Value

Meaning

TRUE(1)

safe to produce ticket

FALSE(0)not safe to produce ticket

BOOL
TicketIsSafe(
TPM2B)*buffer

TPM_GENERATED
BYTE
BYTE

valueToCompare = TPM_GENERATED_VALUE;
bufferToCompare[sizeof(valueToCompare)];*marshalBuffer;{//// If the buffer size is less than the size of TPM_GENERATED_VALUE, assume// it is not safe to generate a ticket
if(buffer->size < sizeof(valueToCompare))return FALSE;
marshalBuffer = bufferToCompare;
TPM_GENERATED_Marshal(&valueToCompare, &marshalBuffer, NULL);
if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare)))return FALSE;
else
return TRUE;}

10.2.22.3.2

TicketComputeVerified()

This function creates a TPMT_TK_VERIFIED ticket.
22
23
24
25
26
27
28
29
30
31

void
TicketComputeVerified(
TPMI_RH_HIERARCHYTPM2B_DIGESTTPM2B_NAME
TPMT_TK_VERIFIED)

hierarchy,*digest,*keyName,*ticketTPM2B_PROOF
HMAC_STATE*proof;hmacState;// IN: hierarchy constant for ticket// IN: digest// IN: name of key that signed the values// OUT: verified ticket{

Page 726
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Trusted Platform Module Library//// Fill in ticket fields
ticket->tag = TPM_ST_VERIFIED;
ticket->hierarchy = hierarchy;
proof = HierarchyGetProof(hierarchy);// Start HMAC using the proof value of the hierarchy as the HMAC key
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,&proof->b);// TPM_ST_VERIFIED
CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);// digest
CryptDigestUpdate2B(&hmacState.hashState, &digest->b);// key name
CryptDigestUpdate2B(&hmacState.hashState, &keyName->b);// doneCryptHmacEnd2B(&hmacState, &ticket->digest.b);
return;}10.2.22.3.3

TicketComputeAuth()This function creates a TPMT_TK_AUTH ticket.
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

void
TicketComputeAuth(
TPM_ST
TPMI_RH_HIERARCHYUINT64BOOL
TPM2B_DIGESTTPM2B_NONCE
TPM2B_NAME
TPMT_TK_AUTH)

type,// IN: the type of ticket.
hierarchy,// IN: hierarchy constant for ticket
timeout,// IN: timeout
expiresOnReset,// IN: flag to indicate if ticket expires on//
TPM Reset*cpHashA,// IN: input cpHashA*policyRef,// IN: input policyRef*entityName,// IN: name of entity*ticket// OUT: Created ticket{
TPM2B_PROOF
HMAC_STATE*proof;hmacState;//// Get proper proof
proof = HierarchyGetProof(hierarchy);// Fill in ticket fields
ticket->tag = type;ticket->hierarchy = hierarchy;// Start HMAC with hierarchy proof as the HMAC key
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,&proof->b);// TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED,
CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag);// cpHash
CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b);// policyRef
CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b);// keyName
CryptDigestUpdate2B(&hmacState.hashState, &entityName->b);// timeout
CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout);
if(timeout != 0){// epoch

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 727
April 15, 2019

Trusted Platform Module Library
91
92
93
94
95
96
97
98
99
100
101
102

Part 4: Supporting Routines

CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE),
g_timeEpoch);// reset countif(expiresOnReset)
CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount),
gp.totalResetCount);}// doneCryptHmacEnd2B(&hmacState, &ticket->digest.b);
return;}10.2.22.3.4

TicketComputeHashCheck()

This function creates a TPMT_TK_HASHCHECK ticket.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

void
TicketComputeHashCheck(
TPMI_RH_HIERARCHY
TPM_ALG_ID
TPM2B_DIGEST
TPMT_TK_HASHCHECK)

hierarchy,
hashAlg,*digest,*ticketTPM2B_PROOF
HMAC_STATE*proof;hmacState;// IN: hierarchy constant for ticket// IN: the hash algorithm for 'digest'// IN: input digest// OUT: Created ticket{//// Get proper proof
proof = HierarchyGetProof(hierarchy);// Fill in ticket fields
ticket->tag = TPM_ST_HASHCHECK;
ticket->hierarchy = hierarchy;// Start HMAC using hierarchy proof as HMAC key
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,&proof->b);// TPM_ST_HASHCHECKCryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);// hash algorithm
CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg);// digest
CryptDigestUpdate2B(&hmacState.hashState, &digest->b);// doneCryptHmacEnd2B(&hmacState, &ticket->digest.b);
return;}10.2.22.3.5

TicketComputeCreation()

This function creates a TPMT_TK_CREATION ticket.
135
136
137
138
139
140
141
142
143

void
TicketComputeCreation(
TPMI_RH_HIERARCHYTPM2B_NAME
TPM2B_DIGEST
TPMT_TK_CREATION)

hierarchy,*name,*creation,*ticketTPM2B_PROOF*proof;// IN: hierarchy for ticket// IN: object name// IN: creation hash// OUT: created ticket{

Page 728
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

HMAC_STATE

Trusted Platform Module LibraryhmacState;// Get proper proof
proof = HierarchyGetProof(hierarchy);// Fill in ticket fields
ticket->tag = TPM_ST_CREATION;
ticket->hierarchy = hierarchy;// Start HMAC using hierarchy proof as HMAC key
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,&proof->b);// TPM_ST_CREATION
CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);// name if provided
if(name != NULL)
CryptDigestUpdate2B(&hmacState.hashState, &name->b);// creation hash
CryptDigestUpdate2B(&hmacState.hashState, &creation->b);// DoneCryptHmacEnd2B(&hmacState, &ticket->digest.b);
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 729
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.23 TpmAsn1.c
10.2.23.1 Includes
1
2
3
4
5

#include "Tpm.h"#define _OIDS_#include "OIDS.h"#include "TpmASN1.h"#include "TpmASN1_fp.h"

10.2.23.2 Unmarshaling Functions
10.2.23.2.1

ASN1UnmarshalContextInitialize()

Function does standard initialization of a context.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Return Value

Meaning

TRUE(1)success

FALSE(0)failureBOOL
ASN1UnmarshalContextInitialize(
ASN1UnmarshalContext
INT16
BYTE

*ctx,
size,
*buffer){
VERIFY(buffer != NULL);VERIFY(size > 0);
ctx->buffer = buffer;ctx->size = size;ctx->offset = 0;
ctx->tag = 0xFF;
return TRUE;
Error:
return FALSE;}

10.2.23.2.2

ASN1DecodeLength()

This function extracts the length of an element from buffer starting at offset.

23
24
25
26
27
28
29
30
31
32

Return Value

Meaning>=0

the extracted length<0

an error

INT16
ASN1DecodeLength(
ASN1UnmarshalContext

*ctx

)
{
BYTE
INT16

first;
value;// Next octet in buffer//
VERIFY(ctx->offset < ctx->size);
first = NEXT_OCTET(ctx);

Page 730
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

Trusted Platform Module Library// If the number of octets of the entity is larger than 127, then the first octet// is the number of octets in the length specifier.
if(first >= 0x80){// Make sure that this length field is contained with the structure being// parsed
CHECK_SIZE(ctx, (first & 0x7F));
if(first == 0x82){// Two octets of size// get the next value
value = (INT16)NEXT_OCTET(ctx);// Make sure that the result will fit in an INT16
VERIFY(value < 0x0080);// Shift up and add next octet
value = (value << 8) + NEXT_OCTET(ctx);}
else if(first == 0x81)
value = NEXT_OCTET(ctx);// Sizes larger than will fit in a INT16 are an error
elsegoto Error;}
else
value = first;// Make sure that the size defined something within the current context
CHECK_SIZE(ctx, value);
return value;
Error:
ctx->size = -1;// Makes everything fail from now on.
return -1;}

10.2.23.2.3

ASN1NextTag()This function extracts the next type from buffer starting at offset. It advances offset as it parses the type
and the length of the type. It returns the length of the type. On return, the length octets starting at offset
are the octets of the type.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

Return Value

Meaning>=0

the number of octets in type<0

an error

INT16
ASN1NextTag(
ASN1UnmarshalContext

*ctx

)
{
// A tag to get?
VERIFY(ctx->offset < ctx->size);// Get it
ctx->tag = NEXT_OCTET(ctx);// Make sure that it is not an extended tag
VERIFY((ctx->tag & 0x1F) != 0x1F);// Get the length field and return that
return ASN1DecodeLength(ctx);
Error:// Attempt to read beyond the end of the context or an illegal tag
ctx->size = -1;// Persistent failurectx->tag = 0xFF;
return -1;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 731
April 15, 2019

Trusted Platform Module Library
84

Part 4: Supporting Routines}

10.2.23.2.4

ASN1GetBitStringValue()

Try to parse a bit string of up to 32 bits from a value that is expected to be a bit string. If there is a generalparsing error, the context->size is set to -1.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

Return Value

Meaning

TRUE(1)success

FALSE(0)failureBOOL
ASN1GetBitStringValue(
ASN1UnmarshalContext
UINT32

*ctx,
*val

)
{
int
INT16
UINT32

shift;
length;value = 0;//
VERIFY((length = ASN1NextTag(ctx)) >= 1);
VERIFY(ctx->tag == ASN1_BITSTRING);// Get the shift value for the bit field (how many bits to loop off of the end)
shift = NEXT_OCTET(ctx);
length--;// the shift count has to make sense
VERIFY((shift < 8) && ((length > 0) || (shift == 0)));// if there are any bytes leftfor(; length > 0; length--){if(length > 1){// for all but the last octet, just shift and add the new octet
VERIFY((value & 0xFF000000) == 0); // can't loose significant bits
value = (value << 8) + NEXT_OCTET(ctx);}
else{// for the last octet, just shift the accumulated value enough to// accept the significant bits in the last octet and shift the last// octet down
VERIFY(((value & (0xFF000000 << (8 - shift)))) == 0);value = (value << (8 - shift)) + (NEXT_OCTET(ctx) >> shift);}}*val = value;
return TRUE;
Error:
ctx->size = -1;
return FALSE;}

10.2.23.3 Marshaling Functions
10.2.23.3.1

Introduction

Marshaling of an ASN.1 structure is accomplished from the bottom up. That is, the things that will be at
the end of the structure are added last. To manage the collecting of the relative sizes, start a context forPage 732
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

the outermost container, if there is one, and then placing items in from the bottom up. If the bottom-mostitem is also within a structure, create a nested context by calling ASN1StartMarshalingContext().
The context control structure contains a buffer pointer, an offset, an end and a stack. offset is the offset
from the start of the buffer of the last added byte. When offset reaches 0, the buffer is full. offset is asigned value so that, when it becomes negative, there is an overflow. Only two functions are allowed tomove bytes into the buffer: ASN1PushByte() and ASN1PushBytes(). These functions make sure that nodata is written beyond the end of the buffer.
When a new context is started, the current value of end is pushed on the stack and end is set to 'offset.
As bytes are added, offset gets smaller. At any time, the count of bytes in the current context is simply
end - offset.
Since starting a new context involves setting end = offset, the number of bytes in the context starts at 0.
The nominal way of ending a context is to use end - offset to set the length value, and then a tag is added
to the buffer. Then the previous end value is popped meaning that the context just ended becomes a
member of the now current context.
The nominal strategy for building a completed ASN.1 structure is to push everything into the buffer andthen move everything to the start of the buffer. The move is simple as the size of the move is the initialend value minus the final offset value. The destination is buffer and the source is buffer + offset. As
Skippy would say "Easy peasy, Joe."
It is not necessary to provide a buffer into which the data is placed. If no buffer is provided, then themarshaling process will return values needed for marshaling. On strategy for filling the buffer would be to
execute the process for building the structure without using a buffer. This would return the overall size ofthe structure. Then that amount of data could be allocated for the buffer and the fill process executed
again with the data going into the buffer. At the end, the data would be in its final resting place.
10.2.23.3.2

ASN1InitialializeMarshalContext()

This creates a structure for handling marshaling of an ASN.1 formatted data structure.
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

void
ASN1InitialializeMarshalContext(
ASN1MarshalContext
INT16
BYTE

*ctx,
length,*buffer){
ctx->buffer = buffer;if(buffer)ctx->offset = length;else
ctx->offset = INT16_MAX;
ctx->end = ctx->offset;
ctx->depth = -1;}

10.2.23.3.3

ASN1StartMarshalContext()

This starts a new constructed element. It is constructed on top of the value that was previously placed in
the structure.
142
143
144
145
146
147
148

void
ASN1StartMarshalContext(
ASN1MarshalContext

*ctx

)
{
pAssert((ctx->depth + 1) < MAX_DEPTH);
ctx->depth++;Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 733
April 15, 2019

Trusted Platform Module Library
149
150
151

Part 4: Supporting Routinesctx->ends[ctx->depth] = ctx->end;
ctx->end = ctx->offset;}

10.2.23.3.4

ASN1EndMarshalContext()

This function restores the end pointer for an encapsulating structure.

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

Return Value

Meaning>0

the size of the encapsulated structure that was just ended<= 0

an error

INT16
ASN1EndMarshalContext(
ASN1MarshalContext

*ctx

)
{
INT16
length;pAssert(ctx->depth >= 0);
length = ctx->end - ctx->offset;
ctx->end = ctx->ends[ctx->depth--];if((ctx->depth == -1) && (ctx->buffer)){
MemoryCopy(ctx->buffer, ctx->buffer + ctx->offset, ctx->end - ctx->offset);}
return length;}10.2.23.3.5

ASN1EndEncapsulation()

This function puts a tag and length in the buffer. In this function, an embedded BIT_STRING is assumed
to be a collection of octets. To indicate that all bits are used, a byte of zero is prepended. If a raw bitstring is needed, a new function like ASN1PushInteger() would be needed.

167
168
169
170
171
172
173
174
175
176
177
178

Return Value

Meaning>0

number of octets in the encapsulation== 0

failureUINT16ASN1EndEncapsulation(
ASN1MarshalContext
BYTE){// only add a leading zero for an encapsulated BIT STRING
if (tag == ASN1_BITSTRING)
ASN1PushByte(ctx, 0);
ASN1PushTagAndLength(ctx, tag, ctx->end - ctx->offset);
return ASN1EndMarshalContext(ctx);}

10.2.23.3.6
179
180
181
182

*ctx,
tag

ASN1PushByte()

BOOL
ASN1PushByte(
ASN1MarshalContext
BYTE

Page 734
April 15, 2019

*ctx,
b

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
183
184
185
186
187
188
189
190
191
192
193
194

Trusted Platform Module Library){if(ctx->offset > 0){
ctx->offset -= 1;
if(ctx->buffer)ctx->buffer[ctx->offset] = b;
return TRUE;}
ctx->offset = -1;
return FALSE;}

10.2.23.3.7

ASN1PushBytes()

Push some raw bytes onto the buffer. count cannot be zero.

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

Return Value

Meaning>0

count bytes== 0

failure unless count was zero

INT16
ASN1PushBytes(
ASN1MarshalContext
INT16
const BYTE){// make sure that count is not negative which would mess up the math; and that// if there is a count, there is a buffer
VERIFY((count >= 0) && ((buffer != NULL) || (count == 0)));// back up the offset to determine where the new octets will get pushedctx->offset -= count;// can't go negative
VERIFY(ctx->offset >= 0);// if there are buffers, move the data, otherwise, assume that this is just a// test.
if(count && buffer && ctx->buffer)
MemoryCopy(&ctx->buffer[ctx->offset], buffer, count);
return count;
Error:
ctx->offset = -1;
return 0;}

10.2.23.3.8

218
219
220
221
222
223
224
225

*ctx,
count,*buffer

ASN1PushNull()

Return Value

Meaning>0

count bytes== 0

failure unless count was zero

INT16
ASN1PushNull(
ASN1MarshalContext

*ctx

)
{
ASN1PushByte(ctx, 0);
ASN1PushByte(ctx, ASN1_NULL);
return (ctx->offset >= 0) ? 2 : 0;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 735
April 15, 2019

Trusted Platform Module Library
226

Part 4: Supporting Routines}

10.2.23.3.9

ASN1PushLength()

Push a length value. This will only handle length values that fit in an INT16.

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
ASN1PushLength(
ASN1MarshalContext
INT16

*ctx,
len

)
{
UINT16
start = ctx->offset;
VERIFY(len >= 0);if(len <= 127)
ASN1PushByte(ctx, (BYTE)len);else{
ASN1PushByte(ctx, (BYTE)(len & 0xFF));len >>= 8;if(len == 0)
ASN1PushByte(ctx, 0x81);
else{
ASN1PushByte(ctx, (BYTE)(len));
ASN1PushByte(ctx, 0x82);}}
goto Exit;
Error:
ctx->offset = -1;
Exit:
return (ctx->offset > 0) ? start - ctx->offset : 0;}

10.2.23.3.10 ASN1PushTagAndLength()

255
256
257
258
259
260
261
262
263
264
265
266

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
ASN1PushTagAndLength(
ASN1MarshalContext
BYTE
INT16

*ctx,
tag,
length){INT16
bytes;
bytes = ASN1PushLength(ctx, length);bytes += (INT16)ASN1PushByte(ctx, tag);
return (ctx->offset < 0) ? 0 : bytes;}

Page 736
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.23.3.11 ASN1PushTaggedOctetString()
This function will push a random octet string.

267
268
269
270
271
272
273
274
275
276
277
278
279
280

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
ASN1PushTaggedOctetString(
ASN1MarshalContext
INT16
const BYTE
BYTE

*ctx,
size,
*string,tag){
ASN1PushBytes(ctx, size, string);// PushTagAndLenght just tells how many octets it added so the total size of this// element is the sum of those octets and input size.
size += ASN1PushTagAndLength(ctx, tag, size);
return size;}

10.2.23.3.12 ASN1PushUINT()
This function pushes an native-endian integer value. This just changes a native-endian integer into a bigendian byte string and calls ASN1PushInteger(). That function will remove leading zeros and make surethat the number is positive.

281
282
283
284
285
286
287
288
289
290

Return Value

Meaning>0

count bytes== 0

failure unless count was zero

INT16
ASN1PushUINT(ASN1MarshalContext
UINT32*ctx,
integer){
BYTE
marshaled[4];UINT32_TO_BYTE_ARRAY(integer, marshaled);
return ASN1PushInteger(ctx, 4, marshaled);}

10.2.23.3.13 ASN1PushInteger
Push a big-endian integer on the end of the buffer

291
292
293
294

Return Value

Meaning>0

the number of bytes marshaled for the integer== 0

failure

INT16
ASN1PushInteger(
ASN1MarshalContext
INT16

Family “2.0”Level 00 Revision 01.55

*ctx,
iLen,

// IN/OUT: buffer context// IN: octets of the integer

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 737
April 15, 2019

Trusted Platform Module Library
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

BYTE

Part 4: Supporting Routines*integer// IN: big-endian integer){// no leading 0's
while((*integer == 0) && (--iLen > 0))
integer++;// Move the bytes to the buffer
ASN1PushBytes(ctx, iLen, integer);// if needed, add a leading byte of 0 to make the number positiveif(*integer & 0x80)
iLen += (INT16)ASN1PushByte(ctx, 0);// PushTagAndLenght just tells how many octets it added so the total size of this// element is the sum of those octets and the adjusted input size.
iLen += ASN1PushTagAndLength(ctx, ASN1_INTEGER, iLen);
return iLen;}

10.2.23.3.14 ASN1PushOID()This function is used to add an OID. An OID is 0x06 followed by a byte of size followed by size bytes.
This is used to avoid having to do anything special in the definition of an OID.

311
312
313
314
315
316
317
318
319
320
321
322
323

Return Value

Meaning>0

the number of bytes marshaled for the integer== 0

failure

INT16
ASN1PushOID(
ASN1MarshalContext
const BYTE

*ctx,
*OID

)
{
if((*OID == ASN1_OBJECT_IDENTIFIER) && ((OID[1] & 0x80) == 0)){
return ASN1PushBytes(ctx, OID[1] + 2, OID);}
ctx->offset = -1;
return 0;}

Page 738
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.24 X509_ECC.c
10.2.24.1 Includes
1
2
3
4
5
6

#include "Tpm.h"#include "X509.h"#include "OIDS.h"#include "TpmASN1_fp.h"#include "X509_spt_fp.h"#include "CryptHash_fp.h"

10.2.24.2 Functions
10.2.24.2.1

X509PushPoint()

This seems like it might be used more than once so...

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
X509PushPoint(
ASN1MarshalContext
TPMS_ECC_POINT

*ctx,
*p

)
{
// Push a bit string containing the public key. For now, push the x, and y// coordinates of the public point, bottom up
ASN1StartMarshalContext(ctx); // BIT STRING{
ASN1PushBytes(ctx, p->y.t.size, p->y.t.buffer);
ASN1PushBytes(ctx, p->x.t.size, p->x.t.buffer);
ASN1PushByte(ctx, 0x04);}
return ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Ends BIT STRING}

10.2.24.2.2

X509AddSigningAlgorithmECC()

This creates the singing algorithm data.

23
24
25
26
27
28
29
30
31
32

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
X509AddSigningAlgorithmECC(OBJECT
TPMT_SIG_SCHEME
ASN1MarshalContext*signKey,*scheme,*ctx

PHASH_DEF

hashDef = CryptGetHashDef(scheme->details.any.hashAlg);){//NOT_REFERENCED(signKey);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 739
April 15, 2019

Trusted Platform Module Library
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

Part 4: Supporting Routines// If the desired hashAlg definition wasn't found...
if(hashDef->hashAlg != scheme->details.any.hashAlg)
return 0;
switch(scheme->scheme){case ALG_ECDSA_VALUE:// Make sure that we have an OID for this hash and ECC
if((hashDef->ECDSA)[0] != ASN1_OBJECT_IDENTIFIER)
break;// if this is just an implementation check, indicate that this// combination is supportedif(!ctx)
return 1;
ASN1StartMarshalContext(ctx);
ASN1PushOID(ctx, hashDef->ECDSA);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
default:
break;}
return 0;}

10.2.24.2.3

X509AddPublicECC()

This function will add the publicKey description to the DER data. If ctx is NULL, then no data istransferred and this function will indicate if the TPM has the values for DER-encoding of the public key.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
X509AddPublicECC(OBJECT
ASN1MarshalContext*object,*ctx){
const BYTE
*curveOid =CryptEccGetOID(object->publicArea.parameters.eccDetail.curveID);if((curveOid == NULL) || (*curveOid != ASN1_OBJECT_IDENTIFIER))
return 0;
//
//
//
//
//
//
//
//

SEQUENCE (2 elem) 1st
SEQUENCE (2 elem) 2nd
OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named curve)
BIT STRING (520 bit) 000001001010000111010101010111001001101101000100000010...
// If this is a check to see if the key can be encoded, it can.
// Need to mark the end sequenceif(ctx == NULL)
return 1;
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st{
X509PushPoint(ctx, &object->publicArea.unique.ecc); // BIT STRINGASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 2nd{
ASN1PushOID(ctx, curveOid); // curve dependent
ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1)}

Page 740
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
85
86
87
88

Trusted Platform Module Library

ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd}
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 741
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.25 X509_RSA.c
10.2.25.1 Includes
1
2
3
4
5
6

#include "Tpm.h"#include "X509.h"#include "TpmASN1_fp.h"#include "X509_spt_fp.h"#include "CryptHash_fp.h"#include "CryptRsa_fp.h"

10.2.25.2 Functions
7#if ALG_RSA

10.2.25.2.1

X509AddSigningAlgorithmRSA()This creates the singing algorithm data.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
X509AddSigningAlgorithmRSA(OBJECT
TPMT_SIG_SCHEME
ASN1MarshalContext*signKey,*scheme,*ctx

TPM_ALG_ID
PHASH_DEF

hashAlg = scheme->details.any.hashAlg;
hashDef = CryptGetHashDef(hashAlg);){//NOT_REFERENCED(signKey);// return failure if hash isn't implemented
if(hashDef->hashAlg != hashAlg)
return 0;
switch(scheme->scheme){case ALG_RSASSA_VALUE:{// if the hash is implemented but there is no PKCS1 OID defined// then this is not a valid signing combination.
if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER)
break;
if(ctx == NULL)
return 1;
ASN1StartMarshalContext(ctx);
ASN1PushOID(ctx, hashDef->PKCS1);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);}
case ALG_RSAPSS_VALUE:// leave if this is just an implementation checkif(ctx == NULL)
return 1;// In the case of SHA1, everything is default and RFC4055 says that// implementations that do signature generation MUST omit the parameter// when defaults are used. )-:if(hashDef->hashAlg == ALG_SHA1_VALUE){

Page 742
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

Trusted Platform Module Library

return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS);}
else{// Going to build something that looks like:// SEQUENCE (2 elem)//
OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)//
SEQUENCE (3 elem)//[0] (1 elem)//
SEQUENCE (2 elem)//
OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
//
NULL
//
[1] (1 elem)//
SEQUENCE (2 elem)//
OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF//
SEQUENCE (2 elem)//
OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
//
NULL
//
[2] (1 elem) salt length//
INTEGER 32// The indentation is just to keep track of where we are in the// structure
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements){
ASN1StartMarshalContext(ctx);// SEQUENCE (3 elements){// [2] (1 elem) salt length//
INTEGER 32
ASN1StartMarshalContext(ctx);{
INT16
saltSize =CryptRsaPssSaltSize((INT16)hashDef->digestSize,(INT16)signKey->publicArea.unique.rsa.t.size);
ASN1PushUINT(ctx, saltSize);}
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2);// Add the mask generation algorithm// [1] (1 elem)//
SEQUENCE (2 elem) 1st//
OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF//
SEQUENCE (2 elem) 2nd//
OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256//
NULL
ASN1StartMarshalContext(ctx);// mask context [1] (1 elem){
ASN1StartMarshalContext(ctx);// SEQUENCE (2 elem) 1st// Handle the 2nd Sequence (sequence (object, null)){
X509PushAlgorithmIdentifierSequence(ctx,hashDef->OID);// add the pkcs1-MGF OID
ASN1PushOID(ctx, OID_MGF1);}// End outer sequence
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);}// End the [1]ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1);// Add the hash algorithm// [0] (1 elem)//
SEQUENCE (2 elem) (done by//
X509PushAlgorithmIdentifierSequence)//
OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST)

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 743
April 15, 2019

Trusted Platform Module Library
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

Part 4: Supporting Routines//
NULL
ASN1StartMarshalContext(ctx); // [0] (1 elem){
X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID);}ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0));}// SEQUENCE (3 elements) end
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);// RSA PSS OID// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
ASN1PushOID(ctx, OID_RSAPSS);}// End Sequence (2 elements)
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);}
default:
break;}
return 0;}

10.2.25.2.2

X509AddPublicRSA()This function will add the publicKey description to the DER data. If fillPtr is NULL, then no data istransferred and this function will indicate if the TPM has the values for DER-encoding of the public key.

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
X509AddPublicRSA(OBJECT
ASN1MarshalContext*object,*ctx){
UINT32

exp = object->publicArea.parameters.rsaDetail.exponent;///*
SEQUENCE (2 elem) 1st
SEQUENCE (2 elem) 2nd
OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
NULL
BIT STRING (1 elem)
SEQUENCE (2 elem) 3rd
INTEGER (2048 bit) 2197304513741227955725834199357401
INTEGER 65537*/// If this is a check to see if the key can be encoded, it can.
// Need to mark the end sequenceif(ctx == NULL)
return 1;
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
ASN1StartMarshalContext(ctx); // BIT STRINGASN1StartMarshalContext(ctx); // SEQUENCE *(2 elem) 3rd// Get public exponent in big-endian byte order.
if(exp == 0)
exp = RSA_DEFAULT_PUBLIC_EXPONENT;

Page 744
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

Trusted Platform Module Library// Push a 4 byte integer. This might get reduced if there are leading zeros or// extended if the high order byte is negative.
ASN1PushUINT(ctx, exp);// Push the public key as an integer
ASN1PushInteger(ctx, object->publicArea.unique.rsa.t.size,
object->publicArea.unique.rsa.t.buffer);// Embed this in a SEQUENCE tag and length in for the key, exponent sequence
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // SEQUENCE (3rd)// Embed this in a BIT STRING
ASN1EndEncapsulation(ctx, ASN1_BITSTRING);// Now add the formatted SEQUENCE for the RSA public key OID. This is a// fully constructed value so it doesn't need to have a context started
X509PushAlgorithmIdentifierSequence(ctx, OID_PKCS1_PUB);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);}#endif // ALG_RSA

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 745
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

10.2.26 X509_spt.c
10.2.26.1 Includes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include "Tpm.h"#include "TpmASN1.h"#include "TpmASN1_fp.h"#define _X509_SPT_#include "X509.h"#include "X509_spt_fp.h"#if ALG_RSA#
include "X509_RSA_fp.h"#endif // ALG_RSA#if ALG_ECC#
include "X509_ECC_fp.h"#endif // ALG_ECC#if ALG_SM2//#
include "X509_SM2_fp.h"#endif // ALG_RSA

10.2.26.2 Unmarshaling Functions
10.2.26.2.1

X509FindExtensionOID()This will search a list of X509 extensions to find an extension with the requested OID. If the extension isfound, the output context (ctx) is set up to point to the OID in the extension.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

Return Value

Meaning

TRUE(1)success

FALSE(0)failure (could be catastrophic)

BOOL
X509FindExtensionByOID(
ASN1UnmarshalContext
ASN1UnmarshalContext
const BYTE

*ctxIn,*ctx,*OID// IN: the context to search// OUT: the extension context// IN: oid to search for

)
{
INT16

length;//pAssert(ctxIn != NULL);// Make the search non-destructive of the input if ctx provided. Otherwise, use// the provided context.
if (ctx == NULL)
ctx = ctxIn;
else if(ctx != ctxIn)*ctx = *ctxIn;
for(;ctx->size > ctx->offset; ctx->offset += length){
VERIFY((length = ASN1NextTag(ctx)) >= 0);// If this is not a constructed sequence, then it doesn't belong// in the extensions.
VERIFY(ctx->tag == ASN1_CONSTRUCTED_SEQUENCE);// Make sure that this entry could hold the OID
if (length >= OID_SIZE(OID)){// See if this is a match for the provided object identifier.
if (MemoryEqual(OID, &(ctx->buffer[ctx->offset]), OID_SIZE(OID))){

Page 746
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
44

Trusted Platform Module Library// Return with ' ctx' set to point to the start of the OID with the
size

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

// set to be the size of the SEQUENCE
ctx->buffer += ctx->offset;
ctx->offset = 0;
ctx->size = length;
return TRUE;}}}VERIFY(ctx->offset == ctx->size);
return FALSE;
Error:
ctxIn->size = -1;
ctx->size = -1;
return FALSE;}

10.2.26.2.2

X509GetExtensionBits()

This function will extract a bit field from an extension. If the extension doesn't contain a bit string, it will
fail.

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

Return Value

Meaning

TRUE(1)success

FALSE(0)failureUINT32
X509GetExtensionBits(
ASN1UnmarshalContext
UINT32*ctx,*value){INT16

length;//while (((length = ASN1NextTag(ctx)) > 0) && (ctx->size > ctx->offset)){// Since this is an extension, the extension value will be in an OCTET STRING
if (ctx->tag == ASN1_OCTET_STRING){
return ASN1GetBitStringValue(ctx, value);}ctx->offset += length;}ctx->size = -1;
return FALSE;}

10.2.26.2.3

X509ProcessExtensions()

This function is used to process the TPMA_OBJECT and KeyUsage() extensions. It is not in theCertifyX509.c code because it makes the code harder to follow.

8081

Error Returns

Meaning

TPM_RCS_ATTRIBUTES

the attributes of object are not consistent with the extension setting

TPM_RC_VALUE

problem parsing the extensions

TPM_RC
X509ProcessExtensions(

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 747
April 15, 2019

Trusted Platform Module Library
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

Part 4: Supporting Routines

OBJECT*object,stringRef*extension// IN: The object with the attributes to//check// IN: The start and length of the extensions){
ASN1UnmarshalContext
ASN1UnmarshalContext
INT16
UINT32ctx;
extensionCtx;
length;value;//
if(!ASN1UnmarshalContextInitialize(&ctx, extension->len, extension->buf)|| ((length = ASN1NextTag(&ctx)) < 0)|| (ctx.tag != X509_EXTENSIONS))
return TPM_RCS_VALUE;
if( ((length = ASN1NextTag(&ctx)) < 0)|| (ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE)))
return TPM_RCS_VALUE;// Get the extension for the TPMA_OBJECT if there is one
if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_TCG_TPMA_OBJECT) &&X509GetExtensionBits(&extensionCtx, &value)){// If an keyAttributes extension was found, it must be exactly the same as the// attributes of the object.
// This cast will work because we know that a TPMA_OBJECT is in a UINT32.
// Set RUNTIME_SIZE_CHECKS to YES to force a check to verify this assumption// during debug. Doing this is lot easier than having to revisit the code// any time a new attribute is added.
// NOTE: MemoryEqual() is used to avoid type-punned pointer warning/error.
if(!MemoryEqual(&value, &object->publicArea.objectAttributes, sizeof(value)))return TPM_RCS_ATTRIBUTES;}// Make sure the failure to find the value wasn't because of a fatal error
else if(extensionCtx.size < 0)return TPM_RCS_VALUE;// Get the keyUsage extension. This one is requiredif(X509FindExtensionByOID(&ctx, &extensionCtx, OID_KEY_USAGE_EXTENSTION) &&X509GetExtensionBits(&extensionCtx, &value)){
x509KeyUsageUnion
keyUsage;
TPMA_OBJECT
attributes = object->publicArea.objectAttributes;//
keyUsage.integer = value;// For KeyUsage:// the 'sign' attribute is SET if Key Usage includes signingif(((keyUsageSign.integer & keyUsage.integer) != 0)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)// and the 'decrypt' attribute is Set if Key Usage includes decryptionuses|| ((keyUsageDecrypt.integer & keyUsage.integer) != 0)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)// Check that 'fixedTPM' is SET if Key Usage is non-repudiation|| (IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, nonrepudiation)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))|| (IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)))
return TPM_RCS_ATTRIBUTES;}
else// The KeyUsage extension is required
return TPM_RCS_VALUE;
return TPM_RC_SUCCESS;}

Page 748
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.26.3 Marshaling Functions
10.2.26.3.1

X509AddSigningAlgorithm()

This creates the singing algorithm data.

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

Return Value

Meaning>0

number of octets added<= 0

failure

INT16
X509AddSigningAlgorithm(
ASN1MarshalContext
OBJECT
TPMT_SIG_SCHEME*ctx,*signKey,*scheme){switch(signKey->publicArea.type){#if ALG_RSA
case ALG_RSA_VALUE:
return X509AddSigningAlgorithmRSA(signKey, scheme, ctx);#endif // ALG_RSA#if ALG_ECC
case ALG_ECC_VALUE:
return X509AddSigningAlgorithmECC(signKey, scheme, ctx);#endif // ALG_ECC#if ALG_SM2
case ALG_SM2:
return X509AddSigningAlgorithmSM2(signKey, scheme,ctx);#endif // ALG_SM2
default:
break;}
return 0;}

10.2.26.3.2

X509AddPublicKey()This function will add the publicKey description to the DER data. If fillPtr is NULL, then no data istransferred and this function will indicate if the TPM has the values for DER-encoding of the public key.

173
174
175
176
177
178
179
180
181
182
183
184
185

Return Value

Meaning>0

number of octets added== 0

failure

INT16
X509AddPublicKey(
ASN1MarshalContext
OBJECT*ctx,*object){
switch(object->publicArea.type){#if ALG_RSA
case ALG_RSA_VALUE:
return X509AddPublicRSA(object, ctx);#endif#if ALG_ECC

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 749
April 15, 2019

Trusted Platform Module Library
186
187
188
189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206
207
208

Part 4: Supporting Routinescase ALG_ECC_VALUE:
return X509AddPublicECC(object, ctx);#endif#if ALG_SM2
case ALG_SM2_VALUE:
break;#endifdefault:
break;}
return FALSE;}

10.2.26.3.3

X509PushAlgorithmIdentifierSequence()

Return Value

Meaning>0

number of bytes added== 0

failure

INT16
X509PushAlgorithmIdentifierSequence(
ASN1MarshalContext
const BYTE
)

*ctx,
*OID

{
ASN1StartMarshalContext(ctx);// hash algorithm
ASN1PushNull(ctx);
ASN1PushOID(ctx, OID);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);}

Page 750
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.27 AC_spt.c
10.2.27.1 Includes
1
2
3
4
5
6
7
8
9
10
11
12
13

#include "Tpm.h"#include "AC_spt_fp.h"#if 1 // This is the simulated AC data.
typedef struct {TPMI_RH_AC
ac;
TPML_AC_CAPABILITIES*acData;} acCapabilities;
TPML_AC_CAPABILITIES acData0001 = {1,{{TPM_AT_PV1, 0x01234567}}};
acCapabilities ac[1] = {0x0001, &acData0001};#define NUM_AC (sizeof(ac) / sizeof(acCapabilities))#endif // 1 The simulated AC data

10.2.27.1.1

AcToCapabilities()

This function returns a pointer to a list of AC capabilities.
14
15
16
17
18
19
20
21
22
23
24
25
26
27

TPML_AC_CAPABILITIES *AcToCapabilities(
TPMI_RH_AC

component

UINT32index;// IN: component){//
for(index = 0; index < NUM_AC; index++){if(ac[index].ac == component)
return ac[index].acData;}
return NULL;}

10.2.27.1.2

AcIsAccessible()

Function to determine if an AC handle references an actual AC
Return Value
28
29
30
31
32
33
34
35
36

MeaningBOOL
AcIsAccessible(
TPM_HANDLE)

acHandle{// In this implementation, the AC exists if there are some capabilities to go// with the handle
return AcToCapabilities(acHandle) != NULL;}

10.2.27.1.3

AcCapabilitiesGet()

This function returns a list of capabilities associated with an AC

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 751
April 15, 2019

Trusted Platform Module Library

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

Part 4: Supporting Routines

Return Value

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO
AcCapabilitiesGet(
TPMI_RH_AC
TPM_AT
TPML_AC_CAPABILITIES

component,// IN: the component
type,// IN: start capability type*capabilityList // OUT: list of handle

TPMI_YES_NOUINT32
TPML_AC_CAPABILITIES

more = NO;i;*capabilities = AcToCapabilities(component);){

pAssert(HandleGetType(component) == TPM_HT_AC);// Initialize output handle list
capabilityList->count = 0;if(capabilities != NULL){// Find the first capability less than or equal to typefor(i = 0; i < capabilities->count; i++){if(capabilities->acCapabilities[i].tag >= type){// copy the capabilities until we run out or fill the list
for(; (capabilityList->count < MAX_AC_CAPABILITIES)&& (i < capabilities->count); i++){capabilityList->acCapabilities[capabilityList->count]= capabilities->acCapabilities[i];capabilityList->count++;}
more = i < capabilities->count;}}}return more;}

10.2.27.1.4

AcSendObject()Stub to handle sending of an AC object
Error Returns
74
75
76
77
78
79
80
81
82
83
84
85
86

Meaning

TPM_RCAcSendObject(
TPM_HANDLEOBJECT
TPMS_AC_OUTPUT

acHandle,*object,*acDataOut// IN: Handle of AC receiving object// IN: object structure to send// OUT: results of operation){
NOT_REFERENCED(object);
NOT_REFERENCED(acHandle);
acDataOut->tag = TPM_AT_ERROR;
acDataOut->data = TPM_AE_NONE;

Page 752
April 15, 2019// indicate that the response contains an// error code// but there is no error.

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
87
88

Trusted Platform Module Library

return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 753
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

Annex A
(informative)
Implementation Dependent
A.1

Introduction

This header file contains definitions that are used to define a TPM profile. The values are chosen by the
manufacturer. The values here are chosen to represent a full featured TPM so that all of the TPM’s
capabilities can be simulated and tested. This file would change based on the implementation.
The file listed below was generated by an automated tool using three documents as inputs. They are:
The TCG_Algorithm Registery,Part 2 of this specification, andA purpose-built document that contains vendor-specific information in tables.
All of the values in this file have #ifdef ‘guards’ so that they may be defined in a commandline.Additionally, TpmBuildSwitches.h allows an additional file to be specified in the compiler commandline and preset any of these values.
A.2
1
2

TpmProfile.h#ifndef _TPM_PROFILE_H_#define _TPM_PROFILE_H_

Table 2:4 - Defines for Logic Values
3
4
5
6
7
8
9
10
11
12
13
14

#undef TRUE
#define TRUE
#undef FALSE#define FALSE#undef YES#define YES#undef NO#define NO#undef SET#define SET#undef CLEAR#define CLEAR

1
0
1
0
1
0

Table 0:1 - Defines for Processor Values
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#ifndef BIG_ENDIAN_TPM#define BIG_ENDIAN_TPM#endif#ifndef LITTLE_ENDIAN_TPM#define LITTLE_ENDIAN_TPM#endif#ifndef MOST_SIGNIFICANT_BIT_0#define MOST_SIGNIFICANT_BIT_0#endif#ifndef LEAST_SIGNIFICANT_BIT_0#define LEAST_SIGNIFICANT_BIT_0#endif#ifndef AUTO_ALIGN#define AUTO_ALIGN#endifNO!BIG_ENDIAN_TPM
NO!MOST_SIGNIFICANT_BIT_0
NO

Table 0:4 - Defines for Implemented Curves
Page 754
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Trusted Platform Module Library#ifndef ECC_NIST_P192#define ECC_NIST_P192#endif#ifndef ECC_NIST_P224#define ECC_NIST_P224#endif#ifndef ECC_NIST_P256#define ECC_NIST_P256#endif#ifndef ECC_NIST_P384#define ECC_NIST_P384#endif#ifndef ECC_NIST_P521#define ECC_NIST_P521#endif#ifndef ECC_BN_P256#define ECC_BN_P256#endif#ifndef ECC_BN_P638#define ECC_BN_P638#endif#ifndef ECC_SM2_P256#define ECC_SM2_P256#endif

NO
NO
YES
YES
NO
YES
NO
NO

Table 0:7 - Defines for Implementation Values
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

#ifndef FIELD_UPGRADE_IMPLEMENTED#define FIELD_UPGRADE_IMPLEMENTED#endif#ifndef RADIX_BITS#define RADIX_BITS#endif#ifndef HASH_ALIGNMENT#define HASH_ALIGNMENT#endif#ifndef SYMMETRIC_ALIGNMENT#define SYMMETRIC_ALIGNMENT#endif#ifndef HASH_LIB#define HASH_LIB#endif#ifndef SYM_LIB#define SYM_LIB#endif#ifndef MATH_LIB#define MATH_LIB#endif#ifndef BSIZE#define BSIZE#endif#ifndef IMPLEMENTATION_PCR#define IMPLEMENTATION_PCR#endif#ifndef PCR_SELECT_MAX#define PCR_SELECT_MAX#endif#ifndef PLATFORM_PCR#define PLATFORM_PCR#endif#ifndef PCR_SELECT_MIN#define PCR_SELECT_MIN#endif#ifndef DRTM_PCR#define DRTM_PCR

Family “2.0”Level 00 Revision 01.55

NO
32
4
4
Ossl
Ossl
Ossl
UINT1624((IMPLEMENTATION_PCR+7)/8)
24((PLATFORM_PCR+7)/8)
17

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 755
April 15, 2019

Trusted Platform Module Library
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

Part 4: Supporting Routines#endif#ifndef HCRTM_PCR#define HCRTM_PCR#endif#ifndef NUM_LOCALITIES#define NUM_LOCALITIES#endif#ifndef MAX_HANDLE_NUM#define MAX_HANDLE_NUM#endif#ifndef MAX_ACTIVE_SESSIONS#define MAX_ACTIVE_SESSIONS#endif#ifndef CONTEXT_SLOT#define CONTEXT_SLOT#endif#ifndef CONTEXT_COUNTER#define CONTEXT_COUNTER#endif#ifndef MAX_LOADED_SESSIONS#define MAX_LOADED_SESSIONS#endif#ifndef MAX_SESSION_NUM#define MAX_SESSION_NUM#endif#ifndef MAX_LOADED_OBJECTS#define MAX_LOADED_OBJECTS#endif#ifndef MIN_EVICT_OBJECTS#define MIN_EVICT_OBJECTS#endif#ifndef NUM_POLICY_PCR_GROUP#define NUM_POLICY_PCR_GROUP#endif#ifndef NUM_AUTHVALUE_PCR_GROUP#define NUM_AUTHVALUE_PCR_GROUP#endif#ifndef MAX_CONTEXT_SIZE#define MAX_CONTEXT_SIZE#endif#ifndef MAX_DIGEST_BUFFER#define MAX_DIGEST_BUFFER#endif#ifndef MAX_NV_INDEX_SIZE#define MAX_NV_INDEX_SIZE#endif#ifndef MAX_NV_BUFFER_SIZE#define MAX_NV_BUFFER_SIZE#endif#ifndef MAX_CAP_BUFFER#define MAX_CAP_BUFFER#endif#ifndef NV_MEMORY_SIZE#define NV_MEMORY_SIZE#endif#ifndef MIN_COUNTER_INDICES#define MIN_COUNTER_INDICES#endif#ifndef NUM_STATIC_PCR#define NUM_STATIC_PCR#endif#ifndef MAX_ALG_LIST_SIZE#define MAX_ALG_LIST_SIZE#endif#ifndef PRIMARY_SEED_SIZE#define PRIMARY_SEED_SIZEPage 756
April 15, 2019

0
5
3
64
UINT16
UINT64
3
3
3
2
1
1
2474
1024
2048
1024
1024
16384
8
16
64
32

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

Trusted Platform Module Library#endif#ifndef CONTEXT_ENCRYPT_ALGORITHM#define CONTEXT_ENCRYPT_ALGORITHM#endif#ifndef NV_CLOCK_UPDATE_INTERVAL#define NV_CLOCK_UPDATE_INTERVAL#endif#ifndef NUM_POLICY_PCR#define NUM_POLICY_PCR#endif#ifndef MAX_COMMAND_SIZE#define MAX_COMMAND_SIZE#endif#ifndef MAX_RESPONSE_SIZE#define MAX_RESPONSE_SIZE#endif#ifndef ORDERLY_BITS#define ORDERLY_BITS#endif#ifndef MAX_SYM_DATA#define MAX_SYM_DATA#endif#ifndef MAX_RNG_ENTROPY_SIZE#define MAX_RNG_ENTROPY_SIZE#endif#ifndef RAM_INDEX_SPACE#define RAM_INDEX_SPACE#endif#ifndef RSA_DEFAULT_PUBLIC_EXPONENT#define RSA_DEFAULT_PUBLIC_EXPONENT#endif#ifndef ENABLE_PCR_NO_INCREMENT#define ENABLE_PCR_NO_INCREMENT#endif#ifndef CRT_FORMAT_RSA#define CRT_FORMAT_RSA#endif#ifndef VENDOR_COMMAND_COUNT#define VENDOR_COMMAND_COUNT#endif#ifndef MAX_VENDOR_BUFFER_SIZE#define MAX_VENDOR_BUFFER_SIZE#endif#ifndef TPM_MAX_DERIVATION_BITS#define TPM_MAX_DERIVATION_BITS#endif#ifndef RSA_MAX_PRIME#define RSA_MAX_PRIME#endif#ifndef RSA_PRIVATE_SIZE#define RSA_PRIVATE_SIZE#endif#ifndef SIZE_OF_X509_SERIAL_NUMBER#define SIZE_OF_X509_SERIAL_NUMBER#endif#ifndef PRIVATE_VENDOR_SPECIFIC_BYTES#define PRIVATE_VENDOR_SPECIFIC_BYTES#endif

AES
12
1
4096
4096
8
128
64
512
0x00010001
YES
YES
0
1024
8192
(MAX_RSA_KEY_BYTES/2)(RSA_MAX_PRIME*5)
20
RSA_PRIVATE_SIZE

Table 0:2 - Defines for Implemented Algorithms
216
217
218
219

#ifndef ALG_AES#define ALG_AES#endif#ifndef ALG_CAMELLIA

Family “2.0”Level 00 Revision 01.55

ALG_YESTCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 757
April 15, 2019

Trusted Platform Module Library
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

#define ALG_CAMELLIA#endif#ifndef ALG_CBC#define ALG_CBC#endif#ifndef ALG_CFB#define ALG_CFB#endif#ifndef ALG_CMAC#define ALG_CMAC#endif#ifndef ALG_CTR#define ALG_CTR#endif#ifndef ALG_ECB#define ALG_ECB#endif#ifndef ALG_ECC#define ALG_ECC#endif#ifndef ALG_ECDAA#define ALG_ECDAA#endif#ifndef ALG_ECDH#define ALG_ECDH#endif#ifndef ALG_ECDSA#define ALG_ECDSA#endif#ifndef ALG_ECMQV#define ALG_ECMQV#endif#ifndef ALG_ECSCHNORR#define ALG_ECSCHNORR#endif#ifndef ALG_HMAC#define ALG_HMAC#endif#ifndef ALG_KDF1_SP800_108#define ALG_KDF1_SP800_108#endif#ifndef ALG_KDF1_SP800_56A#define ALG_KDF1_SP800_56A#endif#ifndef ALG_KDF2#define ALG_KDF2#endif#ifndef ALG_KEYEDHASH#define ALG_KEYEDHASH#endif#ifndef ALG_MGF1#define ALG_MGF1#endif#ifndef ALG_OAEP#define ALG_OAEP#endif#ifndef ALG_OFB#define ALG_OFB#endif#ifndef ALG_RSA#define ALG_RSA#endif#ifndef ALG_RSAES#define ALG_RSAES#endif#ifndef ALG_RSAPSS

Page 758
April 15, 2019

Part 4: Supporting Routines
ALG_NO/* Not specified by vendor */ALG_YESALG_YESALG_YESALG_YESALG_YESALG_YES(ALG_YES && ALG_ECC)(ALG_YES && ALG_ECC)(ALG_YES && ALG_ECC)(ALG_NO && ALG_ECC)(ALG_YES && ALG_ECC)
ALG_YESALG_YES(ALG_YES && ALG_ECC)
ALG_NOALG_YESALG_YES(ALG_YES && ALG_RSA)
ALG_YESALG_YES(ALG_YES && ALG_RSA)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

#define ALG_RSAPSS#endif#ifndef ALG_RSASSA#define ALG_RSASSA#endif#ifndef ALG_SHA#define ALG_SHA#endif#ifndef ALG_SHA1#define ALG_SHA1#endif#ifndef ALG_SHA256#define ALG_SHA256#endif#ifndef ALG_SHA384#define ALG_SHA384#endif#ifndef ALG_SHA3_256#define ALG_SHA3_256#endif#ifndef ALG_SHA3_384#define ALG_SHA3_384#endif#ifndef ALG_SHA3_512#define ALG_SHA3_512#endif#ifndef ALG_SHA512#define ALG_SHA512#endif#ifndef ALG_SM2#define ALG_SM2#endif#ifndef ALG_SM3_256#define ALG_SM3_256#endif#ifndef ALG_SM4#define ALG_SM4#endif#ifndef ALG_SYMCIPHER#define ALG_SYMCIPHER#endif#ifndef ALG_TDES#define ALG_TDES#endif#ifndef ALG_XOR#define ALG_XOR#endifTrusted Platform Module Library(ALG_YES && ALG_RSA)(ALG_YES && ALG_RSA)
ALG_NO/* Not specified by vendor */ALG_YESALG_YESALG_YESALG_NO/* Not specified by vendor */ALG_NO/* Not specified by vendor */ALG_NO/* Not specified by vendor */ALG_NO(ALG_NO && ALG_ECC)
ALG_NOALG_NOALG_YESALG_NOALG_YES

Table 1:00 - Defines for RSA Asymmetric Cipher Algorithm Constants
333
334
335
336
337
338
339
340
341
342
343
344

#ifndef RSA_1024#define RSA_1024#endif#ifndef RSA_2048#define RSA_2048#endif#ifndef RSA_3072#define RSA_3072#endif#ifndef RSA_4096#define RSA_4096#endif(ALG_RSA & YES)
(ALG_RSA & YES)
(ALG_RSA & NO)(ALG_RSA & NO)

Table 1:17 - Defines for AES Symmetric Cipher Algorithm Constants
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 759
April 15, 2019

Trusted Platform Module Library
345
346
347
348
349
350
351
352
353

#ifndef AES_128#define AES_128#endif#ifndef AES_192#define AES_192#endif#ifndef AES_256#define AES_256#endif

Part 4: Supporting Routines(ALG_AES & YES)
(ALG_AES & NO)(ALG_AES & YES)

Table 1:18 - Defines for SM4 Symmetric Cipher Algorithm Constants
354
355
356

#ifndef SM4_128#define SM4_128#endif(ALG_SM4 & YES)

Table 1:19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants
357
358
359
360
361
362
363
364
365

#ifndef CAMELLIA_128#define CAMELLIA_128#endif#ifndef CAMELLIA_192#define CAMELLIA_192#endif#ifndef CAMELLIA_256#define CAMELLIA_256#endif(ALG_CAMELLIA & YES)
(ALG_CAMELLIA & NO)(ALG_CAMELLIA & NO)

Table 1:17 - Defines for TDES Symmetric Cipher Algorithm Constants
366
367
368
369
370
371

#ifndef TDES_128#define TDES_128#endif#ifndef TDES_192#define TDES_192#endif(ALG_TDES & YES)
(ALG_TDES & YES)

Table 0:5 - Defines for Implemented Commands
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396

#ifndef CC_AC_GetCapability#define CC_AC_GetCapability#endif#ifndef CC_AC_Send#define CC_AC_Send#endif#ifndef CC_ActivateCredential#define CC_ActivateCredential#endif#ifndef CC_Certify#define CC_Certify#endif#ifndef CC_CertifyCreation#define CC_CertifyCreation#endif#ifndef CC_CertifyX509#define CC_CertifyX509#endif#ifndef CC_ChangeEPS#define CC_ChangeEPS#endif#ifndef CC_ChangePPS#define CC_ChangePPS#endif#ifndef CC_Clear

Page 760
April 15, 2019

CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

Trusted Platform Module Library#define CC_Clear#endif#ifndef CC_ClearControl#define CC_ClearControl#endif#ifndef CC_ClockRateAdjust#define CC_ClockRateAdjust#endif#ifndef CC_ClockSet#define CC_ClockSet#endif#ifndef CC_Commit#define CC_Commit#endif#ifndef CC_ContextLoad#define CC_ContextLoad#endif#ifndef CC_ContextSave#define CC_ContextSave#endif#ifndef CC_Create#define CC_Create#endif#ifndef CC_CreateLoaded#define CC_CreateLoaded#endif#ifndef CC_CreatePrimary#define CC_CreatePrimary#endif#ifndef CC_DictionaryAttackLockReset#define CC_DictionaryAttackLockReset#endif#ifndef CC_DictionaryAttackParameters#define CC_DictionaryAttackParameters#endif#ifndef CC_Duplicate#define CC_Duplicate#endif#ifndef CC_ECC_Parameters#define CC_ECC_Parameters#endif#ifndef CC_ECDH_KeyGen#define CC_ECDH_KeyGen#endif#ifndef CC_ECDH_ZGen#define CC_ECDH_ZGen#endif#ifndef CC_EC_Ephemeral#define CC_EC_Ephemeral#endif#ifndef CC_EncryptDecrypt#define CC_EncryptDecrypt#endif#ifndef CC_EncryptDecrypt2#define CC_EncryptDecrypt2#endif#ifndef CC_EventSequenceComplete#define CC_EventSequenceComplete#endif#ifndef CC_EvictControl#define CC_EvictControl#endif#ifndef CC_FieldUpgradeData#define CC_FieldUpgradeData#endif#ifndef CC_FieldUpgradeStart

Family “2.0”Level 00 Revision 01.55

CC_YES
CC_YES
CC_YES
CC_YES(CC_YES && ALG_ECC)
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES(CC_YES && ALG_ECC)(CC_YES && ALG_ECC)(CC_YES && ALG_ECC)(CC_YES && ALG_ECC)
CC_YES
CC_YES
CC_YES
CC_YES
CC_NO

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 761
April 15, 2019

Trusted Platform Module Library
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Part 4: Supporting Routines#define CC_FieldUpgradeStart#endif#ifndef CC_FirmwareRead#define CC_FirmwareRead#endif#ifndef CC_FlushContext#define CC_FlushContext#endif#ifndef CC_GetCapability#define CC_GetCapability#endif#ifndef CC_GetCommandAuditDigest#define CC_GetCommandAuditDigest#endif#ifndef CC_GetRandom#define CC_GetRandom#endif#ifndef CC_GetSessionAuditDigest#define CC_GetSessionAuditDigest#endif#ifndef CC_GetTestResult#define CC_GetTestResult#endif#ifndef CC_GetTime#define CC_GetTime#endif#ifndef CC_HMAC#define CC_HMAC#endif#ifndef CC_HMAC_Start#define CC_HMAC_Start#endif#ifndef CC_Hash#define CC_Hash#endif#ifndef CC_HashSequenceStart#define CC_HashSequenceStart#endif#ifndef CC_HierarchyChangeAuth#define CC_HierarchyChangeAuth#endif#ifndef CC_HierarchyControl#define CC_HierarchyControl#endif#ifndef CC_Import#define CC_Import#endif#ifndef CC_IncrementalSelfTest#define CC_IncrementalSelfTest#endif#ifndef CC_Load#define CC_Load#endif#ifndef CC_LoadExternal#define CC_LoadExternal#endif#ifndef CC_MAC#define CC_MAC#endif#ifndef CC_MAC_Start#define CC_MAC_Start#endif#ifndef CC_MakeCredential#define CC_MakeCredential#endif#ifndef CC_NV_Certify

Page 762
April 15, 2019

CC_NO
CC_NO
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES(CC_YES && !ALG_CMAC)(CC_YES && !ALG_CMAC)
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES(CC_YES && ALG_CMAC)(CC_YES && ALG_CMAC)
CC_YES

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

Trusted Platform Module Library#define CC_NV_Certify#endif#ifndef CC_NV_ChangeAuth#define CC_NV_ChangeAuth#endif#ifndef CC_NV_DefineSpace#define CC_NV_DefineSpace#endif#ifndef CC_NV_Extend#define CC_NV_Extend#endif#ifndef CC_NV_GlobalWriteLock#define CC_NV_GlobalWriteLock#endif#ifndef CC_NV_Increment#define CC_NV_Increment#endif#ifndef CC_NV_Read#define CC_NV_Read#endif#ifndef CC_NV_ReadLock#define CC_NV_ReadLock#endif#ifndef CC_NV_ReadPublic#define CC_NV_ReadPublic#endif#ifndef CC_NV_SetBits#define CC_NV_SetBits#endif#ifndef CC_NV_UndefineSpace#define CC_NV_UndefineSpace#endif#ifndef CC_NV_UndefineSpaceSpecial#define CC_NV_UndefineSpaceSpecial#endif#ifndef CC_NV_Write#define CC_NV_Write#endif#ifndef CC_NV_WriteLock#define CC_NV_WriteLock#endif#ifndef CC_ObjectChangeAuth#define CC_ObjectChangeAuth#endif#ifndef CC_PCR_Allocate#define CC_PCR_Allocate#endif#ifndef CC_PCR_Event#define CC_PCR_Event#endif#ifndef CC_PCR_Extend#define CC_PCR_Extend#endif#ifndef CC_PCR_Read#define CC_PCR_Read#endif#ifndef CC_PCR_Reset#define CC_PCR_Reset#endif#ifndef CC_PCR_SetAuthPolicy#define CC_PCR_SetAuthPolicy#endif#ifndef CC_PCR_SetAuthValue#define CC_PCR_SetAuthValue#endif#ifndef CC_PP_Commands

Family “2.0”Level 00 Revision 01.55

CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 763
April 15, 2019

Trusted Platform Module Library
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660

Part 4: Supporting Routines#define CC_PP_Commands#endif#ifndef CC_PolicyAuthValue#define CC_PolicyAuthValue#endif#ifndef CC_PolicyAuthorize#define CC_PolicyAuthorize#endif#ifndef CC_PolicyAuthorizeNV#define CC_PolicyAuthorizeNV#endif#ifndef CC_PolicyCommandCode#define CC_PolicyCommandCode#endif#ifndef CC_PolicyCounterTimer#define CC_PolicyCounterTimer#endif#ifndef CC_PolicyCpHash#define CC_PolicyCpHash#endif#ifndef CC_PolicyDuplicationSelect#define CC_PolicyDuplicationSelect#endif#ifndef CC_PolicyGetDigest#define CC_PolicyGetDigest#endif#ifndef CC_PolicyLocality#define CC_PolicyLocality#endif#ifndef CC_PolicyNV#define CC_PolicyNV#endif#ifndef CC_PolicyNameHash#define CC_PolicyNameHash#endif#ifndef CC_PolicyNvWritten#define CC_PolicyNvWritten#endif#ifndef CC_PolicyOR#define CC_PolicyOR#endif#ifndef CC_PolicyPCR#define CC_PolicyPCR#endif#ifndef CC_PolicyPassword#define CC_PolicyPassword#endif#ifndef CC_PolicyPhysicalPresence#define CC_PolicyPhysicalPresence#endif#ifndef CC_PolicyRestart#define CC_PolicyRestart#endif#ifndef CC_PolicySecret#define CC_PolicySecret#endif#ifndef CC_PolicySigned#define CC_PolicySigned#endif#ifndef CC_PolicyTemplate#define CC_PolicyTemplate#endif#ifndef CC_PolicyTicket#define CC_PolicyTicket#endif#ifndef CC_Policy_AC_SendSelectPage 764
April 15, 2019

CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726

Trusted Platform Module Library#define CC_Policy_AC_SendSelect#endif#ifndef CC_Quote#define CC_Quote#endif#ifndef CC_RSA_Decrypt#define CC_RSA_Decrypt#endif#ifndef CC_RSA_Encrypt#define CC_RSA_Encrypt#endif#ifndef CC_ReadClock#define CC_ReadClock#endif#ifndef CC_ReadPublic#define CC_ReadPublic#endif#ifndef CC_Rewrap#define CC_Rewrap#endif#ifndef CC_SelfTest#define CC_SelfTest#endif#ifndef CC_SequenceComplete#define CC_SequenceComplete#endif#ifndef CC_SequenceUpdate#define CC_SequenceUpdate#endif#ifndef CC_SetAlgorithmSet#define CC_SetAlgorithmSet#endif#ifndef CC_SetCommandCodeAuditStatus#define CC_SetCommandCodeAuditStatus#endif#ifndef CC_SetPrimaryPolicy#define CC_SetPrimaryPolicy#endif#ifndef CC_Shutdown#define CC_Shutdown#endif#ifndef CC_Sign#define CC_Sign#endif#ifndef CC_StartAuthSession#define CC_StartAuthSession#endif#ifndef CC_Startup#define CC_Startup#endif#ifndef CC_StirRandom#define CC_StirRandom#endif#ifndef CC_TestParms#define CC_TestParms#endif#ifndef CC_Unseal#define CC_Unseal#endif#ifndef CC_Vendor_TCG_Test#define CC_Vendor_TCG_Test#endif#ifndef CC_VerifySignature#define CC_VerifySignature#endif#ifndef CC_ZGen_2Phase

Family “2.0”Level 00 Revision 01.55

CC_YES
CC_YES(CC_YES && ALG_RSA)(CC_YES && ALG_RSA)
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES
CC_YES

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 765
April 15, 2019

Trusted Platform Module Library
727
728
729

#define CC_ZGen_2Phase#endif#endif // _TPM_PROFILE_H_

Page 766
April 15, 2019

Part 4: Supporting Routines(CC_YES && ALG_ECC)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

Annex B(informative)
Library-SpecificB.1

Introduction

This clause contains the files that are specific to a cryptographic library used by the TPM code.
Three categories are defined for cryptographic functions:
big number math (asymmetric cryptography),symmetric ciphers, andhash functions.
The code is structured to make it possible to use different libraries for different categories. For example,
one might choose to use OpenSSL for its math library, but use a different library for hashing andsymmetric cryptography. Since OpenSSL supports all three categories, it might be more typical to
combine libraries of specific functions; that is, one library might only contain block ciphers while anothersupports big number math.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 767
April 15, 2019

Trusted Platform Module Library

B.2

Part 4: Supporting Routines

OpenSSL-Specific Files

B.2.1.

Introduction

The following files are specific to a port that uses the OpenSSL library for cryptographic functions.
B.2.2.

Header Files

B.2.2.1.

TpmToOsslHash.h

B.2.2.1.1.

Introduction

This header file is used to splice the OpenSSL hash code into the TPM code.
1
2
3
4
5
6

#ifndef HASH_LIB_DEFINED#define HASH_LIB_DEFINED#define HASH_LIB_OSSL#include <openssl/evp.h>#include <openssl/sha.h>#include <openssl/ossl_typ.h>

B.2.2.1.2.

Links to the OpenSSL HASH code

Redefine the internal name used for each of the hash state structures to the name used by the library.
These defines need to be known in all parts of the TPM so that the structure sizes can be properly
computed when needed.
7
8
9
10
11
12
13

#define tpmHashStateSHA1_t
SHA_CTX#define tpmHashStateSHA256_t
SHA256_CTX#define tpmHashStateSHA384_t
SHA512_CTX#define tpmHashStateSHA512_t
SHA512_CTX#if
ALG_SM3_256#
error "The version of OpenSSL used by this code does not support SM3"
#endif

The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation is
primarily to avoid name space collision. However, if there is a real collision, it will likely show up when thelinker tries to put things together.
14
15
16

#ifdef _CRYPT_HASH_C_
typedef BYTE*PBYTE;
typedef const BYTE*PCBYTE;Define the interface between CryptHash.c to the functions provided by the library. For each method,
define the calling parameters of the method and then define how the method is invoked in CryptHash.c.
All hashes are required to have the same calling sequence. If they don't, create a simple adaptation
function that converts from the standard form of the call to the form used by the specific hash (and thensend a nasty letter to the person who wrote the hash function for the library).
The macro that calls the method also defines how the parameters get swizzled between the default form
(in CryptHash.c)and the library form.
Initialize the hash context
17
18#define HASH_START_METHOD_DEF#define HASH_START(hashState)

Page 768
April 15, 2019

void (HASH_START_METHOD)(PANY_HASH_STATE state)\

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
19

Trusted Platform Module Library((hashState)->def->method.start)(&(hashState)->state);

Add data to the hash
20
21
22
23
24
25

#define HASH_DATA_METHOD_DEF\
void (HASH_DATA_METHOD)(PANY_HASH_STATE state,\
PCBYTE buffer,\size_t size)#define HASH_DATA(hashState, dInSize, dIn)\((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize)

Finalize the hash and get the digest
26
27
28
29

#define HASH_END_METHOD_DEF
void (HASH_END_METHOD)(BYTE *buffer, PANY_HASH_STATE state)#define HASH_END(hashState, buffer)((hashState)->def->method.end)(buffer, &(hashState)->state)\\

Copy the hash context
NOTE:

30
31
32
33
34
35
36
37

For import, export, and copy, memcpy() is used since there is no reformatting necessary between the internaland external forms.

#define HASH_STATE_COPY_METHOD_DEF
void (HASH_STATE_COPY_METHOD)(PANY_HASH_STATE to,
PCANY_HASH_STATE from,size_t size)#define HASH_STATE_COPY(hashStateOut, hashStateIn)((hashStateIn)->def->method.copy)(&(hashStateOut)->state,&(hashStateIn)->state,(hashStateIn)->def->contextSize)

\
\
\
\
\
\

Copy (with reformatting when necessary) an internal hash structure to an external blob
38
39
40
41
42
43
44
45
46

#define#define

HASH_STATE_EXPORT_METHOD_DEF
void (HASH_STATE_EXPORT_METHOD)(BYTE *to,
PCANY_HASH_STATE from,size_t size)
HASH_STATE_EXPORT(to, hashStateFrom)((hashStateFrom)->def->method.copyOut)(&(((BYTE *)(to))[offsetof(HASH_STATE, state)]),&(hashStateFrom)->state,(hashStateFrom)->def->contextSize)

\
\
\
\
\
\
\

Copy from an external blob to an internal formate (with reformatting when necessary
47
48
49
50
51
52
53
54
55

#define#define

HASH_STATE_IMPORT_METHOD_DEF\
void (HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to,\const BYTE *from,\size_t size)
HASH_STATE_IMPORT(hashStateTo, from)\((hashStateTo)->def->method.copyIn)\(&(hashStateTo)->state,\&(((const BYTE *)(from))[offsetof(HASH_STATE, state)]),\(hashStateTo)->def->contextSize)

Function aliases. The code in CryptHash.c uses the internal designation for the functions. These need to
be translated to the function names of the library.
56
57
58
59

#define tpmHashStart_SHA1

SHA1_Init#define tpmHashData_SHA1#define tpmHashEnd_SHA1

SHA1_Update
SHA1_Final

Family “2.0”Level 00 Revision 01.55// external name of the// initialization method

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 769
April 15, 2019

Trusted Platform Module Library
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

Part 4: Supporting Routines#define tpmHashStateCopy_SHA1#define tpmHashStateExport_SHA1#define tpmHashStateImport_SHA1#define tpmHashStart_SHA256#define tpmHashData_SHA256#define tpmHashEnd_SHA256#define tpmHashStateCopy_SHA256#define tpmHashStateExport_SHA256#define tpmHashStateImport_SHA256#define tpmHashStart_SHA384#define tpmHashData_SHA384#define tpmHashEnd_SHA384#define tpmHashStateCopy_SHA384#define tpmHashStateExport_SHA384#define tpmHashStateImport_SHA384#define tpmHashStart_SHA512#define tpmHashData_SHA512#define tpmHashEnd_SHA512#define tpmHashStateCopy_SHA512#define tpmHashStateExport_SHA512#define tpmHashStateImport_SHA512#endif // _CRYPT_HASH_C_#define LibHashInit()

memcpymemcpymemcpySHA256_Init
SHA256_Update
SHA256_Final
memcpymemcpymemcpySHA384_Init
SHA384_Update
SHA384_Final
memcpymemcpymemcpySHA512_Init
SHA512_Update
SHA512_Final
memcpymemcpymemcpyThis definition would change if there were something to report
83
84#define HashLibSimulationEnd()#endif // HASH_LIB_DEFINED

Page 770
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

B.2.2.2.

TpmToOsslMath.h

B.2.2.2.1.

Introduction

This file contains the structure definitions used for ECC in the LibTopCrypt() version of the code. These
definitions would change, based on the library. The ECC-related structures that cross the TPM interface
are defined in TpmTypes.h
1
2
3
4
5
6
7
8
9

#ifndef MATH_LIB_DEFINED#define MATH_LIB_DEFINED#define MATH_LIB_OSSL#include <openssl/evp.h>#include <openssl/ec.h>#if OPENSSL_VERSION_NUMBER >= 0x10100000L#include <openssl/bn_lcl.h>#endif#include <openssl/bn.h>

B.2.2.2.2.

Macros and Defines

Make sure that the library is using the correct size for a crypt word
10
11
12
13
14

#if

defined THIRTY_TWO_BIT && (RADIX_BITS != 32) \|| ((defined SIXTY_FOUR_BIT_LONG || defined SIXTY_FOUR_BIT) \&& (RADIX_BITS != 64))
# error "Ossl library is using different radix"#endif

Allocate a local BIGNUM value. For the allocation, a bigNum structure is created as is a local BIGNUM.
The bigNum is initialized and then the BIGNUM is set to reference the local value.
15
16
17
18
19
20

#define BIG_VAR(name, bits)\
BN_VAR(name##Bn, (bits));\
BIGNUM_##name;\BIGNUM*name = BigInitialized(&_##name,\
BnInit(name##Bn,\
BYTES_TO_CRYPT_WORDS(sizeof(_##name##Bn.d))))Allocate a BIGNUM and initialize with the values in a bigNum initializer
21
22
23
24
25
26
27
28
29
30
31
32
33

#define BIG_INITIALIZED(name, initializer)\
BIGNUM_##name;\BIGNUM*name = BigInitialized(&_##name, initializer)
typedef struct{const ECC_CURVE_DATA*C;// the TPM curve values
EC_GROUP*G;// group parameters
BN_CTX*CTX;// the context for the math (this might not be// the context in which the curve was created>;} OSSL_CURVE_DATA;
typedef OSSL_CURVE_DATA*bigCurve;#define AccessCurveData(E)((E)->C)#include "TpmToOsslSupport_fp.h"

Start and end a context within which the OpenSSL memory management works
34
35#define OSSL_ENTER()#define OSSL_LEAVE()

Family “2.0”Level 00 Revision 01.55

BN_CTX*CTX = OsslContextEnter()
OsslContextLeave(CTX)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 771
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

Start and end a context that spans multiple ECC functions. This is used so that the group for the curve
can persist across multiple frames.
36
37
38
39

#define CURVE_INITIALIZED(name, initializer)\
OSSL_CURVE_DATA_##name;\bigCurve
name = BnCurveInitialize(&_##name, initializer)#define CURVE_FREE(name)
BnCurveFree(name)Start and end a local stack frame within the context of the curve frame
40
41
42

#define ECC_ENTER()#define ECC_LEAVE()#define BN_NEW()

BN_CTX*CTX = OsslPushContext(E->CTX)
OsslPopContext(CTX)
BnNewVariable(CTX)

This definition would change if there were something to report
43
44#define MathLibSimulationEnd()#endif // MATH_LIB_DEFINED

Page 772
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

B.2.2.3.

TpmToOsslSym.h

B.2.2.3.1.

Introduction

Trusted Platform Module LibraryThis header file is used to splice the OpenSSL library into the TPM code.
The support required of a library are a hash module, a block cipher module and portions of a big number
library.
1
2
3
4
5
6
7

#ifndef SYM_LIB_DEFINED#define SYM_LIB_DEFINED#define SYM_LIB_OSSL#include <openssl/aes.h>#include <openssl/des.h>#include <openssl/bn.h>#include <openssl/ossl_typ.h>

B.2.2.3.2.
8
9
10
11
12
13

Links to the OpenSSL AES code

#if
ALG_SM4#error "SM4 is not available"#endif#if
ALG_CAMELLIA#error "Camellia is not available"#endifDefine the order of parameters to the library functions that do block encryption and decryption.
14
15
16
17
18

typedef void(*TpmCryptSetSymKeyCall_t)(
const BYTE *in,
BYTE
*out,
void *keySchedule);

The Crypt functions that call the block encryption function use the parameters in the order:
keySchedulein bufferout buffer Since open SSL uses the order in encryptoCall_t above, need to swizzle the values to theorder required by the library.
19
20#define SWIZZLE(keySchedule, in, out)
(const BYTE *)(in), (BYTE *)(out), (void *)(keySchedule)\

Macros to set up the encryption/decryption key schedules
AES:
21
22
23
24

#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule)\
AES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule))#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule)\
AES_set_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule))

TDES:
25
26
27
28

#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule)\
TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule))#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule)\
TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule))

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 773
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

Macros to alias encryption calls to specific algorithms. This should be used sparingly. Currently, only usedby CryptRand.c
When using these calls, to call the AES block encryption code, the caller should use:
TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out));
29
30
31
32
33
34
35
36
37
38

#define TpmCryptEncryptAES
AES_encrypt#define TpmCryptDecryptAES
AES_decrypt#define tpmKeyScheduleAES
AES_KEY#define TpmCryptEncryptTDES
TDES_encrypt#define TpmCryptDecryptTDES
TDES_decrypt#define tpmKeyScheduleTDES
DES_key_schedule
typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t;#if
ALG_TDES#include "TpmToOsslDesSupport_fp.h"#endifThis definition would change if there were something to report
39
40#define SymLibSimulationEnd()#endif // SYM_LIB_DEFINED

Page 774
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

B.2.3.

Trusted Platform Module Library

Source Files

B.2.3.1.

TpmToOsslDesSupport.c

B.2.3.1.1.

Introduction

The functions in this file are used for initialization of the interface to the OpenSSL library.
B.2.3.1.2.
1
2

Defines and Includes#include "Tpm.h"#if (defined SYM_LIB_OSSL) && ALG_TDES

B.2.3.1.3.
B.2.3.1.3.1.

Functions
TDES_set_encyrpt_key()

This function makes creation of a TDES key look like the creation of a key for any of the other OpenSSL
block ciphers. It will create three key schedules, one for each of the DES keys. If there are only two keys,
then the third schedule is a copy of the first.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

void
TDES_set_encrypt_key(
const BYTEUINT16
tpmKeyScheduleTDES)*key,
keySizeInBits,*keySchedule{
DES_set_key_unchecked((const_DES_cblock *)key, &keySchedule[0]);DES_set_key_unchecked((const_DES_cblock *)&key[8], &keySchedule[1]);// If is two-key, copy the schedule for K1 into K3, otherwise, compute the// the schedule for K3
if(keySizeInBits == 128)
keySchedule[2] = keySchedule[0];else
DES_set_key_unchecked((const_DES_cblock *)&key[16],&keySchedule[2]);}B.2.3.1.3.2.

TDES_encyrpt()

The TPM code uses one key schedule. For TDES, the schedule contains three schedules. OpenSSL
wants the schedules referenced separately. This function does that.
20
21
22
23
24
25
26
27
28
29

void TDES_encrypt(
const BYTE
*in,
BYTE
*out,
tpmKeyScheduleTDES*ks){
DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out,&ks[0], &ks[1], &ks[2],DES_ENCRYPT);}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 775
April 15, 2019

Trusted Platform Module Library

B.2.3.1.3.3.

Part 4: Supporting Routines

TDES_decrypt()

As with TDES_encypt() this function bridges between the TPM single schedule model and the OpenSSL
three schedule model.
30
31
32
33
34
35
36
37
38
39
40

void TDES_decrypt(
const BYTE
*in,
BYTE
*out,
tpmKeyScheduleTDES*ks){
DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out,&ks[0], &ks[1], &ks[2],DES_DECRYPT);}#endif // SYM_LIB_OSSL

Page 776
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

B.2.3.2.

TpmToOsslMath.c

B.2.3.2.1.

Introduction

Trusted Platform Module LibraryThis file contains the math functions that are not implemented in the BnMath() library (yet). These mathfunctions will call the OpenSSL library to execute the operations. There is a difference between theinternal format and the OpenSSL format. To call the OpenSSL function, a BIGNUM structure is createdfor each passed variable. The sizes in the bignum_t are copied and the d pointer in the BIGNUM is set topoint to the d parameter of the bignum_t. On return, SetSizeOsslToTpm() is used for each returned
variable to make sure that the pointers are not changed. The size of the returned BIGGNUM is copied tobignum_t.
B.2.3.2.2.

Introduction

The functions in this file provide the low-level interface between the TPM code and the big number andelliptic curve math routines in OpenSSL.
Most math on big numbers require a context. The context contains the memory in which OpenSSL
creates and manages the big number values. When a OpenSSL math will be called that modifies a
BIGNUM value, that value must be created in an OpenSSL context. The first line of code in such afunction must be: OSSL_ENTER(); and the last operation before returning must be OSSL_LEAVE().
OpenSSL variables can then be created with BnNewVariable(). Constant values to be used by OpenSSL
are created from the bigNum values passed to the functions in this file. Space for the BIGNUM control
block is allocated in the stack of the function and then it is initialized by calling BigInitialized(). Thatfunction sets up the values in the BIGNUM structure and sets the data pointer to point to the data in thebignum_t. This is only used when the value is known to be a constant in the called function.
Because the allocations of constants is on the local stack and the OSSL_ENTER()/OSSL_LEAVE() pair
flushes everything created in OpenSSL memory, there should be no chance of a memory leak.
B.2.3.2.3.
1
2
3

Includes and Defines#include "Tpm.h"#ifdef MATH_LIB_OSSL#include "TpmToOsslMath_fp.h"

B.2.3.2.4.

Functions

B.2.3.2.4.1.

OsslToTpmBn()

This function converts an OpenSSL BIGNUM to a TPM bignum. In this implementation it is assumed that
OpenSSL uses a different control structure but the same data layout -- an array of native-endian words inlittle-endian order.

4
5
6
7
8
9
10

Return Value

Meaning

TRUE(1)success

FALSE(0)failure because value will not fit or OpenSSL variable doesn't exist

BOOL
OsslToTpmBn(
bigNumBIGNUM)bn,*osslBn{
VERIFY(osslBn != NULL);

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 777
April 15, 2019

Trusted Platform Module Library
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Part 4: Supporting Routines// If the bn is NULL, it means that an output value pointer was NULL meaning that// the results is simply to be discarded.
if(bn != NULL)
{
int
i;
//
VERIFY((unsigned)osslBn->top <= BnGetAllocated(bn));for(i = 0; i < osslBn->top; i++)bn->d[i] = osslBn->d[i];BnSetTop(bn, osslBn->top);}
return TRUE;
Error:
return FALSE;}

B.2.3.2.4.2.

BigInitialized()

This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for values that are
passed to OpenSLL when they are not declared as const in the function prototype. Instead, use
BnNewVariable().
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

BIGNUM *BigInitialized(
BIGNUM
bigConst){
if(initializer == NULL)
FAIL(FATAL_ERROR_PARAMETER);
if(toInit == NULL || initializer == NULL)
return NULL;
toInit->d = (BN_ULONG *)&initializer->d[0];toInit->dmax = initializer->allocated;
toInit->top = initializer->size;
toInit->neg = 0;
toInit->flags = 0;
return toInit;}#ifndef OSSL_DEBUG#
define BIGNUM_PRINT(label, bn, eol)#
define DEBUG_PRINT(x)#else#define DEBUG_PRINT(x)printf("%s", x)#define BIGNUM_PRINT(label, bn, eol) BIGNUM_print((label), (bn), (eol))

B.2.3.2.4.3.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

*toInit,initializer

BIGNUM_print()

static void
BIGNUM_print(
const charconst BIGNUM
BOOL)*label,*a,eol

BN_ULONG
int
int

*d;
i;
notZero = FALSE;{

if(label != NULL)
printf("%s", label);if(a == NULL){

Page 778
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

Trusted Platform Module Library

printf("NULL");
goto done;}
if (a->neg)
printf("-");
for(i = a->top, d = &a->d[i - 1]; i > 0; i--){intj;
BN_ULONGl = *d--;for(j = BN_BITS2 - 8; j >= 0; j -= 8){
BYTE
b = (BYTE)((l >> j) & 0xFF);
notZero = notZero || (b != 0);
if(notZero)printf("%02x", b);}if(!notZero)printf("0");}done:
if(eol)printf("\n");return;}#endifB.2.3.2.4.4.

BnNewVariable()This function allocates a new variable in the provided context. If the context does not exist or the
allocation fails, it is a catastrophic failure.
89
90
91
92
93
94
95
96
97
98
99
100
101
102

static BIGNUM *BnNewVariable(
BN_CTX*CTXBIGNUM

*new;

)
{
//
// This check is intended to protect against calling this function without// having initialized the CTX.
if((CTX == NULL) || ((new = BN_CTX_get(CTX)) == NULL))
FAIL(FATAL_ERROR_ALLOCATION);
return new;}
#if LIBRARY_COMPATIBILITY_CHECK

B.2.3.2.4.5.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

MathLibraryCompatibilityCheck()void
MathLibraryCompatibilityCheck(void){
OSSL_ENTER();BIGNUM
crypt_uword_t
BYTE*osslTemp = BnNewVariable(CTX);i;test[] = {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18,
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
BN_VAR(tpmTemp, sizeof(test) * 8); // allocate some space for a test value//// Convert the test data to a bigNum

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 779
April 15, 2019

Trusted Platform Module Library
118
119
120
121
122
123
124
125
126
127
128
129
130

Part 4: Supporting Routines

BnFromBytes(tpmTemp, test, sizeof(test));// Convert the test data to an OpenSSL BIGNUM
BN_bin2bn(test, sizeof(test), osslTemp);// Make sure the values are consistent
VERIFY(osslTemp->top == (int)tpmTemp->size);for(i = 0; i < tpmTemp->size; i++)VERIFY(osslTemp->d[i] == tpmTemp->d[i]);OSSL_LEAVE();
return;Error:FAIL(FATAL_ERROR_MATHLIBRARY);}#endifB.2.3.2.4.6.

BnModMult()

This function does a modular multiply. It first does a multiply and then a divide and returns the remainderof the divide.

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL
BnModMult(
bigNumbigConst
bigConst
bigConst)

result,op1,
op2,
modulus{
OSSL_ENTER();BOOL
OK = TRUE;BIGNUM*bnResult = BN_NEW();BIGNUM*bnTemp = BN_NEW();
BIG_INITIALIZED(bnOp1, op1);
BIG_INITIALIZED(bnOp2, op2);
BIG_INITIALIZED(bnMod, modulus);//
VERIFY(BN_mul(bnTemp, bnOp1, bnOp2, CTX));
VERIFY(BN_div(NULL, bnResult, bnTemp, bnMod, CTX));
VERIFY(OsslToTpmBn(result, bnResult));
goto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}

B.2.3.2.4.7.

BnMult()Multiplies two numbers

157

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL

Page 780
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

Trusted Platform Module Library

BnMult(bigNumbigConst
bigConst)

result,multiplicand,multiplier{
OSSL_ENTER();BIGNUM*bnTemp = BN_NEW();
BOOL
OK = TRUE;
BIG_INITIALIZED(bnA, multiplicand);
BIG_INITIALIZED(bnB, multiplier);//
VERIFY(BN_mul(bnTemp, bnA, bnB, CTX));
VERIFY(OsslToTpmBn(result, bnTemp));goto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}

B.2.3.2.4.8.

BnDiv()

This function divides two bigNum values. The function returns FALSE if there is an error in the operation.

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL
BnDiv(
bigNumbigNumbigConst
bigConst)

quotient,
remainder,
dividend,
divisor{OSSL_ENTER();BIGNUM*bnQ = BN_NEW();BIGNUM*bnR = BN_NEW();
BOOL
OK = TRUE;
BIG_INITIALIZED(bnDend, dividend);
BIG_INITIALIZED(bnSor, divisor);//if(BnEqualZero(divisor))
FAIL(FATAL_ERROR_DIVIDE_ZERO);
VERIFY(BN_div(bnQ, bnR, bnDend, bnSor, CTX));
VERIFY(OsslToTpmBn(quotient, bnQ));
VERIFY(OsslToTpmBn(remainder, bnR));
DEBUG_PRINT("In BnDiv:\n");BIGNUM_PRINT("
bnDividend: ", bnDend, TRUE);BIGNUM_PRINT("
bnDivisor: ", bnSor, TRUE);BIGNUM_PRINT("
bnQuotient: ", bnQ, TRUE);BIGNUM_PRINT(" bnRemainder: ", bnR, TRUE);
goto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 781
April 15, 2019

Trusted Platform Module Library
211

#if

Part 4: Supporting Routines

ALG_RSA

B.2.3.2.4.9.

BnGcd()

Get the greatest common divisor of two numbers

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL
BnGcd(
bigNumbigConst
bigConst)

gcd,
number1,
number2// OUT: the common divisor// IN:// IN:{
OSSL_ENTER();BIGNUM*bnGcd = BN_NEW();
BOOL
OK = TRUE;
BIG_INITIALIZED(bn1, number1);
BIG_INITIALIZED(bn2, number2);//
VERIFY(BN_gcd(bnGcd, bn1, bn2, CTX));
VERIFY(OsslToTpmBn(gcd, bnGcd));
goto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}

B.2.3.2.4.10.

BnModExp()

Do modular exponentiation using bigNum values. The conversion from a bignum_t to a bigNum is trivial
as they are based on the same structure

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL
BnModExp(
bigNumbigConst
bigConst
bigConst)

result,number,exponent,
modulus// OUT: the result// IN: number to exponentiate// IN:// IN:{
OSSL_ENTER();BIGNUM*bnResult = BN_NEW();
BOOL
OK = TRUE;
BIG_INITIALIZED(bnN, number);
BIG_INITIALIZED(bnE, exponent);
BIG_INITIALIZED(bnM, modulus);//
VERIFY(BN_mod_exp(bnResult, bnN, bnE, bnM, CTX));
VERIFY(OsslToTpmBn(result, bnResult));

Page 782
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
251
252
253
254
255
256
257

Trusted Platform Module Librarygoto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}

B.2.3.2.4.11.

BnModInverse()

Modular multiplicative inverse

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL
BnModInverse(
bigNumbigConst
bigConst)

result,number,modulus{
OSSL_ENTER();BIGNUM*bnResult = BN_NEW();
BOOL
OK = TRUE;
BIG_INITIALIZED(bnN, number);
BIG_INITIALIZED(bnM, modulus);//
VERIFY(BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL);VERIFY(OsslToTpmBn(result, bnResult));
goto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}#endif // ALG_RSA#if
ALG_ECC

B.2.3.2.4.12.

PointFromOssl()

Function to copy the point result from an OSSL function to a bigNum

282
283
284
285
286
287
288
289
290
291

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

static BOOL
PointFromOssl(
bigPoint
EC_POINT
bigCurve
)

pOut,
*pIn,
E

BIGNUMBIGNUMBOOL*x = NULL;*y = NULL;OK;// OUT: resulting point// IN: the point to return// IN: the curve{

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 783
April 15, 2019

Trusted Platform Module Library
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

Part 4: Supporting Routines

BN_CTX_start(E->CTX);//
x = BN_CTX_get(E->CTX);y = BN_CTX_get(E->CTX);if(y == NULL)
FAIL(FATAL_ERROR_ALLOCATION);// If this returns false, then the point is at infinity
OK = EC_POINT_get_affine_coordinates_GFp(E->G, pIn, x, y, E->CTX);
if(OK){
OsslToTpmBn(pOut->x, x);
OsslToTpmBn(pOut->y, y);
BnSetWord(pOut->z, 1);}else
BnSetWord(pOut->z, 0);
BN_CTX_end(E->CTX);
return OK;}

B.2.3.2.4.13.

EcPointInitialized()

Allocate and initialize a point.
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

static EC_POINT *EcPointInitialized(
pointConst
bigCurve)

initializer,
E

EC_POINT*P = NULL;{
if(initializer != NULL){
BIG_INITIALIZED(bnX, initializer->x);
BIG_INITIALIZED(bnY, initializer->y);P = EC_POINT_new(E->G);if(E == NULL)
FAIL(FATAL_ERROR_ALLOCATION);
if(!EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX))
P = NULL;}
return P;}

B.2.3.2.4.14.

BnCurveInitialize()This function initializes the OpenSSL curve information structure. This structure points to the TPM-definedvalues for the curve, to the context for the number values in the frame, and to the OpenSSL-definedgroup values.

332
333
334
335

Return Value

Meaning

NULL

the TPM_ECC_CURVE is not valid or there was a problem in in
initializing the curve data

non-NULL

points to E

LIB_EXPORT bigCurve
BnCurveInitialize(
bigCurve
TPM_ECC_CURVE

Page 784
April 15, 2019E,
curveId// IN: curve structure to initialize// IN: curve identifier

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

Trusted Platform Module Library){
const ECC_CURVE_DATA*C = GetCurveData(curveId);if(C == NULL)
E = NULL;
if(E != NULL){// This creates the OpenSSL memory context that stays in effect as long as the// curve (E) is defined.
OSSL_ENTER();// if the allocation fails, the TPM fails
EC_POINT*P = NULL;
BIG_INITIALIZED(bnP, C->prime);
BIG_INITIALIZED(bnA, C->a);
BIG_INITIALIZED(bnB, C->b);
BIG_INITIALIZED(bnX, C->base.x);
BIG_INITIALIZED(bnY, C->base.y);
BIG_INITIALIZED(bnN, C->order);
BIG_INITIALIZED(bnH, C->h);//
E->C = C;
E->CTX = CTX;// initialize EC group, associate a generator point and initialize the point// from the parameter data// Create a group structure
E->G = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, CTX);VERIFY(E->G != NULL);// Allocate a point in the group that will be used in setting the// generator. This is not needed after the generator is set.
P = EC_POINT_new(E->G);
VERIFY(P != NULL);// Need to use this in case Montgomery method is being used
VERIFY(EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, CTX));// Now set the generator
VERIFY(EC_GROUP_set_generator(E->G, P, bnN, bnH));
EC_POINT_free(P);goto Exit;
Error:
EC_POINT_free(P);
BnCurveFree(E);E = NULL;}
Exit:
return E;}

B.2.3.2.4.15.

BnCurveFree()This function will free the allocated components of the curve and end the frame in which the curve data
exists
384
385
386
387
388
389
390
391
392
393

LIB_EXPORT void
BnCurveFree(
bigCurve

E

)
{
if(E)
{
EC_GROUP_free(E->G);
OsslContextLeave(E->CTX);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 785
April 15, 2019

Trusted Platform Module Library
394

Part 4: Supporting Routines}

B.2.3.2.4.16.

BnEccModMult()

This function does a point multiply of the form R = [d]S

395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation; treat as result being point at infinity

LIB_EXPORT BOOL
BnEccModMult(
bigPoint
pointConst
bigConst
bigCurve
)

R,
S,
d,
E

// OUT: computed point// IN: point to multiply by 'd' (optional)// IN: scalar for [d]S{
EC_POINT*pR = EC_POINT_new(E->G);
EC_POINT*pS = EcPointInitialized(S, E);
BIG_INITIALIZED(bnD, d);if(S == NULL)
EC_POINT_mul(E->G, pR, bnD, NULL, NULL, E->CTX);
else
EC_POINT_mul(E->G, pR, NULL, pS, bnD, E->CTX);
PointFromOssl(R, pR, E);
EC_POINT_free(pR);
EC_POINT_free(pS);
return !BnEqualZero(R->z);}

B.2.3.2.4.17.

BnEccModMult2()

This function does a point multiply of the form R = [d]G + [u]Q

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation; treat as result being point at infinity

LIB_EXPORT BOOL
BnEccModMult2(
bigPoint
pointConst
bigConst
pointConst
bigConst
bigCurve
)

R,
S,
d,
Q,
u,
E

// OUT: computed point// IN: optional point// IN: scalar for [d]S or [d]G// IN: second point// IN: second scalar// IN: curve{
EC_POINT*pR = EC_POINT_new(E->G);
EC_POINT*pS = EcPointInitialized(S, E);
BIG_INITIALIZED(bnD, d);
EC_POINT*pQ = EcPointInitialized(Q, E);
BIG_INITIALIZED(bnU, u);if(S == NULL || S == (pointConst)&(AccessCurveData(E)->base))
EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX);
else

Page 786
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

Trusted Platform Module Library{
const EC_POINT*points[2];const BIGNUM*scalars[2];points[0] = pS;
points[1] = pQ;
scalars[0] = bnD;
scalars[1] = bnU;
EC_POINTs_mul(E->G, pR, NULL, 2, points, scalars, E->CTX);}
PointFromOssl(R, pR, E);
EC_POINT_free(pR);
EC_POINT_free(pS);
EC_POINT_free(pQ);
return !BnEqualZero(R->z);}

B.2.3.2.5.

BnEccAdd()

This function does addition of two points.

450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation; treat as result being point at infinity

LIB_EXPORT BOOL
BnEccAdd(
bigPoint
pointConst
pointConst
bigCurve
)

R,
S,
Q,
E

// OUT: computed point// IN: point to multiply by 'd'// IN: second point// IN: curve

EC_POINT
EC_POINT
EC_POINT*pR = EC_POINT_new(E->G);*pS = EcPointInitialized(S, E);*pQ = EcPointInitialized(Q, E);{//
EC_POINT_add(E->G, pR, pS, pQ, E->CTX);
PointFromOssl(R, pR, E);
EC_POINT_free(pR);
EC_POINT_free(pS);
EC_POINT_free(pQ);
return !BnEqualZero(R->z);}#endif // ALG_ECC#endif // MATHLIB OSSL

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 787
April 15, 2019

Trusted Platform Module Library

B.2.3.3.

Part 4: Supporting Routines

TpmToOsslSupport.c

B.2.3.3.1.

Introduction

The functions in this file are used for initialization of the interface to the OpenSSL library.
B.2.3.3.2.
1
2

Defines and Includes#include "Tpm.h"#ifdef MATH_LIB_OSSL

Used to pass the pointers to the correct sub-keys
3

typedef const BYTE *desKeyPointers[3];B.2.3.3.2.1.

SupportLibInit()

This does any initialization required by the support library.
4
5
6
7
8
9
10
11
12
13

LIB_EXPORT int
SupportLibInit(
void){#if LIBRARY_COMPATIBILITY_CHECKMathLibraryCompatibilityCheck();#endifreturn TRUE;}

B.2.3.3.2.2.

OsslContextEnter()This function is used to initialize an OpenSSL context at the start of a function that will call to an
OpenSSL math function.
14
15
16
17
18
19
20
21
22

BN_CTX *OsslContextEnter(void){
BN_CTX*CTX = BN_CTX_new();//
return OsslPushContext(CTX);}

B.2.3.3.2.3.

OsslContextLeave()This is the companion function to OsslContextEnter().
23
24
25
26
27
28
29
30

void
OsslContextLeave(
BN_CTX)*CTX{
OsslPopContext(CTX);
BN_CTX_free(CTX);}

Page 788
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

B.2.3.3.2.4.

Trusted Platform Module Library

OsslPushContext()

This function is used to create a frame in a context. All values allocated within this context after the frame
is started will be automatically freed when the context (OsslPopContext()
31
32
33
34
35
36
37
38
39
40

BN_CTX *OsslPushContext(
BN_CTX)*CTX{
if(CTX == NULL)
FAIL(FATAL_ERROR_ALLOCATION);
BN_CTX_start(CTX);
return CTX;}

B.2.3.3.2.5.

OsslPopContext()

This is the companion function to OsslPushContext().
41
42
43
44
45
46
47
48
49
50

void
OsslPopContext(
BN_CTX)*CTX{// BN_CTX_end can't be called with NULL. It will blow up.
if(CTX != NULL)
BN_CTX_end(CTX);}#endif // MATH_LIB_OSSLFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 789
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

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 bepart of a hardware TPM implementation.
C.2

Cancel.c

C.2.1.

Description

This module simulates the cancel pins on the TPM.
C.2.2.
1

Includes, Typedefs, Structures, and Defines#include "Platform.h"

C.2.3.

FunctionsC.2.3.1.

_plat__IsCanceled()

Check if the cancel flag is set

2
3
4
5
6
7
8
9

Return Value

Meaning

TRUE(1)

if cancel flag is set

FALSE(0)if cancel flag is not set

LIB_EXPORT int_plat__IsCanceled(void){// return cancel flag
return s_isCanceled;}

C.2.3.2.

_plat__SetCancel()

Set cancel flag.
10
11
12
13
14
15
16
17

LIB_EXPORT void
_plat__SetCancel(
void){
s_isCanceled = TRUE;
return;}Page 790
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.2.3.3.

Trusted Platform Module Library_plat__ClearCancel()

Clear cancel flag
18
19
20
21
22
23
24
25

LIB_EXPORT void
_plat__ClearCancel(
void){
s_isCanceled = FALSE;
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 791
April 15, 2019

Trusted Platform Module Library

C.3

Part 4: Supporting Routines

Clock.c

C.3.1.

Description

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 theclock functions may be implementation dependent.
C.3.2.
1
2
3

Includes and Data Definitions#include <assert.h>#include "Platform.h"#include "TpmFail_fp.h"

C.3.3.

Simulator Functions

C.3.3.1.

Introduction

This set of functions is intended to be called by the simulator environment in order to simulate hardware
events.
C.3.3.2.

_plat__TimerReset()This function sets current system clock time as t0 for counting TPM time. This function is called at a
power on event to reset the clock. When the clock is reset, the indication that the clock was stopped isalso set.
4
5
6
7
8
9
10
11
12
13
14
15

LIB_EXPORT void
_plat__TimerReset(void){
s_lastSystemTime = 0;
s_tpmTime = 0;s_adjustRate = CLOCK_NOMINAL;
s_timerReset = TRUE;
s_timerStopped = TRUE;
return;}C.3.3.3.

_plat__TimerRestart()

This function should be called in order to simulate the restart of the timer should it be stopped while
power is still applied.
16
17
18
19
20
21
22
23

LIB_EXPORT void
_plat__TimerRestart(void){
s_timerStopped = TRUE;
return;}Page 792
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.3.4.

Trusted Platform Module Library

Functions Used by TPM

C.3.4.1.

Introduction

These functions are called by the TPM code. They should be replaced by appropriated hardware
functions.
24
25#include <time.h>clock_t
debugTime;

C.3.4.2.

_plat__RealTime()

This is another, probably futile, attempt to define a portable function that will return a 64-bit clock valuethat has mSec resolution.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

uint64_t_plat__RealTime(void){
clock64_t
time;#ifdef _MSC_VER
struct _timeb
sysTime;//_ftime_s(&sysTime);time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm;// set the time back by one hour if daylight savings
if(sysTime.dstflag)time -= 1000 * 60 * 60; // mSec/sec * sec/min * min/hour = ms/hour#else// hopefully, this will work with most UNIX systems
struct timespec
systime;//clock_gettime(CLOCK_MONOTONIC, &systime);time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000);#endifreturn time;}

C.3.4.3.

_plat__TimerRead()This function provides access to the tick timer of the platform. The TPM code uses this value to drive the
TPM Clock.
The tick timer is supposed to run when power is applied to the device. This timer should not be reset bytime events including _TPM_Init(). It should only be reset when TPM power is re-applied.
If the TPM is run in a protected environment, that environment may provide the tick time to the TPM aslong as the time provided by the environment is not allowed to go backwards. If the time provided by thesystem can go backwards during a power discontinuity, then the _plat__Signal_PowerOn() should call_plat__TimerReset().
49
50
51
52
53
54
55
56

LIB_EXPORT uint64_t_plat__TimerRead(void){#ifdef HARDWARE_CLOCK#error"need a defintion for reading the hardware clock"return HARDWARE_CLOCK

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 793
April 15, 2019

Trusted Platform Module Library
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

#else
clock64_t
clock64_t
clock64_t
clock64_t

Part 4: Supporting Routines

timeDiff;
adjustedTimeDiff;
timeNow;
readjustedTimeDiff;// This produces a timeNow that is basically locked to the system clock.
timeNow = _plat__RealTime();// if this hasn't been initialized, initialize it
if(s_lastSystemTime == 0){
s_lastSystemTime = timeNow;
debugTime = clock();s_lastReportedTime = 0;s_realTimePrevious = 0;}// The system time can bounce around and that's OK as long as we don't allow// time to go backwards. When the time does appear to go backwards, set// lastSystemTime to be the new value and then update the reported time.
if(timeNow < s_lastReportedTime)s_lastSystemTime = timeNow;s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime;s_lastSystemTime = timeNow;
timeNow = s_lastReportedTime;// The code above produces a timeNow that is similar to the value returned// by Clock(). The difference is that timeNow does not max out, and it is// at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below// uses that value and does the rate adjustment on the time value.
// If there is no difference in time, then skip all the computations
if(s_realTimePrevious >= timeNow)
return s_tpmTime;// Compute the amount of time since the last update of the system clock
timeDiff = timeNow - s_realTimePrevious;// Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec
adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate);// update the TPM time with the adjusted timeDiff
s_tpmTime += (clock64_t)adjustedTimeDiff;// Might have some rounding error that would loose CLOCKS. See what is not// being used. As mentioned above, this could result in putting back more than// is taken out. Here, we are trying to recreate timeDiff.
readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate )/ CLOCK_NOMINAL;// adjusted is now converted back to being the amount we should advance the// previous sampled time. It should always be less than or equal to timeDiff.
// That is, we could not have use more time than we started with.
s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff;#ifdef DEBUGGING_TIME// Put this in so that TPM time will pass much faster than real time when// doing debug.
// A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second// A good value might be 100
return (s_tpmTime * DEBUG_TIME_MULTIPLIER);#endifreturn s_tpmTime;#endif}Page 794
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.3.4.4.

Trusted Platform Module Library_plat__TimerWasReset()This function is used to interrogate the flag indicating if the tick timer has been reset.
If the resetFlag parameter is SET, then the flag will be CLEAR before the function returns.
120
121
122
123
124
125
126
127
128

LIB_EXPORT BOOL
_plat__TimerWasReset(
void
)
{
BOOL
retVal = s_timerReset;
s_timerReset = FALSE;
return retVal;}

C.3.4.5.

_plat__TimerWasStopped()

This function is used to interrogate the flag indicating if the tick timer has been stopped. If so, this is
typically a reason to roll the nonce.
This function will CLEAR the s_timerStopped flag before returning. This provides functionality that issimilar to status register that is cleared when read. This is the model used here because it is the one thathas the most impact on the TPM code as the flag can only be accessed by one entity in the TPM. Anyother implementation of the hardware can be made to look like a read-once register.
129
130
131
132
133
134
135
136
137

LIB_EXPORT BOOL
_plat__TimerWasStopped(
void
)
{
BOOL
retVal = s_timerStopped;
s_timerStopped = FALSE;
return retVal;}

C.3.4.6.

_plat__ClockAdjustRate()

Adjust the clock rate
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

LIB_EXPORT void
_plat__ClockAdjustRate(int

adjust// IN: the adjust number.
//or negative

It could be positive){// We expect the caller should only use a fixed set of constant values to// adjust the rate
switch(adjust){case CLOCK_ADJUST_COARSE:
s_adjustRate += CLOCK_ADJUST_COARSE;
break;
case -CLOCK_ADJUST_COARSE:
s_adjustRate -= CLOCK_ADJUST_COARSE;
break;
case CLOCK_ADJUST_MEDIUM:
s_adjustRate += CLOCK_ADJUST_MEDIUM;
break;
case -CLOCK_ADJUST_MEDIUM:
s_adjustRate -= CLOCK_ADJUST_MEDIUM;
break;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 795
April 15, 2019

Trusted Platform Module Library
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

Part 4: Supporting Routinescase CLOCK_ADJUST_FINE:
s_adjustRate += CLOCK_ADJUST_FINE;
break;
case -CLOCK_ADJUST_FINE:
s_adjustRate -= CLOCK_ADJUST_FINE;
break;
default:// ignore any other values;
break;}
if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT))s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT;
if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT))s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT;
return;}Page 796
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.4

Entropy.c

C.4.1.
1
2
3
4
5
6
7
8
9
10

Trusted Platform Module Library

Includes and Local Values#define _CRT_RAND_S#include <stdlib.h>#include <memory.h>#include <time.h>#include "Platform.h"#ifdef _MSC_VER#include <process.h>#else#include <unistd.h>#endifThis is the last 32-bits of hardware entropy produced. We have to check to see that two consecutive 32bit 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 powerup, 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."
11

extern uint32_t

C.4.2.

FunctionsC.4.2.1.

rand32()

lastEntropy;

Local function to get a 32-bit random number
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

static uint32_t
rand32(void){
uint32_t
rndNum = rand();#if RAND_MAX < UINT16_MAX// If the maximum value of the random number is a 15-bit number, then shift it up// 15 bits, get 15 more bits, shift that up 2 and then XOR in another value to get// a full 32 bits.
rndNum = (rndNum << 15) ^ rand();rndNum = (rndNum << 2) ^ rand();#elif RAND_MAX == UINT16_MAX// If the maximum size is 16-bits, shift it and add another 16 bits
rndNum = (rndNum << 16) ^ rand();#elif RAND_MAX < UINT32_MAX// If 31 bits, then shift 1 and include another random value to get the extra bit
rndNum = (rndNum << 1) ^ rand();#endifreturn rndNum;}

C.4.2.2.

_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.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 797
April 15, 2019

Trusted Platform Module Library

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

Part 4: Supporting Routines

Return Value

Meaning<0

hardware failure of the entropy generator, this is sticky>= 0

the returned amount of entropy (bytes)

LIB_EXPORT int32_t_plat__GetEntropy(
unsigned charuint32_t*entropy,
amountuint32_t
int32_t

rndNum;ret;// output buffer// amount requested){//
if(amount == 0){// Seed the platform entropy source if the entropy source is software. There// is no reason to put a guard macro (#if or #ifdef) around this code because// this code would not be here if someone was changing it for a system with// actual hardware.
//// NOTE 1: The following command does not provide proper cryptographic// entropy. Its primary purpose to make sure that different instances of the// simulator, possibly started by a script on the same machine, are seeded// differently. Vendors of the actual TPMs need to ensure availability of// proper entropy using their platform-specific means.
//// NOTE 2: In debug builds by default the reference implementation will seed// its RNG deterministically (without using any platform provided randomness).
// See the USE_DEBUG_RNG macro and DRBG_GetEntropy() function.
#ifdef _MSC_VER
srand((unsigned)_plat__RealTime() ^ _getpid());#else
srand((unsigned)_plat__RealTime() ^ getpid());#endiflastEntropy = rand32();
ret = 0;}else{
rndNum = rand32();
if(rndNum == lastEntropy){
ret = -1;}
else{
lastEntropy = rndNum;// Each process will have its random number generator initialized// according to the process id and the initialization time. This is not a// lot of entropy so, to add a bit more, XOR the current time value into// the returned entropy value.
// NOTE: the reason for including the time here rather than have it in// in the value assigned to lastEntropy is that rand() could be broken and// using the time would in the lastEntropy value would hide this.
rndNum ^= (uint32_t)_plat__RealTime();// Only provide entropy 32 bits at a time to test the ability// of the caller to deal with partial results.
ret = MIN(amount, sizeof(rndNum));
memcpy(entropy, &rndNum, ret);}}
return ret;Page 798
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
92

Trusted Platform Module Library}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 799
April 15, 2019

Trusted Platform Module Library1

C.5

LocalityPlat.c

C.5.1.

IncludesPart 4: Supporting Routines#include "Platform.h"

C.5.2.

FunctionsC.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.
2
3
4
5
6
7
8

LIB_EXPORT unsigned char_plat__LocalityGet(void){
return s_locality;}

C.5.2.2.

_plat__LocalitySet()

Set the most recent command locality in locality value form
9
10
11
12
13
14
15
16
17
18

LIB_EXPORT void
_plat__LocalitySet(
unsigned char)

locality{
if(locality > 4 && locality < 32)locality = 0;
s_locality = locality;
return;}Page 800
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.6

Trusted Platform Module Library

NVMem.c

C.6.1.

Description

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.
1
2
3
4
5
6
7
8

Includes and Local#include <memory.h>#include <string.h>#include <assert.h>#include "Platform.h"#if FILE_BACKED_NV#
include<stdio.h>FILE*s_NvFile = NULL;#endifC.6.3.
C.6.3.1.

Functions
NvFileOpen()

This function opens the file used to hold the NV image.
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23

#if FILE_BACKED_NV
Return Value

Meaning>= 0

success-1

error

static int
NvFileOpen(
const char

*mode

)
{
#
#
#

// Try to open an exist NVChip file for read/write
if defined _MSC_VER && 1
if(fopen_s(&s_NvFile, "NVChip", mode) != 0)s_NvFile = NULL;
else
s_NvFile = fopen("NVChip", mode);
endif
return (s_NvFile == NULL) ? -1 : 0;}

C.6.3.2.

NvFileCommit()

Write all of the contents of the NV image to a file.

24

Return Value

Meaning

TRUE(1)success

FALSE(0)failurestatic int

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 801
April 15, 2019

Trusted Platform Module Library

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Part 4: Supporting Routines

NvFileCommit(
void
)
{
int
OK;
// If NV file is not available, return failure
if(s_NvFile == NULL)
return 1;// Write RAM data to NV
fseek(s_NvFile, 0, SEEK_SET);OK = (NV_MEMORY_SIZE == fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NvFile));OK = OK && (0 == fflush(s_NvFile));assert(OK);return OK;}

C.6.3.3.

NvFileSize()This function gets the size of the NV file and puts the file pointer were desired using the seek method
values. SEEK_SET => beginning; SEEK_CUR => current position and SEEK_END => to the end of the
file.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

static long
NvFileSize(
int

leaveAt

)
{
long
long

fileSize;
filePos = ftell(s_NvFile);//
assert(NULL != s_NvFile);
fseek(s_NvFile, 0, SEEK_END);
fileSize = ftell(s_NvFile);
switch(leaveAt){
case SEEK_SET:
filePos = 0;case SEEK_CUR:
fseek(s_NvFile, filePos, SEEK_SET);
break;
case SEEK_END:
break;
default:
assert(FALSE);
break;}
return fileSize;}#endifC.6.3.4.

_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
68
69
70
71
72
73

LIB_EXPORT void
_plat__NvErrors(
int
int
)

recoverable,
unrecoverable{

Page 802
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
74
75
76

Trusted Platform Module Librarys_NV_unrecoverable = unrecoverable;
s_NV_recoverable = recoverable;}

C.6.3.5.

_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.

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

Return Value

Meaning0

if success>0

if receive recoverable error<0

if unrecoverable error

LIB_EXPORT int_plat__NVEnable(void)*platParameter// IN: platform specific parameters{
NOT_REFERENCED(platParameter);// to keep compiler quiet//// Start assuming everything is OK
s_NV_unrecoverable = FALSE;
s_NV_recoverable = FALSE;#if FILE_BACKED_NV
if(s_NvFile != NULL)
return 0;// Initialize all the bytes in the ram copy of the NV_plat__NvMemoryClear(0, NV_MEMORY_SIZE);// If the file exists
if(NvFileOpen("r+b") >= 0){
long
fileSize = NvFileSize(SEEK_SET);// get the file size and leave the// file pointer at the start//// If the size is right, read the dataif(NV_MEMORY_SIZE == fileSize)fread(s_NV, 1, NV_MEMORY_SIZE, s_NvFile);
else
NvFileCommit();// for any other size, initialize it}// If NVChip file does not exist, try to create it for read/write.
else if(NvFileOpen("w+b") >= 0)
NvFileCommit();// Initialize the file
assert(NULL != s_NvFile);// Just in case we are broken for some reason.
#endif// NV contents have been initialized and the error checks have been performed. For// simulation purposes, use the signaling interface to indicate if an error is// to be simulated and the type of the error.
if(s_NV_unrecoverable)
return -1;
return s_NV_recoverable;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 803
April 15, 2019

Trusted Platform Module Library

C.6.3.6.

Part 4: Supporting Routines_plat__NVDisable()

Disable NV memory
117
118
119
120
121
122
123
124
125
126
127
128

LIB_EXPORT void
_plat__NVDisable(
void
)
{
#if

FILE_BACKED_NV
if(NULL != s_NvFile)fclose(s_NvFile);s_NvFile = NULL;#endifreturn;}C.6.3.7.

// Close NV file// Set file handle to NULL

_plat__IsNvAvailable()

Check if NV is available

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

Return Value

Meaning0

NV is available

1

NV is not available due to write failure2

NV is not available due to rate limit

LIB_EXPORT int_plat__IsNvAvailable(
void
)
{
int
retVal = 0;// NV is not available if the TPM is in failure modeif(!s_NvIsAvailable)
retVal = 1;
#if FILE_BACKED_NV
else
retVal = (s_NvFile == NULL);#endifreturn retVal;}

C.6.3.8.

_plat__NvMemoryRead()

Function: Read a chunk of NV memory
144
145
146
147
148
149
150
151
152
153
154

LIB_EXPORT void
_plat__NvMemoryRead(
unsigned int
unsigned int
void)startOffset,
size,
*data

// IN: read start// IN: size of bytes to read// OUT: data buffer{
assert(startOffset + size <= NV_MEMORY_SIZE);
memcpy(data, &s_NV[startOffset], size);// Copy data from RAM
return;}Page 804
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

C.6.3.9.

Trusted Platform Module Library_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.

155
156
157
158
159
160
161
162
163

Return Value

Meaning

TRUE(1)

the NV location is different from the test value

FALSE(0)the NV location is the same as the test value

LIB_EXPORT int_plat__NvIsDifferent(
unsigned int
unsigned int
void)startOffset,
size,
*data

// IN: read start// IN: size of bytes to read// IN: data buffer{
return (memcmp(&s_NV[startOffset], data, size) != 0);}

C.6.3.10. _plat__NvMemoryWrite()This function is used to update NV memory. The write is to a memory copy of NV. At the end of thecurrent command, any changes are written to the actual NV memory.
NOTE:

164
165
166
167
168
169
170
171
172
173
174
175
176
177

A useful optimization would be for this code to compare the current contents of NV with the local copy and notethe blocks that have changed. Then only write those blocks when _plat__NvCommit() is called.

LIB_EXPORT BOOL
_plat__NvMemoryWrite(
unsigned int
unsigned int
void)startOffset,
size,
*data

// IN: write start// IN: size of bytes to write// OUT: data buffer{
if(startOffset + size <= NV_MEMORY_SIZE){
memcpy(&s_NV[startOffset], data, size);
return TRUE;}
return FALSE;// Copy the data to the NV image}

C.6.3.11. _plat__NvMemoryClear()
Function is used to set a range of NV memory bytes to an implementation-dependent value. The value
represents the erase state of the memory.
178
179
180
181
182
183
184
185
186
187

LIB_EXPORT void
_plat__NvMemoryClear(
unsigned int
unsigned int)

start,
size// IN: clear start// IN: number of bytes to clear{
assert(start + size <= NV_MEMORY_SIZE);// In this implementation, assume that the erase value for NV is all 1s
memset(&s_NV[start], 0xff, size);}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 805
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

C.6.3.12. _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
188
189
190
191
192
193
194
195
196
197
198
199

LIB_EXPORT void
_plat__NvMemoryMove(unsigned int
unsigned int
unsigned int)

sourceOffset,
destOffset,
size// IN: source offset// IN: destination offset// IN: size of data being moved{
assert(sourceOffset + size <= NV_MEMORY_SIZE);
assert(destOffset + size <= NV_MEMORY_SIZE);
memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
return;// Move data in RAM}

C.6.3.13. _plat__NvCommit()
This function writes the local copy of NV to NV for permanent store. It will write NV_MEMORY_SIZE
bytes to NV. If a file is use, the entire file is written.

200
201
202
203
204
205
206
207
208
209
210

Return Value

Meaning0

NV write success

non-0

NV write fail

LIB_EXPORT int_plat__NvCommit(
void){#if FILE_BACKED_NV
return (NvFileCommit() ? 0 : 1);#else
return 0;#endif}C.6.3.14. _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
211
212
213
214
215
216
217
218

LIB_EXPORT void
_plat__SetNvAvail(void){
s_NvIsAvailable = TRUE;
return;}C.6.3.15. _plat__ClearNvAvail()
Set the current NV state to unavailable. This function is for testing purpose only. It is not part of theplatform NV logic

Page 806
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

219
220
221
222
223
224
225
226

Trusted Platform Module Library

LIB_EXPORT void
_plat__ClearNvAvail(void){
s_NvIsAvailable = FALSE;
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 807
April 15, 2019

Trusted Platform Module Library

C.7

PowerPlat.c

C.7.1.
1
2

Part 4: Supporting Routines

Includes and Function Prototypes#include#includeC.7.2.

"Platform.h""_TPM_Init_fp.h"

FunctionsC.7.2.1.

_plat__Signal_PowerOn()

Signal platform power on
3
4
5
6
7
8
9
10
11
12
13
14
15

LIB_EXPORT int_plat__Signal_PowerOn(
void){// Reset the timer_plat__TimerReset();// Need to indicate that we lost powers_powerLost = TRUE;
return 0;}

C.7.2.2.

_plat__WasPowerLost()

Test whether power was lost before a _TPM_Init().
This function will clear the hardware indication of power loss before return. This means that there canonly be one spot in the TPM code where this value gets read. This method is used here as it is the mostdifficult to manage in the TPM code and, if the hardware actually works this way, it is hard to make it look
like anything else. So, the burden is placed on the TPM code rather than the platform code

16
17
18
19
20
21
22
23
24

Return Value

Meaning

TRUE(1)

power was lost

FALSE(0)power was not lost

LIB_EXPORT int_plat__WasPowerLost(
void
)
{
BOOL
retVal = s_powerLost;s_powerLost = FALSE;
return retVal;}

C.7.2.3.

_plat_Signal_Reset()This a TPM reset without a power loss.
25
26

LIB_EXPORT int_plat__Signal_Reset(

Page 808
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

Trusted Platform Module Library

void
)
{
// Initialize locality
s_locality = 0;// Command cancel
s_isCanceled = FALSE;_TPM_Init();// if we are doing reset but did not have a power failure, then we should// not need to reload NV ...
return 0;}

C.7.2.4.

_plat__Signal_PowerOff()

Signal platform power off
43
44
45
46
47
48
49
50
51
52

LIB_EXPORT void
_plat__Signal_PowerOff(
void){// Prepare NV memory for power off_plat__NVDisable();return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 809
April 15, 2019

Trusted Platform Module Library

C.8

Part 4: Supporting Routines

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
2#ifndef _PLATFORM_DATA_H_#define _PLATFORM_DATA_H_

From Cancel.c Cancel flag. It is initialized as FALSE, which indicate the command is not being canceled
3
4
5
6
7
8
9
10
11
12

extern int
s_isCanceled;#ifdef _MSC_VER#include <sys/types.h>#include <sys/timeb.h>#else#include <sys/time.h>#include <time.h>#endif#ifndef HARDWARE_CLOCK
typedef uint64_tclock64_t;

This is the value returned the last time that the system clock was read. This is only relevant for asimulator or virtual TPM.
13extern clock64_t

s_realTimePrevious;

These values are used to try to synthesize a long lived version of clock().
14
15

extern clock64_t
extern clock64_t

s_lastSystemTime;s_lastReportedTime;

This is the rate adjusted value that is the equivalent of what would be read from a hardware register that
produced rate adjusted time.
16
17

extern clock64_t
s_tpmTime;#endif // HARDWARE_CLOCK

This value indicates that the timer was reset
18

extern BOOL

s_timerReset;

This value indicates that the timer was stopped. It causes a clock discontinuity.
19

extern BOOL

s_timerStopped;

CLOCK_NOMINAL is the number of hardware ticks per mS. A value of 300000 means that the nominal
clock rate used to drive the hardware clock is 30 MHz. The adjustment rates are used to determine theconversion of the hardware ticks to internal hardware clock value. In practice, we would expect that there
woudl be a hardware register will accumulated mS. It would be incremented by the output of a pre-scaler.
The pre-scaler would divide the ticks from the clock by some value that would compensate for thedifference between clock time and real time. The code in Clock does the emulation of this function.
20#define

CLOCK_NOMINAL

30000

A 1% change in rate is 300 counts
21#define

CLOCK_ADJUST_COARSE

300

A 0.1% change in rate is 30 counts
Page 810
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
22#defineTrusted Platform Module Library

CLOCK_ADJUST_MEDIUM

30

A minimum change in rate is 1 count23#define

CLOCK_ADJUST_FINE

1

The clock tolerance is +/-15% (4500 counts) Allow some guard band (16.7%)
24#define

CLOCK_ADJUST_LIMIT

5000

This variable records the time when _plat__TimerReset() is called. This mechanism allow us to subtract
the time when TPM is power off from the total time reported by clock() function
25

extern uint64_ts_initClock;This variable records the timer adjustment factor.
26

extern unsigned int

s_adjustRate;

For LocalityPlat.c Locality of current command
27

extern unsigned char s_locality;

For 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.
28
29
30
31

#if (!defined VTPM) || ((VTPM != NO) && (VTPM != YES))#
undef VTPM#
defineVTPM
YES// Default: Either YES or NO#endif

For a simulation, use a file to back up the NV
32
33
34
35
36
37
38
39
40
41
42
43

#if (!defined FILE_BACKED_NV) || ((FILE_BACKED_NV != NO) && (FILE_BACKED_NV != YES))#
undef
FILE_BACKED_NV#
define FILE_BACKED_NV(VTPM && YES)// Default: Either YES or NO#endif#if SIMULATION#
undef
FILE_BACKED_NV#
defineFILE_BACKED_NV
YES#endif // SIMULATION
extern unsigned chars_NV[NV_MEMORY_SIZE];
extern BOOL
s_NvIsAvailable;
extern BOOL
s_NV_unrecoverable;
extern BOOL
s_NV_recoverable;

For PPPlat.c Physical presence. It is initialized to FALSE
44

extern BOOLs_physicalPresence;

From Power45

extern BOOL

s_powerLost;

For Entropy.c
46
47

extern uint32_t
lastEntropy;#endif // _PLATFORM_DATA_H_

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 811
April 15, 2019

Trusted Platform Module Library

C.9

PlatformData.c

C.9.1.

Description

Part 4: Supporting Routines

This file will instance the TPM variables that are not stack allocated. The descriptions for these variables
are in Global.h for this project.
C.9.2.
1

Includes#include"Platform.h"

From Cancel.c2

BOOL

s_isCanceled;

From Clock.c
3
4
5
6
7
8
9
10
11

unsigned int
s_adjustRate;
BOOL
s_timerReset;
BOOL
s_timerStopped;#ifndef HARDWARE_CLOCK
clock64_ts_realTimePrevious;
clock64_ts_tpmTime;clock64_t
s_lastSystemTime;clock64_t
s_lastReportedTime;#endifFrom LocalityPlat.c
12

unsigned chars_locality;

From Power.c
13

BOOL

s_powerLost;

From Entropy.c This values is used to determine if the entropy generator is broken. If two consecutive
values are the same, then the entropy generator is considered to be broken.
14

uint32_t

lastEntropy;

For NVMem.c
15
16
17
18

unsigned char
BOOL
BOOL
BOOL

s_NV[NV_MEMORY_SIZE];
s_NvIsAvailable;
s_NV_unrecoverable;
s_NV_recoverable;

From PPPlat.c
19

BOOL

s_physicalPresence;

Page 812
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

C.10 PPPlat.c
C.10.1. Description
This module simulates the physical presence interface pins on the TPM.
C.10.2. Includes
1#include "Platform.h"

C.10.3. Functions
C.10.3.1. _plat__PhysicalPresenceAsserted()
Check if physical presence is signaled

2
3
4
5
6
7
8
9
10

Return Value

Meaning

TRUE(1)

if physical presence is signaled

FALSE(0)if physical presence is not signaled

LIB_EXPORT int_plat__PhysicalPresenceAsserted(void){// Do not know how to check physical presence without real hardware.
// so always return TRUE;
return s_physicalPresence;}

C.10.3.2. _plat__Signal_PhysicalPresenceOn()
Signal physical presence on
11
12
13
14
15
16
17
18

LIB_EXPORT void
_plat__Signal_PhysicalPresenceOn(void){
s_physicalPresence = TRUE;
return;}C.10.3.3. _plat__Signal_PhysicalPresenceOff()
Signal physical presence off
19
20
21
22
23
24
25
26

LIB_EXPORT void
_plat__Signal_PhysicalPresenceOff(void){
s_physicalPresence = FALSE;
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 813
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

C.11 RunCommand.c
C.11.1. Introduction
This module provides the platform specific entry and fail processing. The _plat__RunCommand() function
is used to call to ExecuteCommand() in the TPM code. This function does whatever processing isnecessary to set up the platform in anticipation of the call to the TPM including settup for error
processing.
The _plat__Fail() function is called when there is a failure in the TPM. The TPM code will have set theflag to indicate that the TPM is in failure mode. This call will then recursively call ExecuteCommand() inorder to build the failure mode response. When ExecuteCommand() returns to _plat__Fail(), the platform
will do some platform specif operation to return to the environment in which the TPM is executing. For asimulator, setjmp/longjmp is used. For an OS, a system exit to the OS would be appropriate.
C.11.2. Includes and locals
12
3
4#include "Platform.h"#include <setjmp.h>#include "ExecCommand_fp.h"
jmp_bufs_jumpBuffer;

C.11.3. Functions
C.11.3.1. _plat__RunCommand()This version of RunCommand() will set up a jum_buf and call ExecuteCommand(). If the commandexecutes without failing, it will return and RunCommand() will return. If there is a failure in the command,then _plat__Fail() is called and it will longjump back to RunCommand() which will call ExecuteCommand()again. However, this time, the TPM will be in failure mode so ExecuteCommand() will simply build a
failure response and return.
5
6
7
8
9
10
11
12
13
14
15

LIB_EXPORT void
_plat__RunCommand(
uint32_t
unsigned charuint32_t
unsigned char)requestSize,*request,*responseSize,**response// IN: command buffer size// IN: command buffer// IN/OUT: response buffer size// IN/OUT: response buffer{
setjmp(s_jumpBuffer);
ExecuteCommand(requestSize, request, responseSize, response);}

C.11.3.2. _plat__Fail()This is the platform depended failure exit for the TPM.
16
17
18
19
20
21
22

LIB_EXPORT NORETURN void
_plat__Fail(void){
longjmp(&s_jumpBuffer[0], 1);}

Page 814
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

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 secretvalue 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
12
3
4#include "Platform.h"
const char notReallyUnique[] ="This is not really a unique value. A real unique value should"" 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 moredata than bSize.
NOTE:

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

If a platform unique value has unequal distribution of uniqueness and bSize is smaller than the size of theunique value, the bSize portion with the most uniqueness should be returned.

LIB_EXPORT uint32_t_plat__GetUnique(uint32_t
uint32_t
unsigned char)which,bSize,*b// authorities (0) or details// size of the buffer// output buffer

const charuint32_t*from = notReallyUnique;
retVal = 0;{if(which == 0) // the authorities value{
for(retVal = 0;
*from != 0 && retVal < bSize;
retVal++){*b++ = *from++;
}
}
else
{
#define uSize sizeof(notReallyUnique)b = &b[((bSize < uSize) ? bSize : uSize) - 1];
for(retVal = 0;
*from != 0 && retVal < bSize;
retVal++){*b-- = *from++;}}
return retVal;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 815
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

C.13 DebugHelpers.c
C.13.1. Description
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.13.2. Includes and Local
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#include<stdio.h>#include<time.h>FILE*fDebug = NULL;
unsigned char
*fn = "DebugFile.txt";

static FILE *fileOpen(
unsigned charconst char

*fn,
*mode

)
{
#
#
#

FILE
*f;
if defined _MSC_VER
if(fopen_s(&f, fn, mode) != 0)
f = NULL;else
f = fopen(fn, "w');
endif
return f;}

C.13.2.1. DebugFileOpen()
This function opens the file used to hold the debug data.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

Return Value

Meaning0

success

!= 0

error

int
DebugFileOpen(void){
unsigned char
time_ttimeString[100];t = time(NULL);//// Get current date and time.
ctime_s(timeString, sizeof(timeString), &t);// Try to open the debug file
fDebug = fileOpen(fn, "w");if(fDebug){
fprintf(fDebug, "%s\n", timeString);
fclose(fDebug);return 0;}
return -1;}

void
DebugFileClose(

Page 816
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

Trusted Platform Module Library

void
)
{
if(fDebug)
fclose(fDebug);}

void
DebugDumpBuffer(int
unsigned char
unsigned char

size,
*buf,
*identifier

int

i;

)
{
//
FILE *f = fileOpen(fn, "a");if(!f)
return;if(identifier)fprintf(fDebug, "%s\n", identifier);if(buf){for(i = 0; i < size; i++){if(((i % 16) == 0) && (i))
fprintf(fDebug, "\n");fprintf(fDebug, " %02X", buf[i]);}if((size % 16) != 0)
fprintf(fDebug, "\n");}fclose(f);}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 817
April 15, 2019

Trusted Platform Module LibraryPart 4: Supporting Routines

C.14 Platform.h
1
2
3
4
5
6
7
8
9
10

#ifndef_PLATFORM_H_#define_PLATFORM_H_#include "TpmBuildSwitches.h"#include "BaseTypes.h"#include "TPMB.h"#include "MinMax.h"#include "TpmProfile.h"#include "PlatformData.h"#include "Platform_fp.h"#endif // _PLATFORM_H_

Page 818
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

Trusted Platform Module Library

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 isused to simulate hardware events such as power on/off and locality; and indications such as_TPM_HashStart.

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 819
April 15, 2019

Trusted Platform Module Library

D.2

TpmTcpProtocol.hD.2.1.

Introduction

Part 4: Supporting Routines

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 completed by returning a UINT32=0.
The command TPM_SIGNAL_HASH_DATA takes a UINT32-prepended variable length BYTE array andthe interface protocol acknowledges command completion with a UINT32=0. Most TPM commands areenveloped using the TPM_SEND_COMMAND interface command. The parameters are as indicatedbelow. The interface layer also appends a UIN32=0 to the TPM response for regularity.
D.2.2.
1
2

Typedefs and Defines#ifndef#defineD.2.3.

TCP_TPM_PROTOCOL_H
TCP_TPM_PROTOCOL_H

TPM Commands

All commands acknowledge processing by returning a UINT32 == 0 except where noted
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#define TPM_SIGNAL_POWER_ON
1#define TPM_SIGNAL_POWER_OFF
2#define TPM_SIGNAL_PHYS_PRES_ON3#define TPM_SIGNAL_PHYS_PRES_OFF
4#define TPM_SIGNAL_HASH_START
5#define TPM_SIGNAL_HASH_DATA
6// {UINT32 BufferSize, BYTE[BufferSize] Buffer}#define TPM_SIGNAL_HASH_END
7#define TPM_SEND_COMMAND
8// {BYTE Locality, UINT32 InBufferSize, BYTE[InBufferSize] InBuffer} ->//{UINT32 OutBufferSize, BYTE[OutBufferSize] OutBuffer}#define TPM_SIGNAL_CANCEL_ON
9#define TPM_SIGNAL_CANCEL_OFF
10#define TPM_SIGNAL_NV_ON
11#define TPM_SIGNAL_NV_OFF
12#define TPM_SIGNAL_KEY_CACHE_ON
13#define TPM_SIGNAL_KEY_CACHE_OFF
14#define TPM_REMOTE_HANDSHAKE
15#define TPM_SET_ALTERNATIVE_RESULT 16#define TPM_SIGNAL_RESET
17#define TPM_SIGNAL_RESTART
18#define TPM_SESSION_END
20#define TPM_STOP
21#define TPM_GET_COMMAND_RESPONSE_SIZES 25#define TPM_TEST_FAILURE_MODE
30

D.2.4.
28
29
30
31
32
33
34
35

Enumerations and Structuresenum TpmEndPointInfo{
tpmPlatformAvailable = 0x01,
tpmUsesTbs = 0x02,
tpmInRawMode = 0x04,
tpmSupportsPP = 0x08};

Page 820
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

Trusted Platform Module Library// Existing RPC interface type definitions retained so that the implementation// can be re-used

typedef struct in_buffer{
unsigned long BufferSize;
unsigned char *Buffer;} _IN_BUFFER;
typedef unsigned char *_OUTPUT_BUFFER;
typedef struct out_buffer{
uint32_t
BufferSize;_OUTPUT_BUFFER
Buffer;} _OUT_BUFFER;#ifndef WIN32

typedef unsigned long
typedef void

DWORD;*LPVOID;#undef WINAPI#endif#endifFamily “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 821
April 15, 2019

Trusted Platform Module Library

D.3

Part 4: Supporting Routines

TcpServer.c

D.3.1.

Description

This file contains the socket interface to a TPM simulator.
D.3.2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Includes, Locals, Defines and Function Prototypes#include "TpmBuildSwitches.h"#include <stdio.h>#ifdef _MSC_VER#include <windows.h>#include <winsock.h>#else
typedef int SOCKET;#endif#include <string.h>#include <stdlib.h>#include <stdint.h>//#include "BaseTypes.h"#include "TpmTcpProtocol.h"#include "Manufacture_fp.h"#include "Simulator_fp.h"

To access key cache control in TPM
16
17
18
19
20
21
22
23
24
25
26
27
28
29

void RsaKeyCacheControl(int state);#ifndef __IGNORE_STATE__
static uint32_t ServerVersion = 1;
#define MAX_BUFFER 1048576
char InputBuffer[MAX_BUFFER];//The input data buffer for the simulator.
char OutputBuffer[MAX_BUFFER];//The output data buffer for the simulator.
struct{uint32_t
largestCommandSize;uint32_t
largestCommand;
uint32_t
largestResponseSize;uint32_t
largestResponse;} CommandResponseSizes = {0};#endif // __IGNORE_STATE___

D.3.3.

FunctionsD.3.3.1.

CreateSocket()This function creates a socket listening on PortNumber.
30
31
32
33
34
35
36
37
38
39
40
41
42

static int
CreateSocket(
int
SOCKET)

PortNumber,*listenSocket

WSADATAstructint res;

wsaData;sockaddr_in MyAddress;{//// Initialize Winsock
res = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(res != 0)

Page 822
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

Trusted Platform Module Library{
printf("WSAStartup failed with error: %d\n", res);return -1;}// create listening socket*listenSocket = socket(PF_INET, SOCK_STREAM, 0);if(INVALID_SOCKET == *listenSocket){
printf("Cannot create server listen socket. Error is 0x%x\n",WSAGetLastError());
return -1;}// bind the listening socket to the specified port
ZeroMemory(&MyAddress, sizeof(MyAddress));
MyAddress.sin_port = htons((short)PortNumber);
MyAddress.sin_family = AF_INET;
res = bind(*listenSocket, (struct sockaddr*) &MyAddress, sizeof(MyAddress));
if(res == SOCKET_ERROR){
printf("Bind error. Error is 0x%x\n", WSAGetLastError());
return -1;}// listen/wait for server connections
res = listen(*listenSocket, 3);if(res == SOCKET_ERROR){
printf("Listen error. Error is 0x%x\n", WSAGetLastError());
return -1;}
return 0;}

D.3.3.2.

PlatformServer()This function processes incoming platform requests.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

BOOL
PlatformServer(
SOCKET)s{
BOOL
uint32_t

OK = TRUE;
Command;//for(;;){OK = ReadBytes(s, (char*)&Command, 4);// client disconnected (or other error). We stop processing this client// and return to our caller who can stop the server or listen for another// connection.
if(!OK) return TRUE;
Command = ntohl(Command);switch(Command){case TPM_SIGNAL_POWER_ON:_rpc__Signal_PowerOn(FALSE);
break;
case TPM_SIGNAL_POWER_OFF:_rpc__Signal_PowerOff();
break;
case TPM_SIGNAL_RESET:_rpc__Signal_PowerOn(TRUE);
break;

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 823
April 15, 2019

Trusted Platform Module Library
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

Part 4: Supporting Routinescase TPM_SIGNAL_RESTART:_rpc__Signal_Restart();break;
case TPM_SIGNAL_PHYS_PRES_ON:_rpc__Signal_PhysicalPresenceOn();
break;
case TPM_SIGNAL_PHYS_PRES_OFF:_rpc__Signal_PhysicalPresenceOff();
break;
case TPM_SIGNAL_CANCEL_ON:_rpc__Signal_CancelOn();
break;
case TPM_SIGNAL_CANCEL_OFF:_rpc__Signal_CancelOff();
break;
case TPM_SIGNAL_NV_ON:_rpc__Signal_NvOn();
break;
case TPM_SIGNAL_NV_OFF:_rpc__Signal_NvOff();
break;
case TPM_SIGNAL_KEY_CACHE_ON:_rpc__RsaKeyCacheControl(TRUE);
break;
case TPM_SIGNAL_KEY_CACHE_OFF:_rpc__RsaKeyCacheControl(FALSE);
break;
case TPM_SESSION_END:// Client signaled end-of-session
TpmEndSimulation();return TRUE;
case TPM_STOP:// Client requested the simulator to exit
return FALSE;
case TPM_TEST_FAILURE_MODE:_rpc__ForceFailureMode();break;
case TPM_GET_COMMAND_RESPONSE_SIZES:OK = WriteVarBytes(s, (char *)&CommandResponseSizes,
sizeof(CommandResponseSizes));
memset(&CommandResponseSizes, 0, sizeof(CommandResponseSizes));if(!OK)
return TRUE;
break;
default:
printf("Unrecognized platform interface command %d\n",(int)Command);WriteUINT32(s, 1);
return TRUE;}
WriteUINT32(s, 0);}
return FALSE;}

D.3.3.3.

PlatformSvcRoutine()

This function is called to set up the socket interfaces to listen for commands.
156
157
158
159
160

DWORD WINAPI
PlatformSvcRoutine(
LPVOID)

port{

Page 824
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

int
SOCKET
struct
int
int
BOOL

Trusted Platform Module Library
PortNumber = (int)(INT_PTR)port;
listenSocket, serverSocket;
sockaddr_in HerAddress;
res;length;continueServing;//
res = CreateSocket(PortNumber, &listenSocket);if(res != 0){
printf("Create platform service socket fail\n");return res;}// Loop accepting connections one-by-one until we are killed or asked to stop// Note the platform service is single-threaded so we don't listen for a new// connection until the prior connection drops.
do{printf("Platform server listening on port %d\n", PortNumber);// blocking accept
length = sizeof(HerAddress);
serverSocket = accept(listenSocket,(struct sockaddr*) &HerAddress,&length);if(serverSocket == INVALID_SOCKET){
printf("Accept error. Error is 0x%x\n", WSAGetLastError());
return -1;}
printf("Client accepted\n");// normal behavior on client disconnection is to wait for a new client// to connect
continueServing = PlatformServer(serverSocket);closesocket(serverSocket);} while(continueServing);
return 0;}

D.3.3.4.

PlatformSignalService()This function starts a new thread waiting for platform signals. Platform signals are processed one at atime in the order in which they are received.
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

int
PlatformSignalService(
int)

PortNumber{
HANDLEint
int

hPlatformSvc;
ThreadId;
port = PortNumber;//// Create service thread for platform signals
hPlatformSvc = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PlatformSvcRoutine,(LPVOID)(INT_PTR)port, 0, (LPDWORD)&ThreadId);if(hPlatformSvc == NULL){
printf("Thread Creation failed\n");return -1;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 825
April 15, 2019

Trusted Platform Module Library
219
220Part 4: Supporting Routines

return 0;}

D.3.3.5.

RegularCommandService()This function services regular commands.
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

int
RegularCommandService(
int)

PortNumber{
SOCKET
SOCKET
structint
BOOL

listenSocket;
serverSocket;
sockaddr_in HerAddress;
res, length;
continueServing;//
res = CreateSocket(PortNumber, &listenSocket);if(res != 0){
printf("Create platform service socket fail\n");return res;}// Loop accepting connections one-by-one until we are killed or asked to stop// Note the TPM command service is single-threaded so we don't listen for// a new connection until the prior connection drops.
do{printf("TPM command server listening on port %d\n", PortNumber);// blocking accept
length = sizeof(HerAddress);
serverSocket = accept(listenSocket,(struct sockaddr*) &HerAddress,&length);if(serverSocket == SOCKET_ERROR){
printf("Accept error. Error is 0x%x\n", WSAGetLastError());
return -1;}
printf("Client accepted\n");// normal behavior on client disconnection is to wait for a new client// to connect
continueServing = TpmServer(serverSocket);closesocket(serverSocket);} while(continueServing);
return 0;}

D.3.3.6.

StartTcpServer()This is the 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.
264
265
266
267
268
269

int
StartTcpServer(
int)

PortNumber

int

res;

{

Page 826
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286

Trusted Platform Module Library//// Start Platform Signal Processing Service
res = PlatformSignalService(PortNumber + 1);
if(res != 0){
printf("PlatformSignalService failed\n");return res;}// Start Regular/DRTM TPM command service
res = RegularCommandService(PortNumber);if(res != 0){
printf("RegularCommandService failed\n");return res;}return 0;}

D.3.3.7.

ReadBytes()

This function reads the indicated number of bytes (NumBytes) into buffer from the indicated socket.
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

BOOL
ReadBytes(
SOCKET
char
int
)

s,
*buffer,
NumBytes

{
int
int

res;
numGot = 0;//
while(numGot < NumBytes){
res = recv(s, buffer + numGot, NumBytes - numGot, 0);if(res == -1){
printf("Receive error. Error is 0x%x\n", WSAGetLastError());
return FALSE;}
if(res == 0){
return FALSE;}
numGot += res;}return TRUE;}

D.3.3.8.

WriteBytes()

This function will send the indicated number of bytes (NumBytes) to the indicated socket
313
314
315
316
317
318
319
320
321
322

BOOL
WriteBytes(
SOCKET
char
int
)

s,
*buffer,
NumBytes

{
int
int

res;
numSent = 0;//

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 827
April 15, 2019

Trusted Platform Module Library
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

Part 4: Supporting Routines

while(numSent < NumBytes){
res = send(s, buffer + numSent, NumBytes - numSent, 0);if(res == -1){
if(WSAGetLastError() == 0x2745){
printf("Client disconnected\n");}else{
printf("Send error. Error is 0x%x\n", WSAGetLastError());}
return FALSE;}
numSent += res;}return TRUE;}

D.3.3.9.

WriteUINT32()

Send 4 bytes containing hton(1)
342
343
344
345
346
347
348
349
350
351

BOOL
WriteUINT32(
SOCKET
uint32_t
)

s,
val

{
UINT32 netVal = htonl(val);//
return WriteBytes(s, (char*)&netVal, 4);}

D.3.3.10. ReadVarBytes()
Get a UINT32-length-prepended binary array. Note that the 4-byte length is in network byte order (bigendian).
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

BOOL
ReadVarBytes(
SOCKETchar
uint32_t
int)s,*buffer,*BytesReceived,
MaxLen{int
BOOL

length;res;//
res = ReadBytes(s, (char*)&length, 4);if(!res) return res;length = ntohl(length);*BytesReceived = length;if(length > MaxLen){
printf("Buffer too big. Client says %d\n", length);
return FALSE;}
if(length == 0) return TRUE;
res = ReadBytes(s, buffer, length);if(!res) return res;

Page 828
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
375
376

Trusted Platform Module Library

return TRUE;}

D.3.3.11. WriteVarBytes()
Send a UINT32-length-prepended binary array. Note that the 4-byte length is in network byte order (bigendian).
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

BOOL
WriteVarBytes(
SOCKET
char
int
)

s,
*buffer,
BytesToSend{
uint32_t
BOOL res;

netLength = htonl(BytesToSend);//
res = WriteBytes(s, (char*)&netLength, 4);if(!res)return res;
res = WriteBytes(s, buffer, BytesToSend);
if(!res)return res;return TRUE;}

D.3.3.12. TpmServer()
Processing incoming TPM command requests using the protocol / interface defined above.
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

BOOL
TpmServer(
SOCKET)s{uint32_t
uint32_t
BYTE
BOOL
int
int
_IN_BUFFER_OUT_BUFFER

length;Command;locality;OK;
result;clientVersion;
InBuffer;
OutBuffer;//for(;;){OK = ReadBytes(s, (char*)&Command, 4);// client disconnected (or other error). We stop processing this client// and return to our caller who can stop the server or listen for another// connection.
if(!OK)
return TRUE;
Command = ntohl(Command);switch(Command){case TPM_SIGNAL_HASH_START:_rpc__Signal_Hash_Start();break;
case TPM_SIGNAL_HASH_END:_rpc__Signal_HashEnd();break;
case TPM_SIGNAL_HASH_DATA:

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 829
April 15, 2019

Trusted Platform Module Library
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

Part 4: Supporting Routines

OK = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
if(!OK) return TRUE;
InBuffer.Buffer = (BYTE*)InputBuffer;
InBuffer.BufferSize = length;_rpc__Signal_Hash_Data(InBuffer);
break;
case TPM_SEND_COMMAND:
OK = ReadBytes(s, (char*)&locality, 1);
if(!OK)
return TRUE;
OK = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
if(!OK)
return TRUE;
InBuffer.Buffer = (BYTE*)InputBuffer;
InBuffer.BufferSize = length;
OutBuffer.BufferSize = MAX_BUFFER;
OutBuffer.Buffer = (_OUTPUT_BUFFER)OutputBuffer;// record the number of bytes in the command if it is the largest// we have seen so far.
if(InBuffer.BufferSize > CommandResponseSizes.largestCommandSize){
CommandResponseSizes.largestCommandSize = InBuffer.BufferSize;
memcpy(&CommandResponseSizes.largestCommand,&InputBuffer[6], sizeof(UINT32));}_rpc__Send_Command(locality, InBuffer, &OutBuffer);// record the number of bytes in the response if it is the largest// we have seen so far.
if(OutBuffer.BufferSize > CommandResponseSizes.largestResponseSize){
CommandResponseSizes.largestResponseSize= OutBuffer.BufferSize;
memcpy(&CommandResponseSizes.largestResponse,&OutputBuffer[6], sizeof(UINT32));}
OK = WriteVarBytes(s,(char*)OutBuffer.Buffer,
OutBuffer.BufferSize);if(!OK)
return TRUE;
break;
case TPM_REMOTE_HANDSHAKE:
OK = ReadBytes(s, (char*)&clientVersion, 4);if(!OK)
return TRUE;
if(clientVersion == 0){
printf("Unsupported client version (0).\n");return TRUE;}
OK &= WriteUINT32(s, ServerVersion);
OK &= WriteUINT32(s, tpmInRawMode| tpmPlatformAvailable | tpmSupportsPP);
break;
case TPM_SET_ALTERNATIVE_RESULT:
OK = ReadBytes(s, (char*)&result, 4);if(!OK)
return TRUE;// Alternative result is not applicable to the simulator.
break;
case TPM_SESSION_END:// Client signaled end-of-session
return TRUE;
case TPM_STOP:// Client requested the simulator to exit
return FALSE;

Page 830
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
493
494
495
496
497
498
499
500
501
502

Trusted Platform Module Librarydefault:
printf("Unrecognized TPM interface command %d\n", (int)Command);return TRUE;}
OK = WriteUINT32(s, 0);if(!OK)
return TRUE;}
return FALSE;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 831
April 15, 2019

Trusted Platform Module Library

D.4

Part 4: Supporting Routines

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 coverageof the testing.
D.4.2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Includes and Data Definitions#include <stdlib.h>#include <stdio.h>#include <setjmp.h>#include "TpmBuildSwitches.h"#include <windows.h>#include <winsock.h>#include "Platform_fp.h"#include "ExecCommand_fp.h"#include "Manufacture_fp.h"#include "_TPM_Init_fp.h"#include "_TPM_Hash_Start_fp.h"#include "_TPM_Hash_Data_fp.h"#include "_TPM_Hash_End_fp.h"#include "TpmFail_fp.h"#include "TpmTcpProtocol.h"#include "Simulator_fp.h"
static BOOL
s_isPowerOn = FALSE;

D.4.3.

FunctionsD.4.3.1.

Signal_PowerOn()

This function processes a power-on indication. Among other things, it calls the _TPM_Init() handler.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

void
_rpc__Signal_PowerOn(
BOOL)

isReset{// if power is on and this is not a call to do TPM reset then returnif(s_isPowerOn && !isReset)
return;// If this is a reset but power is not on, then returnif(isReset && !s_isPowerOn)return;// Unless this is just a reset, pass power on signal to platform
if(!isReset)_plat__Signal_PowerOn();// Power on and reset both lead to _TPM_Init()_plat__Signal_Reset();// Set state as power on
s_isPowerOn = TRUE;}

Page 832
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

D.4.3.2.

Trusted Platform Module Library

Signal_Restart()

This function processes the clock restart indication. All it does is call the platform function.
41
42
43
44
45
46
47

void
_rpc__Signal_Restart(
void){_plat__TimerRestart();}D.4.3.3.

Signal_PowerOff()

This function processes the power off indication. Its primary function is to set a flag indicating that thenext power on indication should cause _TPM_Init() to be called.
48
49
50
51
52
53
54
55
56
57
58
59
60
61

void
_rpc__Signal_PowerOff(
void){
if(!s_isPowerOn) return;// Pass power off signal to platform_plat__Signal_PowerOff();s_isPowerOn = FALSE;
return;}D.4.3.4.

_rpc__ForceFailureMode()This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM code suchthat the next call to TPM2_SelfTest() will result in a failure, putting the TPM into Failure Mode.
62
63
64
65
66
67
68

void
_rpc__ForceFailureMode(void){
SetForceFailureMode();}D.4.3.5.

_rpc__Signal_PhysicalPresenceOn()

This function is called to simulate activation of the physical presence pin.
69
70
71
72
73
74
75
76
77
78
79

void
_rpc__Signal_PhysicalPresenceOn(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Pass physical presence on to platform_plat__Signal_PhysicalPresenceOn();

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 833
April 15, 2019

Trusted Platform Module Library
80
81

Part 4: Supporting Routines

return;}D.4.3.6.

_rpc__Signal_PhysicalPresenceOff()

This function is called to simulate deactivation of the physical presence pin.
82
83
84
85
86
87
88
89
90
91
92
93
94

void
_rpc__Signal_PhysicalPresenceOff(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Pass physical presence off to platform_plat__Signal_PhysicalPresenceOff();
return;}D.4.3.7.

_rpc__Signal_Hash_Start()

This function is called to simulate a _TPM_Hash_Start() event. It will call
95
96
97
98
99
100
101
102
103
104
105
106

void
_rpc__Signal_Hash_Start(void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Pass _TPM_Hash_Start signal to TPM_TPM_Hash_Start();return;}D.4.3.8.

_rpc__Signal_Hash_Data()

This function is called to simulate a _TPM_Hash_Data() event.
107
108
109
110
111
112
113
114
115
116
117
118

void
_rpc__Signal_Hash_Data(_IN_BUFFER
)

input

{
// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Pass _TPM_Hash_Data signal to TPM_TPM_Hash_Data(input.BufferSize, input.Buffer);
return;}D.4.3.9.

_rpc__Signal_HashEnd()

This function is called to simulate a _TPM_Hash_End() event.
119

void

Page 834
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines

120
121
122
123
124
125
126
127
128
129
130

Trusted Platform Module Library_rpc__Signal_HashEnd(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Pass _TPM_HashEnd signal to TPM_TPM_Hash_End();return;}D.4.3.10. _rpc__Send_Command()This is the interface to the TPM code.
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

void
_rpc__Send_Command(
unsigned char
_IN_BUFFER_OUT_BUFFER)

locality,
request,*response{// If TPM is power off, reject any commands.
if(!s_isPowerOn){
response->BufferSize = 0;
return;}// Set the locality of the command so that it doesn't change during the command_plat__LocalitySet(locality);// Do implementation-specific command dispatch_plat__RunCommand(request.BufferSize, request.Buffer,&response->BufferSize, &response->Buffer);
return;}D.4.3.11. _rpc__Signal_CancelOn()
This function is used to turn on the indication to cancel a command in process. An executing command is
not interrupted. The command code may periodically check this indication to see if it should abort thecurrent command processing and returned TPM_RC_CANCELLED.
151
152
153
154
155
156
157
158
159
160
161
162
163

void
_rpc__Signal_CancelOn(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Set the platform canceling flag.
_plat__SetCancel();return;}D.4.3.12. _rpc__Signal_CancelOff()
This function is used to turn off the indication to cancel a command in process.
Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 835
April 15, 2019

Trusted Platform Module Library

164
165
166
167
168
169
170
171
172
173
174
175
176

Part 4: Supporting Routines

void_rpc__Signal_CancelOff(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;// Set the platform canceling flag.
_plat__ClearCancel();return;}D.4.3.13. _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.
177
178
179
180
181
182
183
184
185
186
187

void
_rpc__Signal_NvOn(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;_plat__SetNvAvail();return;}D.4.3.14. _rpc__Signal_NvOff()
This function is used to set the indication that NV memory is no longer available.
188
189
190
191
192
193
194
195
196
197
198
199

void
_rpc__Signal_NvOff(
void){// If TPM is power off, reject this signal
if(!s_isPowerOn) return;_plat__ClearNvAvail();return;}void RsaKeyCacheControl(int state);

D.4.3.15. _rpc__RsaKeyCacheControl()This function is used to enable/disable the use of the RSA key cache during simulation.
200
201
202
203
204
205
206
207
208

void
_rpc__RsaKeyCacheControl(
int
)

state

{
#if USE_RSA_KEY_CACHE
RsaKeyCacheControl(state);#else
NOT_REFERENCED(state);

Page 836
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
209
210

Trusted Platform Module Library#endif}D.4.3.16. _rpc__Shutdown()
This function is used to stop the TPM simulator.
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

void
_rpc__Shutdown(
void){
RPC_STATUS status;// Stop TPM
TPM_TearDown();
status = RpcMgmtStopServerListening(NULL);
if(status != RPC_S_OK){
printf("RpcMgmtStopServerListening returned: 0x%x\n", status);exit(status);}status = RpcServerUnregisterIf(NULL, NULL, FALSE);
if(status != RPC_S_OK){
printf("RpcServerUnregisterIf returned 0x%x\n", status);exit(status);}
return;}Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 837
April 15, 2019

Trusted Platform Module Library

D.5

Part 4: Supporting Routines

TPMCmds.c

D.5.1.

Description

This file contains the entry point for the simulator.
D.5.2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Includes, Defines, Data Definitions, and Function Prototypes#include "TpmBuildSwitches.h"#include <stdlib.h>#include <stdio.h>#include <stdint.h>#include <ctype.h>#include <string.h>#include <windows.h>#include <winsock.h>#include "TpmTcpProtocol.h"#include "Manufacture_fp.h"#include "Platform_fp.h"#include "Simulator_fp.h"#define PURPOSE \"TPM Reference Simulator.\nCopyright Microsoft Corp.\n"#define DEFAULT_TPM_PORT 2321
void* MainPointer;

D.5.3.

FunctionsD.5.3.1.

Usage()

This function prints the proper calling sequence for the simulator.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

static void
Usage(
char)*pszProgramName{
fprintf(stderr, "%s", PURPOSE);
fprintf(stderr, "Usage:\n");fprintf(stderr, "%s- Starts the TPM server listening on port %d\n",pszProgramName, DEFAULT_TPM_PORT);
fprintf(stderr,"%s PortNum - Starts the TPM server listening on port PortNum\n",pszProgramName);
fprintf(stderr, "%s ?
- This message\n", pszProgramName);exit(1);}

D.5.3.2.

main()

This is the main entry point for the simulator. It registers the interface and starts listening for clients
32
33
34
35
36
37
38
39

int
main(
int
char
)

argc,
*argv[]{
int portNum = DEFAULT_TPM_PORT;
if(argc > 2)

Page 838
April 15, 2019

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Family “2.0”Level 00 Revision 01.55

Part 4: Supporting Routines
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

Trusted Platform Module Library{
Usage(argv[0]);}if(argc == 2){
if(strcmp(argv[1], "?") == 0){
Usage(argv[0]);}portNum = atoi(argv[1]);if(portNum <= 0 || portNum > 65535){
Usage(argv[0]);}}_plat__NVEnable(NULL);
if(TPM_Manufacture(1) != 0){
exit(1);}// Coverage test - repeated manufacturing attemptif(TPM_Manufacture(0) != 1){
exit(2);}// Coverage test - re-manufacturing
TPM_TearDown();
if(TPM_Manufacture(1) != 0){
exit(3);}// Disable NV memory_plat__NVDisable();StartTcpServer(portNum);
return EXIT_SUCCESS;}

Family “2.0”Level 00 Revision 01.55

TCG PUBLIC REVIEW
Copyright © TCG 2006-2019

Page 839
April 15, 2019