Trusted Platform Module LibraryPart 4: Supporting Routines
Family “2.0”Level 00 Revision 01.64
December 24, 2020

Committee Draft

Contact: admin@trustedcomputinggroup.org

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.

TCG PUBLIC REVIEWTCG

Copyright © TCG 2006-2021

Part 4: Supporting Routines

Trusted Platform Module Library

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 to reproduce,
create derivative works, distribute, display and perform the Source Code and derivative works
thereof, and to grant others the rights granted herein.

•

The TCG grants to the user of the other parts of the specification (other than the Source Code) therights 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 andthe following disclaimers.

•

Redistributions in binary form must reproduce the above copyright licenses, this list of conditions andthe 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 ANYPROPOSAL, 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page ii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

CONTENTSCONTENTS .............................................................................................................................. 3
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 ................................................................ 3

4.2.4

Table-driven Marshaling ..................................................................................... 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 ......................................................................................................... 105
5.8 CompilerDependencies.h ....................................................................................... 113
5.9 Global.h ................................................................................................................ 115
5.9.1
5.9.2
5.9.3

Description ..................................................................................................... 115
Includes.......................................................................................................... 115
Defines and Types .......................................................................................... 115

5.9.4

Loaded Object Structures ................................................................................ 116

5.9.5
5.9.6

AUTH_DUP Types .......................................................................................... 118
Active Session Context ................................................................................... 118

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page iii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

5.9.7

PCR ............................................................................................................... 120

5.9.8
5.9.9

STARTUP_TYPE ............................................................................................ 121
NV .................................................................................................................. 121

5.9.10 COMMIT_INDEX_MASK ................................................................................. 122
5.9.11 RAM Global Values ......................................................................................... 122

5.9.12 Persistent Global Values ................................................................................. 126

5.9.135.9.145.9.155.9.165.9.17

NV Layout ...................................................................................................... 132
Global Macro Definitions ................................................................................. 132
From CryptTest.c ............................................................................................ 134
From Manufacture.c ........................................................................................ 134
Private data .................................................................................................... 134

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page iv
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

5.10 GpMacros.h ........................................................................................................... 139
5.10.1
5.10.25.10.35.10.45.10.5
5.11
5.12
5.13
5.14

Introduction .................................................................................................... 139
For Self-test ................................................................................................... 139
For Failures .................................................................................................... 139
Derived from Vendor-specific values ............................................................... 140
Compile-time Checks ...................................................................................... 140

InternalRoutines.h ................................................................................................. 145
LibSupport.h .......................................................................................................... 147
MinMax.h .............................................................................................................. 147
NV.h ...................................................................................................................... 148

5.14.1 Index Type Definitions .................................................................................... 148
5.14.2 Attribute Macros ............................................................................................. 148
5.14.3 Orderly RAM Values ....................................................................................... 149
5.15
5.16
5.17
5.18
5.19
5.20
5.21
5.22
6

TPMB.h ................................................................................................................. 151
Tpm.h ................................................................................................................... 152
TpmBuildSwitches.h .............................................................................................. 153
TpmError.h ............................................................................................................ 159
TpmTypes.h .......................................................................................................... 160
VendorString.h ...................................................................................................... 199
swap.h .................................................................................................................. 200
ACT.h ................................................................................................................... 202

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

CommandDispatcher.c ........................................................................................... 211

6.3.1
6.3.2
6.3.3

6.4

Introduction .................................................................................................... 206
Includes.......................................................................................................... 206
ExecuteCommand() ........................................................................................ 206

Introduction .................................................................................................... 211
Includes and Typedefs .................................................................................... 211
Marshal/Unmarshal Functions ......................................................................... 213

SessionProcess.c .................................................................................................. 219

6.4.1
6.4.2
6.4.3

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

6.4.4

Session Parsing Functions .............................................................................. 226

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page v
December 24, 2020

Part 4: Supporting Routines

6.4.5

7

Trusted Platform Module Library

Response Session Processing ........................................................................ 245

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

7.3

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

7.3.1
7.3.2

7.4

Includes.......................................................................................................... 257
Functions ....................................................................................................... 257

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

7.4.1
7.4.2

7.5

Includes.......................................................................................................... 254
Functions ....................................................................................................... 254

Includes.......................................................................................................... 260
Functions ....................................................................................................... 260

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

7.5.1
7.5.2

Includes.......................................................................................................... 265
Functions ....................................................................................................... 265

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page vi
December 24, 2020

Part 4: Supporting Routines

7.6

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

7.6.1
7.6.2

Includes.......................................................................................................... 268
Local Functions .............................................................................................. 268

7.6.3

Public Functions ............................................................................................. 272

7.7
7.8

Encrypt Decrypt Support (EncryptDecrypt_spt.c) .................................................... 293
ACT Support (ACT_spt.c) ...................................................................................... 295

7.8.1
7.8.2
7.8.3

8

Trusted Platform Module Library

Introduction .................................................................................................... 295
Includes.......................................................................................................... 295
Functions ....................................................................................................... 295

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

Introduction .................................................................................................... 300
Includes.......................................................................................................... 300
Functions ....................................................................................................... 300

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page vii
December 24, 2020

Part 4: Supporting Routines

8.2

DA.c ...................................................................................................................... 305

8.2.1
8.2.2
8.2.3

8.3

Introduction .................................................................................................... 305
Includes and Data Definitions .......................................................................... 305
Functions ....................................................................................................... 305

Hierarchy.c ............................................................................................................ 309

8.3.1
8.3.2
8.3.3

8.4

Trusted Platform Module Library

Introduction .................................................................................................... 309
Includes.......................................................................................................... 309
Functions ....................................................................................................... 309

NvDynamic.c ......................................................................................................... 313

8.4.1
8.4.2
8.4.3

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

8.4.4

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page viii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

8.4.5

Externally Accessible Functions ...................................................................... 325

8.4.6

NV Max Counter ............................................................................................. 344

8.5

NvReserved.c ........................................................................................................ 346

8.5.1
8.5.2
8.5.3

Introduction .................................................................................................... 346
Includes, Defines ............................................................................................ 346
Functions ....................................................................................................... 346

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page ix
December 24, 2020

Part 4: Supporting Routines

8.6

Object.c ................................................................................................................ 350

8.6.1
8.6.2
8.6.3

8.7

Trusted Platform Module Library

Introduction .................................................................................................... 350
Includes and Data Definitions .......................................................................... 350
Functions ....................................................................................................... 350

PCR.c ................................................................................................................... 367

8.7.1
8.7.2
8.7.3

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page x
December 24, 2020

Part 4: Supporting Routines

8.8

PP.c ...................................................................................................................... 389

8.8.1
8.8.2
8.8.3

8.9

Trusted Platform Module Library

Introduction .................................................................................................... 389
Includes.......................................................................................................... 389
Functions ....................................................................................................... 389

Session.c .............................................................................................................. 392

8.9.1
8.9.2
8.9.3
8.9.4
8.9.5

Introduction .................................................................................................... 392
Includes, Defines, and Local Variables ............................................................ 392
File Scope Function -- ContextIdSetOldest() .................................................... 392
Startup Function -- SessionStartup() ............................................................... 392
Access Functions ............................................................................................ 393

8.9.6

Utility Functions .............................................................................................. 396

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xi
December 24, 2020

Part 4: Supporting Routines

9

Trusted Platform Module Library

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

Bits.c ..................................................................................................................... 417

9.2.1
9.2.2
9.2.3

9.3

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

Entity.c .................................................................................................................. 429

9.4.1
9.4.2
9.4.3

9.5

Introduction .................................................................................................... 417
Includes.......................................................................................................... 417
Functions ....................................................................................................... 417

CommandCodeAttributes.c .................................................................................... 419

9.3.1
9.3.2
9.3.3

9.4

Description ..................................................................................................... 413
Includes and Defines ...................................................................................... 413
AlgorithmCapGetImplemented() ...................................................................... 415
AlgorithmGetImplementedVector() ................................................................... 416

Description ..................................................................................................... 429
Includes.......................................................................................................... 429
Functions ....................................................................................................... 429

Global.c ................................................................................................................ 437

9.5.1
9.5.2

Description ..................................................................................................... 437
Defines and Includes ...................................................................................... 437

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xii
December 24, 2020

Part 4: Supporting Routines

9.6

Handle.c ................................................................................................................ 438

9.6.1
9.6.2
9.6.3

9.7

Includes and Data Definitions .......................................................................... 441
Buffers and Functions ..................................................................................... 441

Locality.c ............................................................................................................... 443

9.8.1
9.8.2
9.9

Description ..................................................................................................... 438
Includes.......................................................................................................... 438
Functions ....................................................................................................... 438

IoBuffers.c ............................................................................................................. 441

9.7.1
9.7.2

9.8

Trusted Platform Module Library

Includes.......................................................................................................... 443
LocalityGetAttributes() .................................................................................... 443

Manufacture.c ....................................................................................................... 444

9.9.1
9.9.2
9.9.3

Description ..................................................................................................... 444
Includes and Data Definitions .......................................................................... 444
Functions ....................................................................................................... 444

9.10 Marshal.c .............................................................................................................. 447
9.10.19.10.29.10.39.10.49.10.59.10.69.10.7

Introduction .................................................................................................... 447
Unmarshal and Marshal a Value ...................................................................... 447
Unmarshal and Marshal a Union ..................................................................... 448
Unmarshal and Marshal a Structure ................................................................ 450
Unmarshal and Marshal an Array .................................................................... 451
TPM2B Handling ............................................................................................. 453
Table Marshal Headers ................................................................................... 453

9.10.8 Table Marshal Source ..................................................................................... 504

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xiii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

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

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

9.15 Response.c ........................................................................................................... 564
9.15.1 Description ..................................................................................................... 564
9.15.2 Includes and Defines ...................................................................................... 564
9.15.3 BuildResponseHeader() .................................................................................. 564
9.16 ResponseCodeProcessing.c .................................................................................. 565
9.16.1 Description ..................................................................................................... 565
9.16.2 Includes and Defines ...................................................................................... 565
9.16.3 RcSafeAddToResult() ..................................................................................... 565
9.17 TpmFail.c .............................................................................................................. 566
9.17.1 Includes, Defines, and Types .......................................................................... 566
9.17.2 Typedefs ........................................................................................................ 566
9.17.3 Local Functions .............................................................................................. 567

9.17.4 Public Functions ............................................................................................. 568

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xiv
December 24, 2020

Part 4: Supporting Routines

10

Trusted Platform Module Library

Cryptographic Functions ................................................................................................. 573
10.1 Headers ................................................................................................................ 573
10.1.1 BnValues.h ..................................................................................................... 573

10.1.2 CryptEcc.h ...................................................................................................... 579

10.1.3 CryptHash.h ................................................................................................... 580

10.1.4 CryptRand.h ................................................................................................... 585

10.1.5 CryptRsa.h ..................................................................................................... 588
10.1.6 CryptTest.h ..................................................................................................... 589
10.1.7 HashTestData.h .............................................................................................. 590
10.1.8 KdfTestData.h ................................................................................................ 592
10.1.9 RsaTestData.h ................................................................................................ 593
10.1.10 SelfTest.h ....................................................................................................... 599

10.1.11 SupportLibraryFunctionPrototypes_fp.h ........................................................... 600

10.1.12 SymmetricTestData.h ...................................................................................... 603
10.1.13 SymmetricTest.h ............................................................................................. 606

10.1.14 EccTestData.h ................................................................................................ 607
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xv
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.15 CryptSym.h ..................................................................................................... 609

10.1.16 OIDs.h ............................................................................................................ 611
10.1.17 PRNG_TestVectors.h ...................................................................................... 615
10.1.18 TpmAsn1.h ..................................................................................................... 616

10.1.19 X509.h............................................................................................................ 617

10.1.20 TpmAlgorithmDefines.h ................................................................................... 619
10.2 Source .................................................................................................................. 626
10.2.1 AlgorithmTests.c ............................................................................................. 626

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xvi
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.2 BnConvert.c .................................................................................................... 641

10.2.3 BnMath.c ........................................................................................................ 646

10.2.4 BnMemory.c ................................................................................................... 657

10.2.5 CryptCmac.c ................................................................................................... 660

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xvii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.6 CryptUtil.c ...................................................................................................... 663

10.2.7 CryptSelfTest.c ............................................................................................... 693

10.2.8 CryptEccData.c ............................................................................................... 697
10.2.9 CryptDes.c ..................................................................................................... 707
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xviii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.10 CryptEccKeyExchange.c ................................................................................. 710

10.2.11 CryptEccMain.c .............................................................................................. 716

10.2.12 CryptEccSignature.c ....................................................................................... 730

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xix
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.13 CryptHash.c .................................................................................................... 745

10.2.14 CryptPrime.c ................................................................................................... 761

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xx
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.15 CryptPrimeSieve.c .......................................................................................... 767

10.2.16 CryptRand.c ................................................................................................... 776

10.2.17 CryptRsa.c ..................................................................................................... 792

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxi
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.18 CryptSmac.c ................................................................................................... 816

10.2.19 CryptSym.c ..................................................................................................... 818

10.2.20 PrimeData.c .................................................................................................... 826
10.2.21 RsaKeyCache.c .............................................................................................. 832

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.22 Ticket.c .......................................................................................................... 836

10.2.23 TpmAsn1.c ..................................................................................................... 840

10.2.24 X509_ECC.c ................................................................................................... 849

10.2.25 X509_RSA.c ................................................................................................... 852

10.2.26 X509_spt.c ..................................................................................................... 856

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxiii
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.27 AC_spt.c ........................................................................................................ 861

10.2.28 CryptEccCrypt.c .............................................................................................. 864

Annex A (informative) Implementation Dependent ................................................................. 868
A.1 Introduction ........................................................................................................... 868
A.2 TpmProfile.h .......................................................................................................... 868
A.3 TpmSizeChecks.c .................................................................................................. 880
A.3.1.
A.3.2.

Includes, Defines, and Types .......................................................................... 880
TpmSizeChecks() ........................................................................................... 880

Annex B (informative) Library-Specific .................................................................................. 883
B.1 Introduction ........................................................................................................... 883
B.2 OpenSSL-Specific Files ......................................................................................... 884
B.2.1.
B.2.2.

Introduction .................................................................................................... 884
Header Files ................................................................................................... 884

B.2.3.

Source Files ................................................................................................... 893

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxiv
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

C.3

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

Clock.c .................................................................................................................. 910

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

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

C.3.4.

Functions Used by TPM .................................................................................. 911

C.4

Entropy.c ............................................................................................................... 915

C.4.1.
C.4.2.

C.5

LocalityPlat.c ......................................................................................................... 918

C.5.1.
C.5.2.

C.6

Includes and Local Values .............................................................................. 915
Functions ....................................................................................................... 915

Includes.......................................................................................................... 918
Functions ....................................................................................................... 918

NVMem.c .............................................................................................................. 919

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

Description ..................................................................................................... 919
Includes and Local .......................................................................................... 919
Functions ....................................................................................................... 919

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxv
December 24, 2020

Part 4: Supporting Routines

C.7

PowerPlat.c ........................................................................................................... 927

C.7.1.
C.7.2.

C.8
C.9

Trusted Platform Module Library

Includes and Function Prototypes.................................................................... 927
Functions ....................................................................................................... 927

PlatformData.h ...................................................................................................... 929
PlatformData.c ...................................................................................................... 931

C.9.1.
C.9.2.

Description ..................................................................................................... 931
Includes.......................................................................................................... 931

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

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

C.12 Unique.c ................................................................................................................ 934
C.12.1. Introduction .................................................................................................... 934
C.12.2. Includes.......................................................................................................... 934
C.12.3. _plat__GetUnique() ......................................................................................... 934
C.13 DebugHelpers.c ..................................................................................................... 935
C.13.1. Description ..................................................................................................... 935
C.13.2. Includes and Local .......................................................................................... 935

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxvi
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

C.14 Platform.h ............................................................................................................. 937
C.15 PlatformACT.h ....................................................................................................... 938
C.16 PlatformACT.c ....................................................................................................... 941
C.16.1. Includes.......................................................................................................... 941
C.16.2. Functions ....................................................................................................... 941

C.17 PlatformClock.h ..................................................................................................... 947
Annex D (informative) Remote Procedure Interface ............................................................... 948
D.1 Introduction ........................................................................................................... 948
D.2 TpmTcpProtocol.h ................................................................................................. 949
D.2.1.
D.2.2.
D.2.3.
D.2.4.
D.3

TcpServer.c ........................................................................................................... 951

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

D.4

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

Description ..................................................................................................... 951
Includes, Locals, Defines and Function Prototypes .......................................... 951
Functions ....................................................................................................... 952

TPMCmdp.c .......................................................................................................... 963

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

Description ..................................................................................................... 963
Includes and Data Definitions .......................................................................... 963
Functions ....................................................................................................... 963

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxvii
December 24, 2020

Part 4: Supporting Routines

D.5

Trusted Platform Module Library

TPMCmds.c ........................................................................................................... 969

D.5.1.
D.5.2.
D.5.3.

Description ..................................................................................................... 969
Includes, Defines, Data Definitions, and Function Prototypes ........................... 969
Functions ....................................................................................................... 969

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page xxviii
December 24, 2020

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 by 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 TPM configuration is largely defined by TpmProfiles.h. This file may be edited in order to change thealgorithms and commands supported by a TPM implementation.
A parser exists to process a Word document that defines the TPM configuration. This parser is used tocreate TpmProfiles.h.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 1
December 24, 2020

Part 4: Supporting Routines

4.2

Structure Parser

4.2.1

Introduction

Trusted Platform Module Library

The program that processes the tables in TPM 2.0 Part 2 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 clauses 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.
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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 2
December 24, 2020

Part 4: Supporting Routines

4.2.2.2

Trusted Platform Module Library

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.
4.2.3
4.2.3.1

Marshaling Code Function Prototypes
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:
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 3
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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 reduced by
the number of octets placed in the buffer.
When the data type is a simple type, the parser will generate code that will marshal the underlying type.
The presumption is that the TPM internal structures are consistent and correct so the marshaling code
does not validate that the data placed in the buffer has a permissible value. 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.
4.2.4

Table-driven Marshaling

The most recent versions of the TPM code includes the option to use table-driven marshaling rather thatthe procedural marshaling described in previous clauses in 4.2.2. The structure and processing of thiscode is complex and is provided in the code.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 4
December 24, 2020

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 the function code areusing the same attributes.

•

CommandDispatchData.h – This file contains the data definitions for the table driven version of thecommand 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
4#if CC_Create // Command must be enabled#ifndef _Create_FP_H_#define _Create_FP_H_

Input structure definition
5
6
7
8
9
10
11

typedef struct {TPMI_DH_OBJECT
TPM2B_SENSITIVE_CREATETPM2B_PUBLIC
TPM2B_DATA
TPML_PCR_SELECTION} Create_In;

parentHandle;
inSensitive;
inPublic;outsideInfo;
creationPCR;

Output structure definition
12
13
14

typedef struct {TPM2B_PRIVATETPM2B_PUBLIC

Family “2.0”Level 00 Revision 01.64

outPrivate;
outPublic;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 5
December 24, 2020

Part 4: Supporting Routines
15
16
17
18

TPM2B_CREATION_DATA
TPM2B_DIGEST
TPMT_TK_CREATION} Create_Out;

Trusted Platform Module LibrarycreationData;
creationHash;creationTicket;

Response code modifiers
19
20
21
22
23

#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
24
25
26
27
28
29
30
31

TPM_RC
TPM2_Create(
Create_In
Create_Out

*in,
*out

);
#endif#endif

4.5// _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).

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 6
December 24, 2020

Part 4: Supporting Routines

5
5.1

Trusted Platform Module Library

Header Files
Introduction

The files in this clause 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
17
18

#ifndef NULL
#define NULL
#endif(0)

typedef 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

UINT8;
BYTE;
INT8;
BOOL;
UINT16;
INT16;UINT32;
INT32;UINT64;
INT64;#endif // _BASE_TYPES_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 7
December 24, 2020

Part 4: Supporting Routines

5.3

Trusted Platform Module Library

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
13
14
15
16

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

#ifndef#define_CAPABILITIES_H_CAPABILITIES_H#define#define#define#define#define#define#define#define#define

MAX_CAP_DATAMAX_CAP_ALGS
MAX_CAP_HANDLESMAX_CAP_CC
MAX_TPM_PROPERTIES
MAX_PCR_PROPERTIES
MAX_ECC_CURVES
MAX_TAGGED_POLICIESMAX_ACT_DATA(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_ACT_DATA))#define

MAX_AC_CAPABILITIES(MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT))#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 8December 24, 2020

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
8
9

#ifdef _COMMAND_CODE_ATTRIBUTES_#include "CommandAttributes.h"#if COMPRESSED_LISTS#
define
PAD_LIST#else#
define
PAD_LIST#endif0
1This is the command code attribute array for GetCapability(). Both this array and s_commandAttributes
provides command code attributes, but tuned for different purpose
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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 9December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

TPMA_CC_INITIALIZER(0x012E, 0, 1, 0, 0, 1, 0, 0, 0),#endif#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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 10December 24, 2020

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

TPMA_CC_INITIALIZER(0x0144, 0, 1, 0, 0, 0, 0, 0, 0),#endif#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 )Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 11
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

TPMA_CC_INITIALIZER(0x015A, 0, 0, 0, 0, 0, 0, 0, 0),#endif#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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 12
December 24, 2020

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

TPMA_CC_INITIALIZER(0x0170, 0, 0, 0, 0, 1, 0, 0, 0),#endif#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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 13
December 24, 2020

Part 4: Supporting Routines
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
383
384
385
386

Trusted Platform Module Library

TPMA_CC_INITIALIZER(0x0186, 0, 0, 0, 0, 0, 1, 0, 0),#endif#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_ACT_SetTimeout)
TPMA_CC_INITIALIZER(0x0198, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ECC_Encrypt)
TPMA_CC_INITIALIZER(0x0199, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_ECC_Decrypt)
TPMA_CC_INITIALIZER(0x019A, 0, 0, 0, 0, 1, 0, 0, 0),#endif#if (PAD_LIST || CC_Vendor_TCG_Test)
TPMA_CC_INITIALIZER(0x0000, 0, 0, 0, 0, 0, 0, 1, 0),#endif
TPMA_ZERO_INITIALIZER()

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 14
December 24, 2020

Part 4: Supporting Routines
387

Trusted Platform Module Library};This is the command code attribute structure.
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

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)(COMMAND_ATTRIBUTES)(CC_EvictControl* // 0x0120(IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)),#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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 15
December 24, 2020

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(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)),#endif#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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 16
December 24, 2020

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#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(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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 17
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library(COMMAND_ATTRIBUTES)(CC_NV_ReadLock(IS_IMPLEMENTED+HANDLE_1_USER)),*// 0x014F#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)),#endif#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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 18
December 24, 2020

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(COMMAND_ATTRIBUTES)(CC_PolicySigned* // 0x0160(IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL+ENCRYPT_2)),#endif#if (PAD_LIST || CC_ContextLoad)(COMMAND_ATTRIBUTES)(CC_ContextLoad*(IS_IMPLEMENTED+NO_SESSIONS+R_HANDLE)),#endif#if (PAD_LIST || CC_ContextSave)(COMMAND_ATTRIBUTES)(CC_ContextSave*(IS_IMPLEMENTED+NO_SESSIONS)),#endif#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)),#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021// 0x0161// 0x0162// 0x0163// 0x0164// 0x0165// 0x0166// 0x0167// 0x0168// 0x0169// 0x016A// 0x016B// 0x016C// 0x016D// 0x016E// 0x016F// 0x0170

Page 19
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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)),#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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021// 0x0171// 0x0172// 0x0173// 0x0174// 0x0175// 0x0176// 0x0177// 0x0178// 0x0179// 0x017A// 0x017B// 0x017C// 0x017D// 0x017E// 0x017F// 0x0180// 0x0181

Page 20
December 24, 2020

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#endif#if (PAD_LIST || CC_PCR_Extend)(COMMAND_ATTRIBUTES)(CC_PCR_Extend* // 0x0182(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_PCR_SetAuthValue)(COMMAND_ATTRIBUTES)(CC_PCR_SetAuthValue* // 0x0183(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_NV_Certify)(COMMAND_ATTRIBUTES)(CC_NV_Certify* // 0x0184(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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 21
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library(COMMAND_ATTRIBUTES)(CC_PolicyAuthorizeNV(IS_IMPLEMENTED+HANDLE_1_USER+ALLOW_TRIAL)),*// 0x0192#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)),#endif#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_ACT_SetTimeout)(COMMAND_ATTRIBUTES)(CC_ACT_SetTimeout* // 0x0198(IS_IMPLEMENTED+HANDLE_1_USER)),#endif#if (PAD_LIST || CC_ECC_Encrypt)(COMMAND_ATTRIBUTES)(CC_ECC_Encrypt* // 0x0199(IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)),#endif#if (PAD_LIST || CC_ECC_Decrypt)(COMMAND_ATTRIBUTES)(CC_ECC_Decrypt* // 0x019A(IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_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_Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 22
December 24, 2020

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
21
22

#ifndef COMMAND_ATTRIBUTES_H#define COMMAND_ATTRIBUTES_H
typedef UINT16#define NOT_IMPLEMENTED#define ENCRYPT_2#define ENCRYPT_4#define DECRYPT_2#define DECRYPT_4#define HANDLE_1_USER#define HANDLE_1_ADMIN#define HANDLE_1_DUP#define HANDLE_2_USER#define PP_COMMAND#define IS_IMPLEMENTED#define NO_SESSIONS#define NV_COMMAND#define PP_REQUIRED#define R_HANDLE#define ALLOW_TRIAL

COMMAND_ATTRIBUTES;(COMMAND_ATTRIBUTES)(0)((COMMAND_ATTRIBUTES)1 << 0)((COMMAND_ATTRIBUTES)1 << 1)((COMMAND_ATTRIBUTES)1 << 2)((COMMAND_ATTRIBUTES)1 << 3)((COMMAND_ATTRIBUTES)1 << 4)((COMMAND_ATTRIBUTES)1 << 5)((COMMAND_ATTRIBUTES)1 << 6)((COMMAND_ATTRIBUTES)1 << 7)((COMMAND_ATTRIBUTES)1 << 8)((COMMAND_ATTRIBUTES)1 << 9)((COMMAND_ATTRIBUTES)1 << 10)((COMMAND_ATTRIBUTES)1 << 11)((COMMAND_ATTRIBUTES)1 << 12)((COMMAND_ATTRIBUTES)1 << 13)((COMMAND_ATTRIBUTES)1 << 14)#endif // COMMAND_ATTRIBUTES_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 23
December 24, 2020

Part 4: Supporting Routines

5.6

Trusted Platform Module Library

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
shorter. ;-)
4
5
6
7
8
9
10
11
12
13
14

#if TABLE_DRIVEN_MARSHAL#
define UNMARSHAL_DISPATCH(name)(marshalIndex_t)name##_MARSHAL_REF#
define MARSHAL_DISPATCH(name)(marshalIndex_t)name##_MARSHAL_REF#
define _UNMARSHAL_T_
marshalIndex_t#
define _MARSHAL_T_
marshalIndex_t#else#
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#endif

The unmarshalArray contains the dispatch functions for the unmarshaling code. The defines in this arrayare used to make it easier to cross reference the unmarshaling values in the types array of eachcommand
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_ACT_H_UNMARSHAL(TPMI_RH_AC_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_ACT),#define TPMI_RH_CLEAR_H_UNMARSHAL(TPMI_RH_ACT_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_HIERARCHY_POLICY_H_UNMARSHAL\(TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_POLICY),#define TPMI_RH_LOCKOUT_H_UNMARSHAL\(TPMI_RH_HIERARCHY_POLICY_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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 24
December 24, 2020

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#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)
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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 25
December 24, 2020

Part 4: Supporting Routines
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
170
171
172
173
174
175
176
177
178
179

Trusted Platform Module Library

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)
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_KDF_SCHEME_P_UNMARSHAL(TPMI_RH_HIERARCHY_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_KDF_SCHEME),#define TPMT_RSA_DECRYPT_P_UNMARSHAL(TPMT_KDF_SCHEME_P_UNMARSHAL + 1)
UNMARSHAL_DISPATCH(TPMT_RSA_DECRYPT),Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 26
December 24, 2020

Part 4: Supporting Routines
180
181
182
183
184
185
186
187
188
189
190

Trusted Platform Module Library#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
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

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 27
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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),#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.
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_UNMARSHAL#define TPM2B_AUTH_P_UNMARSHAL#define TPM2B_NONCE_P_UNMARSHAL#define TPM2B_OPERAND_P_UNMARSHAL#define TPMA_LOCALITY_P_UNMARSHAL#define TPM_CC_P_UNMARSHAL#define TPMI_DH_CONTEXT_H_MARSHAL#define TPMI_DH_OBJECT_H_MARSHAL#define TPMI_SH_AUTH_SESSION_H_MARSHAL#define TPM_HANDLE_H_MARSHAL#define TPM2B_NONCE_P_MARSHAL#define TPMI_YES_NO_P_MARSHAL#define TPM_RC_P_MARSHALUINT32_P_UNMARSHAL
TPM2B_DIGEST_P_UNMARSHAL
TPM2B_DIGEST_P_UNMARSHAL
TPM2B_DIGEST_P_UNMARSHALUINT8_P_UNMARSHALUINT32_P_UNMARSHALUINT32_H_MARSHALUINT32_H_MARSHALUINT32_H_MARSHALUINT32_H_MARSHAL
TPM2B_DIGEST_P_MARSHALUINT8_P_MARSHALUINT32_P_MARSHAL#if CC_Startup#include "Startup_fp.h"
typedef TPM_RC
Startup_In);(Startup_Entry)(*in

typedef const struct {Startup_Entry
UINT16
UINT16
UINT16BYTE

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;offsetOfTypes;
types[3];TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 28
December 24, 2020

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
367

Trusted Platform Module Library} 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)),/* outSize*/
0,/* offsetOfTypes */offsetof(Shutdown_COMMAND_DESCRIPTOR_t, types),/* offsets*/// No parameter offsets;/* types*/{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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 29
December 24, 2020

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

Trusted Platform Module Library

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#if CC_GetTestResult#include "GetTestResult_fp.h"
typedef TPM_RC (GetTestResult_Entry)(
GetTestResult_Out*out);
typedef const struct {GetTestResult_Entry
UINT16
UINT16
UINT16
UINT16BYTE

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;offsetOfTypes;
paramOffsets[1];types[4];TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 30
December 24, 2020

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} 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}};#define _StartAuthSessionDataAddress (&_StartAuthSessionData)#else#define _StartAuthSessionDataAddress 0#endif // CC_StartAuthSession

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 31
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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_In
Create_Out);(Create_Entry)(
*in,
*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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 32
December 24, 2020

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
629
630

Trusted Platform Module Library
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,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_In
Load_Out);(Load_Entry)(
*in,
*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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 33
December 24, 2020

Part 4: Supporting Routines
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
695
696

Trusted Platform Module Library

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,
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 34
December 24, 2020

Part 4: Supporting Routines
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#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))},/* types*/{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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 35
December 24, 2020

Part 4: Supporting Routines
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

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

Trusted Platform Module Library(UINT16)(sizeof(MakeCredential_Out)),
offsetof(MakeCredential_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(MakeCredential_In, credential)),(UINT16)(offsetof(MakeCredential_In, objectName)),(UINT16)(offsetof(MakeCredential_Out, secret))},{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_In
Unseal_Out);(Unseal_Entry)(
*in,
*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,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
UINT16
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 36
December 24, 2020

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

Trusted Platform Module Library

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,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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 37
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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_In
Rewrap_Out);(Rewrap_Entry)(
*in,
*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 = {Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 38
December 24, 2020

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

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

Trusted Platform Module Library&TPM2_Rewrap,(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_In
Import_Out);(Import_Entry)(
*in,
*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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 39
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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);
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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 40
December 24, 2020

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

/* offsets*//* types*/

Trusted Platform Module Library{(UINT16)(offsetof(RSA_Decrypt_In, cipherText)),(UINT16)(offsetof(RSA_Decrypt_In, inScheme)),(UINT16)(offsetof(RSA_Decrypt_In, label))},{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,
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
UINT16
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 41
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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;
UINT16
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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 42
December 24, 2020

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

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_ECC_Encrypt#include "ECC_Encrypt_fp.h"
typedef TPM_RC (ECC_Encrypt_Entry)(
ECC_Encrypt_In*in,
ECC_Encrypt_Out*out);
typedef const struct {ECC_Encrypt_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} ECC_Encrypt_COMMAND_DESCRIPTOR_t;
ECC_Encrypt_COMMAND_DESCRIPTOR_t _ECC_EncryptData = {/* entry*/&TPM2_ECC_Encrypt,/* inSize*/(UINT16)(sizeof(ECC_Encrypt_In)),/* outSize*/(UINT16)(sizeof(ECC_Encrypt_Out)),/* offsetOfTypes */offsetof(ECC_Encrypt_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ECC_Encrypt_In, plainText)),(UINT16)(offsetof(ECC_Encrypt_In, inScheme)),(UINT16)(offsetof(ECC_Encrypt_Out, C2)),(UINT16)(offsetof(ECC_Encrypt_Out, C3))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,
TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 43
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library
TPM2B_ECC_POINT_P_MARSHAL,TPM2B_MAX_BUFFER_P_MARSHAL,TPM2B_DIGEST_P_MARSHAL,END_OF_LIST}};#define _ECC_EncryptDataAddress (&_ECC_EncryptData)#else#define _ECC_EncryptDataAddress 0#endif // CC_ECC_Encrypt#if CC_ECC_Decrypt#include "ECC_Decrypt_fp.h"
typedef TPM_RC (ECC_Decrypt_Entry)(
ECC_Decrypt_In*in,
ECC_Decrypt_Out*out);
typedef const struct {ECC_Decrypt_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[4];BYTE
types[8];} ECC_Decrypt_COMMAND_DESCRIPTOR_t;
ECC_Decrypt_COMMAND_DESCRIPTOR_t _ECC_DecryptData = {/* entry*/&TPM2_ECC_Decrypt,/* inSize*/(UINT16)(sizeof(ECC_Decrypt_In)),/* outSize*/(UINT16)(sizeof(ECC_Decrypt_Out)),/* offsetOfTypes */offsetof(ECC_Decrypt_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ECC_Decrypt_In, C1)),(UINT16)(offsetof(ECC_Decrypt_In, C2)),(UINT16)(offsetof(ECC_Decrypt_In, C3)),(UINT16)(offsetof(ECC_Decrypt_In, inScheme))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_ECC_POINT_P_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,
TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG,END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,END_OF_LIST}};#define _ECC_DecryptDataAddress (&_ECC_DecryptData)#else#define _ECC_DecryptDataAddress 0#endif // CC_ECC_Decrypt#if CC_EncryptDecrypt#include "EncryptDecrypt_fp.h"
typedef TPM_RC (EncryptDecrypt_Entry)(
EncryptDecrypt_In*in,
EncryptDecrypt_Out*out);
typedef const struct {EncryptDecrypt_Entry
UINT16
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 44
December 24, 2020

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
1420

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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 45
December 24, 2020

Part 4: Supporting Routines
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
1484
1485
1486

Trusted Platform Module Library
TPM2B_IV_P_MARSHAL,END_OF_LIST}};#define _EncryptDecrypt2DataAddress (&_EncryptDecrypt2Data)#else#define _EncryptDecrypt2DataAddress 0#endif // CC_EncryptDecrypt2#if CC_Hash#include "Hash_fp.h"
typedef TPM_RC
Hash_In
Hash_Out);(Hash_Entry)(
*in,
*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_In
HMAC_Out);(HMAC_Entry)(
*in,
*out

typedef const struct {HMAC_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[2];BYTE
types[6];} HMAC_COMMAND_DESCRIPTOR_t;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 46
December 24, 2020

Part 4: Supporting Routines
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
1548
1549
1550
1551
1552

Trusted Platform Module Library

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#if CC_MAC#include "MAC_fp.h"
typedef TPM_RC
MAC_InMAC_Out);(MAC_Entry)(
*in,
*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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 47
December 24, 2020

Part 4: Supporting Routines
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
1614
1615
1616
1617
1618

Trusted Platform Module Library);
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 {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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 48
December 24, 2020

Part 4: Supporting Routines
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
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684

Trusted Platform Module Library);
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;
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 49
December 24, 2020

Part 4: Supporting Routines
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
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Trusted Platform Module Library#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,/* offsetOfTypes */offsetof(SequenceUpdate_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(SequenceUpdate_In, buffer))},/* types*/{TPMI_DH_OBJECT_H_UNMARSHAL,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 50
December 24, 2020

Part 4: Supporting Routines
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
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815

Trusted Platform Module Library
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 51
December 24, 2020

Part 4: Supporting Routines
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
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878

Trusted Platform Module Library

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),/* offsets*/{(UINT16)(offsetof(EventSequenceComplete_In,
sequenceHandle)),(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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 52
December 24, 2020

Part 4: Supporting Routines
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
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

Trusted Platform Module Library#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 = {/* entry*/&TPM2_CertifyCreation,/* inSize*/(UINT16)(sizeof(CertifyCreation_In)),/* outSize*/(UINT16)(sizeof(CertifyCreation_Out)),/* offsetOfTypes */offsetof(CertifyCreation_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(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))},/* types*/{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_In
Quote_Out);(Quote_Entry)(
*in,
*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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 53
December 24, 2020

Part 4: Supporting Routines
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
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

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

Trusted Platform Module Library(UINT16)(sizeof(Quote_Out)),
offsetof(Quote_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(Quote_In, qualifyingData)),(UINT16)(offsetof(Quote_In, inScheme)),(UINT16)(offsetof(Quote_In, PCRselect)),(UINT16)(offsetof(Quote_Out, signature))},{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);
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}};

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 54
December 24, 2020

Part 4: Supporting Routines
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
2059
2060
2061
2062
2063
2064
2065

Trusted Platform Module Library#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)),(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
UINT16
UINT16
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;offsetOfTypes;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 55
December 24, 2020

Part 4: Supporting Routines
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
2124
2125
2126
2127
2128
2129
2130
2131

Trusted Platform Module Library

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 = {/* entry*/&TPM2_CertifyX509,/* inSize*/(UINT16)(sizeof(CertifyX509_In)),/* outSize*/(UINT16)(sizeof(CertifyX509_Out)),/* offsetOfTypes */offsetof(CertifyX509_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(CertifyX509_In, signHandle)),(UINT16)(offsetof(CertifyX509_In, reserved)),(UINT16)(offsetof(CertifyX509_In, inScheme)),(UINT16)(offsetof(CertifyX509_In, partialCertificate)),(UINT16)(offsetof(CertifyX509_Out, tbsDigest)),(UINT16)(offsetof(CertifyX509_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,TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPM2B_MAX_BUFFER_P_MARSHAL,TPM2B_DIGEST_P_MARSHAL,
TPMT_SIGNATURE_P_MARSHAL,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 56
December 24, 2020

Part 4: Supporting Routines
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
2190
2191
2192
2193
2194
2195
2196
2197

Trusted Platform Module Library
END_OF_LIST}};#define _CertifyX509DataAddress (&_CertifyX509Data)#else#define _CertifyX509DataAddress 0#endif // CC_CertifyX509#if CC_Commit#include "Commit_fp.h"
typedef TPM_RC
Commit_In
Commit_Out);(Commit_Entry)(
*in,
*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#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
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 57
December 24, 2020

Part 4: Supporting Routines
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
2256
2257
2258
2259
2260
2261
2262
2263

Trusted Platform Module Library

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"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 58
December 24, 2020

Part 4: Supporting Routines
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
2322

typedef TPM_RC
Sign_In
Sign_Out);

Trusted Platform Module Library(Sign_Entry)(
*in,
*out

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)),

2323(UINT16)(offsetof(SetCommandCodeAuditStatus_In, setList)),2324(UINT16)(offsetof(SetCommandCodeAuditStatus_In, clearList))},Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 59
December 24, 2020

Part 4: Supporting Routines
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
2388
2389
2390

/* types

Trusted Platform Module Library*/{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#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 = {Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 60
December 24, 2020

Part 4: Supporting Routines
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
2451
2452
2453
2454
2455
2456

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

Trusted Platform Module Library&TPM2_PCR_Event,(UINT16)(sizeof(PCR_Event_In)),(UINT16)(sizeof(PCR_Event_Out)),
offsetof(PCR_Event_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(PCR_Event_In, eventData))},{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;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

Family “2.0”Level 00 Revision 01.64*entry;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 61
December 24, 2020

Part 4: Supporting Routines
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
2516
2517
2518
2519
2520
2521

Trusted Platform Module Library

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 {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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 62
December 24, 2020

Part 4: Supporting Routines
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
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587

Trusted Platform Module Library#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];} 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 63
December 24, 2020

Part 4: Supporting Routines
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
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653

Trusted Platform Module Library#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
UINT16
UINT16
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;offsetOfTypes;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 64
December 24, 2020

Part 4: Supporting Routines
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
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719

Trusted Platform Module Library

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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 65
December 24, 2020

Part 4: Supporting Routines
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
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785

Trusted Platform Module Library
END_OF_LIST}};#define _PolicyTicketDataAddress (&_PolicyTicketData)#else#define _PolicyTicketDataAddress 0#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))},Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 66
December 24, 2020

Part 4: Supporting Routines
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
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851

/* types*/

Trusted Platform Module Library{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;UINT16
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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 67
December 24, 2020

Part 4: Supporting Routines
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
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915

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

Trusted Platform Module Library0,
offsetof(PolicyNV_COMMAND_DESCRIPTOR_t, types),{(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))},{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;
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"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 68
December 24, 2020

Part 4: Supporting Routines
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
2972
2973
2974
2975
2976
2977
2978
2979

Trusted Platform Module Library

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;
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 69
December 24, 2020

Part 4: Supporting Routines
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
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045

Trusted Platform Module Library#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}};#define _PolicyNameHashDataAddress (&_PolicyNameHashData)#else#define _PolicyNameHashDataAddress 0#endif // CC_PolicyNameHash

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 70
December 24, 2020

Part 4: Supporting Routines
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
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107

Trusted Platform Module Library#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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 71
December 24, 2020

Part 4: Supporting Routines
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
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173

/* types*/

Trusted Platform Module Library(UINT16)(offsetof(PolicyAuthorize_In, keySign)),(UINT16)(offsetof(PolicyAuthorize_In, checkTicket))},{TPMI_SH_POLICY_H_UNMARSHAL,TPM2B_DIGEST_P_UNMARSHAL,TPM2B_NONCE_P_UNMARSHAL,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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 72
December 24, 2020

Part 4: Supporting Routines
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
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239

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

Trusted Platform Module Library(UINT16)(sizeof(PolicyPassword_In)),0,
offsetof(PolicyPassword_COMMAND_DESCRIPTOR_t, types),// No parameter offsets;{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);
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 = {Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 73
December 24, 2020

Part 4: Supporting Routines
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
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305

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

Trusted Platform Module Library&TPM2_PolicyNvWritten,(UINT16)(sizeof(PolicyNvWritten_In)),0,
offsetof(PolicyNvWritten_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(PolicyNvWritten_In, writtenSet))},{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,/* inSize*/(UINT16)(sizeof(PolicyTemplate_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(PolicyTemplate_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(PolicyTemplate_In, templateHash))},/* types*/{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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 74
December 24, 2020

Part 4: Supporting Routines
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
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369

Trusted Platform Module Library

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)),(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))},/* types*/{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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 75
December 24, 2020

Part 4: Supporting Routines
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
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435

Trusted Platform Module Library
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];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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 76
December 24, 2020

Part 4: Supporting Routines
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
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501

/* offsets*//* types*/

Trusted Platform Module Library{(UINT16)(offsetof(SetPrimaryPolicy_In, authPolicy)),(UINT16)(offsetof(SetPrimaryPolicy_In, hashAlg))},{TPMI_RH_HIERARCHY_POLICY_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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 77
December 24, 2020

Part 4: Supporting Routines
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
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567

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

Trusted Platform Module Libraryoffsetof(ChangeEPS_COMMAND_DESCRIPTOR_t, types),// No parameter offsets;{TPMI_RH_PLATFORM_H_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ChangeEPSDataAddress (&_ChangeEPSData)#else#define _ChangeEPSDataAddress 0#endif // CC_ChangeEPS#if CC_Clear#include "Clear_fp.h"
typedef TPM_RC
Clear_In);(Clear_Entry)(*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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 78
December 24, 2020

Part 4: Supporting Routines
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
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631

/* offsets/* types*/*/

Trusted Platform Module Library{(UINT16)(offsetof(ClearControl_In, disable))},{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;UINT16
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 79
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library/* 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,/* inSize*/(UINT16)(sizeof(DictionaryAttackParameters_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(DictionaryAttackParameters_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(DictionaryAttackParameters_In, newMaxTries)),

3669(UINT16)(offsetof(DictionaryAttackParameters_In, newRecoveryTime)),
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690

(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);Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 80
December 24, 2020

Part 4: Supporting Routines
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
3750
3751
3752
3753
3754
3755
3756

Trusted Platform Module Library

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 = {/* entry*/&TPM2_SetAlgorithmSet,/* inSize*/(UINT16)(sizeof(SetAlgorithmSet_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(SetAlgorithmSet_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(SetAlgorithmSet_In, algorithmSet))},/* types*/{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"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 81
December 24, 2020

Part 4: Supporting Routines
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
3816
3817
3818
3819
3820

Trusted Platform Module Library

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)),/* offsetOfTypes */offsetof(FieldUpgradeData_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(FieldUpgradeData_Out, firstDigest))},/* types*/{TPM2B_MAX_BUFFER_P_UNMARSHAL,END_OF_LIST,
TPMT_HA_P_MARSHAL,
TPMT_HA_P_MARSHAL,END_OF_LIST}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 82
December 24, 2020

Part 4: Supporting Routines
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
3882
3883
3884
3885
3886

Trusted Platform Module Library};#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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 83
December 24, 2020

Part 4: Supporting Routines
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
3947
3948
3949
3950
3951
3952

Trusted Platform Module Library
TPMS_CONTEXT_P_MARSHAL,END_OF_LIST}};#define _ContextSaveDataAddress (&_ContextSaveData)#else#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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 84
December 24, 2020

Part 4: Supporting Routines
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
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018

Trusted Platform Module Library
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;
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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 85
December 24, 2020

Part 4: Supporting Routines
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
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084

/* offsets/* types*/*/

Trusted Platform Module Library// No parameter offsets;{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,UINT64_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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 86
December 24, 2020

Part 4: Supporting Routines
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
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150

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

Trusted Platform Module Libraryoffsetof(ClockRateAdjust_COMMAND_DESCRIPTOR_t, types),{(UINT16)(offsetof(ClockRateAdjust_In, rateAdjust))},{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}};#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
UINT16
UINT16
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;outSize;offsetOfTypes;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 87
December 24, 2020

Part 4: Supporting Routines
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
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216

Trusted Platform Module Library

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 {NV_UndefineSpace_Entry
UINT16

Family “2.0”Level 00 Revision 01.64*entry;inSize;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 88
December 24, 2020

Part 4: Supporting Routines
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
4273
4274
4275
4276
4277
4278
4279
4280

Trusted Platform Module Library

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 89
December 24, 2020

Part 4: Supporting Routines
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
4339
4340
4341
4342
4343
4344
4345
4346

Trusted Platform Module Library);
typedef const struct {NV_ReadPublic_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[5];} NV_ReadPublic_COMMAND_DESCRIPTOR_t;
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 90
December 24, 2020

Part 4: Supporting Routines
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
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412

Trusted Platform Module Library#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),/* offsets*/{(UINT16)(offsetof(NV_Increment_In, nvIndex))},/* types*/{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}};

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 91
December 24, 2020

Part 4: Supporting Routines
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478

Trusted Platform Module Library#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}};#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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 92
December 24, 2020

Part 4: Supporting Routines
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543

Trusted Platform Module Library
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 {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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 93
December 24, 2020

Part 4: Supporting Routines
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609

/* types*/

Trusted Platform Module Library(UINT16)(offsetof(NV_Read_In, size)),(UINT16)(offsetof(NV_Read_In, offset))},{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];BYTE
types[4];} NV_ChangeAuth_COMMAND_DESCRIPTOR_t;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 94
December 24, 2020

Part 4: Supporting Routines
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675

Trusted Platform Module Library

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 95
December 24, 2020

Part 4: Supporting Routines
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740

Trusted Platform Module Library#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 {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)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 96
December 24, 2020

Part 4: Supporting Routines
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802

/* types*/

Trusted Platform Module Library(UINT16)(offsetof(AC_Send_In, acDataIn))},{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*in);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_ACT_SetTimeout#include "ACT_SetTimeout_fp.h"
typedef TPM_RC (ACT_SetTimeout_Entry)(
ACT_SetTimeout_In*in);Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 97
December 24, 2020

Part 4: Supporting Routines
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868

Trusted Platform Module Library

typedef const struct {ACT_SetTimeout_Entry*entry;UINT16
inSize;UINT16outSize;
UINT16
offsetOfTypes;
UINT16paramOffsets[1];BYTE
types[4];} ACT_SetTimeout_COMMAND_DESCRIPTOR_t;
ACT_SetTimeout_COMMAND_DESCRIPTOR_t _ACT_SetTimeoutData = {/* entry*/&TPM2_ACT_SetTimeout,/* inSize*/(UINT16)(sizeof(ACT_SetTimeout_In)),/* outSize*/
0,/* offsetOfTypes */offsetof(ACT_SetTimeout_COMMAND_DESCRIPTOR_t, types),/* offsets*/{(UINT16)(offsetof(ACT_SetTimeout_In, startTimeout))},/* types*/{TPMI_RH_ACT_H_UNMARSHAL,UINT32_P_UNMARSHAL,END_OF_LIST,END_OF_LIST}};#define _ACT_SetTimeoutDataAddress (&_ACT_SetTimeoutData)#else#define _ACT_SetTimeoutDataAddress 0#endif // CC_ACT_SetTimeout#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#if (PAD_LIST || CC_EvictControl)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 98
December 24, 2020

Part 4: Supporting Routines
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934

Trusted Platform Module Library(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#if (PAD_LIST || CC_NV_Extend)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 99
December 24, 2020

Part 4: Supporting Routines
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000

Trusted Platform Module Library(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#if (PAD_LIST || CC_GetTime)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 100
December 24, 2020

Part 4: Supporting Routines
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066

Trusted Platform Module Library(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,#endif // CC_SequenceUpdate

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 101
December 24, 2020

Part 4: Supporting Routines
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132

Trusted Platform Module Library#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,#endif // CC_PolicyTicket

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 102
December 24, 2020

Part 4: Supporting Routines
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198

Trusted Platform Module Library#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,#endif // CC_PolicyDuplicationSelectFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 103
December 24, 2020

Part 4: Supporting Routines
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259

Trusted Platform Module Library#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_ACT_SetTimeout)(COMMAND_DESCRIPTOR_t *)_ACT_SetTimeoutDataAddress,#endif // CC_ACT_SetTimeout#if (PAD_LIST || CC_ECC_Encrypt)(COMMAND_DESCRIPTOR_t *)_ECC_EncryptDataAddress,#endif // CC_ECC_Encrypt#if (PAD_LIST || CC_ECC_Decrypt)(COMMAND_DESCRIPTOR_t *)_ECC_DecryptDataAddress,#endif // CC_ECC_Decrypt#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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 104
December 24, 2020

Part 4: Supporting Routines

5.7
1
2

Trusted Platform Module Library

Commands.h#ifndef _COMMANDS_H_#define _COMMANDS_H_

Start-up
3
4
5
6
7
8

#if CC_Startup#include "Startup_fp.h"#endif#if CC_Shutdown#include "Shutdown_fp.h"#endifTesting
9
10
11
12
13
14
15
16
17

#if CC_SelfTest#include "SelfTest_fp.h"#endif#if CC_IncrementalSelfTest#include "IncrementalSelfTest_fp.h"#endif#if CC_GetTestResult#include "GetTestResult_fp.h"#endifSession Commands
18
19
20
21
22
23

#if CC_StartAuthSession#include "StartAuthSession_fp.h"#endif#if 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

#if CC_Create#include "Create_fp.h"#endif#if CC_Load#include "Load_fp.h"#endif#if CC_LoadExternal#include "LoadExternal_fp.h"#endif#if CC_ReadPublic#include "ReadPublic_fp.h"#endif#if CC_ActivateCredential#include "ActivateCredential_fp.h"#endif#if CC_MakeCredential#include "MakeCredential_fp.h"#endif#if CC_Unseal#include "Unseal_fp.h"#endif#if CC_ObjectChangeAuth#include "ObjectChangeAuth_fp.h"#endif#if CC_CreateLoaded#include "CreateLoaded_fp.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 105
December 24, 2020

Part 4: Supporting Routines
50

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

#if CC_Duplicate#include "Duplicate_fp.h"#endif#if CC_Rewrap#include "Rewrap_fp.h"#endif#if 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
78
79
80
81
82
83

#if CC_RSA_Encrypt#include "RSA_Encrypt_fp.h"#endif#if CC_RSA_Decrypt#include "RSA_Decrypt_fp.h"#endif#if CC_ECDH_KeyGen#include "ECDH_KeyGen_fp.h"#endif#if CC_ECDH_ZGen#include "ECDH_ZGen_fp.h"#endif#if CC_ECC_Parameters#include "ECC_Parameters_fp.h"#endif#if CC_ZGen_2Phase#include "ZGen_2Phase_fp.h"#endif#if CC_ECC_Encrypt#include "ECC_Encrypt_fp.h"#endif#if CC_ECC_Decrypt#include "ECC_Decrypt_fp.h"#endifSymmetric Primitives
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

#if CC_EncryptDecrypt#include "EncryptDecrypt_fp.h"#endif#if CC_EncryptDecrypt2#include "EncryptDecrypt2_fp.h"#endif#if CC_Hash#include "Hash_fp.h"#endif#if CC_HMAC#include "HMAC_fp.h"#endif#if CC_MAC#include "MAC_fp.h"#endifRandom Number Generator
99
100
101

#if CC_GetRandom#include "GetRandom_fp.h"#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 106
December 24, 2020

Part 4: Supporting Routines
102
103
104

Trusted Platform Module Library#if CC_StirRandom#include "StirRandom_fp.h"#endifHash/HMAC/Event Sequences
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

#if CC_HMAC_Start#include "HMAC_Start_fp.h"#endif#if CC_MAC_Start#include "MAC_Start_fp.h"#endif#if CC_HashSequenceStart#include "HashSequenceStart_fp.h"#endif#if CC_SequenceUpdate#include "SequenceUpdate_fp.h"#endif#if CC_SequenceComplete#include "SequenceComplete_fp.h"#endif#if CC_EventSequenceComplete#include "EventSequenceComplete_fp.h"#endif

Attestation Commands
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

#if CC_Certify#include "Certify_fp.h"#endif#if CC_CertifyCreation#include "CertifyCreation_fp.h"#endif#if CC_Quote#include "Quote_fp.h"#endif#if CC_GetSessionAuditDigest#include "GetSessionAuditDigest_fp.h"#endif#if CC_GetCommandAuditDigest#include "GetCommandAuditDigest_fp.h"#endif#if CC_GetTime#include "GetTime_fp.h"#endif#if CC_CertifyX509#include "CertifyX509_fp.h"#endifEphemeral EC Keys
144
145
146
147
148
149

#if CC_Commit#include "Commit_fp.h"#endif#if CC_EC_Ephemeral#include "EC_Ephemeral_fp.h"#endifSigning and Signature Verification
150
151
152
153

#if CC_VerifySignature#include "VerifySignature_fp.h"#endif#if CC_Sign

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 107
December 24, 2020

Part 4: Supporting Routines
154
155

Trusted Platform Module Library#include "Sign_fp.h"#endifCommand Audit
156
157
158

#if CC_SetCommandCodeAuditStatus#include "SetCommandCodeAuditStatus_fp.h"#endifIntegrity Collection (PCR)
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

#if CC_PCR_Extend#include "PCR_Extend_fp.h"#endif#if CC_PCR_Event#include "PCR_Event_fp.h"#endif#if CC_PCR_Read#include "PCR_Read_fp.h"#endif#if CC_PCR_Allocate#include "PCR_Allocate_fp.h"#endif#if CC_PCR_SetAuthPolicy#include "PCR_SetAuthPolicy_fp.h"#endif#if CC_PCR_SetAuthValue#include "PCR_SetAuthValue_fp.h"#endif#if CC_PCR_Reset#include "PCR_Reset_fp.h"#endifEnhanced Authorization (EA) Commands
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

#if CC_PolicySigned#include "PolicySigned_fp.h"#endif#if CC_PolicySecret#include "PolicySecret_fp.h"#endif#if CC_PolicyTicket#include "PolicyTicket_fp.h"#endif#if CC_PolicyOR#include "PolicyOR_fp.h"#endif#if CC_PolicyPCR#include "PolicyPCR_fp.h"#endif#if CC_PolicyLocality#include "PolicyLocality_fp.h"#endif#if CC_PolicyNV#include "PolicyNV_fp.h"#endif#if CC_PolicyCounterTimer#include "PolicyCounterTimer_fp.h"#endif#if CC_PolicyCommandCode#include "PolicyCommandCode_fp.h"#endif#if CC_PolicyPhysicalPresence#include "PolicyPhysicalPresence_fp.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 108
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#endif#if CC_PolicyCpHash#include "PolicyCpHash_fp.h"#endif#if CC_PolicyNameHash#include "PolicyNameHash_fp.h"#endif#if CC_PolicyDuplicationSelect#include "PolicyDuplicationSelect_fp.h"#endif#if CC_PolicyAuthorize#include "PolicyAuthorize_fp.h"#endif#if CC_PolicyAuthValue#include "PolicyAuthValue_fp.h"#endif#if CC_PolicyPassword#include "PolicyPassword_fp.h"#endif#if CC_PolicyGetDigest#include "PolicyGetDigest_fp.h"#endif#if CC_PolicyNvWritten#include "PolicyNvWritten_fp.h"#endif#if CC_PolicyTemplate#include "PolicyTemplate_fp.h"#endif#if CC_PolicyAuthorizeNV#include "PolicyAuthorizeNV_fp.h"#endif

Hierarchy Commands
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

#if CC_CreatePrimary#include "CreatePrimary_fp.h"#endif#if CC_HierarchyControl#include "HierarchyControl_fp.h"#endif#if CC_SetPrimaryPolicy#include "SetPrimaryPolicy_fp.h"#endif#if CC_ChangePPS#include "ChangePPS_fp.h"#endif#if CC_ChangeEPS#include "ChangeEPS_fp.h"#endif#if CC_Clear#include "Clear_fp.h"#endif#if CC_ClearControl#include "ClearControl_fp.h"#endif#if CC_HierarchyChangeAuth#include "HierarchyChangeAuth_fp.h"#endifDictionary Attack Functions
264
265
266
267

#if CC_DictionaryAttackLockReset#include "DictionaryAttackLockReset_fp.h"#endif#if CC_DictionaryAttackParameters

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 109
December 24, 2020

Part 4: Supporting Routines
268
269

Trusted Platform Module Library#include "DictionaryAttackParameters_fp.h"#endifMiscellaneous Management Functions
270
271
272
273
274
275

#if CC_PP_Commands#include "PP_Commands_fp.h"#endif#if CC_SetAlgorithmSet#include "SetAlgorithmSet_fp.h"#endifField Upgrade
276
277
278
279
280
281
282
283
284

#if CC_FieldUpgradeStart#include "FieldUpgradeStart_fp.h"#endif#if CC_FieldUpgradeData#include "FieldUpgradeData_fp.h"#endif#if CC_FirmwareRead#include "FirmwareRead_fp.h"#endifContext Management
285
286
287
288
289
290
291
292
293
294
295
296

#if CC_ContextSave#include "ContextSave_fp.h"#endif#if CC_ContextLoad#include "ContextLoad_fp.h"#endif#if CC_FlushContext#include "FlushContext_fp.h"#endif#if CC_EvictControl#include "EvictControl_fp.h"#endifClocks and Timers
297
298
299
300
301
302
303
304
305

#if CC_ReadClock#include "ReadClock_fp.h"#endif#if CC_ClockSet#include "ClockSet_fp.h"#endif#if CC_ClockRateAdjust#include "ClockRateAdjust_fp.h"#endifCapability Commands
306
307
308
309
310
311

#if CC_GetCapability#include "GetCapability_fp.h"#endif#if CC_TestParms#include "TestParms_fp.h"#endifNon-volatile Storage
312#if CC_NV_DefineSpace

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 110
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#include "NV_DefineSpace_fp.h"#endif#if CC_NV_UndefineSpace#include "NV_UndefineSpace_fp.h"#endif#if CC_NV_UndefineSpaceSpecial#include "NV_UndefineSpaceSpecial_fp.h"#endif#if CC_NV_ReadPublic#include "NV_ReadPublic_fp.h"#endif#if CC_NV_Write#include "NV_Write_fp.h"#endif#if CC_NV_Increment#include "NV_Increment_fp.h"#endif#if CC_NV_Extend#include "NV_Extend_fp.h"#endif#if CC_NV_SetBits#include "NV_SetBits_fp.h"#endif#if CC_NV_WriteLock#include "NV_WriteLock_fp.h"#endif#if CC_NV_GlobalWriteLock#include "NV_GlobalWriteLock_fp.h"#endif#if CC_NV_Read#include "NV_Read_fp.h"#endif#if CC_NV_ReadLock#include "NV_ReadLock_fp.h"#endif#if CC_NV_ChangeAuth#include "NV_ChangeAuth_fp.h"#endif#if CC_NV_Certify#include "NV_Certify_fp.h"#endifAttached Components
354
355
356
357
358
359
360
361
362

#if CC_AC_GetCapability#include "AC_GetCapability_fp.h"#endif#if CC_AC_Send#include "AC_Send_fp.h"#endif#if CC_Policy_AC_SendSelect#include "Policy_AC_SendSelect_fp.h"#endifAuthenticated Countdown Timer
363
364
365

#if CC_ACT_SetTimeout#include "ACT_SetTimeout_fp.h"#endifVendor Specific366
367#if CC_Vendor_TCG_Test#include "Vendor_TCG_Test_fp.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 111
December 24, 2020

Part 4: Supporting Routines
368
369
370

Trusted Platform Module Library#endif#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 112
December 24, 2020

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
8
9

#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
10
11
12

#
#
#

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)13
14//#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.
15
16

#
#

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.
17
18
19
20
21
22
23
24
25
26
27
28

#
#
#
#

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
29
30#
define _REDUCE_WARNING_LEVEL_(n)__pragma(warning(push, n))\

Restore the compiler warning level
31
32
33

#
define _NORMAL_WARNING_LEVEL___pragma(warning(pop))#
include <stdint.h>

Family “2.0”Level 00 Revision 01.64\

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 113
December 24, 2020

Part 4: Supporting Routines
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

Trusted Platform Module Library#endif#ifndef _MSC_VER#ifndef WINAPI#
define WINAPI#endif#define __pragma(x)#define REVERSE_ENDIAN_16(_Number) __builtin_bswap16(_Number)#define REVERSE_ENDIAN_32(_Number) __builtin_bswap32(_Number)#define REVERSE_ENDIAN_64(_Number) __builtin_bswap64(_Number)#endif#if defined(__GNUC__)#
define NORETURN#
include <stdint.h>#endif__attribute__((noreturn))

Things that are not defined should be defined as NULL
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

#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_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 114
December 24, 2020

Part 4: Supporting Routines

5.9

Trusted Platform Module Library

Global.h

5.9.1

Description

This file contains internal global type definitions and data declarations that are need between
subsystems. The instantiation of global data is in Global.c. The initialization of global data is in 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

Includes#ifndef#define

GLOBAL_H
GLOBAL_H_REDUCE_WARNING_LEVEL_(2)#include <string.h>#include <stddef.h>_NORMAL_WARNING_LEVEL_#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"#include "ACT.h"

5.9.3
5.9.3.1

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)
26

typedef UINT16

5.9.3.2

NUMBYTES;

Other Types

An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA)
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 115
December 24, 2020

Part 4: Supporting Routines
27

typedef BYTE

Trusted Platform Module Library

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

typedef BYTE

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

typedef BYTE

NAME[sizeof(TPMU_NAME)];

Definition for a PROOF value30

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

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.
32
33
34
35
36

#if CLOCK_STOPS
typedef UINT64#else
typedef UINT32#endif

5.9.4
5.9.4.1

CLOCK_NONCE;
CLOCK_NONCE;

Loaded Object Structures
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.4.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.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

typedef struct{unsignedpublicOnly : 1;

unsigned

epsHierarchy : 1;

unsigned

ppsHierarchy : 1;

unsigned

spsHierarchy : 1;

unsigned

evict : 1;

Family “2.0”Level 00 Revision 01.64//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-2021

Page 116
December 24, 2020

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

//
//

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.
81
82#define#endif

RSA_prime_flag

5.9.4.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.
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 117
December 24, 2020

Part 4: Supporting Routines

5.9.4.4

Trusted Platform Module Library

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

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

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

5.9.4.5

HASH_OBJECT_BUFFER[sizeof(HASH_OBJECT)];ANY_OBJECTThis is the union for holding either a sequence object or a regular object for ContextSave() andContextLoad().
115
116
117
118
119
120
121

typedef union ANY_OBJECT{OBJECT
entity;
HASH_OBJECT
hash;} ANY_OBJECT;
typedef BYTE

5.9.5

ANY_OBJECT_BUFFER[sizeof(ANY_OBJECT)];

AUTH_DUP Types

These values are used in the authorization processing.
122
123
124
125
126

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

5.9.6
5.9.6.1

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

Active Session Context
Description

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 118
December 24, 2020

Part 4: Supporting Routines

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

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.
//4) 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.6.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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 119
December 24, 2020

Part 4: Supporting Routines

NOTE

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

Trusted Platform Module Library

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

typedef struct SESSION{SESSION_ATTRIBUTESUINT32attributes;
pcrCounter;

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;// 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

union{
TPM2B_NAME

boundEntity;// value used to track the entity to// which the session is bound

TPM2B_DIGEST

cpHash;// the required cpHash value for the// command being authorized// the required nameHash// the required template for creation

TPM2B_DIGESTTPM2B_DIGEST} u1;

nameHash;templateHash;

union{
TPM2B_DIGESTTPM2B_DIGEST} u2;

auditDigest;policyDigest;// audit session digest// policyHash// audit log and policyHash may// share space to save memory} SESSION;#define#define#define#define

EXPIRES_ON_RESETTIMEOUT_ON_RESET
EXPIRES_ON_RESTARTTIMEOUT_ON_RESTART

typedef BYTE

5.9.7
5.9.7.1

INT32_MIN
UINT64_MAX(INT32_MIN + 1)
(UINT64_MAX - 1)

SESSION_BUF[sizeof(SESSION)];

PCR
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.
227#define PCR_SAVE_SPACE(HASH, Hash)

Family “2.0”Level 00 Revision 01.64

BYTE Hash[NUM_STATIC_PCR][HASH##_DIGEST_SIZE];TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 120
December 24, 2020

Part 4: Supporting Routines
228
229
230
231
232
233
234
235
236
237
238

typedef struct PCR_SAVE{
FOR_EACH_HASH(PCR_SAVE_SPACE)// 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.7.2
239

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.
240
241
242
243
244
245
246

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

PCR_AUTHVALUEThis structure holds the PCR policies, one for each group of PCR controlled by policy.
247
248
249
250

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

5.9.8

STARTUP_TYPE

This enumeration is the possible startup types. The type is determined by the combination of
TPM2_ShutDown() and TPM2_Startup.
251
252
253
254
255
256

typedef enum{
SU_RESET,
SU_RESTART,
SU_RESUME} STARTUP_TYPE;

5.9.9
5.9.9.1

NV
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.
257
258
259
260
261

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 121
December 24, 2020

Part 4: Supporting Routines

5.9.9.2

Trusted Platform Module Library

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.
262
263
264

typedef UINT32

NV_REF;

typedef BYTE

*NV_RAM_REF;

5.9.9.3

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.
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

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

5.9.10

intVal;pin;

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

#if

ALG_ECC#define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1))#endif

5.9.11
5.9.11.1

RAM Global Values
Description

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 122
December 24, 2020

Part 4: Supporting Routines

5.9.11.2
289
290

Crypto Self-Test Values

EXTERN ALGORITHM_VECTOR
EXTERN ALGORITHM_VECTOR

5.9.11.3

Trusted Platform Module Libraryg_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.
291
292
293
294
295

#define g_rcIndexInitializer {EXTERN const UINT16

5.9.11.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.
296

EXTERN TPM_HANDLE

5.9.11.5g_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.
297

EXTERN

5.9.11.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.
298
299
300
301
302

#if CLOCK_STOPSEXTERN CLOCK_NONCE#else#define g_timeEpoch#endif

5.9.11.7

g_timeEpoch;
gp.timeEpochg_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.
303

EXTERN BOOL

Family “2.0”Level 00 Revision 01.64

g_phEnable;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 123
December 24, 2020

Part 4: Supporting Routines

5.9.11.8

Trusted Platform Module Libraryg_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).
304

EXTERN BOOL

5.9.11.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.
305

EXTERN TPMI_DH_OBJECT

g_DRTMHandle;

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

EXTERNBOOL

g_DrtmPreStartup;

5.9.11.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.
307

EXTERN

BOOL

g_StartupLocality3;

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

308
309

This is a reserved value.

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

5.9.11.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.
310
311#define SU_DA_USED_VALUE#define TPM_SU_DA_USED(SU_NONE_VALUE - 1)
(TPM_SU)(SU_DA_USED_VALUE)

5.9.11.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 indicates
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 124
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Librarythat the last TPM2_Startup() was received at locality 3. These flags are only
TPM2_Shutdown(STATE).
312
313
314
315

#define PRE_STARTUP_FLAG#define STARTUP_LOCALITY_3

relevant if after a

0x80000x4000#if USE_DA_USED

5.9.11.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 gp.orderly is set to SU_NONE_VALUE
316
317

EXTERN#endifBOOL

g_daUsed;

5.9.11.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.
318
319
320
321
322

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

323

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.11.18 g_clearOrderlyThis flag indicates if the execution of a command should cause the orderly state to be cleared. This flagis 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.
324

EXTERN BOOL

Family “2.0”Level 00 Revision 01.64

g_clearOrderly;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 125
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

5.9.11.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.
325

EXTERN TPM_SU

g_prevOrderlyState;

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

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
327

EXTERN TPM_RC

g_NvStatus;

5.9.11.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.
328
329
330

EXTERN TPM2B_AUTH

g_platformUniqueAuthorities; // Reserved for RNG

EXTERN TPM2B_AUTH

g_platformUniqueDetails;

5.9.12
5.9.12.1// referenced by VENDOR_PERMANENT

Persistent Global Values
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.12.2

PERSISTENT_DATA

This structure holds the persistent values that only change as a consequence of a specific Protected
Capability and are not affected by TPM power events (TPM2_Startup() or TPM2_Shutdown().
331
332
333
334
335
336
337
338

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

Family “2.0”Level 00 Revision 01.64

disableClear;// TRUE if TPM2_Clear() using

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 126
December 24, 2020

Part 4: Supporting Routines
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
393
394
395
396
397
398
399
400
401
402
403
404

Trusted Platform Module Library// lockoutAuth is disabled// 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().

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 127
December 24, 2020

Part 4: Supporting Routines
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
463
464
465
466
467
468
469
470

BYTE

Trusted Platform Module LibraryppList[(COMMAND_COUNT + 7) / 8];//*********************************************************************************//
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//*****************************************************************************

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 128
December 24, 2020

Part 4: Supporting Routines
471
472
473
474
475
476
477
478
479
480

Trusted Platform Module Library// timeEpoch contains a nonce that has a vendor=specific size (should not be// 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.12.3

gp;

ORDERLY_DATA

The data in this structure is saved to NV on each TPM2_Shutdown().
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

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// These are the ACT Timeout values. They are saved with the other timers#define DefineActData(N) ACT_STATE
ACT_##N;
FOR_EACH_ACT(DefineActData)// this is the 'signaled' attribute data for all the ACT. It is done this way so// that they can be manipulated by ACT number rather than having to access a// structure.
UINT16signaledACT;UINT16preservedSignaled;} ORDERLY_DATA;#if ACCUMULATE_SELF_HEAL_TIMER#defines_selfHealTimergo.selfHealTimer#defines_lockoutTimergo.lockoutTimer#endif // ACCUMULATE_SELF_HEAL_TIMER

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 129
December 24, 2020

Part 4: Supporting Routines
530
531
532

#

Trusted Platform Module Librarydefine drbgDefault go.drbgState

EXTERN ORDERLY_DATA

5.9.12.4

go;

STATE_CLEAR_DATA

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

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;//*****************************************************************************//
ACT//*****************************************************************************#define DefineActPolicySpace(N)TPMT_HA
act_##N;
FOR_EACH_ACT(DefineActPolicySpace)} STATE_CLEAR_DATA;EXTERN STATE_CLEAR_DATA gc;

5.9.12.5

State Reset Data

This structure contains data is that is saved on Shutdown(STATE) and restored on the subsequent
Startup(ANY). That is, the data is preserved across TPM Resume and TPM Restart.
If a default value is specified in the comments this value is applied on TPM Reset.
567
568
569
570
571
572
573
574
575
576

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

Family “2.0”Level 00 Revision 01.64

nullSeed;// The seed value for the TPM_RN_NULL

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 130
December 24, 2020

Part 4: Supporting Routines
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
631
632
633
634
635
636
637
638
639
640
641
642

Trusted Platform Module Library// 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
CONTEXT_SLOTCONTEXT_COUNTER

objectContextID;// This is the context ID for a saved// object context. The default reset// value is 0.
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}.
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 131
December 24, 2020

Part 4: Supporting Routines
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

Trusted Platform Module Library// 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;

5.9.13

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
659
660
661
662
663
664
665

#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.14Global Macro Definitions

The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members of
the PERSISTENT_DATA structure in NV.
666
667
668
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

typedef UINT16
COMMAND_INDEX;#define UNIMPLEMENTED_COMMAND_INDEX((COMMAND_INDEX)(~0))

typedef struct _COMMAND_FLAGS_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 132
December 24, 2020

Part 4: Supporting Routines
680
681
682
683
684
685

Trusted Platform Module Library{
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.
The following macros are used to define the space for the CP and RP hashes. Space, is provided foreach implemented hash algorithm because it is not known what the caller may use.
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

#define CP_HASH(HASH, Hash)#define RP_HASH(HASH, Hash)

TPM2B_##HASH##_DIGESTTPM2B_##HASH##_DIGEST

Hash##CpHash;
Hash##RpHash;

typedef struct COMMAND{
TPM_STtag;
TPM_CC
code;
COMMAND_INDEX
index;UINT32handleNum;// the parsed command tag// the parsed command code// the computed command index// the number of entity handles in the//handle area of the command
TPM_HANDLE
handles[MAX_HANDLE_NUM]; // the parsed handle values
UINT32
sessionNum;// the number of sessions found
INT32
parameterSize;// starts out with the parsed command size// and is reduced and values are// 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.
INT32
authSize;// this is initialized with the parsed size// of authorizationSize field and should// be zero when the authorizations are// parsed.
BYTE*parameterBuffer;// input to ExecuteCommand
BYTE*responseBuffer;// input to ExecuteCommand
FOR_EACH_HASH(CP_HASH)// space for the CP hashes
FOR_EACH_HASH(RP_HASH)// space for the RP hashes} COMMAND;

Global string constants for consistency in KDF function calls. These string constants are shared acrossfunctions to make sure that they are all using consistent string values.
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

#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");

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 133
December 24, 2020

Part 4: Supporting Routines
734
735
736
737
738
739
740

Trusted Platform Module Library

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

5.9.15

From CryptTest.c

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

EXTERN CRYPTO_SELF_TEST_STATE

5.9.16742

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

EXTERN BOOL

5.9.175.9.17.1744

g_initialized;

Private data
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
745

EXTERN TPM_HANDLEs_sessionHandles[MAX_SESSION_NUM];

Array of authorization session attributes
746

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
747

EXTERN TPM_HANDLEs_associatedHandles[MAX_SESSION_NUM];

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

EXTERN TPM2B_NONCE

s_nonceCaller[MAX_SESSION_NUM];

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

EXTERN TPM2B_AUTH

s_inputAuthValues[MAX_SESSION_NUM];

Array of pointers to the SESSION structures for the sessions in a command
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 134
December 24, 2020

Part 4: Supporting Routines
750

EXTERN SESSION

Trusted Platform Module Library*s_usedSessions[MAX_SESSION_NUM];

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

Index of the session used for encryption of a response parameter
752

EXTERN UINT32

s_encryptSessionIndex;

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

EXTERN UINT32

s_decryptSessionIndex;

Index of a session used for audit
754

EXTERN UINT32

s_auditSessionIndex;

The cpHash for command audit
755
756
757

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

EXTERN BOOL

#endif // SESSION_PROCESS_C

5.9.17.2761

s_DAPendingOnNV;

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.
762
763#if !ACCUMULATE_SELF_HEAL_TIMER
EXTERN UINT64
s_selfHealTimer;This variable holds the accumulated time that the lockoutAuth has been blocked.
764
765
766
767

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

5.9.17.3
768

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

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

EXTERN BYTE

s_indexOrderlyRam[RAM_INDEX_SPACE];

Family “2.0”Level 00 Revision 01.64// The orderly NV Index data

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 135
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryThis 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.
771

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,s_lastNvIndex will contain the index header information. It will have been loaded when the handles wereverified.
NOTE

772
773
774

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

EXTERNEXTERNEXTERN

NV_INDEX
NV_REF
BYTE

s_cachedNvIndex;
s_cachedNvRef;*s_cachedNvRamRef;

Initial NV Index/evict object iterator value
775
776
777

#define(NV_REF)0xFFFFFFFF#endif

5.9.17.4
778

NV_REF_INIT

From Object.c#if defined OBJECT_C || defined GLOBAL_C

This type is the container for an object.
779
780
781

EXTERN OBJECT#endif // OBJECT_C

5.9.17.5
782

s_objects[MAX_LOADED_OBJECTS];

From PCR.c#if defined PCR_C || defined GLOBAL_C

The following macro is used to define the per-implemented-hash space. This implementation reserves
space for all implemented hashes.
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798

#define PCR_ALL_HASH(HASH, Hash)

BYTE

Hash##Pcr[HASH##_DIGEST_SIZE];

typedef struct{
FOR_EACH_HASH(PCR_ALL_HASH)} PCR;
typedef struct{unsigned int

stateSave : 1;

unsigned int

resetLocality : 5;

unsigned int

extendLocality : 5;// 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} PCR_Attributes;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 136
December 24, 2020

Part 4: Supporting Routines
799
800
801
802

EXTERN PCR

s_pcrs[IMPLEMENTATION_PCR];#endif // PCR_C

5.9.17.6
803

Trusted Platform Module Library

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

Container for HMAC or policy session tracking information
804
805
806
807
808
809
810

typedef struct{
BOOL
SESSION} SESSION_SLOT;

occupied;session;

EXTERN SESSION_SLOT// 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.
811

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)
812
813
814

EXTERN int#endif // SESSION_C

5.9.17.7815

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.
816
817
818
819

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.17.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 is not useful for anything other than helping the vendor to know in which filethe failure occurred.
820
821
822
823
824
825

EXTERN BOOL
#if SIMULATIONEXTERN BOOL
#endifg_inFailureMode;// Indicates that the TPM is in failure mode

g_forceFailureMode;// flag to force failure mode during test

typedef void(FailFunction)(const char *function, int line, int code);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 137
December 24, 2020

Part 4: Supporting Routines
826
827
828
829
830
831
832
833
834
835

Trusted Platform Module Library#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;#endif // TPM_FAIL_C

5.9.17.9

From ACT_spt.c

This value is used to indicate if an ACT has been updated since the last TPM2_Startup() (one bit for eachACT). If the ACT is not updated (TPM2_ACT_SetTimeout()) after a startup, then on each
TPM2_Shutdown() the TPM will save 1/2 of the current timer value. This prevents an attack on the ACT
by saving the counter and then running for a long period of time before doing a TPM Restart. A quick
TPM2_Shutdown() after each
836

EXTERN UINT16

s_ActUpdated;

5.9.17.10 From CommandCodeAttributes.c
This array is instanced in CommandCodeAttributes.c when it includes CommandCodeAttributes.h. Don'tchange the extern to EXTERN.
837
838
839
840

externextern

const
const

TPMA_CCCOMMAND_ATTRIBUTES

s_ccAttr[];s_commandAttributes[];#endif // GLOBAL_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 138
December 24, 2020

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
8
9

#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.
10
11#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.
12
13
14
15
16
17
18
19

#

define

\
\
\

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

5.10.3
20
21
22
23
24
25
26
27
28
29
30
31
32

TEST_HASH(alg)if(TEST_BIT(alg, g_toTest)&& (alg != TPM_ALG_NULL))
CryptTestAlgorithm(alg, NULL)For Failures#if defined _POSIX_#
define FUNCTION_NAME#else#
define FUNCTION_NAME#endif0__FUNCTION__#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.
33
34
35
36
37

#ifndef NO_LONGJMP#
define FAIL_RETURN(returnCode)#define TPM_FAIL_RETURNNORETURN void#else#
define FAIL_RETURN(returnCode) return (returnCode)Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 139
December 24, 2020

Part 4: Supporting Routines
38
39#
define TPM_FAIL_RETURN#endifTrusted Platform Module Libraryvoid

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.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

#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 TpmProfile.h
56
57
58
59
60

#define PCR_SELECT_MIN#define PCR_SELECT_MAX#define MAX_ORDERLY_COUNT#define RSA_MAX_PRIME#define RSA_PRIVATE_SIZE

5.10.5((PLATFORM_PCR+7)/8)((IMPLEMENTATION_PCR+7)/8)((1 << ORDERLY_BITS) - 1)
(MAX_RSA_KEY_BYTES / 2)
(RSA_MAX_PRIME * 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 is not 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
61
62
63
64
65

#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.
66
67
68
69
70
71
72

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

\
\
\
\

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 140
December 24, 2020

Part 4: Supporting Routines
73
74
75
76
77
78
79
80
81
82
83

Trusted Platform Module Library#endif#ifndef MIN# define MIN(a, b) ((a) < (b) ? (a) : (b))#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.
84
85
86

#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)
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

#ifndef LIB_EXPORT#
define LIB_EXPORT#
define LIB_IMPORT#endif#ifndef NORETURN#
define NORETURN _Noreturn#endif#ifndef NOT_REFERENCED#
define NOT_REFERENCED(x = x)
#endif((void) (x))#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.
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

#ifndef CONTEXT_HASH_ALGORITHM#
if defined ALG_SHA3_512 && ALG_SHA3_512 == YES#
define CONTEXT_HASH_ALGORITHM
SHA3_512#
elif defined ALG_SHA512 && ALG_SHA512 == YES#
define CONTEXT_HASH_ALGORITHM
SHA512#elif defined ALG_SHA3_384 && ALG_SHA3_384 == YES#
define CONTEXT_HASH_ALGORITHM
SHA3_384#
elif defined ALG_SHA384 && ALG_SHA384 == YES#
define CONTEXT_HASH_ALGORITHM
SHA384#elif defined ALG_SHA3_256 && ALG_SHA3_256 == YES#
define CONTEXT_HASH_ALGORITHM
SHA3_256#
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_SIZEFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 141
December 24, 2020

Part 4: Supporting Routines
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

Trusted Platform Module Library#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 :(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...
150
151
152
153
154
155

#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 followed156#define PROOF_SIZECONTEXT_INTEGRITY_HASH_SIZE

As required by P1.14.4
157
158#define COMPLIANT_PROOF_SIZE(MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES)))\As required by P1.14.3.1
159
160#define COMPLIANT_PRIMARY_SEED_SIZE
BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2)\This is the pre-errata version
161
162
163
164
165
166
167
168
169
170
171
172
173

#ifndef PRIMARY_SEED_SIZE#
define PRIMARY_SEED_SIZE#endifPROOF_SIZE#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_SIZEFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 142
December 24, 2020

Part 4: Supporting Routines
174
175
176
177
178
179

Trusted Platform Module Library#error "PROOF_SIZE is not compliant with TPM specification"
#
endif
#
if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE#
error 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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

#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_ALGORITHMCAMELLIA#
elif CONTEXT_ENCRYPT_ALG == ALG_TDES_VALUE#
error Are you kidding?
#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.
200
201
202

#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. Stealing 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.
203#define EXPIRATION_BIT ((UINT64)1 << 63)

Check for consistency of the bit ordering of bit fields
204
205
206

#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
207
208
209
210
211
212
213
214
215

#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)#
define TPMA_ZERO_INITIALIZER()
{0}
#else
#
define IS_ATTRIBUTE(a, type, b)((a & type##_##b) != 0)#
define SET_ATTRIBUTE(a, type, b)(a |= type##_##b)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 143
December 24, 2020

Part 4: Supporting Routines
216
217
218
219
220
221
222

Trusted Platform Module Library##define CLEAR_ATTRIBUTE(a, type, b)(a &= ~type##_##b)
define GET_ATTRIBUTE(a, type, b)(type)((a & type##_##b) >> type##_##b##_SHIFT)#
define TPMA_ZERO_INITIALIZER()(0)#endif\#define VERIFY(_X) if(!(_X)) goto Error

These macros determine if the values in this file are referenced or instanced. Global.c defines
GLOBAL_C so all the values in this file will be instanced in Global.obj. For all other files that include thisfile, the values will simply be external references. For constants, there can be an initializer.
223
224
225
226
227
228
229

#ifdef GLOBAL_C#define EXTERN#define INITIALIZER(_value_)#else#define EXTERN extern#define INITIALIZER(_value_)#endif= _value_

This macro will create an OID. All OIDs are in DER form with a first octet of 0x06 indicating an OID
fallowed by an octet indicating the number of octets in the rest of the OID. This allows a user of this OID
to know how much/little to copy.
230
231#define MAKE_OID(NAME)
EXTERN const BYTE OID##NAME[] INITIALIZER({OID##NAME##_VALUE})\

This definition is moved from TpmProfile.h because it is not actually vendor- specific. It has to be thesame size as the sequence parameter of a TPMS_CONTEXT and that is a UINT64. So, this is aninvariant value
232
233
234

#define CONTEXT_COUNTERUINT64#endif // GP_MACROS_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 144
December 24, 2020

Part 4: Supporting Routines

5.11
1
2
3
4
5
6

Trusted Platform Module Library

InternalRoutines.h#ifndef#define

INTERNAL_ROUTINES_H
INTERNAL_ROUTINES_H#if !defined _LIB_SUPPORT_H_ && !defined _TPM_H_#error "Should not be called"#endif

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

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

#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 "ACT_spt_fp.h"#include "PCR_fp.h"#include "DA_fp.h"#include "TpmFail_fp.h"#include "SessionProcess_fp.h"

Internal support functions
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#include "CommandCodeAttributes_fp.h"#include "Marshal.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
39
40
41
42
43
44

#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
45#include "BnConvert_fp.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 145
December 24, 2020

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
71
72
73
74
75
76
77

Trusted Platform Module Library#include "BnMath_fp.h"#include "BnMemory_fp.h"#include "Ticket_fp.h"#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"#include "CryptEccCrypt_fp.h"#endif#if CC_MAC || CC_MAC_Start#
include "CryptSmac_fp.h"#
if ALG_CMAC#
include "CryptCmac_fp.h"#
endif#endif

Support library78#include "SupportLibraryFunctionPrototypes_fp.h"

Linkage to platform functions
79
80
81

#include "Platform_fp.h"#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 146
December 24, 2020

Part 4: Supporting Routines

5.12

Trusted Platform Module Library

LibSupport.h

This header file is used to select the library code that gets included in the TPM build.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#ifndef _LIB_SUPPORT_H_#define _LIB_SUPPORT_H_#ifndef RADIX_BITS#
if defined(__x86_64__) || defined(__x86_64)|| defined(__amd64__) || defined(__amd64)|| defined(_WIN64) || defined(_M_X64)|| defined(_M_ARM64) || defined(__aarch64__)|| defined(__PPC64__) || defined(__s390x__)|| defined(__powerpc64__) || defined(__ppc64__)#
define RADIX_BITS
64#elif defined(__i386__) || defined(__i386) || defined(i386)|| defined(_WIN32) || defined(_M_IX86)|| defined(_M_ARM) || defined(__arm__) || defined(__thumb__)#
define RADIX_BITS
32
#
else
#
error Unable to determine RADIX_BITS from compiler environment#
endif#endif // RADIX_BITS

\
\
\
\
\
\
\

These macros use the selected libraries to the proper include files.
20
21
22

#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_)

Include the options for hashing and symmetric. Defer the load of the math package Until the bignum
parameters are defined.
23
24
25
26
27
28
29

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

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

MinMax.h#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_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 147
December 24, 2020

Part 4: Supporting Routines

5.14

Trusted Platform Module LibraryNV.h5.14.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 isdefined12
3
4#ifndef#define_NV_H__NV_H_#ifdef

TPM_NT_ORDINARY

If TPM_NT_ORDINARY is defined, then the TPM_NT field is present in a TPMA_NV
56#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
7
8
9
10
11
12
13
14
15
16

#

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)#endif5.14.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
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)\#

defineIsNvCounterIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_COUNTER)\#

defineIsNvBitsIndex(attributes)(GET_TPM_NT(attributes) == TPM_NT_BITS)\#

defineIsNvExtendIndex(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)#endif\\typedef struct {UINT32size;
TPM_HANDLE handle;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 148
December 24, 2020

Part 4: Supporting Routines
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

Trusted Platform Module Library} 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))
typedef struct {UINT32
TPM_HANDLE
TPMA_NV} NV_RAM_HEADER;

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 UINT64 maxCounter value.
58

typedef UINT32 NV_LIST_TERMINATOR[3];5.14.3

Orderly RAM Values

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

NV_RAM_REF_INIT

0This is the starting address of the RAM space used for orderly data
60
61

#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.
62
63#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
64
65

#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.
66
67#define

NV_ORDERLY_END\(NV_ORDERLY_START + sizeof(s_indexOrderlyRam))

Macro to check that an orderly RAM address is with range.
68
69
70
71
72
73
74

#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;

Family “2.0”Level 00 Revision 01.64

\
\
\
\

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 149
December 24, 2020

Part 4: Supporting Routines
75

Trusted Platform Module Library}

Routinely have to clear the orderly flag and fail if the NV is not available so that it can be cleared.
76
77
78
79
80
81
82
83
84
85

#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))

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.
86
87
88

#define SET_NV_UPDATE(type)#endifg_updateNV |= (type)// _NV_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 150
December 24, 2020

Part 4: Supporting Routines

5.15

Trusted Platform Module Library

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 and initialize a TPM2B value
16
17
18
19
20

#define TPM2B_INIT(TYPE, name) \TPM2B_##TYPE
name = {sizeof(name.t.buffer), {0}}#define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes)#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 151
December 24, 2020

Part 4: Supporting Routines

5.16

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
17
18
19

#ifndef#define_TPM_H__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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 152
December 24, 2020

Part 4: Supporting Routines

5.17

Trusted Platform Module Library

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
7

#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
8
9
10
11
12

#ifdef PROFILE#
define PROFILE_QUOTE(a) #a#
define PROFILE_INCLUDE(a) PROFILE_QUOTE(a)#include PROFILE_INCLUDE(PROFILE)#endifNeed an unambiguous definition for DEBUG. Do not change this
13
14
15
16
17
18
19
20
21
22
23
24

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

This definition is required for the re-factored code
25
26
27
28
29

#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
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 153
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Virtual TPM. The interfaces for a Virtual TPM should be modified from the standard ones in the Simulator
project.
If SIMULATION is in the compile parameters without modifiers, make SIMULATION == YES
30
31
32
33

#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.
34
35
36
37
38
39
40
41
42
43
44

#if !(defined LIBRARY_COMPATIBILITY_CHECK)|| (( LIBRARY_COMPATIBILITY_CHECK != NO)&& (LIBRARY_COMPATIBILITY_CHECK != YES))#
undef
LIBRARY_COMPATIBILITY_CHECK#
define LIBRARY_COMPATIBILITY_CHECK YES// 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
45
46
47
48

#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
49
50
51
52
53

#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
54
55
56
57

#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.
58
59
60
61

#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.
62
63
64
65

#if RSA_KEY_SIEVE && SIMULATION#
if !(defined RSA_INSTRUMENT)|| ((RSA_INSTRUMENT != NO) && (RSA_INSTRUMENT != YES))#
undef
RSA_INSTRUMENT

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 154
December 24, 2020

Part 4: Supporting Routines
66
67
68

#
define#endif#endifTrusted Platform Module Library

RSA_INSTRUMENTNO// Default: Either YES or NO

This switch enables the RNG state save and restore
69
70
71
72
73

#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

74
75
76
77
78

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.
79
80
81
82

#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.
83
84
85
86
87
88

#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 simulation89#if SIMULATION && DEBUG

This forces the use of a smaller context slot size. This reduction reduces the range of the epoch allowing
the tester to force the epoch to occur faster than the normal defined in TpmProfile.h
90
91
92

#
#
#

if !(defined CONTEXT_SLOT)
define CONTEXT_SLOT
endif

UINT8

Enables use of the key cache. Default is YES
93
94
95
96

#
#
#

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 155
December 24, 2020

Part 4: Supporting Routines
97#

Trusted Platform Module Library

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
98
99
100
101
102
103
104
105
106
107

#
#
#
#
#
#
#
#
#

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
else
undef
USE_KEY_CACHE_FILE
define USE_KEY_CACHE_FILE
NO
endif// USE_RSA_KEY_CACHE\

This 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.
108
109
110
111

#
#
#
#

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

Do not 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
112
113
114
115
116
117
118

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

NO
NO
NO

#if DEBUG

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 is not 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.
119
120
121
122
123

#
#
#
#

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 TpmProfile.h. The combination
might not be consistent. A function is defined (TpmSizeChecks()) that is used to verify the sizes at run
time. To enable the function, define this parameter.
124
125
126
127
128

#
#
#
#

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 156
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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)
129
130
131
132
133

#
#
#
#

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 == NO
134
135
136
137
138
139

#
#
#
#

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.
140
141
142
143
144

#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.
145
146
147
148
149

#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.
150
151
152
153
154

#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
155
156
157
158
159

#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_STRUCTURESNO// Default: Either YES or NO#endif\This define is used to control the debug for the CertifyX509() command.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 157
December 24, 2020

Part 4: Supporting Routines
160
161
162
163
164

Trusted Platform Module Library#if !(defined CERTIFYX509_DEBUG)|| ((CERTIFYX509_DEBUG != NO) && (CERTIFYX509_DEBUG != YES))#
undef
CERTIFYX509_DEBUG#
define CERTIFYX509_DEBUG YES// Default: Either YES or NO#endif\This define is used to enable the new table-driven marshaling code.
165
166
167
168
169

#if !(defined TABLE_DRIVEN_MARSHAL)|| ((TABLE_DRIVEN_MARSHAL != NO) && (TABLE_DRIVEN_MARSHAL != YES))#
undef
TABLE_DRIVEN_MARSHAL#
define TABLE_DRIVEN_MARSHAL NO // Default: Either YES or NO#endif\Change 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.
170
171
172
173
174
175

#define#define#define#define

ALG_YESALG_NO
CC_YES
CC_NO

YES
NO
YES
NO

#endif // _TPM_BUILD_SWITCHES_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 158
December 24, 2020

Part 4: Supporting Routines

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

Trusted Platform Module Library

TpmError.h#ifndef _TPM_ERROR_H#define _TPM_ERROR_H#define#define#define#define#define#define#define#define#defineFATAL_ERROR_ALLOCATIONFATAL_ERROR_DIVIDE_ZEROFATAL_ERROR_INTERNALFATAL_ERROR_PARAMETERFATAL_ERROR_ENTROPYFATAL_ERROR_SELF_TESTFATAL_ERROR_CRYPTOFATAL_ERROR_NV_UNRECOVERABLEFATAL_ERROR_REMANUFACTURED#define#define#define#define#define#defineFATAL_ERROR_DRBGFATAL_ERROR_MOVE_SIZEFATAL_ERROR_COUNTER_OVERFLOWFATAL_ERROR_SUBTRACTFATAL_ERROR_MATHLIBRARYFATAL_ERROR_FORCED

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

#endif // _TPM_ERROR_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 159
December 24, 2020

Part 4: Supporting Routines

5.19
1
2

Trusted Platform Module Library

TpmTypes.h#ifndef _TPM_TYPES_H_#define _TPM_TYPES_H_

TCG Algorithm Registry: Table 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.64

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-2021

Page 160
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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)TCG Algorithm Registry: Table 4 - 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)

TPM 2.0 Part 2: Table 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

Family “2.0”Level 00 Revision 01.64

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-2021

Page 161
December 24, 2020

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.64(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-2021

Page 162
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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 TPM_CC_ACT_SetTimeout#define TPM_CC_ECC_Encrypt#define TPM_CC_ECC_Decrypt#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)(TPM_CC)(0x00000198)(TPM_CC)(0x00000199)(TPM_CC)(0x0000019A)
0x20000000(TPM_CC)(0x20000000)

TPM 2.0 Part 2: Table 5 - Definition of Types for Documentation Clarity
227
228
229
230
231
232
233
234
235
236
237
238

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

TPM 2.0 Part 2: Table 6 - Definition of TPM_SPEC Constants
239

typedef UINT32

Family “2.0”Level 00 Revision 01.64

TPM_SPEC;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 163
December 24, 2020

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

Trusted Platform Module Library#define TYPE_OF_TPM_SPEC#define SPEC_FAMILY#define TPM_SPEC_FAMILY#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

UINT320x322E3000(TPM_SPEC)(SPEC_FAMILY)00(TPM_SPEC)(SPEC_LEVEL)
162(TPM_SPEC)(SPEC_VERSION)
2020(TPM_SPEC)(SPEC_YEAR)53(TPM_SPEC)(SPEC_DAY_OF_YEAR)

TPM 2.0 Part 2: Table 7 - Definition of TPM_CONSTANTS32 Constants
251
252
253
254

typedef UINT32#define TYPE_OF_TPM_CONSTANTS32#define TPM_GENERATED_VALUE#define TPM_MAX_DERIVATION_BITS

TPM_CONSTANTS32;
UINT32(TPM_CONSTANTS32)(0xFF544347)(TPM_CONSTANTS32)(8192)

TPM 2.0 Part 2: Table 16 - Definition of TPM_RC Constants
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

Family “2.0”Level 00 Revision 01.64

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)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 164
December 24, 2020

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
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_ATTRIBUTES#define TPM_RC_HASH#define TPM_RCS_HASH#define TPM_RC_VALUE#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

Family “2.0”Level 00 Revision 01.64

Trusted Platform Module Library(TPM_RC)(RC_FMT1+0x002)(TPM_RC)(RC_FMT1+0x003)(TPM_RC)(RC_FMT1+0x003)(TPM_RC)(RC_FMT1+0x004)(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)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 165
December 24, 2020

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
407
408
409
410

Trusted Platform Module Library#define TPM_RC_SESSION_MEMORY#define TPM_RC_MEMORY#define TPM_RC_SESSION_HANDLES#define TPM_RC_OBJECT_HANDLES#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+0x003)(TPM_RC)(RC_WARN+0x004)(TPM_RC)(RC_WARN+0x005)(TPM_RC)(RC_WARN+0x006)(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)

TPM 2.0 Part 2: Table 17 - Definition of TPM_CLOCK_ADJUST Constants
411
412
413
414
415
416
417
418
419

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)

TPM 2.0 Part 2: Table 18 - Definition of TPM_EO Constants
420
421
422
423

typedef UINT16#define TYPE_OF_TPM_EO#define TPM_EO_EQ#define TPM_EO_NEQ

Family “2.0”Level 00 Revision 01.64

TPM_EO;UINT16(TPM_EO)(0x0000)(TPM_EO)(0x0001)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 166
December 24, 2020

Part 4: Supporting Routines
424
425
426
427
428
429
430
431
432
433

#define TPM_EO_SIGNED_GT#define TPM_EO_UNSIGNED_GT#define TPM_EO_SIGNED_LT#define TPM_EO_UNSIGNED_LT#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

Trusted Platform Module Library(TPM_EO)(0x0002)(TPM_EO)(0x0003)(TPM_EO)(0x0004)(TPM_EO)(0x0005)(TPM_EO)(0x0006)(TPM_EO)(0x0007)(TPM_EO)(0x0008)(TPM_EO)(0x0009)(TPM_EO)(0x000A)(TPM_EO)(0x000B)

TPM 2.0 Part 2: Table 19 - Definition of TPM_ST Constants
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

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)

TPM 2.0 Part 2: Table 20 - Definition of TPM_SU Constants
454
455
456
457

typedef UINT16#define TYPE_OF_TPM_SU#define TPM_SU_CLEAR#define TPM_SU_STATETPM_SU;UINT16(TPM_SU)(0x0000)(TPM_SU)(0x0001)

TPM 2.0 Part 2: Table 21 - Definition of TPM_SE Constants
458
459
460
461
462

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)

TPM 2.0 Part 2: Table 22 - Definition of TPM_CAP Constants
463
464
465
466
467
468
469
470
471
472
473
474
475

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_POLICIESFamily “2.0”Level 00 Revision 01.64

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)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 167
December 24, 2020

Part 4: Supporting Routines
476
477
478

Trusted Platform Module Library#define TPM_CAP_ACT#define TPM_CAP_LAST#define TPM_CAP_VENDOR_PROPERTY(TPM_CAP)(0x0000000A)(TPM_CAP)(0x0000000A)(TPM_CAP)(0x00000100)

TPM 2.0 Part 2: Table 23 - Definition of TPM_PT Constants
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_AVAILFamily “2.0”Level 00 Revision 01.64

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)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 168
December 24, 2020

Part 4: Supporting Routines
538
539
540
541
542
543
544
545
546
547
548
549
550
551

Trusted Platform Module Library#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_AVAIL#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+7)(TPM_PT)(PT_VAR+8)(TPM_PT)(PT_VAR+9)(TPM_PT)(PT_VAR+10)(TPM_PT)(PT_VAR+11)(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)

TPM 2.0 Part 2: Table 24 - Definition of TPM_PT_PCR Constants
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570

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)

TPM 2.0 Part 2: Table 25 - Definition of TPM_PS Constants
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

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)

TPM 2.0 Part 2: Table 26 - Definition of Types for Handles
589
590

typedef UINT32#define TYPE_OF_TPM_HANDLE

TPM_HANDLE;UINT32

TPM 2.0 Part 2: Table 27 - Definition of TPM_HT Constants
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 169
December 24, 2020

Part 4: Supporting Routines
591
592
593
594
595
596
597
598
599
600
601
602

Trusted Platform Module Library

typedef UINT8#define TYPE_OF_TPM_HT#define TPM_HT_PCR#define TPM_HT_NV_INDEX#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;
UINT8(TPM_HT)(0x00)(TPM_HT)(0x01)(TPM_HT)(0x02)(TPM_HT)(0x02)(TPM_HT)(0x03)(TPM_HT)(0x03)(TPM_HT)(0x40)(TPM_HT)(0x80)(TPM_HT)(0x81)(TPM_HT)(0x90)

TPM 2.0 Part 2: Table 28 - Definition of TPM_RH Constants
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

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_ACT_0#define TPM_RH_ACT_F#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)(0x40000110)(TPM_RH)(0x4000011F)(TPM_RH)(0x4000011F)

TPM 2.0 Part 2: Table 29 - Definition of TPM_HC Constants
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

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 170
December 24, 2020

Part 4: Supporting Routines
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

#define PLATFORM_PERSISTENT#define NV_INDEX_FIRST#define NV_INDEX_LAST#define PERMANENT_FIRST#define PERMANENT_LAST#define HR_NV_AC#define NV_AC_FIRST#define NV_AC_LAST#define HR_AC#define AC_FIRST#define AC_LAST

Trusted Platform Module Library(TPM_HC)((PERSISTENT_FIRST+0x00800000))(TPM_HC)((HR_NV_INDEX+0))(TPM_HC)((NV_INDEX_FIRST+0x00FFFFFF))(TPM_HC)(TPM_RH_FIRST)(TPM_HC)(TPM_RH_LAST)(TPM_HC)(((TPM_HT_NV_INDEX<<HR_SHIFT)+0xD00000))(TPM_HC)((HR_NV_AC+0))(TPM_HC)((HR_NV_AC+0x0000FFFF))(TPM_HC)((TPM_HT_AC<<HR_SHIFT))(TPM_HC)((HR_AC+0))(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;

\
\
\
\

This is the initializer for a TPMA_ALGORITHM structure
683
684
685
686
687
688

#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
689
690
691
692
693
694
695
696
697

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.
698
699
700
701
702
703
704

#define TPMA_ALGORITHM_INITIALIZER(
asymmetric, symmetric, hash,object,bits_at_4,
signing,
encrypting, method,
bits_at_11)(TPMA_ALGORITHM)((asymmetric << 0) + (symmetric << 1) + (hash << 2)+(object << 3)+ (signing << 8)+ (encrypting << 9) +(method << 10))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\

Page 171
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_OBJECT {// Table 2:31
unsigned
Reserved_bit_at_0: 1;
unsigned
fixedTPM: 1;
unsigned
stClear: 1;
unsigned
Reserved_bit_at_3: 1;
unsigned
fixedParent: 1;
unsignedsensitiveDataOrigin: 1;
unsigned
userWithAuth: 1;
unsigned
adminWithPolicy: 1;
unsigned
Reserved_bits_at_8: 2;
unsignednoDA: 1;
unsigned
encryptedDuplication: 1;
unsigned
Reserved_bits_at_12: 4;
unsigned
restricted: 1;
unsigned
decrypt: 1;
unsignedsign: 1;
unsignedx509sign: 1;
unsigned
Reserved_bits_at_20: 12;} TPMA_OBJECT;\\

This is the initializer for a TPMA_OBJECT structure
734
735
736
737
738
739
740
741
742
743
744
745
746
747

#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
748
749
750
751
752
753
754
755
756
757
758
759
760
761

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

Family “2.0”Level 00 Revision 01.64

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)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 172
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryThis is the initializer for a TPMA_OBJECT bit array.
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

#define TPMA_OBJECT_INITIALIZER(
bit_at_0,
fixedtpm,
stclear,
bit_at_3,
fixedparent,
sensitivedataorigin,userwithauth,adminwithpolicy,
bits_at_8,
noda,
encryptedduplication, bits_at_12,
restricted,
decrypt,sign,
x509sign,
bits_at_20)(TPMA_OBJECT)((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;\\

This is the initializer for a TPMA_SESSION structure
795
796
797
798
799
800

#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
801
802
803
804
805
806
807
808

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.
809
810
811
812
813
814

#define TPMA_SESSION_INITIALIZER(
continuesession, auditexclusive, auditreset,
decrypt,
encrypt,
audit)(TPMA_SESSION)((continuesession << 0) + (auditexclusive << 1)(auditreset << 2)+ (decrypt << 5)Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

bits_at_3,
+
+

\
\
\
\
\
\

Page 173
December 24, 2020

Part 4: Supporting Routines
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

Trusted Platform Module Library(encrypt << 6)#endif // USE_BIT_FIELD_STRUCTURES+ (audit << 7))#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;
unsigned
TPM_LOC_ONE: 1;
unsigned
TPM_LOC_TWO: 1;
unsigned
TPM_LOC_THREE: 1;
unsigned
TPM_LOC_FOUR: 1;
unsigned
Extended: 3;} TPMA_LOCALITY;\\This is the initializer for a TPMA_LOCALITY structure
834
835
836
837
838
839

#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
840
841
842
843
844
845
846
847
848

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.
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869

#define TPMA_LOCALITY_INITIALIZER(
tpm_loc_zero, tpm_loc_one,
tpm_loc_two,
tpm_loc_four, extended)(TPMA_LOCALITY)((tpm_loc_zero << 0) + (tpm_loc_one << 1)(tpm_loc_three << 3) + (tpm_loc_four << 4)#endif // USE_BIT_FIELD_STRUCTURES

tpm_loc_three,+ (tpm_loc_two << 2)+ (extended << 5))#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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

+

\
\
\
\
\

\
\
\
\

Page 174
December 24, 2020

Part 4: Supporting Routines
870
871
872
873
874
875
876

Trusted Platform Module Library

unsigned
lockoutAuthSet
unsigned
Reserved_bits_at_3
unsigned
disableClear
unsigned
inLockout
unsigned
tpmGeneratedEPS
unsigned
Reserved_bits_at_11} TPMA_PERMANENT;

: 1;
: 5;
: 1;
: 1;
: 1;
: 21;

This is the initializer for a TPMA_PERMANENT structure
877
878
879
880
881
882
883
884

#define TPMA_PERMANENT_INITIALIZER(
ownerauthset,
endorsementauthset, lockoutauthset,
bits_at_3,
disableclear,inlockout,
tpmgeneratedeps,
bits_at_11){ownerauthset,
endorsementauthset, lockoutauthset,
bits_at_3,
disableclear,inlockout,
tpmgeneratedeps,
bits_at_11}#else // USE_BIT_FIELD_STRUCTURES

\
\
\
\
\
\

This implements Table 2:34 TPMA_PERMANENT using bit masking
885
886
887
888
889
890
891
892

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

#define TPMA_PERMANENT_INITIALIZER(
ownerauthset,
endorsementauthset, lockoutauthset,
bits_at_3,
disableclear,inlockout,
tpmgeneratedeps,
bits_at_11)(TPMA_PERMANENT)((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;

\
\
\
\

This is the initializer for a TPMA_STARTUP_CLEAR structure921#define TPMA_STARTUP_CLEAR_INITIALIZER(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 175
December 24, 2020

Part 4: Supporting Routines
922
923
924

Trusted Platform Module Libraryphenable, 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
925
926
927
928
929
930
931

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.
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

#define TPMA_STARTUP_CLEAR_INITIALIZER(
phenable, shenable, ehenable, phenablenv, bits_at_4, orderly)(TPMA_STARTUP_CLEAR)((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;\\This is the initializer for a TPMA_MEMORY structure
953
954
955
956

#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
957
958
959
960
961

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.
962
963
964
965
966
967
968
969

#define TPMA_MEMORY_INITIALIZER(
sharedram, sharednv, objectcopiedtoram, bits_at_3)(TPMA_MEMORY)((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)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 176
December 24, 2020

Part 4: Supporting Routines
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986

Trusted Platform Module Library#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;\\

This is the initializer for a TPMA_CC structure
987
988
989
990
991
992

#define TPMA_CC_INITIALIZER(
commandindex, 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
993
994
995
996
997
998
999
1000
1001
1002
1003

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.
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

#define TPMA_CC_INITIALIZER(
commandindex, bits_at_16,
nv,
chandles,rhandle,v,(TPMA_CC)((commandindex << 0) + (nv << 22)(flushed << 24)+ (chandles << 25)(v << 29))
#endif // USE_BIT_FIELD_STRUCTURES

extensive,
bits_at_30)

\
\
\
\
\
\

flushed,+ (extensive << 23)+ (rhandle << 28)++#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;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 177
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryThis is the initializer for a TPMA_MODES structure
1025
1026

#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
1027
1028
1029

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

#define TPMA_MODES_INITIALIZER(fips_140_2, bits_at_1)(TPMA_MODES)((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){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 {// Table 2:39
unsigned
Reserved_bits_at_0: 23;
unsigned
decipherOnly: 1;
unsigned
encipherOnly: 1;
unsignedcRLSign: 1;
unsigned
keyCertSign: 1;
unsigned
keyAgreement: 1;
unsigned
dataEncipherment: 1;
unsigned
keyEncipherment: 1;
unsignednonrepudiation: 1;
unsigned
digitalSignature: 1;} TPMA_X509_KEY_USAGE;

\
\
\
\

This is the initializer for a TPMA_X509_KEY_USAGE structure
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066

#define TPMA_X509_KEY_USAGE_INITIALIZER(
bits_at_0,
decipheronly,
crlsign,keycertsign,
dataencipherment, keyencipherment,
digitalsignature){bits_at_0,
decipheronly,
crlsign,keycertsign,
dataencipherment, keyencipherment,
digitalsignature}#else // USE_BIT_FIELD_STRUCTURES

\
\
\
\
\
\
\
\

encipheronly,
keyagreement,
nonrepudiation,
encipheronly,
keyagreement,
nonrepudiation,

This implements Table 2:39 TPMA_X509_KEY_USAGE using bit masking
1067
1068
1069
1070
1071
1072
1073

typedef UINT32#define TYPE_OF_TPMA_X509_KEY_USAGE#define TPMA_X509_KEY_USAGE_decipherOnly#define TPMA_X509_KEY_USAGE_encipherOnly#define TPMA_X509_KEY_USAGE_cRLSign#define TPMA_X509_KEY_USAGE_keyCertSign#define TPMA_X509_KEY_USAGE_keyAgreement

Family “2.0”Level 00 Revision 01.64

TPMA_X509_KEY_USAGE;
UINT32((TPMA_X509_KEY_USAGE)1 << 23)((TPMA_X509_KEY_USAGE)1 << 24)((TPMA_X509_KEY_USAGE)1 << 25)((TPMA_X509_KEY_USAGE)1 << 26)((TPMA_X509_KEY_USAGE)1 << 27)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 178
December 24, 2020

Part 4: Supporting Routines
1074
1075
1076
1077

Trusted Platform Module Library#define TPMA_X509_KEY_USAGE_dataEncipherment#define TPMA_X509_KEY_USAGE_keyEncipherment#define TPMA_X509_KEY_USAGE_nonrepudiation#define TPMA_X509_KEY_USAGE_digitalSignature((TPMA_X509_KEY_USAGE)1 << 28)((TPMA_X509_KEY_USAGE)1 << 29)((TPMA_X509_KEY_USAGE)1 << 30)((TPMA_X509_KEY_USAGE)1 << 31)This is the initializer for a TPMA_X509_KEY_USAGE bit array.
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

#define TPMA_X509_KEY_USAGE_INITIALIZER(
bits_at_0,
decipheronly,
encipheronly,
crlsign,keycertsign,
keyagreement,
dataencipherment, keyencipherment, nonrepudiation,
digitalsignature)(TPMA_X509_KEY_USAGE)((decipheronly << 23)+ (encipheronly << 24)+(crlsign << 25)+ (keycertsign << 26)+(keyagreement << 27)+ (dataencipherment << 28) +(keyencipherment << 29) + (nonrepudiation << 30)+(digitalsignature << 31))
#endif // USE_BIT_FIELD_STRUCTURES

\
\
\
\
\
\
\
\
\
\

#define TYPE_OF_TPMA_ACTUINT32#define TPMA_ACT_TO_UINT32(a)(*((UINT32 *)&(a)))#define UINT32_TO_TPMA_ACT(a)(*((TPMA_ACT *)&(a)))#define TPMA_ACT_TO_BYTE_ARRAY(i, a)
UINT32_TO_BYTE_ARRAY((TPMA_ACT_TO_UINT32(i)), (a))#define BYTE_ARRAY_TO_TPMA_ACT(i, a){ UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_ACT(x); }#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_ACT {// Table 2:40
unsignedsignaled: 1;
unsignedpreserveSignaled: 1;
unsigned
Reserved_bits_at_2: 30;} TPMA_ACT;\\This is the initializer for a TPMA_ACT structure
1104
1105
1106

#define TPMA_ACT_INITIALIZER(signaled, preservesignaled, bits_at_2){signaled, preservesignaled, bits_at_2}#else // USE_BIT_FIELD_STRUCTURES\

This implements Table 2:40 TPMA_ACT using bit masking
1107
1108
1109
1110

typedef UINT32#define TYPE_OF_TPMA_ACT#define TPMA_ACT_signaled#define TPMA_ACT_preserveSignaled

TPMA_ACT;UINT32((TPMA_ACT)1 << 0)((TPMA_ACT)1 << 1)This is the initializer for a TPMA_ACT bit array.
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125

#define TPMA_ACT_INITIALIZER(signaled, preservesignaled, bits_at_2)(TPMA_ACT)((signaled << 0) + (preservesignaled << 1))#endif // USE_BIT_FIELD_STRUCTURES
typedef BYTE

TPMI_YES_NO;// Table 2:41

typedef TPM_HANDLE

TPMI_DH_OBJECT;// Table 2:42

typedef TPM_HANDLE

TPMI_DH_PARENT;// Table 2:43

typedef TPM_HANDLE

TPMI_DH_PERSISTENT;// Table 2:44

typedef TPM_HANDLE

TPMI_DH_ENTITY;// Table 2:45

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 179
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library

typedef TPM_HANDLE

TPMI_DH_PCR;// Table 2:46

typedef TPM_HANDLE

TPMI_SH_AUTH_SESSION;// Table 2:47

typedef TPM_HANDLE

TPMI_SH_HMAC;// Table 2:48

typedef TPM_HANDLE

TPMI_SH_POLICY;// Table 2:49

typedef TPM_HANDLE

TPMI_DH_CONTEXT;// Table 2:50

typedef TPM_HANDLE

TPMI_DH_SAVED;// Table 2:51

typedef TPM_HANDLE

TPMI_RH_HIERARCHY;// Table 2:52

typedef TPM_HANDLE

TPMI_RH_ENABLES;// Table 2:53

typedef TPM_HANDLE

TPMI_RH_HIERARCHY_AUTH; // Table 2:54

typedef TPM_HANDLE

TPMI_RH_HIERARCHY_POLICY;

typedef TPM_HANDLE

TPMI_RH_PLATFORM;// Table 2:56

typedef TPM_HANDLE

TPMI_RH_OWNER;// Table 2:57

typedef TPM_HANDLE

TPMI_RH_ENDORSEMENT;// Table 2:58

typedef TPM_HANDLE

TPMI_RH_PROVISION;// Table 2:59

typedef TPM_HANDLE

TPMI_RH_CLEAR;// Table 2:60

typedef TPM_HANDLE

TPMI_RH_NV_AUTH;// Table 2:61

typedef TPM_HANDLE

TPMI_RH_LOCKOUT;// Table 2:62

typedef TPM_HANDLE

TPMI_RH_NV_INDEX;// Table 2:63

typedef TPM_HANDLE

TPMI_RH_AC;// Table 2:64

typedef TPM_HANDLE

TPMI_RH_ACT;// Table 2:65

typedef TPM_ALG_ID

TPMI_ALG_HASH;// Table 2:66

typedef TPM_ALG_ID

TPMI_ALG_ASYM;// Table 2:67

typedef TPM_ALG_ID

TPMI_ALG_SYM;// Table 2:68

typedef TPM_ALG_ID

TPMI_ALG_SYM_OBJECT;// Table 2:69

typedef TPM_ALG_ID

TPMI_ALG_SYM_MODE;// Table 2:70

typedef TPM_ALG_ID

TPMI_ALG_KDF;// Table 2:71

typedef TPM_ALG_ID

TPMI_ALG_SIG_SCHEME;// Table 2:72

typedef TPM_ALG_ID

TPMI_ECC_KEY_EXCHANGE;// Table 2:73

typedef TPM_ST

TPMI_ST_COMMAND_TAG;// Table 2:74

typedef TPM_ALG_ID

TPMI_ALG_MAC_SCHEME;// Table 2:75

typedef TPM_ALG_ID

TPMI_ALG_CIPHER_MODE;// Table 2:76

typedef BYTE

TPMS_EMPTY;// Table 2:77

typedef struct {TPM_ALG_ID

alg;

Family “2.0”Level 00 Revision 01.64// Table 2:78

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 180
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

TPMA_ALGORITHM
attributes;} TPMS_ALGORITHM_DESCRIPTION;
typedef union {#if ALG_SHA1
BYTE#endif // ALG_SHA1#if ALG_SHA256
BYTE#endif // ALG_SHA256#if ALG_SHA384
BYTE#endif // ALG_SHA384#if ALG_SHA512
BYTE#endif // ALG_SHA512#if ALG_SM3_256
BYTE#endif // ALG_SM3_256#if ALG_SHA3_256
BYTE#endif // ALG_SHA3_256#if ALG_SHA3_384
BYTE#endif // ALG_SHA3_384#if ALG_SHA3_512
BYTE#endif // ALG_SHA3_512} TPMU_HA;
typedef struct {TPMI_ALG_HASH
TPMU_HA} TPMT_HA;
typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_DIGEST;
typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_DATA;// Table 2:79
sha1[SHA1_DIGEST_SIZE];
sha256[SHA256_DIGEST_SIZE];
sha384[SHA384_DIGEST_SIZE];
sha512[SHA512_DIGEST_SIZE];
sm3_256[SM3_256_DIGEST_SIZE];
sha3_256[SHA3_256_DIGEST_SIZE];
sha3_384[SHA3_384_DIGEST_SIZE];
sha3_512[SHA3_512_DIGEST_SIZE];// Table 2:80
hashAlg;
digest;// Table 2:81
size;
buffer[sizeof(TPMU_HA)];t;b;// Table 2:82
size;
buffer[sizeof(TPMT_HA)];t;b;

TPM 2.0 Part 2: Table 83 - Definition of Types for TPM2B_NONCE
1242

typedef TPM2B_DIGESTTPM2B_NONCE;TPM 2.0 Part 2: Table 84 - Definition of Types for TPM2B_AUTH
1243

typedef TPM2B_DIGESTTPM2B_AUTH;

TPM 2.0 Part 2: Table 85 - Definition of Types for TPM2B_OPERAND
1244
1245
1246

typedef TPM2B_DIGEST
typedef union {Family “2.0”Level 00 Revision 01.64

TPM2B_OPERAND;// Table 2:86

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 181
December 24, 2020

Part 4: Supporting Routines
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
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

struct {UINT16BYTE}
TPM2B} TPM2B_EVENT;

size;
buffer[1024];t;b;

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 {UINT16BYTE}
TPM2B} TPM2B_IV;// Table 2:87
size;
buffer[MAX_DIGEST_BUFFER];// Table 2:88
size;
buffer[MAX_NV_BUFFER_SIZE];// Table 2:89
size;
buffer[sizeof(UINT64)];// Table 2:90
size;
buffer[MAX_SYM_BLOCK_SIZE];t;b;

typedef union {TPMT_HA
TPM_HANDLE} TPMU_NAME;
typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_NAME;

Trusted Platform Module Library// Table 2:91
digest;handle;// Table 2:92
size;
name[sizeof(TPMU_NAME)];t;b;

typedef struct {
UINT8
BYTE
} TPMS_PCR_SELECT;// Table 2:93
sizeofSelect;
pcrSelect[PCR_SELECT_MAX];

typedef struct {TPMI_ALG_HASH
UINT8
BYTE
} TPMS_PCR_SELECTION;// Table 2:94
hash;sizeofSelect;
pcrSelect[PCR_SELECT_MAX];

typedef struct {TPM_ST
TPMI_RH_HIERARCHY

Family “2.0”Level 00 Revision 01.64// Table 2:97
tag;hierarchy;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 182
December 24, 2020

Part 4: Supporting Routines
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
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

TPM2B_DIGEST} TPMT_TK_CREATION;

Trusted Platform Module Librarydigest;typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_VERIFIED;

tag;hierarchy;
digest;typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_AUTH;

tag;hierarchy;
digest;typedef struct {TPM_ST
TPMI_RH_HIERARCHYTPM2B_DIGEST} TPMT_TK_HASHCHECK;

tag;
hierarchy;
digest;typedef struct {TPM_ALG_ID
TPMA_ALGORITHM} TPMS_ALG_PROPERTY;

alg;
algProperties;

typedef struct {TPM_PTUINT32} TPMS_TAGGED_PROPERTY;

property;
value;

typedef struct {TPM_PT_PCR
UINT8
BYTE
} TPMS_TAGGED_PCR_SELECT;// Table 2:98// Table 2:99// Table 2:100// Table 2:101// Table 2:102// Table 2:103
tag;sizeofSelect;
pcrSelect[PCR_SELECT_MAX];

typedef struct {TPM_HANDLE
TPMT_HA} TPMS_TAGGED_POLICY;

handle;policyHash;// Table 2:104

typedef struct {TPM_HANDLEUINT32
TPMA_ACT} TPMS_ACT_DATA;

handle;timeout;
attributes;// Table 2:105

typedef struct {UINT32
TPM_CC} TPML_CC;// Table 2:106
count;
commandCodes[MAX_CAP_CC];

typedef struct {UINT32
TPMA_CC} TPML_CCA;// Table 2:107
count;
commandAttributes[MAX_CAP_CC];

typedef struct {UINT32
TPM_ALG_ID} TPML_ALG;// Table 2:108
count;
algorithms[MAX_ALG_LIST_SIZE];

typedef struct {UINT32
TPM_HANDLE

Family “2.0”Level 00 Revision 01.64// Table 2:109
count;
handle[MAX_CAP_HANDLES];

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 183
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library} TPML_HANDLE;
typedef struct {UINT32TPM2B_DIGEST} TPML_DIGEST;

count;
digests[8];// Table 2:110

typedef struct {UINT32
TPMT_HA} TPML_DIGEST_VALUES;

count;
digests[HASH_COUNT];// Table 2:111

typedef struct {UINT32
TPMS_PCR_SELECTION} TPML_PCR_SELECTION;// Table 2:112
count;
pcrSelections[HASH_COUNT];

typedef struct {UINT32
TPMS_ALG_PROPERTY} TPML_ALG_PROPERTY;// Table 2:113
count;
algProperties[MAX_CAP_ALGS];

typedef struct {UINT32
TPMS_TAGGED_PROPERTY} TPML_TAGGED_TPM_PROPERTY;// Table 2:114
count;
tpmProperty[MAX_TPM_PROPERTIES];

typedef struct {UINT32
TPMS_TAGGED_PCR_SELECT} TPML_TAGGED_PCR_PROPERTY;// Table 2:115
count;
pcrProperty[MAX_PCR_PROPERTIES];

typedef struct {UINT32
TPM_ECC_CURVE} TPML_ECC_CURVE;// Table 2:116
count;
eccCurves[MAX_ECC_CURVES];

typedef struct {UINT32
TPMS_TAGGED_POLICY} TPML_TAGGED_POLICY;// Table 2:117
count;
policies[MAX_TAGGED_POLICIES];

typedef struct {UINT32
TPMS_ACT_DATA} TPML_ACT_DATA;// Table 2:118

typedef union {TPML_ALG_PROPERTY
TPML_HANDLE
TPML_CCA
TPML_CC
TPML_CC
TPML_PCR_SELECTION
TPML_TAGGED_TPM_PROPERTY
TPML_TAGGED_PCR_PROPERTY#if ALG_ECC
TPML_ECC_CURVE#endif // ALG_ECC
TPML_TAGGED_POLICY
TPML_ACT_DATA} TPMU_CAPABILITIES;

count;
actData[MAX_ACT_DATA];

typedef struct {TPM_CAP
TPMU_CAPABILITIESFamily “2.0”Level 00 Revision 01.64// Table 2:119
algorithms;
handles;command;
ppCommands;
auditCommands;
assignedPCR;
tpmProperties;
pcrProperties;
eccCurves;
authPolicies;
actData;// Table 2:120
capability;
data;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 184
December 24, 2020

Part 4: Supporting Routines
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
1484
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

Trusted Platform Module Library} TPMS_CAPABILITY_DATA;
typedef struct {UINT64
UINT32
UINT32
TPMI_YES_NO} TPMS_CLOCK_INFO;

clock;
resetCount;restartCount;safe;

typedef struct {UINT64
TPMS_CLOCK_INFO} TPMS_TIME_INFO;

time;clockInfo;

typedef struct {TPMS_TIME_INFOUINT64} TPMS_TIME_ATTEST_INFO;

time;
firmwareVersion;

typedef struct {TPM2B_NAME
TPM2B_NAME} TPMS_CERTIFY_INFO;

name;
qualifiedName;

typedef struct {TPML_PCR_SELECTION
TPM2B_DIGEST} TPMS_QUOTE_INFO;

pcrSelect;
pcrDigest;

typedef struct {UINT64
TPM_ALG_ID
TPM2B_DIGESTTPM2B_DIGEST} TPMS_COMMAND_AUDIT_INFO;

auditCounter;digestAlg;
auditDigest;
commandDigest;

typedef struct {TPMI_YES_NO
TPM2B_DIGEST} TPMS_SESSION_AUDIT_INFO;

exclusiveSession;
sessionDigest;

typedef struct {TPM2B_NAME
TPM2B_DIGEST} TPMS_CREATION_INFO;

objectName;creationHash;

typedef struct {TPM2B_NAME
UINT16
TPM2B_MAX_NV_BUFFER} TPMS_NV_CERTIFY_INFO;// Table 2:121// Table 2:122// Table 2:123// Table 2:124// Table 2:125// Table 2:126// Table 2:127// Table 2:128// Table 2:129
indexName;
offset;nvContents;

typedef struct {TPM2B_NAME
indexName;TPM2B_DIGEST
nvDigest;} TPMS_NV_DIGEST_CERTIFY_INFO;// Table 2:130

typedef TPM_ST// Table 2:131

typedef union {TPMS_CERTIFY_INFO
TPMS_CREATION_INFO
TPMS_QUOTE_INFO
TPMS_COMMAND_AUDIT_INFO
TPMS_SESSION_AUDIT_INFO
TPMS_TIME_ATTEST_INFOFamily “2.0”Level 00 Revision 01.64

TPMI_ST_ATTEST;// Table 2:132
certify;creation;
quote;
commandAudit;
sessionAudit;time;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 185
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library

TPMS_NV_CERTIFY_INFO
TPMS_NV_DIGEST_CERTIFY_INFO} TPMU_ATTEST;
typedef struct {TPM_CONSTANTS32
TPMI_ST_ATTEST
TPM2B_NAME
TPM2B_DATA
TPMS_CLOCK_INFOUINT64
TPMU_ATTEST} TPMS_ATTEST;
typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_ATTEST;

nv;
nvDigest;// Table 2:133

magic;
type;
qualifiedSigner;
extraData;
clockInfo;firmwareVersion;
attested;// Table 2:134
size;
attestationData[sizeof(TPMS_ATTEST)];t;b;

typedef struct {TPMI_SH_AUTH_SESSION
TPM2B_NONCE
TPMA_SESSION
TPM2B_AUTH} TPMS_AUTH_COMMAND;// Table 2:135
sessionHandle;
nonce;
sessionAttributes;
hmac;

typedef struct {TPM2B_NONCE
TPMA_SESSION
TPM2B_AUTH} TPMS_AUTH_RESPONSE;

nonce;
sessionAttributes;
hmac;

typedef TPM_KEY_BITS

TPMI_TDES_KEY_BITS;// Table 2:137

typedef TPM_KEY_BITS

TPMI_AES_KEY_BITS;// Table 2:137

typedef TPM_KEY_BITS

TPMI_SM4_KEY_BITS;// Table 2:137

typedef TPM_KEY_BITS

TPMI_CAMELLIA_KEY_BITS; // Table 2:137

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

Family “2.0”Level 00 Revision 01.64// Table 2:136// Table 2:138
tdes;
aes;
sm4;
camellia;
sym;
xor;

// Table 2:139
tdes;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 186
December 24, 2020

Part 4: Supporting Routines
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
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

#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 {UINT16BYTE}
TPM2B} TPM2B_LABEL;

aes;
sm4;
camellia;sym;// Table 2:141
algorithm;
keyBits;mode;// Table 2:142
algorithm;
keyBits;mode;// Table 2:143
size;
buffer[MAX_SYM_KEY_BYTES];// Table 2:144
sym;// Table 2:145
size;
buffer[LABEL_MAX_BUFFER];t;b;

typedef struct {TPM2B_LABELTPM2B_LABEL} TPMS_DERIVE;
typedef union {struct {UINT16BYTE}
TPM2B} TPM2B_DERIVE;

Trusted Platform Module Library// Table 2:146
label;
context;// Table 2:147
size;
buffer[sizeof(TPMS_DERIVE)];t;b;typedef union {BYTE
TPMS_DERIVE} TPMU_SENSITIVE_CREATE;
typedef union {struct {UINT16BYTE

Family “2.0”Level 00 Revision 01.64// Table 2:148
create[MAX_SYM_DATA];
derive;// Table 2:149
size;
buffer[sizeof(TPMU_SENSITIVE_CREATE)];TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 187
December 24, 2020

Part 4: Supporting Routines
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666

Trusted Platform Module Library

}
t;
TPM2B
b;
} TPM2B_SENSITIVE_DATA;
typedef struct {TPM2B_AUTH
TPM2B_SENSITIVE_DATA} TPMS_SENSITIVE_CREATE;

userAuth;data;// Table 2:150

typedef struct {UINT16
TPMS_SENSITIVE_CREATE} TPM2B_SENSITIVE_CREATE;

size;
sensitive;// Table 2:151

typedef struct {TPMI_ALG_HASH} TPMS_SCHEME_HASH;

hashAlg;// Table 2:152

typedef struct {TPMI_ALG_HASHUINT16} TPMS_SCHEME_ECDAA;

hashAlg;
count;

typedef TPM_ALG_ID

TPMI_ALG_KEYEDHASH_SCHEME;// Table 2:153

TPM 2.0 Part 2: Table 155 - Definition of Types for HMAC_SIG_SCHEME
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686

typedef TPMS_SCHEME_HASH

TPMS_SCHEME_HMAC;

typedef struct {TPMI_ALG_HASH
TPMI_ALG_KDF} TPMS_SCHEME_XOR;

hashAlg;
kdf;

typedef union {#if ALG_HMAC
TPMS_SCHEME_HMAC#endif // ALG_HMAC#if ALG_XOR
TPMS_SCHEME_XOR#endif // ALG_XOR} TPMU_SCHEME_KEYEDHASH;// Table 2:156// Table 2:157
hmac;
xor;

typedef struct {TPMI_ALG_KEYEDHASH_SCHEME
TPMU_SCHEME_KEYEDHASH} TPMT_KEYEDHASH_SCHEME;// Table 2:158
scheme;details;

TPM 2.0 Part 2: Table 159 - Definition of Types for RSA Signature Schemes
1687
1688

typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH

TPMS_SIG_SCHEME_RSASSA;TPMS_SIG_SCHEME_RSAPSS;TPM 2.0 Part 2: Table 160 - Definition of Types for ECC Signature Schemes
1689
1690
1691
1692
1693
1694
1695
1696
1697

typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_ECDAA
typedef union {#if ALG_ECC
TPMS_SIG_SCHEME_ECDAA#endif // ALG_ECC

Family “2.0”Level 00 Revision 01.64

TPMS_SIG_SCHEME_ECDSA;TPMS_SIG_SCHEME_SM2;
TPMS_SIG_SCHEME_ECSCHNORR;
TPMS_SIG_SCHEME_ECDAA;// Table 2:161
ecdaa;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 188
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#if ALG_RSASSA
TPMS_SIG_SCHEME_RSASSA#endif // ALG_RSASSA#if ALG_RSAPSSTPMS_SIG_SCHEME_RSAPSS#endif // ALG_RSAPSS#if ALG_ECDSATPMS_SIG_SCHEME_ECDSA#endif // ALG_ECDSA#if ALG_SM2
TPMS_SIG_SCHEME_SM2#endif // ALG_SM2#if ALG_ECSCHNORR
TPMS_SIG_SCHEME_ECSCHNORR#endif // ALG_ECSCHNORR#if ALG_HMAC
TPMS_SCHEME_HMAC#endif // ALG_HMAC
TPMS_SCHEME_HASH} TPMU_SIG_SCHEME;
typedef struct {TPMI_ALG_SIG_SCHEME
TPMU_SIG_SCHEME} TPMT_SIG_SCHEME;

rsassa;rsapss;ecdsa;
sm2;
ecschnorr;
hmac;
any;
// Table 2:162
scheme;details;

TPM 2.0 Part 2: Table 163 - Definition of Types for Encryption Schemes
1723
1724

typedef TPMS_SCHEME_HASH
typedef TPMS_EMPTYTPMS_ENC_SCHEME_OAEP;TPMS_ENC_SCHEME_RSAES;TPM 2.0 Part 2: Table 164 - Definition of Types for ECC Key Exchange
1725
1726

typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH

TPMS_KEY_SCHEME_ECDH;
TPMS_KEY_SCHEME_ECMQV;

TPM 2.0 Part 2: Table 165 - Definition of Types for KDF Schemes
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

typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH
typedef TPMS_SCHEME_HASH

TPMS_KDF_SCHEME_MGF1;
TPMS_KDF_SCHEME_KDF1_SP800_56A;
TPMS_KDF_SCHEME_KDF2;
TPMS_KDF_SCHEME_KDF1_SP800_108;

typedef union {#if ALG_MGF1
TPMS_KDF_SCHEME_MGF1#endif // ALG_MGF1#if ALG_KDF1_SP800_56A
TPMS_KDF_SCHEME_KDF1_SP800_56A#endif // ALG_KDF1_SP800_56A#if ALG_KDF2
TPMS_KDF_SCHEME_KDF2#endif // ALG_KDF2#if ALG_KDF1_SP800_108
TPMS_KDF_SCHEME_KDF1_SP800_108#endif // ALG_KDF1_SP800_108
TPMS_SCHEME_HASH} TPMU_KDF_SCHEME;
typedef struct {TPMI_ALG_KDF
TPMU_KDF_SCHEME} TPMT_KDF_SCHEME;Family “2.0”Level 00 Revision 01.64// Table 2:166
mgf1;
kdf1_sp800_56a;
kdf2;
kdf1_sp800_108;
anyKdf;// Table 2:167

scheme;details;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 189
December 24, 2020

Part 4: Supporting Routines
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
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818

typedef TPM_ALG_ID

Trusted Platform Module Library
TPMI_ALG_ASYM_SCHEME;

typedef union {#if ALG_ECDH
TPMS_KEY_SCHEME_ECDH#endif // ALG_ECDH#if ALG_ECMQV
TPMS_KEY_SCHEME_ECMQV#endif // ALG_ECMQV#if ALG_ECC
TPMS_SIG_SCHEME_ECDAA#endif // ALG_ECC#if ALG_RSASSA
TPMS_SIG_SCHEME_RSASSA#endif // ALG_RSASSA#if ALG_RSAPSSTPMS_SIG_SCHEME_RSAPSS#endif // ALG_RSAPSS#if ALG_ECDSATPMS_SIG_SCHEME_ECDSA#endif // ALG_ECDSA#if ALG_SM2
TPMS_SIG_SCHEME_SM2#endif // ALG_SM2#if ALG_ECSCHNORR
TPMS_SIG_SCHEME_ECSCHNORR#endif // ALG_ECSCHNORR#if ALG_RSAESTPMS_ENC_SCHEME_RSAES#endif // ALG_RSAES#if ALG_OAEP
TPMS_ENC_SCHEME_OAEP#endif // ALG_OAEP
TPMS_SCHEME_HASH} TPMU_ASYM_SCHEME;
typedef struct {TPMI_ALG_ASYM_SCHEME
TPMU_ASYM_SCHEME} TPMT_ASYM_SCHEME;
typedef TPM_ALG_ID
typedef struct {TPMI_ALG_RSA_SCHEME
TPMU_ASYM_SCHEME} TPMT_RSA_SCHEME;
typedef TPM_ALG_ID
typedef struct {TPMI_ALG_RSA_DECRYPTTPMU_ASYM_SCHEME} TPMT_RSA_DECRYPT;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_PUBLIC_KEY_RSA;
typedef TPM_KEY_BITS
typedef union {Family “2.0”Level 00 Revision 01.64// Table 2:168// Table 2:169

ecdh;
ecmqv;
ecdaa;
rsassa;rsapss;ecdsa;
sm2;
ecschnorr;rsaes;
oaep;
anySig;// Table 2:170
scheme;details;

TPMI_ALG_RSA_SCHEME;// Table 2:171// Table 2:172

scheme;details;
TPMI_ALG_RSA_DECRYPT;// Table 2:173// Table 2:174

scheme;details;// Table 2:175
size;
buffer[MAX_RSA_KEY_BYTES];TPMI_RSA_KEY_BITS;// Table 2:176// Table 2:177

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 190
December 24, 2020

Part 4: Supporting Routines
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
1866
1867
1868
1869
1870

Trusted Platform Module Librarystruct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_PRIVATE_KEY_RSA;

size;buffer[RSA_PRIVATE_SIZE];

typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_ECC_PARAMETER;// Table 2:178
size;
buffer[MAX_ECC_KEY_BYTES];

typedef struct {TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER} TPMS_ECC_POINT;// Table 2:179
x;y;typedef struct {UINT16
TPMS_ECC_POINT} TPM2B_ECC_POINT;

size;
point;// Table 2:180

typedef TPM_ALG_ID

TPMI_ALG_ECC_SCHEME;// Table 2:181

typedef TPM_ECC_CURVE

TPMI_ECC_CURVE;// Table 2:182

typedef struct {TPMI_ALG_ECC_SCHEME
TPMU_ASYM_SCHEME} TPMT_ECC_SCHEME;

scheme;details;

typedef struct {TPM_ECC_CURVEUINT16
TPMT_KDF_SCHEME
TPMT_ECC_SCHEME
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER
TPM2B_ECC_PARAMETER} TPMS_ALGORITHM_DETAIL_ECC;

curveID;
keySize;
kdf;
sign;
p;
a;
b;
gX;
gY;
n;
h;

typedef struct {TPMI_ALG_HASH
TPM2B_PUBLIC_KEY_RSA} TPMS_SIGNATURE_RSA;

hash;
sig;

// Table 2:183// Table 2:184// Table 2:185

TPM 2.0 Part 2: Table 186 - Definition of Types for Signature
1871
1872
1873
1874
1875
1876
1877
1878

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:187
hash;signatureR;
signatureS;

TPM 2.0 Part 2: Table 188 - Definition of Types for TPMS_SIGNATURE_ECC
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 191
December 24, 2020

Part 4: Supporting Routines
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
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

typedef TPMS_SIGNATURE_ECC
typedef TPMS_SIGNATURE_ECC
typedef TPMS_SIGNATURE_ECC
typedef TPMS_SIGNATURE_ECC

Trusted Platform Module Library
TPMS_SIGNATURE_ECDAA;
TPMS_SIGNATURE_ECDSA;TPMS_SIGNATURE_SM2;
TPMS_SIGNATURE_ECSCHNORR;

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#if ALG_ECC
TPMS_SIGNATURE_ECDSA#endif // ALG_ECC#if ALG_ECC
TPMS_SIGNATURE_SM2#endif // ALG_ECC#if ALG_ECC
TPMS_SIGNATURE_ECSCHNORR#endif // ALG_ECC#if ALG_HMAC
TPMT_HA#endif // ALG_HMAC
TPMS_SCHEME_HASH} TPMU_SIGNATURE;
typedef struct {TPMI_ALG_SIG_SCHEME
TPMU_SIGNATURE} TPMT_SIGNATURE;
typedef union {#if ALG_ECC
BYTE#endif // ALG_ECC#if ALG_RSA
BYTE#endif // ALG_RSA#if ALG_SYMCIPHER
BYTE#endif // ALG_SYMCIPHER#if ALG_KEYEDHASH
BYTE#endif // ALG_KEYEDHASH} TPMU_ENCRYPTED_SECRET;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_ENCRYPTED_SECRET;
typedef TPM_ALG_ID
typedef union {#if ALG_KEYEDHASHTPM2B_DIGEST#endif // ALG_KEYEDHASH#if ALG_SYMCIPHER
TPM2B_DIGEST

Family “2.0”Level 00 Revision 01.64// Table 2:189
ecdaa;
rsassa;rsapss;ecdsa;
sm2;
ecschnorr;
hmac;
any;
// Table 2:190
sigAlg;signature;// Table 2:191
ecc[sizeof(TPMS_ECC_POINT)];rsa[MAX_RSA_KEY_BYTES];
symmetric[sizeof(TPM2B_DIGEST)];
keyedHash[sizeof(TPM2B_DIGEST)];// Table 2:192
size;
secret[sizeof(TPMU_ENCRYPTED_SECRET)];

TPMI_ALG_PUBLIC;// Table 2:193// Table 2:194

keyedHash;sym;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 192
December 24, 2020

Part 4: Supporting Routines
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
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010

#endif // ALG_SYMCIPHER#if ALG_RSA
TPM2B_PUBLIC_KEY_RSA#endif // ALG_RSA#if ALG_ECC
TPMS_ECC_POINT#endif // ALG_ECC
TPMS_DERIVE} TPMU_PUBLIC_ID;

Trusted Platform Module Library

rsa;
ecc;
derive;typedef struct {TPMT_KEYEDHASH_SCHEME} TPMS_KEYEDHASH_PARMS;

scheme;typedef struct {TPMT_SYM_DEF_OBJECT
TPMT_ASYM_SCHEME} TPMS_ASYM_PARMS;

symmetric;
scheme;typedef struct {TPMT_SYM_DEF_OBJECT
TPMT_RSA_SCHEME
TPMI_RSA_KEY_BITS
UINT32} TPMS_RSA_PARMS;

symmetric;
scheme;keyBits;
exponent;

typedef struct {TPMT_SYM_DEF_OBJECT
TPMT_ECC_SCHEME
TPMI_ECC_CURVE
TPMT_KDF_SCHEME} TPMS_ECC_PARMS;

symmetric;
scheme;curveID;
kdf;

typedef union {#if ALG_KEYEDHASH
TPMS_KEYEDHASH_PARMS#endif // ALG_KEYEDHASH#if ALG_SYMCIPHER
TPMS_SYMCIPHER_PARMS#endif // ALG_SYMCIPHER#if ALG_RSA
TPMS_RSA_PARMS#endif // ALG_RSA#if ALG_ECC
TPMS_ECC_PARMS#endif // ALG_ECC
TPMS_ASYM_PARMS} TPMU_PUBLIC_PARMS;// Table 2:195// Table 2:196// Table 2:197// Table 2:198// Table 2:199
keyedHashDetail;symDetail;rsaDetail;eccDetail;asymDetail;typedef struct {TPMI_ALG_PUBLIC
TPMU_PUBLIC_PARMS} TPMT_PUBLIC_PARMS;

type;
parameters;

typedef struct {TPMI_ALG_PUBLICTPMI_ALG_HASH
TPMA_OBJECT
TPM2B_DIGEST
TPMU_PUBLIC_PARMS
TPMU_PUBLIC_ID} TPMT_PUBLIC;

type;
nameAlg;
objectAttributes;
authPolicy;
parameters;
unique;typedef struct {UINT16
TPMT_PUBLIC

Family “2.0”Level 00 Revision 01.64// Table 2:200// Table 2:201// Table 2:202
size;
publicArea;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 193
December 24, 2020

Part 4: Supporting Routines
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
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076

Trusted Platform Module Library} TPM2B_PUBLIC;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_TEMPLATE;// Table 2:203
size;
buffer[sizeof(TPMT_PUBLIC)];

typedef union {// Table 2:204
struct {UINT16size;
BYTE
buffer[PRIVATE_VENDOR_SPECIFIC_BYTES];
}
t;
TPM2B
b;
} TPM2B_PRIVATE_VENDOR_SPECIFIC;
typedef union {#if ALG_RSA
TPM2B_PRIVATE_KEY_RSA#endif // ALG_RSA#if ALG_ECC
TPM2B_ECC_PARAMETER#endif // ALG_ECC#if ALG_KEYEDHASHTPM2B_SENSITIVE_DATA#endif // ALG_KEYEDHASH#if ALG_SYMCIPHER
TPM2B_SYM_KEY#endif // ALG_SYMCIPHER
TPM2B_PRIVATE_VENDOR_SPECIFIC} TPMU_SENSITIVE_COMPOSITE;
typedef struct {TPMI_ALG_PUBLIC
TPM2B_AUTH
TPM2B_DIGEST
TPMU_SENSITIVE_COMPOSITE} TPMT_SENSITIVE;// Table 2:205
rsa;
ecc;
bits;
sym;
any;
// Table 2:206
sensitiveType;authValue;
seedValue;sensitive;

typedef struct {UINT16
TPMT_SENSITIVE} TPM2B_SENSITIVE;

size;
sensitiveArea;

typedef struct {TPM2B_DIGESTTPM2B_DIGESTTPM2B_SENSITIVE} _PRIVATE;

integrityOuter;
integrityInner;sensitive;

typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_PRIVATE;
typedef struct {TPM2B_DIGESTTPM2B_DIGEST} TPMS_ID_OBJECT;
typedef union {Family “2.0”Level 00 Revision 01.64// Table 2:207// Table 2:208// Table 2:209
size;
buffer[sizeof(_PRIVATE)];// Table 2:210
integrityHMAC;
encIdentity;// Table 2:211

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 194
December 24, 2020

Part 4: Supporting Routines
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095

struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_ID_OBJECT;

Trusted Platform Module Librarysize;
credential[sizeof(TPMS_ID_OBJECT)];#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:212
unsigned
index
: 24;
unsigned
RH_NV: 8;} TPM_NV_INDEX;This is the initializer for a TPM_NV_INDEX structure
2096
2097

#define TPM_NV_INDEX_INITIALIZER(index, rh_nv) {index, rh_nv}#else // USE_BIT_FIELD_STRUCTURES

This implements Table 2:212 TPM_NV_INDEX using bit masking
2098
2099
2100
2101
2102
2103

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.
2104
2105
2106
2107

#define TPM_NV_INDEX_INITIALIZER(index, rh_nv)(TPM_NV_INDEX)((index << 0) + (rh_nv << 24))
#endif // USE_BIT_FIELD_STRUCTURES\\

TPM 2.0 Part 2: Table 213 - Definition of TPM_NT Constants
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128

typedef UINT32#define TYPE_OF_TPM_NT#define TPM_NT_ORDINARY#define TPM_NT_COUNTER#define TPM_NT_BITS#define TPM_NT_EXTEND#define TPM_NT_PIN_FAIL#define TPM_NT_PIN_PASS

TPM_NT;UINT32(TPM_NT)(0x0)(TPM_NT)(0x1)(TPM_NT)(0x2)(TPM_NT)(0x4)(TPM_NT)(0x8)(TPM_NT)(0x9)typedef struct {UINT32
pinCount;
UINT32pinLimit;} TPMS_NV_PIN_COUNTER_PARAMETERS;// Table 2:214#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); }Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 195
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#if USE_BIT_FIELD_STRUCTURES
typedef struct TPMA_NV {unsigned
PPWRITE
unsigned
OWNERWRITE
unsigned
AUTHWRITE
unsigned
POLICYWRITE
unsigned
TPM_NT
unsigned
Reserved_bits_at_8
unsigned
POLICY_DELETE
unsigned
WRITELOCKED
unsigned
WRITEALL
unsigned
WRITEDEFINE
unsigned
WRITE_STCLEAR
unsigned
GLOBALLOCK
unsigned
PPREAD
unsigned
OWNERREAD
unsigned
AUTHREAD
unsigned
POLICYREAD
unsigned
Reserved_bits_at_20
unsigned
NO_DA
unsigned
ORDERLY
unsigned
CLEAR_STCLEAR
unsigned
READLOCKED
unsigned
WRITTEN
unsigned
PLATFORMCREATE
unsigned
READ_STCLEAR} TPMA_NV;// Table 2:215
: 1;
: 1;
: 1;
: 1;
: 4;
: 2;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 5;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;
: 1;

This is the initializer for a TPMA_NV structure
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169

#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,
bits_at_20,
no_da,
readlocked,
written,#else // USE_BIT_FIELD_STRUCTURES

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,orderly,
clear_stclear,platformcreate, read_stclear}

\
\
\
\
\
\
\
\
\
\
\
\

This implements Table 2:215 TPMA_NV using bit masking
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187

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

Family “2.0”Level 00 Revision 01.64

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)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 196
December 24, 2020

Part 4: Supporting Routines
2188
2189
2190
2191
2192
2193
2194

Trusted Platform Module Library#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)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.
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

#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)(TPMA_NV)((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 {TPMI_RH_NV_INDEXTPMI_ALG_HASH
TPMA_NVTPM2B_DIGESTUINT16} TPMS_NV_PUBLIC;

nvIndex;
nameAlg;
attributes;
authPolicy;
dataSize;

typedef struct {UINT16
TPMS_NV_PUBLIC} TPM2B_NV_PUBLIC;

size;
nvPublic;

typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_CONTEXT_SENSITIVE;
typedef struct {TPM2B_DIGESTTPM2B_CONTEXT_SENSITIVE} TPMS_CONTEXT_DATA;
typedef union {struct {UINT16
BYTE
}
t;
TPM2B
b;
} TPM2B_CONTEXT_DATA;

Family “2.0”Level 00 Revision 01.64

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

// Table 2:216// Table 2:217// Table 2:218
size;
buffer[MAX_CONTEXT_SIZE];// Table 2:219
integrity;
encrypted;// Table 2:220
size;
buffer[sizeof(TPMS_CONTEXT_DATA)];TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 197
December 24, 2020

Part 4: Supporting Routines
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270

Trusted Platform Module Library

typedef struct {UINT64
TPMI_DH_SAVED
TPMI_RH_HIERARCHYTPM2B_CONTEXT_DATA} TPMS_CONTEXT;

sequence;
savedHandle;
hierarchy;
contextBlob;// Table 2:221

typedef struct {TPML_PCR_SELECTION
TPM2B_DIGEST
TPMA_LOCALITY
TPM_ALG_ID
TPM2B_NAME
TPM2B_NAME
TPM2B_DATA} TPMS_CREATION_DATA;

pcrSelect;
pcrDigest;
locality;
parentNameAlg;
parentName;
parentQualifiedName;outsideInfo;

typedef struct {UINT16
TPMS_CREATION_DATA} TPM2B_CREATION_DATA;

size;
creationData;// Table 2:223// Table 2:224

TPM 2.0 Part 2: Table 225 - Definition of TPM_AT Constants
2271
2272
2273
2274
2275
2276

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)

TPM 2.0 Part 2: Table 226 - Definition of TPM_AE Constants
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291

typedef UINT32#define TYPE_OF_TPM_AE#define TPM_AE_NONE

TPM_AE;UINT32(TPM_AE)(0x00000000)

typedef struct {TPM_ATUINT32} TPMS_AC_OUTPUT;

tag;
data;

typedef struct {UINT32
TPMS_AC_OUTPUT} TPML_AC_CAPABILITIES;// Table 2:227// Table 2:228
count;
acCapabilities[MAX_AC_CAPABILITIES];#endif // _TPM_TYPES_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 198
December 24, 2020

Part 4: Supporting Routines

5.20
1
2

Trusted Platform Module Library

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
13

#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.
14
15
16
17

#ifndef VENDOR_STRING_1#error VENDOR_STRING_1 is not provided. \Please modify include/VendorString.h to provide a vendor-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
26

#ifndef FIRMWARE_V1#error FIRMWARE_V1 is not provided. \Please modify include/VendorString.h to provide a vendor-specific firmware \version#endif#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 199
December 24, 2020

Part 4: Supporting Routines

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

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

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)

AUTO_ALIGN == NO

The aggregation macros for machines that do not allow unaligned access or for little-endian machines.
Aggregate bytes into an UINT
21
22
23
24
25
26
27
28
29
30
31
32

#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
33
34
35
36

#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
37
38
39
40
41

#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
42
43
44
45

#define BYTE_ARRAY_TO_UINT8(b)#define BYTE_ARRAY_TO_UINT16(b)#define BYTE_ARRAY_TO_UINT32(b)#define BYTE_ARRAY_TO_UINT64(b)Family “2.0”Level 00 Revision 01.64*((uint8_t *)(b))
REVERSE_ENDIAN_16(*((uint16_t *)(b)))
REVERSE_ENDIAN_32(*((uint32_t *)(b)))
REVERSE_ENDIAN_64(*((uint64_t *)(b)))

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 200
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Disaggregate a UINT into a byte array
46
47
48
49
50
51
52
53
54

#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)#endif// BIG_ENDIAN_TPM#endif// AUTO_ALIGN == NO#endif// _SWAP_H

Family “2.0”Level 00 Revision 01.64{*((uint8_t *)(b)) = (i);}{*((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-2021

Page 201
December 24, 2020

Part 4: Supporting Routines

5.22
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
62
63

Trusted Platform Module LibraryACT.h#ifndef _ACT_H_#define _ACT_H_#include "TpmProfile.h"#if !(defined RH_ACT_0) || (RH_ACT_0 != YES)#
undef
RH_ACT_0#
define RH_ACT_0 NO#
define IF_ACT_0_IMPLEMENTED(op)#else#define IF_ACT_0_IMPLEMENTED(op) op(0)#endif#if !(defined RH_ACT_1) || (RH_ACT_1 != YES)#
undef
RH_ACT_1#
define RH_ACT_1 NO#
define IF_ACT_1_IMPLEMENTED(op)#else#define IF_ACT_1_IMPLEMENTED(op) op(1)#endif#if !(defined RH_ACT_2) || (RH_ACT_2 != YES)#
undef
RH_ACT_2#
define RH_ACT_2 NO#
define IF_ACT_2_IMPLEMENTED(op)#else#define IF_ACT_2_IMPLEMENTED(op) op(2)#endif#if !(defined RH_ACT_3) || (RH_ACT_3 != YES)#
undef
RH_ACT_3#
define RH_ACT_3 NO#
define IF_ACT_3_IMPLEMENTED(op)#else#define IF_ACT_3_IMPLEMENTED(op) op(3)#endif#if !(defined RH_ACT_4) || (RH_ACT_4 != YES)#
undef
RH_ACT_4#
define RH_ACT_4 NO#
define IF_ACT_4_IMPLEMENTED(op)#else#define IF_ACT_4_IMPLEMENTED(op) op(4)#endif#if !(defined RH_ACT_5) || (RH_ACT_5 != YES)#
undef
RH_ACT_5#
define RH_ACT_5 NO#
define IF_ACT_5_IMPLEMENTED(op)#else#define IF_ACT_5_IMPLEMENTED(op) op(5)#endif#if !(defined RH_ACT_6) || (RH_ACT_6 != YES)#
undef
RH_ACT_6#
define RH_ACT_6 NO#
define IF_ACT_6_IMPLEMENTED(op)#else#define IF_ACT_6_IMPLEMENTED(op) op(6)#endif#if !(defined RH_ACT_7) || (RH_ACT_7 != YES)#
undef
RH_ACT_7#
define RH_ACT_7 NO#
define IF_ACT_7_IMPLEMENTED(op)#else#define IF_ACT_7_IMPLEMENTED(op) op(7)#endif#if !(defined RH_ACT_8) || (RH_ACT_8 != YES)#
undef
RH_ACT_8

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 202
December 24, 2020

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

Trusted Platform Module Library#define RH_ACT_8 NO#
define IF_ACT_8_IMPLEMENTED(op)#else#define IF_ACT_8_IMPLEMENTED(op) op(8)#endif#if !(defined RH_ACT_9) || (RH_ACT_9 != YES)#
undef
RH_ACT_9#
define RH_ACT_9 NO#
define IF_ACT_9_IMPLEMENTED(op)#else#define IF_ACT_9_IMPLEMENTED(op) op(9)#endif#if !(defined RH_ACT_A) || (RH_ACT_A != YES)#
undef
RH_ACT_A#
define RH_ACT_A NO#
define IF_ACT_A_IMPLEMENTED(op)#else#define IF_ACT_A_IMPLEMENTED(op) op(A)#endif#if !(defined RH_ACT_B) || (RH_ACT_B != YES)#
undef
RH_ACT_B#
define RH_ACT_B NO#
define IF_ACT_B_IMPLEMENTED(op)#else#define IF_ACT_B_IMPLEMENTED(op) op(B)#endif#if !(defined RH_ACT_C) || (RH_ACT_C != YES)#
undef
RH_ACT_C#
define RH_ACT_C NO#
define IF_ACT_C_IMPLEMENTED(op)#else#define IF_ACT_C_IMPLEMENTED(op) op(C)#endif#if !(defined RH_ACT_D) || (RH_ACT_D != YES)#
undef
RH_ACT_D#
define RH_ACT_D NO#
define IF_ACT_D_IMPLEMENTED(op)#else#define IF_ACT_D_IMPLEMENTED(op) op(D)#endif#if !(defined RH_ACT_E) || (RH_ACT_E != YES)#
undef
RH_ACT_E#
define RH_ACT_E NO#
define IF_ACT_E_IMPLEMENTED(op)#else#define IF_ACT_E_IMPLEMENTED(op) op(E)#endif#if !(defined RH_ACT_F) || (RH_ACT_F != YES)#
undef
RH_ACT_F#
define RH_ACT_F NO#
define IF_ACT_F_IMPLEMENTED(op)#else#define IF_ACT_F_IMPLEMENTED(op) op(F)#endif#ifndef TPM_RH_ACT_0#error Need numeric definition for TPM_RH_ACT_0#endif#ifndef TPM_RH_ACT_1#
define TPM_RH_ACT_1#endif#ifndef TPM_RH_ACT_2#
define TPM_RH_ACT_2#endif#ifndef TPM_RH_ACT_3

Family “2.0”Level 00 Revision 01.64(TPM_RH_ACT_0 + 1)
(TPM_RH_ACT_0 + 2)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 203
December 24, 2020

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

#
define TPM_RH_ACT_3#endif#ifndef TPM_RH_ACT_4#
define TPM_RH_ACT_4#endif#ifndef TPM_RH_ACT_5#
define TPM_RH_ACT_5#endif#ifndef TPM_RH_ACT_6#
define TPM_RH_ACT_6#endif#ifndef TPM_RH_ACT_7#
define TPM_RH_ACT_7#endif#ifndef TPM_RH_ACT_8#
define TPM_RH_ACT_8#endif#ifndef TPM_RH_ACT_9#
define TPM_RH_ACT_9#endif#ifndef TPM_RH_ACT_A#
define TPM_RH_ACT_A#endif#ifndef TPM_RH_ACT_B#
define TPM_RH_ACT_B#endif#ifndef TPM_RH_ACT_C#
define TPM_RH_ACT_C#endif#ifndef TPM_RH_ACT_D#
define TPM_RH_ACT_D#endif#ifndef TPM_RH_ACT_E#
define TPM_RH_ACT_E#endif#ifndef TPM_RH_ACT_F#
define TPM_RH_ACT_F#endifTrusted Platform Module Library(TPM_RH_ACT_0 + 3)
(TPM_RH_ACT_0 + 4)
(TPM_RH_ACT_0 + 5)
(TPM_RH_ACT_0 + 6)
(TPM_RH_ACT_0 + 7)
(TPM_RH_ACT_0 + 8)
(TPM_RH_ACT_0 + 9)
(TPM_RH_ACT_0 + 0xA)
(TPM_RH_ACT_0 + 0xB)
(TPM_RH_ACT_0 + 0xC)
(TPM_RH_ACT_0 + 0xD)
(TPM_RH_ACT_0 + 0xE)
(TPM_RH_ACT_0 + 0xF)

#define FOR_EACH_ACT(op)
IF_ACT_0_IMPLEMENTED(op)
IF_ACT_1_IMPLEMENTED(op)
IF_ACT_2_IMPLEMENTED(op)
IF_ACT_3_IMPLEMENTED(op)
IF_ACT_4_IMPLEMENTED(op)
IF_ACT_5_IMPLEMENTED(op)
IF_ACT_6_IMPLEMENTED(op)
IF_ACT_7_IMPLEMENTED(op)
IF_ACT_8_IMPLEMENTED(op)
IF_ACT_9_IMPLEMENTED(op)
IF_ACT_A_IMPLEMENTED(op)
IF_ACT_B_IMPLEMENTED(op)
IF_ACT_C_IMPLEMENTED(op)
IF_ACT_D_IMPLEMENTED(op)
IF_ACT_E_IMPLEMENTED(op)
IF_ACT_F_IMPLEMENTED(op)

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

This is the mask for ACT that are implemented
186
187
188
189
190
191

//#define ACT_MASK(N)| (1 << 0x##N)//#define ACT_IMPLEMENTED_MASK(0 FOR_EACH_ACT(ACT_MASK))#define CASE_ACT_HANDLE(N)#define CASE_ACT_NUMBER(N)

Family “2.0”Level 00 Revision 01.64

case TPM_RH_ACT_##N:
case 0x##N:

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 204
December 24, 2020

Part 4: Supporting Routines
192
193
194
195
196
197
198
199

Trusted Platform Module Library

typedef struct ACT_STATE{UINT32
remaining;
TPM_ALG_ID
hashAlg;
TPM2B_DIGEST
authPolicy;} ACT_STATE, *P_ACT_STATE;#endif // _ACT_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 205
December 24, 2020

Part 4: Supporting Routines

6

Trusted Platform Module Library

Main

6.1

Introduction

The files in this clause 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 sizing
3
4// #include "CommandResponseSizes_fp.h"

6.2.3

ExecuteCommand()The function performs the following steps.
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 BuildResponseSession() to:1) when necessary, encrypt a parameter2) build the response authorization sessions
3) update the audit sessions and nonces
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 206
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryCalls 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

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

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// 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 207
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 208
December 24, 2020

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

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;}
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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 209
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarygoto 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;}
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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 210
December 24, 2020

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

Unlike other unmarshaling functions, parmBufferStart does not advance but parmBufferSize is reduced.

Includes and Typedefs#include "Tpm.h"#include "Marshal.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_ARGSCOMMAND_IN_ARG
COMMAND_OUT_ARG
COMMAND_INOUT_ARG} COMMAND_t;*noArgs;*inArg;*outArg;*inOutArg;

This structure is used by ParseHandleBuffer() and CommandDispatcher(). The parameters in thisstructure are unique for each command. The parameters are:commandholds the address of the command processing function that is called by Command
Dispatcher

inSizeThis is the size of the command-dependent input structure. The input structure holds theunmarshaled handles and command parameters. If the command takes no arguments(handles or parameters) then inSize will have a value of 0.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 211
December 24, 2020

Part 4: Supporting Routines

26
27
28
29
30
31
32
33

Trusted Platform Module Library

outSize

This is the size of the command-dependent output structure. The output structure holds
the results of the command in an unmarshaled form. When command processing iscompleted, these values are marshaled into the output buffer. It is always the case thatthe unmarshaled version of an output structure is larger then the marshaled version. Thisis 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 marshaled or unmarshaled.
The list of types follows the offsets array. The offsets array is variable sized so thetypesOffset filed is necessary for the handle and command processing to be able to findthe types that are being handled. The offsets array may be empty. The types structure is
described below.

offsets

This is an array of offsets of each of the parameters in the command or response. When
processing the command parameters (not handles) the list contains the offset of the next
parameter. For example, if the first command parameter has a size of 4 and there is asecond command parameter, then the offset would be 4, indicating that the second
parameter starts at 4. If the second parameter has a size of 8, and there is a thirdparameter, then the second entry in offsets is 12 (4 for the first parameter and 8 for thesecond). 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 andcall command. If a command has no response parameters and only one commandparameter, 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:

34
35
36
37
38

0

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 andunmarshaling functions. The types list is constructedwith a byte of 0xff at the end of the commandparameters and with an 0xff at the end of the response
parameters.

#if COMPRESSED_LISTS#
define PAD_LIST 0#else#
define PAD_LIST 1#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 212
December 24, 2020

Part 4: Supporting Routines
39
40
41
42
43
44
45
46
47
48
49
50

Trusted Platform Module Library#define _COMMAND_TABLE_DISPATCH_#include "CommandDispatchData.h"#define TEST_COMMAND

TPM_CC_Startup#define NEW_CC#else#include "Commands.h"#endif

6.3.3
6.3.3.1

Marshal/Unmarshal Functions
ParseHandleBuffer()

This is the table-driven version of the handle buffer unmarshaling code
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

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;// 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++){#if TABLE_DRIVEN_MARSHAL
marshalIndex_t
index;
index = unmarshalArray[dType] | ((type & 0x80) ? NULL_FLAG : 0);
result = Unmarshal(index, &(command->handles[command->handleNum]),&command->parameterBuffer, &command->parameterSize);#else// See if unmarshaling of this handle type requires a flagif(dType < HANDLE_FIRST_FLAG_TYPE)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 213
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library{// 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);}#endif// 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.3.2

CommandDispatcher()

Function to unmarshal the command parameters, call the selected action code, and marshal the
response parameters.
141
142
143
144
145
146
147
148
149
150
151
152

TPM_RC
CommandDispatcher(
COMMAND)*command{#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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 214
December 24, 2020

Part 4: Supporting Routines
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
218

TPM_HANDLE

Trusted Platform Module Library*handles = &command->handles[0];//command->handleNum = 0;

MemoryIoBufferAllocationReset();// The command-specific code knows how// many handles there are. This is for// cataloging the number of response// handles// 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
commandIn = 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 buffer

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 215
December 24, 2020

Part 4: Supporting Routines
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
283
284

//

Trusted Platform Module Libraryfor(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 TABLE_DRIVEN_MARSHAL{
marshalIndex_t
index = unmarshalArray[dType];
index |= (type & 0x80) ? NULL_FLAG : 0;
result = Unmarshal(index, &commandIn[offset], &command->parameterBuffer,&command->parameterSize);}#else
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);}#endifif(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// marshaling type. If that type happens to be the STOP value, then there

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 216
December 24, 2020

Part 4: Supporting Routines
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
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

Trusted Platform Module Library// 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++){#if TABLE_DRIVEN_MARSHAL
marshalIndex_t
index = marshalArray[dType];command->parameterSize += Marshal(index, &commandOut[offset],&command->responseBuffer,&maxOutSize);#else
const MARSHAL_t
f = marshalArray[dType];command->parameterSize += f(&commandOut[offset],&command->responseBuffer,&maxOutSize);#endifoffset = *offsets++;}
result = (maxOutSize < 0) ? TPM_RC_FAILURE : TPM_RC_SUCCESS;
Exit:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 217
December 24, 2020

Part 4: Supporting Routines
351
352
353
354

Trusted Platform Module Library

MemoryIoBufferZero();return result;#endif}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 218
December 24, 2020

Part 4: Supporting Routines

6.4

SessionProcess.c

6.4.1

Introduction

Trusted Platform Module LibraryThis 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
3
4
5

Includes and Data Definitions#define SESSION_PROCESS_C#include "Tpm.h"#include "ACT.h"

6.4.3
6.4.3.1

Authorization Support Functions
IsDAExempted()

This function indicates if a handle is exempted from DA logic. A handle is exempted if it is:a primary seed handle;
an object with noDA bit SET;an NV Index with TPMA_NV_NO_DA bit SET; ora PCR handle.
Return Value

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

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 219
December 24, 2020

Part 4: Supporting Routines
31
32
33
34
35
36
37
38
39
40
41
42

Trusted Platform Module Library

result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA);
break;}
case 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.

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 Return

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 220
December 24, 2020

Part 4: Supporting Routines
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// the lockout authorization will be reset at startup.
if(gp.lockoutRecovery != 0){
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.
Return Value

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 221
December 24, 2020

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;the command requires the ADMIN role and the authorized entity is a permanent handle or an NV
Index; orthe authorized entity is a PCR belonging to a policy group, and has its policy initialized
Return Value

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 222
December 24, 2020

Part 4: Supporting Routines

6.4.3.5

Trusted Platform Module Library

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.
Return Value

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

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;
FOR_EACH_ACT(CASE_ACT_HANDLE){// The ACT auth value is not available if the platform is disabledresult = g_phEnable == SET;
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.
{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 223
December 24, 2020

Part 4: Supporting Routines
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
283
284

OBJECT
TPMA_OBJECT

Trusted Platform Module Library*object;
attributes;//
object = HandleToObject(handle);
attributes = object->publicArea.objectAttributes;// 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// a) userWithAuth bit is SET, or// b) 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:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 224
December 24, 2020

Part 4: Supporting Routines
285
286
287
288
289
290
291
292
293
294

Trusted Platform Module Library// PCR handle.
// authValue is always allowed for PCR
result = TRUE;
break;
default:// Otherwise, authValue is not available
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.
Return Value

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

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;#define ACT_GET_POLICY(N)case TPM_RH_ACT_##N:
if(go.ACT_##N.authPolicy.t.size != 0)
result = TRUE;
break;\\\\

FOR_EACH_ACT(ACT_GET_POLICY)
case TPM_RH_LOCKOUT:
if(gp.lockoutPolicy.t.size != 0)
result = TRUE;
break;
default:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 225
December 24, 2020

Part 4: Supporting Routines
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

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// 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
393

Trusted Platform Module Library

Session Parsing Functions
ClearCpRpHashes()

void

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 226
December 24, 2020

Part 4: Supporting Routines
394
395
396
397
398
399
400
401
402
403
404
405
406

Trusted Platform Module Library

ClearCpRpHashes(
COMMAND)*command{// The macros expand according to the implemented hash algorithms. An IDE may// complain that COMMAND does not contain SHA1CpHash or SHA1RpHash because of the// complexity of the macro expansion where the data space is defined; but, if SHA1// is implemented, it actually does and the compiler is happy.
#define CLEAR_CP_HASH(HASH, Hash)command->Hash##CpHash.b.size = 0;
FOR_EACH_HASH(CLEAR_CP_HASH)#define CLEAR_RP_HASH(HASH, Hash)command->Hash##RpHash.b.size = 0;
FOR_EACH_HASH(CLEAR_RP_HASH)}

6.4.4.2

GetCpHashPointer()

Function to get a pointer to the cpHash of the command
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

static TPM2B_DIGEST *GetCpHashPointer(
COMMAND
TPMI_ALG_HASH)*command,hashAlg

TPM2B_DIGEST*retVal;{//// Define the macro that will expand for each implemented algorithm in the switch// statement below.
#define GET_CP_HASH_POINTER(HASH, Hash)\case ALG_##HASH##_VALUE:\
retVal = (TPM2B_DIGEST *)&command->Hash##CpHash;\
break;
switch(hashAlg){// For each implemented hash, this will expand as defined above// by GET_CP_HASH_POINTER. Your IDE may complain that// 'struct "COMMAND" has no field "SHA1CpHash"' but the compiler says// it does, so...
FOR_EACH_HASH(GET_CP_HASH_POINTER)
default:
retVal = NULL;
break;}
return retVal;}

6.4.4.3

GetRpHashPointer()

Function to get a pointer to the RpHash() of the command
435
436
437
438
439
440
441
442
443
444
445

static TPM2B_DIGEST *GetRpHashPointer(
COMMAND
TPMI_ALG_HASH)*command,hashAlg

TPM2B_DIGEST*retVal;{//// Define the macro that will expand for each implemented algorithm in the switch// statement below.
#define GET_RP_HASH_POINTER(HASH, Hash)\

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 227
December 24, 2020

Part 4: Supporting Routines
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

Trusted Platform Module Librarycase ALG_##HASH##_VALUE:
retVal = (TPM2B_DIGEST *)&command->Hash##RpHash;
break;\\

switch(hashAlg){// For each implemented hash, this will expand as defined above// by GET_RP_HASH_POINTER. Your IDE may complain that// 'struct "COMMAND" has no field 'SHA1RpHash'" but the compiler says// it does, so...
FOR_EACH_HASH(GET_RP_HASH_POINTER)
default:
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.
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

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);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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 228
December 24, 2020

Part 4: Supporting Routines
499
500
501
502
503
504
505
506
507
508
509

Trusted Platform Module Librarystatic 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()
Return Value

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

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#endif)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 data

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 229
December 24, 2020

Part 4: Supporting Routines
550
551
552
553

Trusted Platform Module LibrarytHash.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.
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

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[].

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

Error Return

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 230
December 24, 2020

Part 4: Supporting Routines
595
596
597
598
599
600

else
{

Trusted Platform Module Library// 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.
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

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,// 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));

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 231
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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]),&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.

701

Error Return

Meaning

TPM_RC_AUTH_FAIL

authorization failure caused failureCount increment

TPM_RC_BAD_AUTH

authorization failure did not cause failureCount increment

static TPM_RC

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 232
December 24, 2020

Part 4: Supporting Routines
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721

Trusted Platform Module Library

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.

722
723
724
725
726
727
728
729
730
731

Error Return

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_HASHUINT8Family “2.0”Level 00 Revision 01.64*session;
authPolicy;
policyAlg;
locality;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 233
December 24, 2020

Part 4: Supporting Routines
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
790
791
792
793
794
795
796
797

Trusted Platform Module Library//// 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
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();Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 234
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Libraryif(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;}
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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 235
December 24, 2020

Part 4: Supporting Routines

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
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913

Trusted Platform Module Library

Error Return

Meaning

TPM_RC_SUCCSS

unmarshaled without error

TPM_RC_SIZE

the number of bytes unmarshaled is not the same as the value
for authorizationSize in the command

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(&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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 236
December 24, 2020

Part 4: Supporting Routines
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
977
978
979

Trusted Platform Module Library{// 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.
if(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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 237
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarys_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 ispending. Otherwise the TPM is locked out if checking for lockoutAuth (lockoutAuthCheck == TRUE) anduse of lockoutAuth is disabled, or failedTries >= maxTries

1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027

Error Return

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 238
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// ... 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.
Error Return

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 bea policy session)

TPM_RC_POLICY_FAIL

if policy session fails

TPM_RC_POLICY_CC

command code of policy was wrong

TPM_RC_EXPIRED

the policy session has expired

TPM_RC_PCR
TPM_RC_AUTH_UNAVAILABLE
1061
1062
1063
1064
1065
1066

authValue or authPolicy unavailable

static TPM_RC
CheckAuthSession(
COMMANDUINT32)*command,sessionIndex// IN: primary parsing structure// IN: index of session to be processed{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 239
December 24, 2020

Part 4: Supporting Routines
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
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

TPM_RCSESSIONTPM_HANDLE
TPM_HANDLE
TPM_HT
BOOL

Trusted Platform Module Library

result = TPM_RC_SUCCESS;*session = NULL;
sessionHandle = s_sessionHandles[sessionIndex];
associatedHandle = s_associatedHandles[sessionIndex];
sessionHandleType = HandleGetType(sessionHandle);
authUsed;//
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);}
authUsed = session->attributes.includeAuth;}else// Password session
authUsed = TRUE;// If the authorization session is going to use an authValue, then make sure// that access to that authValue isn't locked out.
if(authUsed){// 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 240
December 24, 2020

Part 4: Supporting Routines
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
1194
1195

Trusted Platform Module Libraryif(!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((TPM_RS_PW == sessionHandle) || (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.
if((TPM_HT_NV_INDEX == HandleGetType(associatedHandle)) && authUsed){
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++;
else
pinData.pin.pinCount = 0;
NvWriteUINT64Data(nvIndex, pinData.intVal);}// If this is a PIN PASS Index, increment if we have used the// authorization value.
// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 241
December 24, 2020

Part 4: Supporting Routines

6.4.4.15

Trusted Platform Module Library

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.

1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

Error Return

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.

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236

Error Return

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 242
December 24, 2020

Part 4: Supporting Routines
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
1296
1297
1298
1299
1300
1301
1302

Trusted Platform Module Library// 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{
session = 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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 243
December 24, 2020

Part 4: Supporting Routines
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
1362
1363

Trusted Platform Module Library

}
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){// 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 244
December 24, 2020

Part 4: Supporting Routines

6.4.4.17

Trusted Platform Module Library

CheckAuthNoSession()

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

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

Error Return

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;}

6.4.5
6.4.5.1

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.
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 245
December 24, 2020

Part 4: Supporting Routines
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417

Trusted Platform Module Library// 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.
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

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;}6.4.5.4

UpdateAuditDigest()

Function to update an audit digest
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 246
December 24, 2020

Part 4: Supporting Routines
1457
1458
1459
1460
1461
1462

Trusted Platform Module Library

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.
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473

static void
Audit(COMMANDSESSION)*command,*auditSession// IN: primary control structure// IN: loaded audit session{
UpdateAuditDigest(command, auditSession->authHashAlg,&auditSession->u2.auditDigest);
return;}#ifdef

6.4.5.6

TPM_CC_GetCommandAuditDigest

CommandAudit()

This function updates the command audit digest.
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
1505
1506

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// 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;}#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 247
December 24, 2020

Part 4: Supporting Routines

6.4.5.7

Trusted Platform Module Library

UpdateAuditSessionStatus()

This function updates the internal audit related states of a session. It will:
initialize the session as audit session and set it to be exclusive if this is the first time it is used foraudit or audit reset was requested;report exclusive audit session;
extend audit log; andclear exclusive audit session if no audit session found in the command.
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
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559

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// 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);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 248
December 24, 2020

Part 4: Supporting Routines
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569

Trusted Platform Module Library}// 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.
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

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 in// 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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 249
December 24, 2020

Part 4: Supporting Routines
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631

Trusted Platform Module Library

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

This function updates internal sessions by:restarting session time; andclearing a policy session since nonce is rolling.
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649

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);}
return;}6.4.5.10

BuildSingleResponseAuth()

Function to compute response HMAC value for a policy or HMAC session.
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 250
December 24, 2020

Part 4: Supporting Routines
1668
1669
1670
1671

Trusted Platform Module Library

UpdateInternalSession(session, sessionIndex);
return &session->nonceTPM;}

6.4.5.11

UpdateAllNonceTPM()

Updates TPM nonce for all sessions in command.
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692

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 ofcommand→responseBuffer. The size of the authorization area is accumulated in command→authSize.
When this is called, command→responseBuffer is pointing at the next location in the response buffer tobe filled. This is where the authorization sessions will go, if any. command→parameterSize is the numberof bytes that have been marshaled as parameters in the output buffer.
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 251
December 24, 2020

Part 4: Supporting Routines
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
1778
1779
1780
1781

Trusted Platform Module Library// 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// 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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 252
December 24, 2020

Part 4: Supporting Routines
1782
1783
1784
1785
1786
1787
1788
1789

Trusted Platform Module Library&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().
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804

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;}}}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 253
December 24, 2020

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

Functions7.2.2.1

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 254
December 24, 2020

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

Trusted Platform Module Library// 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 Return

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 themodulus of signHandle (for an RSA key); invalid commit status
or failed to generate 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 255
December 24, 2020

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.
Return Value

130
131
132
133
134
135
136
137
138

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 256
December 24, 2020

Part 4: Supporting Routines

7.3

Context Management Command Support (Context_spt.c)

7.3.1
1
2

Trusted Platform Module Library

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(sequence2B.t.size <= sizeof(sequence2B.t.buffer));
MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence, sequence2B.t.size);// Get handle value in 2B format
handle2B.t.size = sizeof(contextBlob->savedHandle);cAssert(handle2B.t.size <= sizeof(handle2B.t.buffer));
MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle, handle2B.t.size);// 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);// Copy the rest as the IV
pAssert(iv->t.size <= sizeof(iv->t.buffer));

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 257
December 24, 2020

Part 4: Supporting Routines
50
51
52
53

Trusted Platform Module Library

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 258
December 24, 2020

Part 4: Supporting Routines

7.3.2.3

Trusted Platform Module Library

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.
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

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.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

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);}}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 259
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 260
December 24, 2020

Part 4: Supporting Routines
50
51

Trusted Platform Module Library

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 261
December 24, 2020

Part 4: Supporting Routines
108
109
110
111
112
113
114
115
116
117
118

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

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
151
152
153
154
155
156
157
158
159

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 262
December 24, 2020

Part 4: Supporting Routines

7.4.2.5

Trusted Platform Module Library

PolicySptCheckCondition()

Checks to see if the condition in the policy is satisfied.
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

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:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 263
December 24, 2020

Part 4: Supporting Routines
221
222
223
224
225
226
227
228
229
230
231
232
233
234

Trusted Platform Module Library// 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)
return FALSE;}
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return TRUE;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 264
December 24, 2020

Part 4: Supporting Routines

7.5

NV Command Support (NV_spt.c)

7.5.1
1
2

Trusted Platform Module Library

Includes#include "Tpm.h"#include "NV_spt_fp.h"

7.5.2
7.5.2.1

Functions
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 Return

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 265
December 24, 2020

Part 4: Supporting Routines

7.5.2.2

Trusted Platform Module Library

NvWriteAccessChecks()

Common routine for validating a write Used by TPM2_NV_Write, TPM2_NV_Increment, 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

Error Return

Meaning

TPM_RC_NV_AUTHORIZATION

Authorization fails

TPM_RC_NV_LOCKED

Write locked

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 266
December 24, 2020

Part 4: Supporting Routines

7.5.2.4

Trusted Platform Module Library

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 267
December 24, 2020

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

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
27
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// 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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 268
December 24, 2020

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

const TPM2B

Trusted Platform Module Library*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.
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

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
CryptKDFa(hashAlg, seed, INTEGRITY_KEY, NULL, NULL,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 269
December 24, 2020

Part 4: Supporting Routines
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

Trusted Platform Module Library

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
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
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
136
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.64// 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 this//buffer is reserved for integrity

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 270
December 24, 2020

Part 4: Supporting Routines
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

Trusted Platform Module Library

)
{
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

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

Error Return

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 271
December 24, 2020

Part 4: Supporting Routines

7.6.3

Trusted Platform Module Library

Public Functions

7.6.3.1

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.
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

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 the implementation
digestSize = (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

The isParent attribute is SET when an object is loaded and it has attributes that are suitable for a parent object.

Return Value

215
216
217
218
219
220
221

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.

222
223

Error Return

Meaning

TPM_RC_ATTRIBUTES

sensitiveDataOrigin is not consistent with the object typeotherreturns from PublicAttributesValidation()

TPM_RC
CreateChecks(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 272
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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 TPM_ALG_KEYEDHASH:// 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 TPM_ALG_SYMCIPHER:// 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 273
December 24, 2020

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
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 Library

Error Return

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 hash object

TPM_RC_SYMMETRIC

a storage key with no symmetric algorithm specified; or nonstorage key with symmetric algorithm different from
TPM_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 TPM_ALG_SYMCIPHER:
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 TPM_ALG_KEYEDHASH:
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// TPM_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;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 274
December 24, 2020

Part 4: Supporting Routines
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
383
384
385
386
387
388
389
390

Trusted Platform Module Library// Must select a digest.
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// TPM_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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 275
December 24, 2020

Part 4: Supporting Routines
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
449
450
451
452

Trusted Platform Module Library// Special checks for an ECC key#if ALG_ECC
if(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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 276
December 24, 2020

Part 4: Supporting Routines

7.6.3.5

Trusted Platform Module Library

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

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

Error Return

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 inject sensitive data for an asymmetric key; attempt tocreate a symmetric cipher 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
in publicArea

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 = TPMA_ZERO_INITIALIZER();{//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 both

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 277
December 24, 2020

Part 4: Supporting Routines
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

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 278
December 24, 2020

Part 4: Supporting Routines
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// 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.
595
596
597
598
599
600
601
602
603
604
605
606
607
608

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 279
December 24, 2020

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 280
December 24, 2020

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

Trusted Platform Module Library// 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

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

Error Return

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 blocksize

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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 281
December 24, 2020

Part 4: Supporting Routines
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

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 Returns the size of the marshaled area.
751
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
MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg));

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 282
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarybuffer += 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.
797
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 computationif(parent == NULL)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 283
December 24, 2020

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

Trusted Platform Module Library{// 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 an 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

851
852
853
854
855
856
857
858
859
860
861

Error Return

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.64// 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//objects. 2. duplication blob with inner

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 284
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library//
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:
marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 285
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

apply inner wrap to the sensitive area if required
apply outer wrap if required
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
977
978
979
980
981

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);}// Marshal sensitive area

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 286
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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:
check the integrity HMAC of the input private area
decrypt the private buffer
unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 287
December 24, 2020

Part 4: Supporting Routines

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

Trusted Platform Module Library

Error Return

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){// 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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 288
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

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);// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 289
December 24, 2020

Part 4: Supporting Routines
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

Trusted Platform Module Library+ 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

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

Error Return

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- (sizeof(UINT16) + CryptHashGetDigestSize(outerHash));// Unmarshal secret buffer to TPM2B_DIGEST structure
buffer = sensitiveData;
size = (INT32)dataSize;
result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 290
December 24, 2020

Part 4: Supporting Routines
1185
1186
1187
1188
1189
1190
1191

Trusted Platform Module Library// 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.
1192
1193
1194
1195
1196
1197
1198
1199
1200

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

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
if(labelContext->context.t.size == 0)
MemoryCopy2B(&labelContext->context.b, &sensitiveValue.context.b,
sizeof(labelContext->label.t.buffer));}
return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 291
December 24, 2020

Part 4: Supporting Routines

7.6.3.19

Trusted Platform Module Library

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

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.
1278
1279
1280
1281
1282
1283
1284

void
ObjectSetExternal(
OBJECT)*object{
object->attributes.external = SET;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 292
December 24, 2020

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

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 Return

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 matchthe 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 293
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library{// then the input mode has to be TPM_ALG_NULL or the same as the keyif((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;
if(((mode == TPM_ALG_ECB) && (ivIn->t.size != 0))|| ((mode != TPM_ALG_ECB) && (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 == TPM_ALG_CBC) || (mode == TPM_ALG_ECB))&& ((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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 294
December 24, 2020

Part 4: Supporting Routines

7.8

Trusted Platform Module Library

ACT Support (ACT_spt.c)

7.8.1

Introduction

This code implements the ACT update code. It does not use a mutex. This code uses a platform service(_plat__ACT_UpdateCounter()) that returns false if the update is not accepted. If this occurs, then
TPM_RC_RETRY should be sent to the caller so that they can retry the operation later. The
implementation of this is platform dependent but the reference uses a simple flag to indicate that an
update is pending and the only process that can clear that flag is the process that does the actual update.
7.8.2
1
2
3

Includes#include "Tpm.h"#include "ACT_spt_fp.h"#include "Platform_fp.h"

7.8.3
7.8.3.1

Functions_ActResume()

This function does the resume processing for an ACT. It updates the saved count and turns signaling
back on if necessary.
4
5
6
7
8
9
10
11
12
13
14
15
16

static void
_ActResume(
UINT32
ACT_STATE

act,*actData//IN: the act number//IN: pointer to the saved ACT data){// If the act was non-zero, then restore the counter value.
if(actData->remaining > 0)_plat__ACT_UpdateCounter(act, actData->remaining);// if the counter was zero and the ACT signaling, enable the signaling.
else if(go.signaledACT & (1 << act))_plat__ACT_SetSignaled(act, TRUE);}

7.8.3.2

ActStartup()This function is called by TPM2_Startup() to initialize the ACT counter values.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

BOOL
ActStartup(
STARTUP_TYPE

type

)
{
// Reset all the ACT hardware_plat__ACT_Initialize();// If this not a cold start, copy all the current 'signaled' settings to// 'preservedSignaled'.
if (g_powerWasLost)
go.preservedSignaled = 0;
else
go.preservedSignaled |= go.signaledACT;// For TPM_RESET or TPM_RESTART, the ACTs will all be disabled and the output// de-asserted.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 295
December 24, 2020

Part 4: Supporting Routines
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

Trusted Platform Module Libraryif(type != SU_RESUME){
go.signaledACT = 0;
#define CLEAR_ACT_POLICY(N)go.ACT_##N.hashAlg = TPM_ALG_NULL;
go.ACT_##N.authPolicy.b.size = 0;
FOR_EACH_ACT(CLEAR_ACT_POLICY)}
else{// Resume each of the implemented ACT#define RESUME_ACT(N)_ActResume(0x##N, &go.ACT_##N);\\

FOR_EACH_ACT(RESUME_ACT)}// set no ACT updated since last startup. This is to enable the halving of the// timeout values_ActUpdated = 0;
_plat__ACT_EnableTicks(TRUE);
return TRUE;}

7.8.3.3_ActSaveState()

Get the counter state and the signaled state for an ACT. If the ACT has not been updated since the lasttime it was saved, then divide the count by 2.
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

static void
_ActSaveState(
UINT32
P_ACT_STATE

act,
actData){
actData->remaining = _plat__ACT_GetRemaining(act);// If the ACT hasn't been updated since the last startup, then it should be// be halved.
if((s_ActUpdated & (1 << act)) == 0){// Don't halve if the count is set to max or if halving would make it zeroif((actData->remaining != UINT32_MAX) && (actData->remaining > 1))
actData->remaining /= 2;}if(_plat__ACT_GetSignaled(act))
go.signaledACT |= (1 << act);}

7.8.3.4

ActGetSignaled()

This function returns the state of the signaled flag associated with an ACT.
73
74
75
76
77
78
79
80
81

BOOL
ActGetSignaled(
TPM_RH

actHandle

UINT32

act = actHandle - TPM_RH_ACT_0;){//
return _plat__ACT_GetSignaled(act);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 296
December 24, 2020

Part 4: Supporting Routines

7.8.3.5

Trusted Platform Module Library

ActShutdown()

This function saves the current state of the counters
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

BOOL
ActShutdown(
TPM_SU

state//IN: the type of the shutdown.

){// if this is not shutdown state, then the only type of startup is TPM_RESTART// so the timer values will be cleared. If this is shutdown state, get the current// countdown and signaled values. Plus, if the counter has not been updated// since the last restart, divide the time by 2 so that there is no attack on the// countdown by saving the countdown state early and then not using the TPM.
if(state == TPM_SU_STATE){// This will be populated as each of the ACT is queriedgo.signaledACT = 0;// Get the current count and the signaled state#define SAVE_ACT_STATE(N) _ActSaveState(0x##N, &go.ACT_##N);
FOR_EACH_ACT(SAVE_ACT_STATE);}
return TRUE;}

7.8.3.6

ActIsImplemented()

This function determines if an ACT is implemented in both the TPM and the platform code.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

BOOL
ActIsImplemented(
UINT32act){// This switch accounts for the TPM implemented values.
switch(act){
FOR_EACH_ACT(CASE_ACT_NUMBER)// This ensures that the platform implements the values implemented by// the TPM
return _plat__ACT_GetImplemented(act);
default:
break;}
return FALSE;}

7.8.3.7

ActCounterUpdate()

This function updates the ACT counter. If the counter already has a pending update, it returns
TPM_RC_RETRY so that the update can be tried again later.
120
121
122
123
124
125
126
127
128

TPM_RC
ActCounterUpdate(
TPM_RHUINT32handle,newValue

UINT32
TPM_RCact;
result;//IN: the handle of the act//IN: the value to set in the ACT){//Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 297
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Libraryact = handle - TPM_RH_ACT_0;// This should never fail, but...
if(!_plat__ACT_GetImplemented(act))
result = TPM_RC_VALUE;
else{// Will need to clear orderly so fail if we are orderly and NV is// not available
if(NV_IS_ORDERLY)RETURN_IF_NV_IS_NOT_AVAILABLE;// if the attempt to update the counter fails, it means that there is an// update pending so wait until it has occurred and then do an update.
if(!_plat__ACT_UpdateCounter(act, newValue))
result = TPM_RC_RETRY;
else{// Indicate that the ACT has been updated since last TPM2_Startup().
s_ActUpdated |= (UINT16)(1 << act);// Clear the preservedSignaled attribute.
go.preservedSignaled &= ~((UINT16)(1 << act));// Need to clear the orderly flag
g_clearOrderly = TRUE;
result = TPM_RC_SUCCESS;}}
return result;}7.8.3.8

ActGetCapabilityData()

This function returns the list of ACT data
Return Value

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

Meaning

YES

if more ACT data is availableNO

if no more ACT data to

TPMI_YES_NO
ActGetCapabilityData(
TPM_HANDLEUINT32
TPML_ACT_DATA

actHandle,
maxCount,*actList// IN: the handle for the starting ACT// IN: maximum allowed return values// OUT: ACT data list){// Initialize output property list
actList->count = 0;// Make sure that the starting handle value is in range (again)
if((actHandle < TPM_RH_ACT_0) || (actHandle > TPM_RH_ACT_F))
return FALSE;// The maximum count of curves we may return is MAX_ECC_CURVES
if(maxCount > MAX_ACT_DATA)
maxCount = MAX_ACT_DATA;// Scan the ACT data from the starting ACT
for(; actHandle <= TPM_RH_ACT_F; actHandle++){UINT32
act = actHandle - TPM_RH_ACT_0;
if(actList->count < maxCount){if(ActIsImplemented(act))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 298
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library{
TPMS_ACT_DATA*actData = &actList->actData[actList->count];//
memset(&actData->attributes, 0, sizeof(actData->attributes));
actData->handle = actHandle;
actData->timeout = _plat__ACT_GetRemaining(act);
if(_plat__ACT_GetSignaled(act))
SET_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled);
else
CLEAR_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled);
if (go.preservedSignaled & (1 << act))
SET_ATTRIBUTE(actData->attributes, TPMA_ACT, preserveSignaled);
actList->count++;
}
}
else
{
if(_plat__ACT_GetImplemented(act))
return YES;}}// If we get here, either all of the ACT values were put in the list, or the list// was filled and there are no more ACT values to return
return NO;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 299
December 24, 2020

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
8.1.3.1

FunctionsCommandAuditPreInstall_Init()

This function initializes the command audit list. This function 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 300
December 24, 2020

Part 4: Supporting Routines
33
34
35
36
37
38

Trusted Platform Module Library{// 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.
Return Value

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 301
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

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

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.
Return Value

88
89
90
91
92
93
94
95

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 302
December 24, 2020

Part 4: Supporting Routines

Return Value

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

Trusted Platform Module Library

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.
143
144
145

void
CommandAuditGetDigest(
TPM2B_DIGEST*digestFamily “2.0”Level 00 Revision 01.64// OUT: command digest

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 303
December 24, 2020

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

Trusted Platform Module Library){
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 304
December 24, 2020

Part 4: Supporting Routines

8.2

Trusted Platform Module Library

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
8.2.3.1

Functions
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
31

BOOL
DAStartup(
STARTUP_TYPE)

type// IN: startup type{
NOT_REFERENCED(type);#if !ACCUMULATE_SELF_HEAL_TIMER_plat__TimerWasReset();s_selfHealTimer = 0;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 305
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarys_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 an 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.
83
84
85
86
87
88

void
DARegisterFailure(
TPM_HANDLE)

handle// IN: handle for failure{// Reset the timer associated with lockout if the handle is the lockoutAuth.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 306
December 24, 2020

Part 4: Supporting Routines
89
90
91
92
93
94

Trusted Platform Module Libraryif(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.
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

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);}}// LockoutAuth self healing logic// If lockoutAuth is enabled, do nothing.

Family “2.0”Level 00 Revision 01.64

Otherwise, try to see if we

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 307
December 24, 2020

Part 4: Supporting Routines
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

Trusted Platform Module Library// 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 308
December 24, 2020

Part 4: Supporting Routines

8.3

Trusted Platform Module Library

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
8.3.3.1

Functions
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 309
December 24, 2020

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

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.
92
93
94
95
96

TPM2B_PROOF *HierarchyGetProof(
TPMI_RH_HIERARCHY)

hierarchy// IN: hierarchy constant{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 310
December 24, 2020

Part 4: Supporting Routines
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

TPM2B_PROOF

Trusted Platform Module Library*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.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 311
December 24, 2020

Part 4: Supporting Routines

NOTE

Trusted Platform Module Library

The TPM_RH_NULL hierarchy is always enabled.

Return Value

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 312
December 24, 2020

Part 4: Supporting Routines

8.4

Trusted Platform Module Library

NvDynamic.c

8.4.1

Introduction

The NV memory is divided into two areas: 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. The values are in
the gp PERSISTENT_DATA structure in RAM and mapped to locations in NV.
8.4.2
1
2

Includes, Defines and Data Definitions#define NV_C
#include "Tpm.h"

8.4.3
8.4.3.1

Local Functions
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. Everytime 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 are no more elements in the set, a 0 value is returned indicating the end of traversal.
3
4
5
6
7
8
9
10
11
12
13
14

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;//// If iterator is at the beginning of list
if(*iter == NV_REF_INIT){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 313
December 24, 2020

Part 4: Supporting Routines
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

Trusted Platform Module Library// 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

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

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// OUT: the handle of the found type or 0// IN: the iterator// IN: the handle type to look for

NV_REF
TPM_HANDLE

addr;
nvHandle = 0;{//
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 314
December 24, 2020

Part 4: Supporting Routines

56
57

Trusted Platform Module Library

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.
58
59

#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
60
61
62
63
64
65
66
67
68
69
70
71

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.
72
73
74
75
76
77
78
79
80
81
82

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 315
December 24, 2020

Part 4: Supporting Routines

Return Value

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

Trusted Platform Module Library

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.
133
134
135

NV_REF
NvWriteNvListEnd(
NV_REF

end

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 316
December 24, 2020

Part 4: Supporting Routines
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

Trusted Platform Module Library){// 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.
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

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 317
December 24, 2020

Part 4: Supporting Routines
191
192
193
194
195
196
197
198
199
200

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 318
December 24, 2020

Part 4: Supporting Routines

8.4.4
8.4.4.1

Trusted Platform Module Library

RAM-based NV Index Data Access Functions
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
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

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

static NV_RAM_REF
NvRamGetEnd(
void)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 319
December 24, 2020

Part 4: Supporting Routines
287
288
289
290
291
292
293
294

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.
Return Value

295
296
297
298
299
300
301
302
303
304
305

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 = (UINT32)(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.
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

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.
322
323
324
325

void
NvUpdateIndexOrderlyData(
void)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 320
December 24, 2020

Part 4: Supporting Routines
326
327
328
329

Trusted Platform Module Library{// 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.
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

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.
361
362
363
364
365
366
367

static void
NvDeleteRAM(
TPMI_RH_NV_INDEX)

handle// IN: NV handle

NV_RAM_REF
NV_RAM_REF

nodeAddress;
nextNode;{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 321
December 24, 2020

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

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, (int)(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.
392
393
394
395
396
397
398
399
400
401

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.
402
403
404
405
406
407
408
409
410

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 322
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

411
412
413
414
415
416
417
418
419
420
421
422
423

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
424
425
426
427
428
429
430

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

431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

Error Return

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 323
December 24, 2020

Part 4: Supporting Routines

8.4.4.14

Trusted Platform Module Library

NvReadNvIndexAttributes()

This function returns the attributes of an NV Index.
450
451
452
453
454
455
456
457
458
459
460
461

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.
462
463
464
465
466
467
468
469
470
471
472

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.

473
474
475
476
477
478
479
480
481
482
483

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 324
December 24, 2020

Part 4: Supporting Routines
484
485
486
487
488
489
490
491
492
493

Trusted Platform Module Librarystatic 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
8.4.5.1

Externally Accessible Functions
NvIsPlatformPersistentHandle()

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

494
495
496
497
498
499
500

Meaning

TRUE(1)

handle references a platform persistent object

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.
Return Value

501
502
503
504
505
506
507

Meaning

TRUE(1)

handle is owner persistent handle

FALSE(0)handle is not owner persistent handle and may not be a
persistent handle 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 325
December 24, 2020

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

Trusted Platform Module Library

Error Return

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 createdusing platformAuth

TPM_RC_NV_READLOCKED

Index is present but locked for reading and command does notwrite 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 326
December 24, 2020

Part 4: Supporting Routines

8.4.5.4

Trusted Platform Module Library

NvGetEvictObject()

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

556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

Error Return

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
577
578
579
580
581
582
583
584
585
586

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.
587
588
589
590
591
592
593
594
595
596

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;{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 327
December 24, 2020

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

Trusted Platform Module Library//pAssert(nvIndex != NULL);
nvAttributes = nvIndex->publicArea.attributes;
pAssert(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.
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

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}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 328
December 24, 2020

Part 4: Supporting Routines

8.4.5.8

Trusted Platform Module Library

NvGetUINT64Data()

Get data in integer format of a bit or counter NV Index.
This function requires that the NV Index is defined and that the NV Index previously has been written.
655
656
657
658
659
660
661
662
663
664
665
666

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.

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

Error Return

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()688

Error Return

Meaning

TPM_RC_NV_RATE

NV is rate limiting so retry

TPM_RC_NV_UNAVAILABLE

NV is not available

TPM_RC

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 329
December 24, 2020

Part 4: Supporting Routines
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709

Trusted Platform Module Library

NvWriteIndexAuth(
NV_REF
TPM2B_AUTH)

locator,*authValue// IN: location of the index// IN: the authValue to write{
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
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

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 330
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryThis 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
but not multiple index data. This is important because we will normally be handling the index for which wehave the cached pointer values.

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

Error Return

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 331
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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),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)
815
816
817
818
819
820
821
822
823
824
825

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.
826
827
828
829
830
831

TPM2B_NAME *NvGetIndexName(
NV_INDEX*nvIndex,

TPM2B_NAME
)

*name

Family “2.0”Level 00 Revision 01.64// IN: the index over which the name is to be//computed// OUT: name of the index

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 332
December 24, 2020

Part 4: Supporting Routines
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853

Trusted Platform Module Library{
UINT16
BYTE
BYTE
HASH_STATE

dataSize, digestSize;marshalBuffer[sizeof(TPMS_NV_PUBLIC)];*buffer;hashState;//// 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.
854
855
856
857
858
859
860
861
862
863

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.

864
865
866
867
868
869
870
871
872
873
874
875

Error Return

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 333
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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;// 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.

910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

Error Return

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 334
December 24, 2020

Part 4: Supporting Routines
929
930
931
932
933
934
935
936
937
938
939

Trusted Platform Module Libraryobject->evictHandle = evictHandle;// Now put this in NV
result = NvAdd(sizeof(OBJECT), sizeof(OBJECT), evictHandle, (BYTE *)object);// 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.

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

Error Return

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
965
966
967
968
969
970
971
972
973
974
975

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 335
December 24, 2020

Part 4: Supporting Routines
976

Trusted Platform Module Library}

8.4.5.20

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.

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

Error Return

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 336
December 24, 2020

Part 4: Supporting Routines
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

Trusted Platform Module Library

result = NvDelete(currentAddr);
if(result != TPM_RC_SUCCESS)
break;// 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().

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

Error Return

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 337
December 24, 2020

Part 4: Supporting Routines
1080

Trusted Platform Module Library}

8.4.5.22

InsertSort()

Sort a handle into handle list in ascending order. The total handle number in the list should not exceed
MAX_CAP_HANDLES
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

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.
Return Value

1122

Meaning

YES

if there are more handles available

NO

all the available handles has been returned

TPMI_YES_NO

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 338
December 24, 2020

Part 4: Supporting Routines
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
1157
1158
1159
1160

Trusted Platform Module Library

NvCapGetPersistent(
TPMI_DH_OBJECTUINT32
TPML_HANDLE)

handle,count,*handleList// IN: start handle// IN: maximum number of returned handles// 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.
Return Value

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 339
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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 = 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.
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211

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.
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 340
December 24, 2020

Part 4: Supporting Routines

8.4.5.27

Trusted Platform Module Library

NvCapGetPersistentAvail()This function returns an estimate of the number of additional persistent objects that could be loaded into
NV memory.
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247

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.
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264

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.
1265
1266
1267
1268
1269
1270
1271

static TPMA_NV
NvSetStartupAttributes(
TPMA_NV
STARTUP_TYPE)

attributes,
type// IN: attributes to change// IN: start up type{// Clear read lock

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 341
December 24, 2020

Part 4: Supporting Routines
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 342
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library}// 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.
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

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 = (int)(RAM_ORDERLY_END - NvRamGetEnd());// Return the min of counter number in NV and in RAM
if(availNVSpace / NV_INDEX_COUNTER_SIZEFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 343
December 24, 2020

Part 4: Supporting Routines
1381
1382
1383
1384
1385

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.
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401

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 kept 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.
1402
1403
1404
1405
1406
1407
1408

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 344
December 24, 2020

Part 4: Supporting Routines
1409
1410
1411
1412
1413
1414
1415
1416

Trusted Platform Module Libraryvoid
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.
1417
1418
1419
1420
1421
1422
1423

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
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 345
December 24, 2020

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. The values are in
the gp PERSISTENT_DATA structure in RAM and mapped to locations in NV.
8.5.2
1
2

Includes, Defines#define NV_C
#include"Tpm.h"8.5.3
8.5.3.1

Functions
NvInitStatic()

This function initializes the static variables used in the NV subsystem.
3
4
5
6
7
8
9
10
11
12
13

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 346
December 24, 2020

Part 4: Supporting Routines

8.5.3.2

Trusted Platform Module Library

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.
Return Value

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Meaning

TRUE(1)

all NV was initialized

FALSE(0)the NV containing saved state had an error and
TPM2_Startup(CLEAR) is required

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);
NvInitStatic();}
return nvError == 0;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 347
December 24, 2020

Part 4: Supporting Routines

8.5.3.5

Trusted Platform Module Library

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
91
92
93
94
95

BOOL
NvWrite(UINT32
UINT32void)

nvOffset,size,*inBuffer// IN: location in NV to receive data// IN: size of the data to move// IN: location containing data to write{// Input type should be valid

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 348
December 24, 2020

Part 4: Supporting Routines
96
97
98
99
100
101
102
103

Trusted Platform Module Libraryif(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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 349
December 24, 2020

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
3

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

4
5
6
7
8
9
10

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.
11
12
13
14
15
16
17

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 350
December 24, 2020

Part 4: Supporting Routines
30
31
32

Trusted Platform Module Library}
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().
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

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.
Return Value

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

Meaning

TRUE(1)

handle references a loaded object

FALSE(0)handle is not an object handle, or it does not reference toa loaded object

BOOL
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);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 351
December 24, 2020

Part 4: Supporting Routines

8.6.3.6

Trusted Platform Module Library

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.
Return Value

67
68
69
70
71
72
73
74
75
76

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.
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

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.
95
96
97
98
99
100

void
GetQualifiedName(TPMI_DH_OBJECT
TPM2B_NAME)

handle,*qualifiedName// IN: handle of the object// OUT: qualified name of the object{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 352
December 24, 2020

Part 4: Supporting Routines
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

OBJECT

Trusted Platform Module Library*object;//
switch(HandleGetType(handle)){case TPM_HT_PERMANENT:
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.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

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

GetHierarchy()

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.
144
145
146
147
148
149

TPMI_RH_HIERARCHY
GetHierarchy(
TPMI_DH_OBJECT)

handle// IN :object handle

OBJECT*object = HandleToObject(handle);

Family “2.0”

TCG PUBLIC REVIEW{

Level 00 Revision 01.64

Copyright © TCG 2006-2021

Page 353
December 24, 2020

Part 4: Supporting Routines
150
151
152

Trusted Platform Module Library//
return ObjectGetHierarchy(object);}

8.6.3.11

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.
Return Value

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

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.
175
176
177
178
179
180
181
182
183
184
185
186
187
188

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 354
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Libraryvoid
ObjectSetLoadedAttributes(
OBJECTTPM_HANDLE)*object,parentHandle// IN: object attributes to finalize// IN: the parent handle{
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 355
December 24, 2020

Part 4: Supporting Routines
255
256
257
258
259
260
261
262
263

Trusted Platform Module Libraryobject->attributes.isParent = SET;}
ComputeQualifiedName(parentHandle, object->publicArea.nameAlg,&object->name, &object->qualifiedName);}// 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.
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

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))){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 356
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// Do the cryptographic key validation
result = CryptValidateKeys(publicArea, sensitive, blamePublic,
blameSensitive);
if(result != TPM_RC_SUCCESS)
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.
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 357
December 24, 2020

Part 4: Supporting Routines
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388

Trusted Platform Module Library// This has no name algorithm and the name is the Empty Buffer
object->nameAlg = TPM_ALG_NULL;// 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.

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

Error Return

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;}#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 358
December 24, 2020

Part 4: Supporting Routines

8.6.3.17

Trusted Platform Module Library

ObjectCreateHashSequence()

This function creates a hash sequence object.

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

Error Return

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.

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460

Error Return

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 359
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Libraryvoid
ObjectTerminateEvent(void){
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.
Return Value

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

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));}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 360
December 24, 2020

Part 4: Supporting Routines
514
515
516

Trusted Platform Module Library}
return newObject;}

8.6.3.21

FlushObject()

This function frees an object slot.
This function requires that the object is loaded.
517
518
519
520
521
522
523
524
525
526
527
528
529

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.
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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 361
December 24, 2020

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 Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 362
December 24, 2020

Part 4: Supporting Routines
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

Trusted Platform Module Library

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//

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 363
December 24, 2020

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.
Return Value

692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

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 == TPM_ALG_RSA|| object->publicArea.type == TPM_ALG_ECC));}

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 364
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

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

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.
751
752
753
754
755
756
757
758

UINT32
ObjectCapGetTransientAvail(
void){
UINT32
UINT32i;num = 0;//

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 365
December 24, 2020

Part 4: Supporting Routines
759
760
761
762
763
764
765

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.
766
767
768
769
770
771
772
773
774
775
776
777
778
779

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 366
December 24, 2020

Part 4: Supporting Routines

8.7

Trusted Platform Module Library

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
8.7.3.1

Functions
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.
Return Value

21
22
23
24

Meaning

TRUE(1)

PCR belongs an authorization group

FALSE(0)PCR does not belong an authorization group

BOOL
PCRBelongsAuthGroup(
TPMI_DH_PCR
UINT32handle,*groupIndex

Family “2.0”Level 00 Revision 01.64// IN: handle of PCR// OUT: group index if PCR belongs a

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 367
December 24, 2020

Part 4: Supporting Routines
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

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.
Return Value

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

Meaning

TRUE(1)

PCR belongs to a policy group

FALSE(0)PCR does not belong to 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 368
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

Meaning

TRUE(1)

PCR belongs to a TCB group

FALSE(0)PCR does not belong to a 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.
Return Value

83
84
85
86
87
88
89
90
91

Meaning

TRUE(1)the PCR may 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.
92
93
94
95
96
97
98
99
100
101
102
103
104
105

TPM2B_AUTH *PCRGetAuthValue(
TPMI_DH_PCR)

handle// IN: PCR handle{
UINT32groupIndex;

if(PCRBelongsAuthGroup(handle, &groupIndex)){
return &gc.pcrAuthValues.auth[groupIndex];}
else{
return NULL;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 369
December 24, 2020

Part 4: Supporting Routines
106
107

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.
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 370
December 24, 2020

Part 4: Supporting Routines
156
157
158
159
160
161
162
163
164
165
166

Trusted Platform Module Library= 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.
Return Value

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

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){#define HASH_CASE(HASH, Hash)case TPM_ALG_##HASH:
retVal = gc.pcrSave.Hash[pcrIndex];
break;\\\

FOR_EACH_HASH(HASH_CASE)#undef HASH_CASE
default:
FAIL(FATAL_ERROR_INTERNAL);}
return retVal;}

8.7.3.9

PcrIsAllocated()

This function indicates if a PCR number for the particular hash algorithm is allocated.
Return Value

189
190
191
192
193
194
195
196

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

Family “2.0”Level 00 Revision 01.64

i;allocated = FALSE;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 371
December 24, 2020

Part 4: Supporting Routines
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

Trusted Platform Module Libraryif(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.
Return Value

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

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){#define HASH_CASE(HASH, Hash)case TPM_ALG_##HASH:
pcr = s_pcrs[pcrNumber].Hash##Pcr;
break;\\\

FOR_EACH_HASH(HASH_CASE)#undef HASH_CASE
default:
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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 372
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

242
243
244
245
246
247
248
249
250
251
252

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

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
for(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.
286
287

void
PcrDrtm(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 373
December 24, 2020

Part 4: Supporting Routines
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

Trusted Platform Module Library

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().
310
311
312
313
314
315
316
317
318
319
320
321
322

void
PCR_ClearAuth(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().
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 374
December 24, 2020

Part 4: Supporting Routines
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
393
394
395
396
397
398
399
400
401
402
403
404
405

Trusted Platform Module Library}// 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);if(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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 375
December 24, 2020

Part 4: Supporting Routines
406

Trusted Platform Module Library}

8.7.3.16

PCRStateSave()This function is used to save the PCR values that will be restored on TPM Resume.
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

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;
UINT32 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 376
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

452
453
454
455
456
457
458
459
460
461
462
463

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.
Return Value

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

Meaning

TRUE(1)

TPM2_PCR_Reset is allowed

FALSE(0)TPM2_PCR_Reset is not allowed

BOOL
PCRIsResetAllowed(
TPMI_DH_PCR)

handle// 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().
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 377
December 24, 2020

Part 4: Supporting Routines
488
489
490
491
492
493
494
495
496
497
498
499
500
501

Trusted Platform Module Libraryvoid
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.
Return Value

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518

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
UINT8
UINT32

commandLocality;
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.
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533

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 allocatedFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 378
December 24, 2020

Part 4: Supporting Routines
534
535
536
537
538
539
540
541
542
543
544
545
546

Trusted Platform Module Libraryif(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.
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

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
UINT32
UINT32
UINT32

hashState;*select;*pcrData;// will point to a digest
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;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 379
December 24, 2020

Part 4: Supporting Routines
592

Trusted Platform Module Library}

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

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// 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++;}}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 380
December 24, 2020

Part 4: Supporting Routines
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

Trusted Platform Module Library// 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

PCRAllocate()

This function is used to change the PCR allocation.

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

Error Return

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];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 381
December 24, 2020

Part 4: Supporting Routines
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
761
762
763
764

Trusted Platform Module Library

break;}}// The j loop must exit with a match.
pAssert(j < newAllocate.count);}// 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 382
December 24, 2020

Part 4: Supporting Routines

8.7.3.25

Trusted Platform Module Library

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

void
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.26

PCRResetDynamics()

This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence.
805
806
807
808
809
810
811
812
813
814
815
816
817

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++){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 383
December 24, 2020

Part 4: Supporting Routines
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

BYTE
UINT32Trusted Platform Module Library*pcrData;
pcrSize;

pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);
if(pcrData != NULL){
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.27

PCRCapGetAllocation()

This function is used to get the current allocation of PCR banks.
Return Value

837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853

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

PCRSetSelectBit()

This function sets a bit in a bitmap array.
854
855
856
857
858
859
860
861
862

static void
PCRSetSelectBit(
UINT32
BYTE)

pcr,*bitmap// IN: PCR number// OUT: bit map to be set{
bitmap[pcr / 8] |= (1 << (pcr % 8));return;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 384
December 24, 2020

Part 4: Supporting Routines

8.7.3.29

Trusted Platform Module Library

PCRGetProperty()

This function returns the selected PCR property.
Return Value

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

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 385
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

PCRSetSelectBit(pcr, select->pcrSelect);break;
case TPM_PT_PCR_EXTEND_L4:
if((s_initAttributes[pcr].extendLocality & 0x10) != 0)
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.30

PCRCapGetProperties()

This function returns a list of PCR properties starting at property.
Return Value

960
961
962
963
964
965
966
967
968
969
970

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 386
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

select->count = 0;// The maximum count of properties we may return is MAX_PCR_PROPERTIES
if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES;// 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.31

PCRCapGetHandles()This function is used to get a list of handles of PCR, started from handle. If handle exceeds the maximum
PCR handle range, an empty list will be returned and the return value will be NO.
Return Value

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 387
December 24, 2020

Part 4: Supporting Routines
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038

Trusted Platform Module Library{// If we have not filled up the return list, add this PCR// handle to it
handleList->handle[handleList->count] = i + PCR_FIRST;
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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 388
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 389
December 24, 2020

Part 4: Supporting Routines
35
36
37

Trusted Platform Module Library

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.
Return Value

55
56
57
58
59
60
61
62

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.
Return Value

63
64
65
66
67

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

commandCode,count,*commandList

Family “2.0”Level 00 Revision 01.64// IN: start command code// IN: count of returned TPM_CC// OUT: list of TPM_CC

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 390
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 391
December 24, 2020

Part 4: Supporting Routines

8.9

1
2

Session.c

8.9.1

Introduction

8.9.2

Includes, Defines, and Local Variables#define SESSION_C#include "Tpm.h"

8.9.3
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

Trusted Platform Module Library

File Scope Function -- ContextIdSetOldest()

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

8.9.4

Startup Function -- SessionStartup()This function initializes the session subsystem on TPM2_Startup().
37
38
39
40
41
42
43
44
45
46

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++)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 392
December 24, 2020

Part 4: Supporting Routines
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 Librarys_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
8.9.5.1

Access Functions
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.
NOTE

A PWAP authorization does not have a session.

Return Value

86
87
88
89
90
91
92
93

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 393
December 24, 2020

Part 4: Supporting Routines
94
95
96
97
98
99
100
101
102
103
104

Trusted Platform Module Libraryhandle = 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.

Return Value

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

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;}

8.9.5.3

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

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_SESSIONSFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 394
December 24, 2020

Part 4: Supporting Routines
136
137
138
139
140
141
142
143
144
145
146
147

Trusted Platform Module Library// 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.
Return Value

148
149
150
151
152
153
154
155
156
157
158
159

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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

SESSION *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.
// should always get a valid sessionIndex

Family “2.0”Level 00 Revision 01.64

Because session is loaded, we

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 395
December 24, 2020

Part 4: Supporting Routines
178
179
180
181
182
183

Trusted Platform Module LibrarysessionIndex = gr.contextArray[slotIndex] - 1;
pAssert(sessionIndex < MAX_LOADED_SESSIONS);
return &s_sessions[sessionIndex].session;
}

8.9.6

Utility Functions

8.9.6.1

ContextIdSessionCreate()

This function is called when a session is created. It will check to see if the current gap would prevent a
context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find an
open slot in contextArray, set contextArray to the slot. This routine requires that the caller has determined
the session array index for the session.

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

Error Return

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// 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 396
December 24, 2020

Part 4: Supporting Routines
223
224
225

Trusted Platform Module Library}
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.

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

Error Return

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++){// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 397
December 24, 2020

Part 4: Supporting Routines
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
331
332
333
334
335
336

Trusted Platform Module Library// 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)// 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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 398
December 24, 2020

Part 4: Supporting Routines
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

Trusted Platform Module Library

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 aloaded session. Otherwise, it should not be called at the first place.

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

Error Return

Meaning

TPM_RC_CONTEXT_GAP

a contextID could not be assigned

TPM_RC_TOO_MANY_CONTEXTS

the 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));// 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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 399
December 24, 2020

Part 4: Supporting Routines
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// 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.

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

Error Return

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++)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 400
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Libraryif(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;}

8.9.6.5

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.
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 401
December 24, 2020

Part 4: Supporting Routines
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516

Trusted Platform Module LibraryslotIndex = 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.
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

void
SessionComputeBoundEntity(
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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 402
December 24, 2020

Part 4: Supporting Routines

8.9.6.7

Trusted Platform Module Library

SessionSetStartTime()

This function is used to initialize the session timing
549
550
551
552
553
554
555
556
557

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

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;// 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 403
December 24, 2020

Part 4: Supporting Routines

8.9.6.9

Trusted Platform Module Library

SessionCapGetLoaded()This function returns a list of handles of loaded session, started from input handle
Handle must be in valid loaded session handle range, but does not have to point to a loaded session.
Return Value

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

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
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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 404
December 24, 2020

Part 4: Supporting Routines

8.9.6.10

Trusted Platform Module Library

SessionCapGetSaved()

This function returns a list of handles for saved session, starting at handle.
Handle must be in a valid handle range, but does not have to point to a saved session
Return Value

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

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
for(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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 405
December 24, 2020

Part 4: Supporting Routines

8.9.6.11

Trusted Platform Module Library

SessionCapGetLoadedNumber()This function return the number of authorization sessions currently loaded into TPM RAM.
702
703
704
705
706
707
708

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

709
710
711
712
713
714
715

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.
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730

UINT32
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.
731
732
733
734
735
736

UINT32
SessionCapGetActiveAvail(
void){
UINT32

Family “2.0”Level 00 Revision 01.64

i;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 406
December 24, 2020

Part 4: Supporting Routines
737
738
739
740
741
742
743
744
745

UINT32Trusted Platform Module Librarynum = 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 407
December 24, 2020

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 "PlatformClock.h"

8.10.38.10.3.1

Functions
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 408
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryThis 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(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 409
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 410
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarycase 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146

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.
147
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".
if(NV_IS_AVAILABLE)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 411
December 24, 2020

Part 4: Supporting Routines
159
160
161
162
163
164

Trusted Platform Module LibraryclockInfo->safe = go.clockSafe;elseclockInfo->safe = NO;
return;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 412
December 24, 2020

Part 4: Supporting Routines

9

Trusted Platform Module Library

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
TPMA_ALGORITHM} ALGORITHM;

algID;
attributes;

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

Family “2.0”Level 00 Revision 01.64

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)},TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 413
December 24, 2020

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{TPM_ALG_SM4,
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)},#endif#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, 0, 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

Family “2.0”Level 00 Revision 01.64

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)},TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 414
December 24, 2020

Part 4: Supporting Routines
118
119
120

{TPM_ALG_ECB,#endif};

9.1.3

Trusted Platform Module Library
TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)},AlgorithmCapGetImplemented()

This function is used by TPM2_GetCapability() to return a list of the implemented algorithms.
Return Value

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

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 415
December 24, 2020

Part 4: Supporting Routines

9.1.4

Trusted Platform Module Library

AlgorithmGetImplementedVector()

This function returns the bit vector of the implemented algorithms.
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

LIB_EXPORTvoid(
ALGORITHM_VECTOR)*implemented// OUT: the implemented bits are SET{
int

index;// Nothing implemented until we say it isMemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR));// Go through the list of implemented algorithms and SET the corresponding bit in// in the implemented 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 416
December 24, 2020

Part 4: Supporting Routines

9.2

Trusted Platform Module Library

Bits.c9.2.1

Introduction

This file contains bit manipulation routines. They operate on bit arrays. The 0th bit in the array is theright-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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 417
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 418
December 24, 2020

Part 4: Supporting Routines

9.3

Trusted Platform Module Library

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
3
4
5
6
7

#ifndef CC_VEND#define
CC_VEND#endif(TPM_CC)(0x20000000)

typedef UINT16

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

8
9

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.
Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX
other
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

command is not implemented
index 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)Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 419
December 24, 2020

Part 4: Supporting Routines
25

Trusted Platform Module Library#endif9.3.3.2

GetClosestCommandIndex()

This function returns the command index for the command with a value that is equal to or greater than the
input value
Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX
other
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

command is not implemented
index 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 420
December 24, 2020

Part 4: Supporting Routines
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
132
133
134
135
136
137
138
139
140
141
142

Trusted Platform Module Library// compiler happy
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// 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"#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 421
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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
pAssert(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.
Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX
other
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

command is not implemented
index 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 422
December 24, 2020

Part 4: Supporting Routines
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

Trusted Platform Module Library// it look like a large unsigned number, this will cause it to fail// the unsigned check below.
if(commandIndex >= LIBRARY_COMMAND_ARRAY_SIZE|| (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.
Return Value

Meaning

UNIMPLEMENTED_COMMAND_INDEX

the index
command

other

218
219
220
221
222
223
224
225
226
227
228
229
230
231

no more implemented commands
of

the

next

implemented

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
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;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 423
December 24, 2020

Part 4: Supporting Routines
242

Trusted Platform Module Library}

9.3.3.6

CommandAuthRole()

This function returns the authorization role required of a handle.

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

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
Return Value

268
269
270
271
272
273
274
275

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 424
December 24, 2020

Part 4: Supporting Routines

9.3.3.8

Trusted Platform Module Library

DecryptSize()This function returns the size of the decrypt size field. This function returns 0 if decryption is not allowed
Return Value

276
277
278
279
280
281
282
283

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.
Return Value

284
285
286
287
288
289
290

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
291
292
293
294
295
296
297

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
298
299
300
301

BOOL
IsWriteOperation(
COMMAND_INDEX)

commandIndex

Family “2.0”Level 00 Revision 01.64// IN: Command to check

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 425
December 24, 2020

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

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 426
December 24, 2020

Part 4: Supporting Routines
361
362

Trusted Platform Module Library#endif}9.3.3.13

CommandCapGetCCList()

This function returns a list of implemented commands and command attributes starting from thecommand in commandCode.
Return Value

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

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 427
December 24, 2020

Part 4: Supporting Routines

Return Value

403
404
405
406
407
408
409

Trusted Platform Module Library

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 428
December 24, 2020

Part 4: Supporting Routines

9.4

Trusted Platform Module Library

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 Return

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 429
December 24, 2020

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:// Rather than have #ifdefs all over the code,// CASE_ACT_HANDLE is defined in ACT.h. It is 'case TPM_RH_ACT_x:'// FOR_EACH_ACT(CASE_ACT_HANDLE) creates a simple// case TPM_RH_ACT_x: // for each of the implemented ACT.
FOR_EACH_ACT(CASE_ACT_HANDLE)
break;
default:// If the implementation has a manufacturer-specific value// then test for it here. Since this implementation does// not have any, this implementation returns the same failure// that unmarshaling of a bad handle would produce.
if(((TPM_RH)handle >= TPM_RH_AUTH_00)&& ((TPM_RH)handle <= TPM_RH_AUTH_FF))// if the implementation has a manufacturer-specific value
result = TPM_RC_VALUE;
else// The handle is in the range of reserved handles but is// not implemented in this TPM.
result = TPM_RC_VALUE;
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 430
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarysession = 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:// 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.
Return Value
count
141
142
143
144
145
146
147
148
149
150
151

Meaning
number 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))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 431
December 24, 2020

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

Trusted Platform Module Library{#ifdefcase TPM_HT_PERMANENT:{
switch(handle){
case TPM_RH_OWNER:// ownerAuth for TPM_RH_OWNER
pAuth = &gp.ownerAuth;break;
case TPM_RH_ENDORSEMENT:// endorsementAuth for TPM_RH_ENDORSEMENT
pAuth = &gp.endorsementAuth;break;// The ACT use platformAuth for auth
FOR_EACH_ACT(CASE_ACT_HANDLE)
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
pAuth = &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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 432
December 24, 2020

Part 4: Supporting Routines
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

Trusted Platform Module Library

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 defect// in the unmarshaling code.
FAIL(FATAL_ERROR_INTERNAL);
break;}// Copy the authValue
MemoryCopy2B((TPM2B *)auth, (TPM2B *)pAuth, 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.
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 433
December 24, 2020

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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

Trusted Platform Module Library

hashAlg = gp.lockoutAlg;
break;#define ACT_GET_POLICY(N)case TPM_RH_ACT_##N:*authPolicy = go.ACT_##N.authPolicy;
hashAlg = go.ACT_##N.hashAlg;
break;// Get the policy for each implemented ACT
FOR_EACH_ACT(ACT_GET_POLICY)
default:
hashAlg = TPM_ALG_ERROR;
break;}
break;
case TPM_HT_TRANSIENT:// authPolicy for an object{
OBJECT *object = HandleToObject(handle);*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.
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 434
December 24, 2020

Part 4: Supporting Routines
329
330
331
332
333
334
335
336
337
338
339
340
341
342

Trusted Platform Module Library

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;}

9.4.3.5

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

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 435
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library}
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){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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 436
December 24, 2020

Part 4: Supporting Routines

9.5
9.5.1

Trusted Platform Module Library

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 an external 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 ANYOTHER FILE.
NOTEThis 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
4
5
6
7

Defines and Includes#define GLOBAL_C#include "Tpm.h"#include "OIDs.h"#if CC_CertifyX509#
include "X509.h"#endif // CC_CertifyX509

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 437
December 24, 2020

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:#endif// Each of the implemented ACT#define ACT_IMPLEMENTED_CASE(N)case TPM_RH_ACT_##N:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 438
December 24, 2020

Part 4: Supporting Routines
39
40
41
42
43
44
45
46
47
48
49

Trusted Platform Module Library

FOR_EACH_ACT(ACT_IMPLEMENTED_CASE)
return inHandle;
break;
default:
break;}}// 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.
Return Value

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

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 439
December 24, 2020

Part 4: Supporting Routines

9.6.3.4

Trusted Platform Module Library

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.
Return Value

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 440
December 24, 2020

Part 4: Supporting Routines

9.7

Trusted Platform Module Library

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 441
December 24, 2020

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

this function is here because there was no better place for it.

Return Value

49
50
51
52
53
54
55

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 442
December 24, 2020

Part 4: Supporting Routines

9.8

Locality.c

9.8.1
1

Trusted Platform Module Library

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 443
December 24, 2020

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

Functions9.9.3.1

TPM_Manufacture()

This function initializes the TPM values in preparation for the TPM''s first use. This function will fail if
previously called. The TPM can be re-manufactured by calling TPM_Teardown() first and then calling thisfunction again.
Return Value

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

Meaning-1

failure0

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.
if(!TpmSizeChecks())
return -1;#endif#if LIBRARY_COMPATIBILITY_CHECK// Make sure that the attached library performs as expected.
if(!MathLibraryCompatibilityCheck())
return -1;#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();Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 444
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// Clear the magic value in the DRBG statego.drbgState.magic = 0;
CryptStartup(SU_RESET);// default configuration for PCR
PCRSimStart();// 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 445
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.

93
94
95
96
97
98
99
100

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.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 446
December 24, 2020

Part 4: Supporting Routines

9.10

Trusted Platform Module Library

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 447
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 448
December 24, 2020

Part 4: Supporting Routines

27
28

Trusted Platform Module Library

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 clause illustrates this.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 449
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 450
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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)

Family “2.0”Level 00 Revision 01.64// This check is triggered by the {:8} notation

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 451
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 452
December 24, 2020

Part 4: Supporting Routines

9.10.6

Trusted Platform Module Library

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;

9.10.79.10.7.1
1
2

size;
buffer[1024];t;b;

Table Marshal Headers
TableMarshal.h#ifndef _TABLE_MARSHAL_H_#define _TABLE_MARSHAL_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 453
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

These are the basic unmarshaling types. This is in the first byte of each structure descriptor that ispassed to Marshal()/Unmarshal() for processing.
3
4
5
6
7
8
9
10
11
12
13
14

#define UINT_MTYPE#define VALUES_MTYPE#define TABLE_MTYPE#define MIN_MAX_MTYPE#define ATTRIBUTES_MTYPE#define STRUCTURE_MTYPE#define TPM2B_MTYPE#define TPM2BS_MTYPE#define LIST_MTYPE#define ERROR_MTYPE#define NULL_MTYPE#define COMPOSITE_MTYPE

Family “2.0”Level 00 Revision 01.64

0(UINT_MTYPE + 1)
(VALUES_MTYPE + 1)
(TABLE_MTYPE + 1)
(MIN_MAX_MTYPE + 1)
(ATTRIBUTES_MTYPE + 1)
(STRUCTURE_MTYPE + 1)
(TPM2B_MTYPE + 1)
(TPM2BS_MTYPE + 1) // TPML
(LIST_MTYPE + 1)
(ERROR_MTYPE + 1)
(NULL_MTYPE + 1)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 454
December 24, 2020

Part 4: Supporting Routines

9.10.7.1.1.1

Trusted Platform Module Library

The Marshal Index

A structure is used to hold the values that guide the marshaling/unmarshaling of each of the types. Eachstructure has a name and an address. For a structure to define a TPMS_name, the structure is a
TPMS_name_MARSHAL_STRUCT and its index is TPMS_name_MARSHAL_INDEX. So, to get theproper structure, use the associated marshal index. The marshal index is passed to Marshal() or
Unmarshal() and those functions look up the proper structure.
To handle structures that allow a null value, the upper bit of each marshal index indicates if the null value
is allowed. This is the NULL_FLAG. It is defined in TableMarshalIndex.h because it is needed by code
outside of the marshaling code.
A structure will have a list of marshal indexes to indicate what to unmarshal. When that index appears ina structure/union, the value will contain a flag to indicate that the NULL_FLAG should be SET on the callto Unmarshal() to unmarshal the type. The caller simply takes the entry and passes it to Unmarshal() toindicate that the NULL_FLAG is SET. There is also the opportunity to SET the NULL_FLAG in the called
structure if the NULL_FLAG was set in the call to the calling structure. This is indicated by:
15#define NULL_MASK~(NULL_FLAG)

When looking up the value to marshal, the upper bit of the marshal index is masked to yield the actualindex. The MSb is the flag bit that indicates if a null flag is set. Code does not verify that the bit is clear
when the called object does not take a flag as this is a benign error.
the modifier byte as used by each MTYPE shown as a structure. They are expressed as a bit maps
below. However, the code uses masking and not bit fields. The types show below are just to help inunderstanding.
NOTE

LSb0 bit numbering is assumed in these typedefs.

When used in an UINT_MTYPE
16
17
18
19
20

typedef struct integerModifier {unsignedsize : 2;
unsignedsign : 1;
unsignedunused : 7;
} integerModifier;When used in a VALUES_MTYPE
21
22
23
24
25
26

typedef struct valuesModifier {unsignedsize : 2;
unsignedsign : 1;
unsignedunused : 5;
unsignedtakesNull : 1;
} valuesModifier;When used in a TABLE_MTYPE
27
28
29
30
31
32
33

typedef struct tableModifier {unsignedsize : 2;
unsignedsign : 1;
unsignedunused : 3;
unsigned
hasBits : 1;
unsignedtakesNull : 1;
} tableModifier;the modifier byte for MIN_MAX_MTYPE
34

typedef struct minMaxModifier {Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 455
December 24, 2020

Part 4: Supporting Routines
35
36
37
38
39
40

unsigned
unsigned
unsigned
unsigned
unsigned} minMaxModifier;

Trusted Platform Module Librarysize : 2;
sign : 1;
unused : 3;
hasBits : 1;
takesNull : 1;

the modifier byte for ATTRIBUTES_MTYPE
41
42
43
44
45

typedef struct attributesModifier {unsignedsize : 2;
unsignedsign : 1;
unsignedunused : 5;
} attributesModifier;the modifier byte is not present in a STRUCTURE_MTYPE or an TPM2B_MTYPE
the modifier byte for a TPM2BS_MTYPE
46
47
48
49
50
51

typedef struct tpm2bsModifier {unsigned
offset : 4;
unsignedunused : 2;
unsignedsizeEqual : 1;
unsigned
propigateNull : 1;
} tpm2bsModifier;the modifier byte for a LIST_MTYPE
52
53
54
55
56
57

typedef struct listModifier {unsigned
offset : 4;
unsignedunused : 2;
unsignedsizeEqual : 1;
unsigned
propigateNull : 1;
} listModifier;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 456
December 24, 2020

Part 4: Supporting Routines

9.10.7.1.1.2

Trusted Platform Module Library

Modifier Octet Values

These are in used in anything that is an integer value. Theses would not be in structure modifier bytes(they would be used in values in structures but not the STRUCTURE_MTYPE header.
58
59
60
61
62
63
64

#define ONE_BYTES#define TWO_BYTES#define FOUR_BYTES#define EIGHT_BYTES#define SIZE_MASK#define IS_SIGNED#define SIGNED_MASK

(0)
(1)
(2)
(3)
(0x3)
(1 << 2)// when the unmarshaled type is a signed value(SIZE_MASK | IS_SIGNED)

This may be used for any type except a UINT_MTYPE
65#define TAKES_NULL(1 << 7)// when the type takes a null

When referencing a structure, this flag indicates if a null is to be propagated to the referenced structure or
type.
66

#define PROPAGATE_NULL(TAKES_NULL)

Can be used in min-max or table structures.
67#define HAS_BITS(1 << 6)// when bit mask is present

In a union, we need to know if this is a union of constant arrays.
68#define IS_ARRAY_UNION(1 << 6)

In a TPM2BS_MTYPE
69
70#define SIZE_EQUAL#define OFFSET_MASK(1 << 6)(0xF)

Right now, there are three spare bits in the modifiers field.
Within the descriptor word of each entry in a StructMarsh_mst(), there is a selector field to determine
which of the sub-types the entry represents and a field that is used to reference another structure entry.
This is a 6-bit field allowing a structure to have 64 entries. This should be more than enough as the
structures are not that long. As of now, only 10-bits of the descriptor word leaving room for expansion.
These are the values used in a STRUCTURE_MTYPE to identify the sub-type of the thing being
processed
71
72
73#define SIMPLE_STYPE#define UNION_STYPE#define ARRAY_STYPE

0
1
2

The code used GET_ to get the element type and the compiler uses SET_ to initialize the value. The
element type is the three bits (2:0).
74
75#define GET_ELEMENT_TYPE(val)#define SET_ELEMENT_TYPE(val)(val & 7)(val & 7)

When an entry is an array or union, this references the structure entry that contains the dimension or
selector value. The code then uses this number to look up the structure entry for that element to find out
what it and where is it in memory. When this is not a reference, it is a simple type and it could be used as

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 457
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Libraryan array value or a union selector. When a simple value, this field contains the size of the associatedvalue (ONE_BYTES, TWO_BYTES ...)The entry size/number is 6 bits (13:8).
76
77
78
79

#define GET_ELEMENT_NUMBER(val)#define SET_ELEMENT_NUMBER(val)#define GET_ELEMENT_SIZE(val)#define SET_ELEMENT_SIZE(val)(((val) >> 8) & 0x3F)(((val) & 0x3F) << 8)
GET_ELEMENT_NUMBER(val)SET_ELEMENT_NUMBER(val)This determines if the null flag is propagated to this type. If generate, the NULL_FLAG is SET in the index
value. This flag is one bit (7)
80
81
82

#define ELEMENT_PROPAGATE(PROPAGATE_NULL)#define INDEX_MASK((UINT16)NULL_MASK)This is used in all bit-field checks. These are used when a value that is checked is conditional (dependent
on the compilation). For example, if AES_128 is (NO), then the bit associated with AES_128 will be 0. In
some cases, the bit value is found by checking that the input is within the range of the table, and thenusing the (val - min) value to index the bit. This would be used when verifying that a particular algorithm isimplemented. In other cases, there is a bit for each value in a table. For example, if checking the key
sizes, there is a list of possible key sizes allowed by the algorithm registry and a bit field to indicate if thatkey size is allowed in the implementation. The smallest bit field has 32-bits because it is implemented aspart of the values array in structures that allow bit fields.
83
84#define IS_BIT_SET32(bit, bits)((((UINT32 *)bits)[bit >> 5] & (1 << (bit & 0x1F))) != 0)\

For a COMPOSITE_MTYPE, the qualifiers byte has an element size and count.
85
86
87
88

#define SET_ELEMENT_COUNT(count)#define GET_ELEMENT_COUNT(val)#endif // _TABLE_MARSHAL_H_

9.10.7.2
12
3
4
5((count & 0x1F) << 3)((val >> 3) & 0x1F)

TableMarshalDefines.h#ifndef _TABLE_MARSHAL_DEFINES_H_#define _TABLE_MARSHAL_DEFINES_H_#define NULL_SHIFT#define NULL_FLAG

15(1 << NULL_SHIFT)

The range macro processes a min, max value and produces a values that is used in the computation tosee if something is within a range. The max value is (max-min). This lets the check for something (val)within a range become: if((val - min) <= max) // passes if in range if((val - min) > max) // passes if not inrange This works because all values are converted to UINT32 values before the compare. For (val - min),all values greater than or equal to val will become positive values with a value equal to min being zero.
This means that in an unsigned compare against max, any value that is outside the range will appear to
be a number greater than max. The benefit of this operation is that this will work even if the input value isa signed number as long as the input is sign extended.
6
7#define RANGE(_min_, _max_, _base_)(UINT32)_min_, (UINT32)((_base_)(_max_ - _min_))\This macro is like the offsetof macro but, instead of computing the offset of a structure element, it
computes the stride between elements that are in a structure array. This is used instead of sizeof()
because the sizeof() operator on a structure can return an implementation dependent value.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 458
December 24, 2020

Part 4: Supporting Routines
8910#define STRIDE(s)Trusted Platform Module Library((UINT16)(size_t)&(((s *)0)[1]))#define MARSHAL_REF(TYPE)((UINT16)(offsetof(MARSHAL_DATA, TYPE)))

This macro creates the entry in the array lookup table1112#define ARRAY_MARSHAL_ENTRY(TYPE){(marshalIndex_t)TYPE##_MARSHAL_REF, (UINT16)STRIDE(TYPE)}\

Defines for array lookup
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#define UINT8_ARRAY_MARSHAL_INDEX#define TPM_CC_ARRAY_MARSHAL_INDEX#define TPMA_CC_ARRAY_MARSHAL_INDEX#define TPM_ALG_ID_ARRAY_MARSHAL_INDEX#define TPM_HANDLE_ARRAY_MARSHAL_INDEX#define TPM2B_DIGEST_ARRAY_MARSHAL_INDEX#define TPMT_HA_ARRAY_MARSHAL_INDEX#define TPMS_PCR_SELECTION_ARRAY_MARSHAL_INDEX#define TPMS_ALG_PROPERTY_ARRAY_MARSHAL_INDEX#define TPMS_TAGGED_PROPERTY_ARRAY_MARSHAL_INDEX#define TPMS_TAGGED_PCR_SELECT_ARRAY_MARSHAL_INDEX#define TPM_ECC_CURVE_ARRAY_MARSHAL_INDEX#define TPMS_TAGGED_POLICY_ARRAY_MARSHAL_INDEX#define TPMS_ACT_DATA_ARRAY_MARSHAL_INDEX#define TPMS_AC_OUTPUT_ARRAY_MARSHAL_INDEX

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

// 0x00// 0x01// 0x02// 0x03// 0x04// 0x05// 0x06// 0x07// 0x08// 0x09// 0x0A// 0x0B// 0x0C// 0x0D// 0x0E

Defines for referencing a type by offset
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

#define UINT8_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, UINT8_DATA)))#define BYTE_MARSHAL_REF
UINT8_MARSHAL_REF#define TPM_HT_MARSHAL_REF
UINT8_MARSHAL_REF#define TPMA_LOCALITY_MARSHAL_REF
UINT8_MARSHAL_REF#define UINT16_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, UINT16_DATA)))#define TPM_KEY_SIZE_MARSHAL_REF
UINT16_MARSHAL_REF#define TPM_KEY_BITS_MARSHAL_REF
UINT16_MARSHAL_REF#define TPM_ALG_ID_MARSHAL_REF
UINT16_MARSHAL_REF#define TPM_ST_MARSHAL_REF
UINT16_MARSHAL_REF#define UINT32_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, UINT32_DATA)))#define TPM_ALGORITHM_ID_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_MODIFIER_INDICATOR_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_AUTHORIZATION_SIZE_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_PARAMETER_SIZE_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_SPEC_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_CONSTANTS32_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_CC_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_RC_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_PT_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_PT_PCR_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_PS_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_HANDLE_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_RH_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_HC_MARSHAL_REF
UINT32_MARSHAL_REF#define TPMA_PERMANENT_MARSHAL_REF
UINT32_MARSHAL_REF#define TPMA_STARTUP_CLEAR_MARSHAL_REF
UINT32_MARSHAL_REF#define TPMA_MEMORY_MARSHAL_REF
UINT32_MARSHAL_REF#define TPMA_CC_MARSHAL_REF
UINT32_MARSHAL_REF#define TPMA_MODES_MARSHAL_REF
UINT32_MARSHAL_REF#define TPMA_X509_KEY_USAGE_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_NV_INDEX_MARSHAL_REF
UINT32_MARSHAL_REF#define TPM_AE_MARSHAL_REF
UINT32_MARSHAL_REF

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 459
December 24, 2020

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

Trusted Platform Module Library#define UINT64_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, UINT64_DATA)))#define INT8_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, INT8_DATA)))#define INT16_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, INT16_DATA)))#define INT32_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, INT32_DATA)))#define INT64_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, INT64_DATA)))#define UINT0_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, UINT0_DATA)))#define TPM_ECC_CURVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_ECC_CURVE_DATA)))#define TPM_CLOCK_ADJUST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_CLOCK_ADJUST_DATA)))#define TPM_EO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_EO_DATA)))#define TPM_SU_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_SU_DATA)))#define TPM_SE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_SE_DATA)))#define TPM_CAP_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_CAP_DATA)))#define TPMA_ALGORITHM_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMA_ALGORITHM_DATA)))#define TPMA_OBJECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMA_OBJECT_DATA)))#define TPMA_SESSION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMA_SESSION_DATA)))#define TPMA_ACT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMA_ACT_DATA)))#define TPMI_YES_NO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_YES_NO_DATA)))#define TPMI_DH_OBJECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_OBJECT_DATA)))#define TPMI_DH_PARENT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_PARENT_DATA)))#define TPMI_DH_PERSISTENT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_PERSISTENT_DATA)))#define TPMI_DH_ENTITY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_ENTITY_DATA)))#define TPMI_DH_PCR_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_PCR_DATA)))#define TPMI_SH_AUTH_SESSION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_SH_AUTH_SESSION_DATA)))#define TPMI_SH_HMAC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_SH_HMAC_DATA)))#define TPMI_SH_POLICY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_SH_POLICY_DATA)))#define TPMI_DH_CONTEXT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_CONTEXT_DATA)))#define TPMI_DH_SAVED_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_DH_SAVED_DATA)))#define TPMI_RH_HIERARCHY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_HIERARCHY_DATA)))#define TPMI_RH_ENABLES_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_ENABLES_DATA)))#define TPMI_RH_HIERARCHY_AUTH_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_HIERARCHY_AUTH_DATA)))#define TPMI_RH_HIERARCHY_POLICY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_HIERARCHY_POLICY_DATA)))#define TPMI_RH_PLATFORM_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_PLATFORM_DATA)))#define TPMI_RH_OWNER_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_OWNER_DATA)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 460
December 24, 2020

Part 4: Supporting Routines
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
194

Trusted Platform Module Library#define TPMI_RH_ENDORSEMENT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_ENDORSEMENT_DATA)))#define TPMI_RH_PROVISION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_PROVISION_DATA)))#define TPMI_RH_CLEAR_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_CLEAR_DATA)))#define TPMI_RH_NV_AUTH_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_NV_AUTH_DATA)))#define TPMI_RH_LOCKOUT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_LOCKOUT_DATA)))#define TPMI_RH_NV_INDEX_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_NV_INDEX_DATA)))#define TPMI_RH_AC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_AC_DATA)))#define TPMI_RH_ACT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RH_ACT_DATA)))#define TPMI_ALG_HASH_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_HASH_DATA)))#define TPMI_ALG_ASYM_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_ASYM_DATA)))#define TPMI_ALG_SYM_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SYM_DATA)))#define TPMI_ALG_SYM_OBJECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SYM_OBJECT_DATA)))#define TPMI_ALG_SYM_MODE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SYM_MODE_DATA)))#define TPMI_ALG_KDF_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_KDF_DATA)))#define TPMI_ALG_SIG_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SIG_SCHEME_DATA)))#define TPMI_ECC_KEY_EXCHANGE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ECC_KEY_EXCHANGE_DATA)))#define TPMI_ST_COMMAND_TAG_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ST_COMMAND_TAG_DATA)))#define TPMI_ALG_MAC_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_MAC_SCHEME_DATA)))#define TPMI_ALG_CIPHER_MODE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_CIPHER_MODE_DATA)))#define TPMS_EMPTY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_EMPTY_DATA)))#define TPMS_ENC_SCHEME_RSAES_MARSHAL_REF
TPMS_EMPTY_MARSHAL_REF#define TPMS_ALGORITHM_DESCRIPTION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ALGORITHM_DESCRIPTION_DATA)))#define TPMU_HA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_HA_DATA)))#define TPMT_HA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_HA_DATA)))#define TPM2B_DIGEST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_DIGEST_DATA)))#define TPM2B_NONCE_MARSHAL_REF
TPM2B_DIGEST_MARSHAL_REF#define TPM2B_AUTH_MARSHAL_REF
TPM2B_DIGEST_MARSHAL_REF#define TPM2B_OPERAND_MARSHAL_REF
TPM2B_DIGEST_MARSHAL_REF#define TPM2B_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_DATA_DATA)))#define TPM2B_EVENT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_EVENT_DATA)))#define TPM2B_MAX_BUFFER_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_MAX_BUFFER_DATA)))#define TPM2B_MAX_NV_BUFFER_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_MAX_NV_BUFFER_DATA)))#define TPM2B_TIMEOUT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_TIMEOUT_DATA)))#define TPM2B_IV_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_IV_DATA)))#define NULL_UNION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, NULL_UNION_DATA)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 461
December 24, 2020

Part 4: Supporting Routines
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
260

Trusted Platform Module Library#define TPMU_NAME_MARSHAL_REF
NULL_UNION_MARSHAL_REF#define TPMU_SENSITIVE_CREATE_MARSHAL_REF
NULL_UNION_MARSHAL_REF#define TPM2B_NAME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_NAME_DATA)))#define TPMS_PCR_SELECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_PCR_SELECT_DATA)))#define TPMS_PCR_SELECTION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_PCR_SELECTION_DATA)))#define TPMT_TK_CREATION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_TK_CREATION_DATA)))#define TPMT_TK_VERIFIED_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_TK_VERIFIED_DATA)))#define TPMT_TK_AUTH_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_TK_AUTH_DATA)))#define TPMT_TK_HASHCHECK_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_TK_HASHCHECK_DATA)))#define TPMS_ALG_PROPERTY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ALG_PROPERTY_DATA)))#define TPMS_TAGGED_PROPERTY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_TAGGED_PROPERTY_DATA)))#define TPMS_TAGGED_PCR_SELECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_TAGGED_PCR_SELECT_DATA)))#define TPMS_TAGGED_POLICY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_TAGGED_POLICY_DATA)))#define TPMS_ACT_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ACT_DATA_DATA)))#define TPML_CC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_CC_DATA)))#define TPML_CCA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_CCA_DATA)))#define TPML_ALG_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_ALG_DATA)))#define TPML_HANDLE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_HANDLE_DATA)))#define TPML_DIGEST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_DIGEST_DATA)))#define TPML_DIGEST_VALUES_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_DIGEST_VALUES_DATA)))#define TPML_PCR_SELECTION_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_PCR_SELECTION_DATA)))#define TPML_ALG_PROPERTY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_ALG_PROPERTY_DATA)))#define TPML_TAGGED_TPM_PROPERTY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_TAGGED_TPM_PROPERTY_DATA)))#define TPML_TAGGED_PCR_PROPERTY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_TAGGED_PCR_PROPERTY_DATA)))#define TPML_ECC_CURVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_ECC_CURVE_DATA)))#define TPML_TAGGED_POLICY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_TAGGED_POLICY_DATA)))#define TPML_ACT_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_ACT_DATA_DATA)))#define TPMU_CAPABILITIES_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_CAPABILITIES_DATA)))#define TPMS_CAPABILITY_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CAPABILITY_DATA_DATA)))#define TPMS_CLOCK_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CLOCK_INFO_DATA)))#define TPMS_TIME_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_TIME_INFO_DATA)))#define TPMS_TIME_ATTEST_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_TIME_ATTEST_INFO_DATA)))#define TPMS_CERTIFY_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CERTIFY_INFO_DATA)))#define TPMS_QUOTE_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_QUOTE_INFO_DATA)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 462
December 24, 2020

Part 4: Supporting Routines
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
326

Trusted Platform Module Library#define TPMS_COMMAND_AUDIT_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_COMMAND_AUDIT_INFO_DATA)))#define TPMS_SESSION_AUDIT_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SESSION_AUDIT_INFO_DATA)))#define TPMS_CREATION_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CREATION_INFO_DATA)))#define TPMS_NV_CERTIFY_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_NV_CERTIFY_INFO_DATA)))#define TPMS_NV_DIGEST_CERTIFY_INFO_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_NV_DIGEST_CERTIFY_INFO_DATA)))#define TPMI_ST_ATTEST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ST_ATTEST_DATA)))#define TPMU_ATTEST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_ATTEST_DATA)))#define TPMS_ATTEST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ATTEST_DATA)))#define TPM2B_ATTEST_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_ATTEST_DATA)))#define TPMS_AUTH_COMMAND_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_AUTH_COMMAND_DATA)))#define TPMS_AUTH_RESPONSE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_AUTH_RESPONSE_DATA)))#define TPMI_TDES_KEY_BITS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_TDES_KEY_BITS_DATA)))#define TPMI_AES_KEY_BITS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_AES_KEY_BITS_DATA)))#define TPMI_SM4_KEY_BITS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_SM4_KEY_BITS_DATA)))#define TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_CAMELLIA_KEY_BITS_DATA)))#define TPMU_SYM_KEY_BITS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_SYM_KEY_BITS_DATA)))#define TPMU_SYM_MODE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_SYM_MODE_DATA)))#define TPMT_SYM_DEF_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_SYM_DEF_DATA)))#define TPMT_SYM_DEF_OBJECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_SYM_DEF_OBJECT_DATA)))#define TPM2B_SYM_KEY_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_SYM_KEY_DATA)))#define TPMS_SYMCIPHER_PARMS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SYMCIPHER_PARMS_DATA)))#define TPM2B_LABEL_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_LABEL_DATA)))#define TPMS_DERIVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_DERIVE_DATA)))#define TPM2B_DERIVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_DERIVE_DATA)))#define TPM2B_SENSITIVE_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_SENSITIVE_DATA_DATA)))#define TPMS_SENSITIVE_CREATE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SENSITIVE_CREATE_DATA)))#define TPM2B_SENSITIVE_CREATE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_SENSITIVE_CREATE_DATA)))#define TPMS_SCHEME_HASH_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SCHEME_HASH_DATA)))#define TPMS_SCHEME_HMAC_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_SIG_SCHEME_SM2_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_ENC_SCHEME_OAEP_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_KEY_SCHEME_ECDH_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_KDF_SCHEME_MGF1_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 463
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#define TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_KDF_SCHEME_KDF2_MARSHAL_REF
TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF#define TPMS_SCHEME_ECDAA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SCHEME_ECDAA_DATA)))#define TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF
TPMS_SCHEME_ECDAA_MARSHAL_REF#define TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_KEYEDHASH_SCHEME_DATA)))#define TPMS_SCHEME_XOR_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SCHEME_XOR_DATA)))#define TPMU_SCHEME_KEYEDHASH_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_SCHEME_KEYEDHASH_DATA)))#define TPMT_KEYEDHASH_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_KEYEDHASH_SCHEME_DATA)))#define TPMU_SIG_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_SIG_SCHEME_DATA)))#define TPMT_SIG_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_SIG_SCHEME_DATA)))#define TPMU_KDF_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_KDF_SCHEME_DATA)))#define TPMT_KDF_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_KDF_SCHEME_DATA)))#define TPMI_ALG_ASYM_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_ASYM_SCHEME_DATA)))#define TPMU_ASYM_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_ASYM_SCHEME_DATA)))#define TPMI_ALG_RSA_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_RSA_SCHEME_DATA)))#define TPMT_RSA_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_RSA_SCHEME_DATA)))#define TPMI_ALG_RSA_DECRYPT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_RSA_DECRYPT_DATA)))#define TPMT_RSA_DECRYPT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_RSA_DECRYPT_DATA)))#define TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_PUBLIC_KEY_RSA_DATA)))#define TPMI_RSA_KEY_BITS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_RSA_KEY_BITS_DATA)))#define TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_PRIVATE_KEY_RSA_DATA)))#define TPM2B_ECC_PARAMETER_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_ECC_PARAMETER_DATA)))#define TPMS_ECC_POINT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ECC_POINT_DATA)))#define TPM2B_ECC_POINT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_ECC_POINT_DATA)))#define TPMI_ALG_ECC_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_ECC_SCHEME_DATA)))#define TPMI_ECC_CURVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ECC_CURVE_DATA)))#define TPMT_ECC_SCHEME_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_ECC_SCHEME_DATA)))#define TPMS_ALGORITHM_DETAIL_ECC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ALGORITHM_DETAIL_ECC_DATA)))#define TPMS_SIGNATURE_RSA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SIGNATURE_RSA_DATA)))#define TPMS_SIGNATURE_RSASSA_MARSHAL_REF
TPMS_SIGNATURE_RSA_MARSHAL_REF#define TPMS_SIGNATURE_RSAPSS_MARSHAL_REF
TPMS_SIGNATURE_RSA_MARSHAL_REF#define TPMS_SIGNATURE_ECC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_SIGNATURE_ECC_DATA)))#define TPMS_SIGNATURE_ECDAA_MARSHAL_REF
TPMS_SIGNATURE_ECC_MARSHAL_REF#define TPMS_SIGNATURE_ECDSA_MARSHAL_REF
TPMS_SIGNATURE_ECC_MARSHAL_REF#define TPMS_SIGNATURE_SM2_MARSHAL_REF
TPMS_SIGNATURE_ECC_MARSHAL_REF#define TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF
TPMS_SIGNATURE_ECC_MARSHAL_REF#define TPMU_SIGNATURE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_SIGNATURE_DATA)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 464
December 24, 2020

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
454
455
456
457
458

Trusted Platform Module Library#define TPMT_SIGNATURE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_SIGNATURE_DATA)))#define TPMU_ENCRYPTED_SECRET_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_ENCRYPTED_SECRET_DATA)))#define TPM2B_ENCRYPTED_SECRET_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_ENCRYPTED_SECRET_DATA)))#define TPMI_ALG_PUBLIC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMI_ALG_PUBLIC_DATA)))#define TPMU_PUBLIC_ID_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_PUBLIC_ID_DATA)))#define TPMS_KEYEDHASH_PARMS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_KEYEDHASH_PARMS_DATA)))#define TPMS_RSA_PARMS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_RSA_PARMS_DATA)))#define TPMS_ECC_PARMS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_ECC_PARMS_DATA)))#define TPMU_PUBLIC_PARMS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_PUBLIC_PARMS_DATA)))#define TPMT_PUBLIC_PARMS_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_PUBLIC_PARMS_DATA)))#define TPMT_PUBLIC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_PUBLIC_DATA)))#define TPM2B_PUBLIC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_PUBLIC_DATA)))#define TPM2B_TEMPLATE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_TEMPLATE_DATA)))#define TPM2B_PRIVATE_VENDOR_SPECIFIC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_PRIVATE_VENDOR_SPECIFIC_DATA)))#define TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMU_SENSITIVE_COMPOSITE_DATA)))#define TPMT_SENSITIVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMT_SENSITIVE_DATA)))#define TPM2B_SENSITIVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_SENSITIVE_DATA)))#define TPM2B_PRIVATE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_PRIVATE_DATA)))#define TPM2B_ID_OBJECT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_ID_OBJECT_DATA)))#define TPMS_NV_PIN_COUNTER_PARAMETERS_MARSHAL_REF \((UINT16)(offsetof(MarshalData_st, TPMS_NV_PIN_COUNTER_PARAMETERS_DATA)))#define TPMA_NV_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMA_NV_DATA)))#define TPMS_NV_PUBLIC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_NV_PUBLIC_DATA)))#define TPM2B_NV_PUBLIC_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_NV_PUBLIC_DATA)))#define TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_CONTEXT_SENSITIVE_DATA)))#define TPMS_CONTEXT_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CONTEXT_DATA_DATA)))#define TPM2B_CONTEXT_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_CONTEXT_DATA_DATA)))#define TPMS_CONTEXT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CONTEXT_DATA)))#define TPMS_CREATION_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_CREATION_DATA_DATA)))#define TPM2B_CREATION_DATA_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM2B_CREATION_DATA_DATA)))#define TPM_AT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPM_AT_DATA)))#define TPMS_AC_OUTPUT_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPMS_AC_OUTPUT_DATA)))#define TPML_AC_CAPABILITIES_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, TPML_AC_CAPABILITIES_DATA)))#define Type00_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type00_DATA)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 465
December 24, 2020

Part 4: Supporting Routines
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
515
516
517
518
519
520
521
522
523
524

Trusted Platform Module Library#define Type01_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type01_DATA)))#define Type02_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type02_DATA)))#define Type03_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type03_DATA)))#define Type04_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type04_DATA)))#define Type05_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type05_DATA)))#define Type06_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type06_DATA)))#define Type07_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type07_DATA)))#define Type08_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type08_DATA)))#define Type09_MARSHAL_REF
Type08_MARSHAL_REF#define Type14_MARSHAL_REF
Type08_MARSHAL_REF#define Type10_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type10_DATA)))#define Type11_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type11_DATA)))#define Type12_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type12_DATA)))#define Type13_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type13_DATA)))#define Type15_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type15_DATA)))#define Type16_MARSHAL_REF
Type15_MARSHAL_REF#define Type17_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type17_DATA)))#define Type18_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type18_DATA)))#define Type19_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type19_DATA)))#define Type20_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type20_DATA)))#define Type21_MARSHAL_REF
Type20_MARSHAL_REF#define Type22_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type22_DATA)))#define Type23_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type23_DATA)))#define Type24_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type24_DATA)))#define Type25_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type25_DATA)))#define Type26_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type26_DATA)))#define Type27_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type27_DATA)))#define Type28_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type28_DATA)))#define Type29_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type29_DATA)))#define Type30_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type30_DATA)))#define Type31_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type31_DATA)))#define Type32_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type32_DATA)))#define Type33_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type33_DATA)))#define Type34_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type34_DATA)))#define Type35_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type35_DATA)))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 466
December 24, 2020

Part 4: Supporting Routines
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
581
582
583
584
585
586
587
588
589
590

Trusted Platform Module Library#define Type36_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type36_DATA)))#define Type37_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type37_DATA)))#define Type38_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type38_DATA)))#define Type39_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type39_DATA)))#define Type40_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type40_DATA)))#define Type41_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type41_DATA)))#define Type42_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type42_DATA)))#define Type43_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type43_DATA)))#define Type44_MARSHAL_REF\((UINT16)(offsetof(MarshalData_st, Type44_DATA)))//#defines to change calling sequence for code using marshaling#define UINT8_Unmarshal(target, buffer, size)
Unmarshal(UINT8_MARSHAL_REF, (target), (buffer), (size))#define UINT8_Marshal(source, buffer, size)
Marshal(UINT8_MARSHAL_REF, (source), (buffer), (size))#define BYTE_Unmarshal(target, buffer, size)
Unmarshal(UINT8_MARSHAL_REF, (target), (buffer), (size))#define BYTE_Marshal(source, buffer, size)
Marshal(UINT8_MARSHAL_REF, (source), (buffer), (size))#define INT8_Unmarshal(target, buffer, size)
Unmarshal(INT8_MARSHAL_REF, (target), (buffer), (size))#define INT8_Marshal(source, buffer, size)
Marshal(INT8_MARSHAL_REF, (source), (buffer), (size))#define UINT16_Unmarshal(target, buffer, size)
Unmarshal(UINT16_MARSHAL_REF, (target), (buffer), (size))#define UINT16_Marshal(source, buffer, size)
Marshal(UINT16_MARSHAL_REF, (source), (buffer), (size))#define INT16_Unmarshal(target, buffer, size)
Unmarshal(INT16_MARSHAL_REF, (target), (buffer), (size))#define INT16_Marshal(source, buffer, size)
Marshal(INT16_MARSHAL_REF, (source), (buffer), (size))#define UINT32_Unmarshal(target, buffer, size)
Unmarshal(UINT32_MARSHAL_REF, (target), (buffer), (size))#define UINT32_Marshal(source, buffer, size)
Marshal(UINT32_MARSHAL_REF, (source), (buffer), (size))#define INT32_Unmarshal(target, buffer, size)
Unmarshal(INT32_MARSHAL_REF, (target), (buffer), (size))#define INT32_Marshal(source, buffer, size)
Marshal(INT32_MARSHAL_REF, (source), (buffer), (size))#define UINT64_Unmarshal(target, buffer, size)
Unmarshal(UINT64_MARSHAL_REF, (target), (buffer), (size))#define UINT64_Marshal(source, buffer, size)
Marshal(UINT64_MARSHAL_REF, (source), (buffer), (size))#define INT64_Unmarshal(target, buffer, size)
Unmarshal(INT64_MARSHAL_REF, (target), (buffer), (size))#define INT64_Marshal(source, buffer, size)
Marshal(INT64_MARSHAL_REF, (source), (buffer), (size))#define TPM_ALGORITHM_ID_Unmarshal(target, buffer, size)
Unmarshal(TPM_ALGORITHM_ID_MARSHAL_REF, (target), (buffer), (size))#define TPM_ALGORITHM_ID_Marshal(source, buffer, size)
Marshal(TPM_ALGORITHM_ID_MARSHAL_REF, (source), (buffer), (size))#define TPM_MODIFIER_INDICATOR_Unmarshal(target, buffer, size)
Unmarshal(TPM_MODIFIER_INDICATOR_MARSHAL_REF, (target), (buffer), (size))#define TPM_MODIFIER_INDICATOR_Marshal(source, buffer, size)
Marshal(TPM_MODIFIER_INDICATOR_MARSHAL_REF, (source), (buffer), (size))#define TPM_AUTHORIZATION_SIZE_Unmarshal(target, buffer, size)
Unmarshal(TPM_AUTHORIZATION_SIZE_MARSHAL_REF, (target), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 467
December 24, 2020

Part 4: Supporting Routines
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
650
651
652
653
654
655
656

Trusted Platform Module Library#define TPM_AUTHORIZATION_SIZE_Marshal(source, buffer, size)
Marshal(TPM_AUTHORIZATION_SIZE_MARSHAL_REF, (source), (buffer), (size))#define TPM_PARAMETER_SIZE_Unmarshal(target, buffer, size)
Unmarshal(TPM_PARAMETER_SIZE_MARSHAL_REF, (target), (buffer), (size))#define TPM_PARAMETER_SIZE_Marshal(source, buffer, size)
Marshal(TPM_PARAMETER_SIZE_MARSHAL_REF, (source), (buffer), (size))#define TPM_KEY_SIZE_Unmarshal(target, buffer, size)
Unmarshal(TPM_KEY_SIZE_MARSHAL_REF, (target), (buffer), (size))#define TPM_KEY_SIZE_Marshal(source, buffer, size)
Marshal(TPM_KEY_SIZE_MARSHAL_REF, (source), (buffer), (size))#define TPM_KEY_BITS_Unmarshal(target, buffer, size)
Unmarshal(TPM_KEY_BITS_MARSHAL_REF, (target), (buffer), (size))#define TPM_KEY_BITS_Marshal(source, buffer, size)
Marshal(TPM_KEY_BITS_MARSHAL_REF, (source), (buffer), (size))#define TPM_CONSTANTS32_Marshal(source, buffer, size)
Marshal(TPM_CONSTANTS32_MARSHAL_REF, (source), (buffer), (size))#define TPM_ALG_ID_Unmarshal(target, buffer, size)
Unmarshal(TPM_ALG_ID_MARSHAL_REF, (target), (buffer), (size))#define TPM_ALG_ID_Marshal(source, buffer, size)
Marshal(TPM_ALG_ID_MARSHAL_REF, (source), (buffer), (size))#define TPM_ECC_CURVE_Unmarshal(target, buffer, size)
Unmarshal(TPM_ECC_CURVE_MARSHAL_REF, (target), (buffer), (size))#define TPM_ECC_CURVE_Marshal(source, buffer, size)
Marshal(TPM_ECC_CURVE_MARSHAL_REF, (source), (buffer), (size))#define TPM_CC_Unmarshal(target, buffer, size)
Unmarshal(TPM_CC_MARSHAL_REF, (target), (buffer), (size))#define TPM_CC_Marshal(source, buffer, size)
Marshal(TPM_CC_MARSHAL_REF, (source), (buffer), (size))#define TPM_RC_Marshal(source, buffer, size)
Marshal(TPM_RC_MARSHAL_REF, (source), (buffer), (size))#define TPM_CLOCK_ADJUST_Unmarshal(target, buffer, size)
Unmarshal(TPM_CLOCK_ADJUST_MARSHAL_REF, (target), (buffer), (size))#define TPM_EO_Unmarshal(target, buffer, size)
Unmarshal(TPM_EO_MARSHAL_REF, (target), (buffer), (size))#define TPM_EO_Marshal(source, buffer, size)
Marshal(TPM_EO_MARSHAL_REF, (source), (buffer), (size))#define TPM_ST_Unmarshal(target, buffer, size)
Unmarshal(TPM_ST_MARSHAL_REF, (target), (buffer), (size))#define TPM_ST_Marshal(source, buffer, size)
Marshal(TPM_ST_MARSHAL_REF, (source), (buffer), (size))#define TPM_SU_Unmarshal(target, buffer, size)
Unmarshal(TPM_SU_MARSHAL_REF, (target), (buffer), (size))#define TPM_SE_Unmarshal(target, buffer, size)
Unmarshal(TPM_SE_MARSHAL_REF, (target), (buffer), (size))#define TPM_CAP_Unmarshal(target, buffer, size)
Unmarshal(TPM_CAP_MARSHAL_REF, (target), (buffer), (size))#define TPM_CAP_Marshal(source, buffer, size)
Marshal(TPM_CAP_MARSHAL_REF, (source), (buffer), (size))#define TPM_PT_Unmarshal(target, buffer, size)
Unmarshal(TPM_PT_MARSHAL_REF, (target), (buffer), (size))#define TPM_PT_Marshal(source, buffer, size)
Marshal(TPM_PT_MARSHAL_REF, (source), (buffer), (size))#define TPM_PT_PCR_Unmarshal(target, buffer, size)
Unmarshal(TPM_PT_PCR_MARSHAL_REF, (target), (buffer), (size))#define TPM_PT_PCR_Marshal(source, buffer, size)
Marshal(TPM_PT_PCR_MARSHAL_REF, (source), (buffer), (size))#define TPM_PS_Marshal(source, buffer, size)
Marshal(TPM_PS_MARSHAL_REF, (source), (buffer), (size))#define TPM_HANDLE_Unmarshal(target, buffer, size)
Unmarshal(TPM_HANDLE_MARSHAL_REF, (target), (buffer), (size))#define TPM_HANDLE_Marshal(source, buffer, size)
Marshal(TPM_HANDLE_MARSHAL_REF, (source), (buffer), (size))#define TPM_HT_Unmarshal(target, buffer, size)
Unmarshal(TPM_HT_MARSHAL_REF, (target), (buffer), (size))#define TPM_HT_Marshal(source, buffer, size)
Marshal(TPM_HT_MARSHAL_REF, (source), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 468
December 24, 2020

Part 4: Supporting Routines
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
717
718
719
720
721
722

Trusted Platform Module Library#define TPM_RH_Unmarshal(target, buffer, size)\
Unmarshal(TPM_RH_MARSHAL_REF, (target), (buffer), (size))#define TPM_RH_Marshal(source, buffer, size)\
Marshal(TPM_RH_MARSHAL_REF, (source), (buffer), (size))#define TPM_HC_Unmarshal(target, buffer, size)\
Unmarshal(TPM_HC_MARSHAL_REF, (target), (buffer), (size))#define TPM_HC_Marshal(source, buffer, size)\
Marshal(TPM_HC_MARSHAL_REF, (source), (buffer), (size))#define TPMA_ALGORITHM_Unmarshal(target, buffer, size)\
Unmarshal(TPMA_ALGORITHM_MARSHAL_REF, (target), (buffer), (size))#define TPMA_ALGORITHM_Marshal(source, buffer, size)\
Marshal(TPMA_ALGORITHM_MARSHAL_REF, (source), (buffer), (size))#define TPMA_OBJECT_Unmarshal(target, buffer, size)\
Unmarshal(TPMA_OBJECT_MARSHAL_REF, (target), (buffer), (size))#define TPMA_OBJECT_Marshal(source, buffer, size)\
Marshal(TPMA_OBJECT_MARSHAL_REF, (source), (buffer), (size))#define TPMA_SESSION_Unmarshal(target, buffer, size)\
Unmarshal(TPMA_SESSION_MARSHAL_REF, (target), (buffer), (size))#define TPMA_SESSION_Marshal(source, buffer, size)\
Marshal(TPMA_SESSION_MARSHAL_REF, (source), (buffer), (size))#define TPMA_LOCALITY_Unmarshal(target, buffer, size)\
Unmarshal(TPMA_LOCALITY_MARSHAL_REF, (target), (buffer), (size))#define TPMA_LOCALITY_Marshal(source, buffer, size)\
Marshal(TPMA_LOCALITY_MARSHAL_REF, (source), (buffer), (size))#define TPMA_PERMANENT_Marshal(source, buffer, size)\
Marshal(TPMA_PERMANENT_MARSHAL_REF, (source), (buffer), (size))#define TPMA_STARTUP_CLEAR_Marshal(source, buffer, size)\
Marshal(TPMA_STARTUP_CLEAR_MARSHAL_REF, (source), (buffer), (size))#define TPMA_MEMORY_Marshal(source, buffer, size)\
Marshal(TPMA_MEMORY_MARSHAL_REF, (source), (buffer), (size))#define TPMA_CC_Marshal(source, buffer, size)\
Marshal(TPMA_CC_MARSHAL_REF, (source), (buffer), (size))#define TPMA_MODES_Marshal(source, buffer, size)\
Marshal(TPMA_MODES_MARSHAL_REF, (source), (buffer), (size))#define TPMA_X509_KEY_USAGE_Marshal(source, buffer, size)\
Marshal(TPMA_X509_KEY_USAGE_MARSHAL_REF, (source), (buffer), (size))#define TPMA_ACT_Unmarshal(target, buffer, size)\
Unmarshal(TPMA_ACT_MARSHAL_REF, (target), (buffer), (size))#define TPMA_ACT_Marshal(source, buffer, size)\
Marshal(TPMA_ACT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_YES_NO_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_YES_NO_MARSHAL_REF, (target), (buffer), (size))#define TPMI_YES_NO_Marshal(source, buffer, size)\
Marshal(TPMI_YES_NO_MARSHAL_REF, (source), (buffer), (size))#define TPMI_DH_OBJECT_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_DH_OBJECT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),\(size))#define TPMI_DH_OBJECT_Marshal(source, buffer, size)\
Marshal(TPMI_DH_OBJECT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_DH_PARENT_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_DH_PARENT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),\(size))#define TPMI_DH_PARENT_Marshal(source, buffer, size)\
Marshal(TPMI_DH_PARENT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_DH_PERSISTENT_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_DH_PERSISTENT_MARSHAL_REF, (target), (buffer), (size))#define TPMI_DH_PERSISTENT_Marshal(source, buffer, size)\
Marshal(TPMI_DH_PERSISTENT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_DH_ENTITY_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_DH_ENTITY_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),\(size))#define TPMI_DH_PCR_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_DH_PCR_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),\(size))#define TPMI_SH_AUTH_SESSION_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_SH_AUTH_SESSION_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 469
December 24, 2020

Part 4: Supporting Routines
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
779
780
781
782
783
784
785
786
787
788

Trusted Platform Module Library(buffer), (size))#define TPMI_SH_AUTH_SESSION_Marshal(source, buffer, size)\
Marshal(TPMI_SH_AUTH_SESSION_MARSHAL_REF, (source), (buffer), (size))#define TPMI_SH_HMAC_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_SH_HMAC_MARSHAL_REF, (target), (buffer), (size))#define TPMI_SH_HMAC_Marshal(source, buffer, size)\
Marshal(TPMI_SH_HMAC_MARSHAL_REF, (source), (buffer), (size))#define TPMI_SH_POLICY_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_SH_POLICY_MARSHAL_REF, (target), (buffer), (size))#define TPMI_SH_POLICY_Marshal(source, buffer, size)\
Marshal(TPMI_SH_POLICY_MARSHAL_REF, (source), (buffer), (size))#define TPMI_DH_CONTEXT_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_DH_CONTEXT_MARSHAL_REF, (target), (buffer), (size))#define TPMI_DH_CONTEXT_Marshal(source, buffer, size)\
Marshal(TPMI_DH_CONTEXT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_DH_SAVED_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_DH_SAVED_MARSHAL_REF, (target), (buffer), (size))#define TPMI_DH_SAVED_Marshal(source, buffer, size)\
Marshal(TPMI_DH_SAVED_MARSHAL_REF, (source), (buffer), (size))#define TPMI_RH_HIERARCHY_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_RH_HIERARCHY_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\(buffer), (size))#define TPMI_RH_HIERARCHY_Marshal(source, buffer, size)\
Marshal(TPMI_RH_HIERARCHY_MARSHAL_REF, (source), (buffer), (size))#define TPMI_RH_ENABLES_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_RH_ENABLES_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\(buffer), (size))#define TPMI_RH_ENABLES_Marshal(source, buffer, size)\
Marshal(TPMI_RH_ENABLES_MARSHAL_REF, (source), (buffer), (size))#define TPMI_RH_HIERARCHY_AUTH_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_HIERARCHY_AUTH_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_HIERARCHY_POLICY_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_HIERARCHY_POLICY_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_PLATFORM_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_PLATFORM_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_OWNER_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_RH_OWNER_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer), \(size))#define TPMI_RH_ENDORSEMENT_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_RH_ENDORSEMENT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\(buffer), (size))#define TPMI_RH_PROVISION_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_PROVISION_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_CLEAR_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_CLEAR_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_NV_AUTH_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_NV_AUTH_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_LOCKOUT_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_LOCKOUT_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_NV_INDEX_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_NV_INDEX_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_NV_INDEX_Marshal(source, buffer, size)\
Marshal(TPMI_RH_NV_INDEX_MARSHAL_REF, (source), (buffer), (size))#define TPMI_RH_AC_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_AC_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_ACT_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_RH_ACT_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RH_ACT_Marshal(source, buffer, size)\
Marshal(TPMI_RH_ACT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_HASH_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_ALG_HASH_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer), \(size))#define TPMI_ALG_HASH_Marshal(source, buffer, size)\
Marshal(TPMI_ALG_HASH_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_ASYM_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_ALG_ASYM_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer), \Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 470
December 24, 2020

Part 4: Supporting Routines
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
845
846
847
848
849
850
851
852
853
854

Trusted Platform Module Library(size))#define TPMI_ALG_ASYM_Marshal(source, buffer, size)
Marshal(TPMI_ALG_ASYM_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_SYM_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_SYM_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),(size))#define TPMI_ALG_SYM_Marshal(source, buffer, size)
Marshal(TPMI_ALG_SYM_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_SYM_OBJECT_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_SYM_OBJECT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_SYM_OBJECT_Marshal(source, buffer, size)
Marshal(TPMI_ALG_SYM_OBJECT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_SYM_MODE_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_SYM_MODE_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_SYM_MODE_Marshal(source, buffer, size)
Marshal(TPMI_ALG_SYM_MODE_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_KDF_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_KDF_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),(size))#define TPMI_ALG_KDF_Marshal(source, buffer, size)
Marshal(TPMI_ALG_KDF_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_SIG_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_SIG_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_SIG_SCHEME_Marshal(source, buffer, size)
Marshal(TPMI_ALG_SIG_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ECC_KEY_EXCHANGE_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ECC_KEY_EXCHANGE_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ECC_KEY_EXCHANGE_Marshal(source, buffer, size)
Marshal(TPMI_ECC_KEY_EXCHANGE_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ST_COMMAND_TAG_Unmarshal(target, buffer, size)
Unmarshal(TPMI_ST_COMMAND_TAG_MARSHAL_REF, (target), (buffer), (size))#define TPMI_ST_COMMAND_TAG_Marshal(source, buffer, size)
Marshal(TPMI_ST_COMMAND_TAG_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_MAC_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_MAC_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_MAC_SCHEME_Marshal(source, buffer, size)
Marshal(TPMI_ALG_MAC_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_CIPHER_MODE_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_CIPHER_MODE_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_CIPHER_MODE_Marshal(source, buffer, size)
Marshal(TPMI_ALG_CIPHER_MODE_MARSHAL_REF, (source), (buffer), (size))#define TPMS_EMPTY_Unmarshal(target, buffer, size)
Unmarshal(TPMS_EMPTY_MARSHAL_REF, (target), (buffer), (size))#define TPMS_EMPTY_Marshal(source, buffer, size)
Marshal(TPMS_EMPTY_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ALGORITHM_DESCRIPTION_Marshal(source, buffer, size)
Marshal(TPMS_ALGORITHM_DESCRIPTION_MARSHAL_REF, (source), (buffer), (size))#define TPMU_HA_Unmarshal(target, buffer, size, selector)
UnmarshalUnion(TPMU_HA_MARSHAL_REF, (target), (buffer), (size), (selector))#define TPMU_HA_Marshal(source, buffer, size, selector)
MarshalUnion(TPMU_HA_MARSHAL_REF, (source), (buffer), (size), (selector))#define TPMT_HA_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMT_HA_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),(size))#define TPMT_HA_Marshal(source, buffer, size)
Marshal(TPMT_HA_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_DIGEST_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_DIGEST_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_DIGEST_Marshal(source, buffer, size)
Marshal(TPM2B_DIGEST_MARSHAL_REF, (source), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 471
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library#define TPM2B_DATA_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_DATA_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_DATA_Marshal(source, buffer, size)
Marshal(TPM2B_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_NONCE_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_NONCE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_NONCE_Marshal(source, buffer, size)
Marshal(TPM2B_NONCE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_AUTH_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_AUTH_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_AUTH_Marshal(source, buffer, size)
Marshal(TPM2B_AUTH_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_OPERAND_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_OPERAND_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_OPERAND_Marshal(source, buffer, size)
Marshal(TPM2B_OPERAND_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_EVENT_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_EVENT_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_EVENT_Marshal(source, buffer, size)
Marshal(TPM2B_EVENT_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_MAX_BUFFER_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_MAX_BUFFER_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_MAX_BUFFER_Marshal(source, buffer, size)
Marshal(TPM2B_MAX_BUFFER_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_MAX_NV_BUFFER_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_MAX_NV_BUFFER_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_MAX_NV_BUFFER_Marshal(source, buffer, size)
Marshal(TPM2B_MAX_NV_BUFFER_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_TIMEOUT_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_TIMEOUT_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_TIMEOUT_Marshal(source, buffer, size)
Marshal(TPM2B_TIMEOUT_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_IV_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_IV_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_IV_Marshal(source, buffer, size)
Marshal(TPM2B_IV_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_NAME_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_NAME_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_NAME_Marshal(source, buffer, size)
Marshal(TPM2B_NAME_MARSHAL_REF, (source), (buffer), (size))#define TPMS_PCR_SELECT_Unmarshal(target, buffer, size)
Unmarshal(TPMS_PCR_SELECT_MARSHAL_REF, (target), (buffer), (size))#define TPMS_PCR_SELECT_Marshal(source, buffer, size)
Marshal(TPMS_PCR_SELECT_MARSHAL_REF, (source), (buffer), (size))#define TPMS_PCR_SELECTION_Unmarshal(target, buffer, size)
Unmarshal(TPMS_PCR_SELECTION_MARSHAL_REF, (target), (buffer), (size))#define TPMS_PCR_SELECTION_Marshal(source, buffer, size)
Marshal(TPMS_PCR_SELECTION_MARSHAL_REF, (source), (buffer), (size))#define TPMT_TK_CREATION_Unmarshal(target, buffer, size)
Unmarshal(TPMT_TK_CREATION_MARSHAL_REF, (target), (buffer), (size))#define TPMT_TK_CREATION_Marshal(source, buffer, size)
Marshal(TPMT_TK_CREATION_MARSHAL_REF, (source), (buffer), (size))#define TPMT_TK_VERIFIED_Unmarshal(target, buffer, size)
Unmarshal(TPMT_TK_VERIFIED_MARSHAL_REF, (target), (buffer), (size))#define TPMT_TK_VERIFIED_Marshal(source, buffer, size)
Marshal(TPMT_TK_VERIFIED_MARSHAL_REF, (source), (buffer), (size))#define TPMT_TK_AUTH_Unmarshal(target, buffer, size)
Unmarshal(TPMT_TK_AUTH_MARSHAL_REF, (target), (buffer), (size))#define TPMT_TK_AUTH_Marshal(source, buffer, size)
Marshal(TPMT_TK_AUTH_MARSHAL_REF, (source), (buffer), (size))#define TPMT_TK_HASHCHECK_Unmarshal(target, buffer, size)
Unmarshal(TPMT_TK_HASHCHECK_MARSHAL_REF, (target), (buffer), (size))#define TPMT_TK_HASHCHECK_Marshal(source, buffer, size)
Marshal(TPMT_TK_HASHCHECK_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ALG_PROPERTY_Marshal(source, buffer, size)
Marshal(TPMS_ALG_PROPERTY_MARSHAL_REF, (source), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 472
December 24, 2020

Part 4: Supporting Routines
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
981
982
983
984
985
986

Trusted Platform Module Library#define TPMS_TAGGED_PROPERTY_Marshal(source, buffer, size)
Marshal(TPMS_TAGGED_PROPERTY_MARSHAL_REF, (source), (buffer), (size))#define TPMS_TAGGED_PCR_SELECT_Marshal(source, buffer, size)
Marshal(TPMS_TAGGED_PCR_SELECT_MARSHAL_REF, (source), (buffer), (size))#define TPMS_TAGGED_POLICY_Marshal(source, buffer, size)
Marshal(TPMS_TAGGED_POLICY_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ACT_DATA_Marshal(source, buffer, size)
Marshal(TPMS_ACT_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPML_CC_Unmarshal(target, buffer, size)
Unmarshal(TPML_CC_MARSHAL_REF, (target), (buffer), (size))#define TPML_CC_Marshal(source, buffer, size)
Marshal(TPML_CC_MARSHAL_REF, (source), (buffer), (size))#define TPML_CCA_Marshal(source, buffer, size)
Marshal(TPML_CCA_MARSHAL_REF, (source), (buffer), (size))#define TPML_ALG_Unmarshal(target, buffer, size)
Unmarshal(TPML_ALG_MARSHAL_REF, (target), (buffer), (size))#define TPML_ALG_Marshal(source, buffer, size)
Marshal(TPML_ALG_MARSHAL_REF, (source), (buffer), (size))#define TPML_HANDLE_Marshal(source, buffer, size)
Marshal(TPML_HANDLE_MARSHAL_REF, (source), (buffer), (size))#define TPML_DIGEST_Unmarshal(target, buffer, size)
Unmarshal(TPML_DIGEST_MARSHAL_REF, (target), (buffer), (size))#define TPML_DIGEST_Marshal(source, buffer, size)
Marshal(TPML_DIGEST_MARSHAL_REF, (source), (buffer), (size))#define TPML_DIGEST_VALUES_Unmarshal(target, buffer, size)
Unmarshal(TPML_DIGEST_VALUES_MARSHAL_REF, (target), (buffer), (size))#define TPML_DIGEST_VALUES_Marshal(source, buffer, size)
Marshal(TPML_DIGEST_VALUES_MARSHAL_REF, (source), (buffer), (size))#define TPML_PCR_SELECTION_Unmarshal(target, buffer, size)
Unmarshal(TPML_PCR_SELECTION_MARSHAL_REF, (target), (buffer), (size))#define TPML_PCR_SELECTION_Marshal(source, buffer, size)
Marshal(TPML_PCR_SELECTION_MARSHAL_REF, (source), (buffer), (size))#define TPML_ALG_PROPERTY_Marshal(source, buffer, size)
Marshal(TPML_ALG_PROPERTY_MARSHAL_REF, (source), (buffer), (size))#define TPML_TAGGED_TPM_PROPERTY_Marshal(source, buffer, size)
Marshal(TPML_TAGGED_TPM_PROPERTY_MARSHAL_REF, (source), (buffer), (size))#define TPML_TAGGED_PCR_PROPERTY_Marshal(source, buffer, size)
Marshal(TPML_TAGGED_PCR_PROPERTY_MARSHAL_REF, (source), (buffer), (size))#define TPML_ECC_CURVE_Marshal(source, buffer, size)
Marshal(TPML_ECC_CURVE_MARSHAL_REF, (source), (buffer), (size))#define TPML_TAGGED_POLICY_Marshal(source, buffer, size)
Marshal(TPML_TAGGED_POLICY_MARSHAL_REF, (source), (buffer), (size))#define TPML_ACT_DATA_Marshal(source, buffer, size)
Marshal(TPML_ACT_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPMU_CAPABILITIES_Marshal(source, buffer, size, selector)
MarshalUnion(TPMU_CAPABILITIES_MARSHAL_REF, (source), (buffer), (size),(selector))#define TPMS_CAPABILITY_DATA_Marshal(source, buffer, size)
Marshal(TPMS_CAPABILITY_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_CLOCK_INFO_Unmarshal(target, buffer, size)
Unmarshal(TPMS_CLOCK_INFO_MARSHAL_REF, (target), (buffer), (size))#define TPMS_CLOCK_INFO_Marshal(source, buffer, size)
Marshal(TPMS_CLOCK_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_TIME_INFO_Unmarshal(target, buffer, size)
Unmarshal(TPMS_TIME_INFO_MARSHAL_REF, (target), (buffer), (size))#define TPMS_TIME_INFO_Marshal(source, buffer, size)
Marshal(TPMS_TIME_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_TIME_ATTEST_INFO_Marshal(source, buffer, size)
Marshal(TPMS_TIME_ATTEST_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_CERTIFY_INFO_Marshal(source, buffer, size)
Marshal(TPMS_CERTIFY_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_QUOTE_INFO_Marshal(source, buffer, size)
Marshal(TPMS_QUOTE_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_COMMAND_AUDIT_INFO_Marshal(source, buffer, size)
Marshal(TPMS_COMMAND_AUDIT_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SESSION_AUDIT_INFO_Marshal(source, buffer, size)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 473
December 24, 2020

Part 4: Supporting Routines
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
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052

Trusted Platform Module Library

Marshal(TPMS_SESSION_AUDIT_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_CREATION_INFO_Marshal(source, buffer, size)\
Marshal(TPMS_CREATION_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_NV_CERTIFY_INFO_Marshal(source, buffer, size)\
Marshal(TPMS_NV_CERTIFY_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(source, buffer, size)\
Marshal(TPMS_NV_DIGEST_CERTIFY_INFO_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ST_ATTEST_Marshal(source, buffer, size)\
Marshal(TPMI_ST_ATTEST_MARSHAL_REF, (source), (buffer), (size))#define TPMU_ATTEST_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_ATTEST_MARSHAL_REF, (source), (buffer), (size), (selector))#define TPMS_ATTEST_Marshal(source, buffer, size)\
Marshal(TPMS_ATTEST_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_ATTEST_Marshal(source, buffer, size)\
Marshal(TPM2B_ATTEST_MARSHAL_REF, (source), (buffer), (size))#define TPMS_AUTH_COMMAND_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_AUTH_COMMAND_MARSHAL_REF, (target), (buffer), (size))#define TPMS_AUTH_RESPONSE_Marshal(source, buffer, size)\
Marshal(TPMS_AUTH_RESPONSE_MARSHAL_REF, (source), (buffer), (size))#define TPMI_TDES_KEY_BITS_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_TDES_KEY_BITS_MARSHAL_REF, (target), (buffer), (size))#define TPMI_TDES_KEY_BITS_Marshal(source, buffer, size)\
Marshal(TPMI_TDES_KEY_BITS_MARSHAL_REF, (source), (buffer), (size))#define TPMI_AES_KEY_BITS_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_AES_KEY_BITS_MARSHAL_REF, (target), (buffer), (size))#define TPMI_AES_KEY_BITS_Marshal(source, buffer, size)\
Marshal(TPMI_AES_KEY_BITS_MARSHAL_REF, (source), (buffer), (size))#define TPMI_SM4_KEY_BITS_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_SM4_KEY_BITS_MARSHAL_REF, (target), (buffer), (size))#define TPMI_SM4_KEY_BITS_Marshal(source, buffer, size)\
Marshal(TPMI_SM4_KEY_BITS_MARSHAL_REF, (source), (buffer), (size))#define TPMI_CAMELLIA_KEY_BITS_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF, (target), (buffer), (size))#define TPMI_CAMELLIA_KEY_BITS_Marshal(source, buffer, size)\
Marshal(TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF, (source), (buffer), (size))#define TPMU_SYM_KEY_BITS_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_SYM_KEY_BITS_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_SYM_KEY_BITS_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_SYM_KEY_BITS_MARSHAL_REF, (source), (buffer), (size),\(selector))#define TPMU_SYM_MODE_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_SYM_MODE_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_SYM_MODE_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_SYM_MODE_MARSHAL_REF, (source), (buffer), (size), (selector))#define TPMT_SYM_DEF_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMT_SYM_DEF_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer), \(size))#define TPMT_SYM_DEF_Marshal(source, buffer, size)\
Marshal(TPMT_SYM_DEF_MARSHAL_REF, (source), (buffer), (size))#define TPMT_SYM_DEF_OBJECT_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMT_SYM_DEF_OBJECT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\(buffer), (size))#define TPMT_SYM_DEF_OBJECT_Marshal(source, buffer, size)\
Marshal(TPMT_SYM_DEF_OBJECT_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_SYM_KEY_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_SYM_KEY_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_SYM_KEY_Marshal(source, buffer, size)\
Marshal(TPM2B_SYM_KEY_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SYMCIPHER_PARMS_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SYMCIPHER_PARMS_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SYMCIPHER_PARMS_Marshal(source, buffer, size)\
Marshal(TPMS_SYMCIPHER_PARMS_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_LABEL_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_LABEL_MARSHAL_REF, (target), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 474
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library#define TPM2B_LABEL_Marshal(source, buffer, size)
Marshal(TPM2B_LABEL_MARSHAL_REF, (source), (buffer), (size))#define TPMS_DERIVE_Unmarshal(target, buffer, size)
Unmarshal(TPMS_DERIVE_MARSHAL_REF, (target), (buffer), (size))#define TPMS_DERIVE_Marshal(source, buffer, size)
Marshal(TPMS_DERIVE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_DERIVE_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_DERIVE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_DERIVE_Marshal(source, buffer, size)
Marshal(TPM2B_DERIVE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_SENSITIVE_DATA_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_SENSITIVE_DATA_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_SENSITIVE_DATA_Marshal(source, buffer, size)
Marshal(TPM2B_SENSITIVE_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SENSITIVE_CREATE_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SENSITIVE_CREATE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_SENSITIVE_CREATE_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_SENSITIVE_CREATE_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SCHEME_HASH_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SCHEME_HASH_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SCHEME_HASH_Marshal(source, buffer, size)
Marshal(TPMS_SCHEME_HASH_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SCHEME_ECDAA_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SCHEME_ECDAA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SCHEME_ECDAA_Marshal(source, buffer, size)
Marshal(TPMS_SCHEME_ECDAA_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0),(target), (buffer), (size))#define TPMI_ALG_KEYEDHASH_SCHEME_Marshal(source, buffer, size)
Marshal(TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SCHEME_HMAC_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SCHEME_HMAC_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SCHEME_HMAC_Marshal(source, buffer, size)
Marshal(TPMS_SCHEME_HMAC_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SCHEME_XOR_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SCHEME_XOR_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SCHEME_XOR_Marshal(source, buffer, size)
Marshal(TPMS_SCHEME_XOR_MARSHAL_REF, (source), (buffer), (size))#define TPMU_SCHEME_KEYEDHASH_Unmarshal(target, buffer, size, selector)
UnmarshalUnion(TPMU_SCHEME_KEYEDHASH_MARSHAL_REF, (target), (buffer), (size),(selector))#define TPMU_SCHEME_KEYEDHASH_Marshal(source, buffer, size, selector)
MarshalUnion(TPMU_SCHEME_KEYEDHASH_MARSHAL_REF, (source), (buffer), (size),(selector))#define TPMT_KEYEDHASH_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMT_KEYEDHASH_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMT_KEYEDHASH_SCHEME_Marshal(source, buffer, size)
Marshal(TPMT_KEYEDHASH_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIG_SCHEME_RSASSA_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIG_SCHEME_RSASSA_Marshal(source, buffer, size)
Marshal(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIG_SCHEME_RSAPSS_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIG_SCHEME_RSAPSS_Marshal(source, buffer, size)
Marshal(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIG_SCHEME_ECDSA_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIG_SCHEME_ECDSA_Marshal(source, buffer, size)
Marshal(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIG_SCHEME_SM2_Unmarshal(target, buffer, size)
Unmarshal(TPMS_SIG_SCHEME_SM2_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIG_SCHEME_SM2_Marshal(source, buffer, size)
Marshal(TPMS_SIG_SCHEME_SM2_MARSHAL_REF, (source), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 475
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library#define TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIG_SCHEME_ECSCHNORR_Marshal(source, buffer, size)\
Marshal(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIG_SCHEME_ECDAA_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIG_SCHEME_ECDAA_Marshal(source, buffer, size)\
Marshal(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF, (source), (buffer), (size))#define TPMU_SIG_SCHEME_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_SIG_SCHEME_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_SIG_SCHEME_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_SIG_SCHEME_MARSHAL_REF, (source), (buffer), (size),\(selector))#define TPMT_SIG_SCHEME_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMT_SIG_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\(buffer), (size))#define TPMT_SIG_SCHEME_Marshal(source, buffer, size)\
Marshal(TPMT_SIG_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ENC_SCHEME_OAEP_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_ENC_SCHEME_OAEP_MARSHAL_REF, (target), (buffer), (size))#define TPMS_ENC_SCHEME_OAEP_Marshal(source, buffer, size)\
Marshal(TPMS_ENC_SCHEME_OAEP_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ENC_SCHEME_RSAES_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_ENC_SCHEME_RSAES_MARSHAL_REF, (target), (buffer), (size))#define TPMS_ENC_SCHEME_RSAES_Marshal(source, buffer, size)\
Marshal(TPMS_ENC_SCHEME_RSAES_MARSHAL_REF, (source), (buffer), (size))#define TPMS_KEY_SCHEME_ECDH_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KEY_SCHEME_ECDH_MARSHAL_REF, (target), (buffer), (size))#define TPMS_KEY_SCHEME_ECDH_Marshal(source, buffer, size)\
Marshal(TPMS_KEY_SCHEME_ECDH_MARSHAL_REF, (source), (buffer), (size))#define TPMS_KEY_SCHEME_ECMQV_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF, (target), (buffer), (size))#define TPMS_KEY_SCHEME_ECMQV_Marshal(source, buffer, size)\
Marshal(TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF, (source), (buffer), (size))#define TPMS_KDF_SCHEME_MGF1_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KDF_SCHEME_MGF1_MARSHAL_REF, (target), (buffer), (size))#define TPMS_KDF_SCHEME_MGF1_Marshal(source, buffer, size)\
Marshal(TPMS_KDF_SCHEME_MGF1_MARSHAL_REF, (source), (buffer), (size))#define TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF, (target), (buffer),\(size))#define TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(source, buffer, size)\
Marshal(TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF, (source), (buffer), (size))#define TPMS_KDF_SCHEME_KDF2_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KDF_SCHEME_KDF2_MARSHAL_REF, (target), (buffer), (size))#define TPMS_KDF_SCHEME_KDF2_Marshal(source, buffer, size)\
Marshal(TPMS_KDF_SCHEME_KDF2_MARSHAL_REF, (source), (buffer), (size))#define TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF, (target), (buffer),\(size))#define TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(source, buffer, size)\
Marshal(TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF, (source), (buffer), (size))#define TPMU_KDF_SCHEME_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_KDF_SCHEME_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_KDF_SCHEME_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_KDF_SCHEME_MARSHAL_REF, (source), (buffer), (size),\(selector))#define TPMT_KDF_SCHEME_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMT_KDF_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\(buffer), (size))#define TPMT_KDF_SCHEME_Marshal(source, buffer, size)\
Marshal(TPMT_KDF_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_ASYM_SCHEME_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMI_ALG_ASYM_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),\Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 476
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library(buffer), (size))#define TPMI_ALG_ASYM_SCHEME_Marshal(source, buffer, size)
Marshal(TPMI_ALG_ASYM_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMU_ASYM_SCHEME_Unmarshal(target, buffer, size, selector)
UnmarshalUnion(TPMU_ASYM_SCHEME_MARSHAL_REF, (target), (buffer), (size),(selector))#define TPMU_ASYM_SCHEME_Marshal(source, buffer, size, selector)
MarshalUnion(TPMU_ASYM_SCHEME_MARSHAL_REF, (source), (buffer), (size),(selector))#define TPMI_ALG_RSA_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_RSA_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_RSA_SCHEME_Marshal(source, buffer, size)
Marshal(TPMI_ALG_RSA_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMT_RSA_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMT_RSA_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMT_RSA_SCHEME_Marshal(source, buffer, size)
Marshal(TPMT_RSA_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_RSA_DECRYPT_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_RSA_DECRYPT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_RSA_DECRYPT_Marshal(source, buffer, size)
Marshal(TPMI_ALG_RSA_DECRYPT_MARSHAL_REF, (source), (buffer), (size))#define TPMT_RSA_DECRYPT_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMT_RSA_DECRYPT_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMT_RSA_DECRYPT_Marshal(source, buffer, size)
Marshal(TPMT_RSA_DECRYPT_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_PUBLIC_KEY_RSA_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_PUBLIC_KEY_RSA_Marshal(source, buffer, size)
Marshal(TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF, (source), (buffer), (size))#define TPMI_RSA_KEY_BITS_Unmarshal(target, buffer, size)
Unmarshal(TPMI_RSA_KEY_BITS_MARSHAL_REF, (target), (buffer), (size))#define TPMI_RSA_KEY_BITS_Marshal(source, buffer, size)
Marshal(TPMI_RSA_KEY_BITS_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_PRIVATE_KEY_RSA_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_PRIVATE_KEY_RSA_Marshal(source, buffer, size)
Marshal(TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_ECC_PARAMETER_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_ECC_PARAMETER_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_ECC_PARAMETER_Marshal(source, buffer, size)
Marshal(TPM2B_ECC_PARAMETER_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ECC_POINT_Unmarshal(target, buffer, size)
Unmarshal(TPMS_ECC_POINT_MARSHAL_REF, (target), (buffer), (size))#define TPMS_ECC_POINT_Marshal(source, buffer, size)
Marshal(TPMS_ECC_POINT_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_ECC_POINT_Unmarshal(target, buffer, size)
Unmarshal(TPM2B_ECC_POINT_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_ECC_POINT_Marshal(source, buffer, size)
Marshal(TPM2B_ECC_POINT_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_ECC_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMI_ALG_ECC_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMI_ALG_ECC_SCHEME_Marshal(source, buffer, size)
Marshal(TPMI_ALG_ECC_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ECC_CURVE_Unmarshal(target, buffer, size)
Unmarshal(TPMI_ECC_CURVE_MARSHAL_REF, (target), (buffer), (size))#define TPMI_ECC_CURVE_Marshal(source, buffer, size)
Marshal(TPMI_ECC_CURVE_MARSHAL_REF, (source), (buffer), (size))#define TPMT_ECC_SCHEME_Unmarshal(target, buffer, size, flag)
Unmarshal(TPMT_ECC_SCHEME_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target),(buffer), (size))#define TPMT_ECC_SCHEME_Marshal(source, buffer, size)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 477
December 24, 2020

Part 4: Supporting Routines
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
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316

Trusted Platform Module Library

Marshal(TPMT_ECC_SCHEME_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ALGORITHM_DETAIL_ECC_Marshal(source, buffer, size)\
Marshal(TPMS_ALGORITHM_DETAIL_ECC_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_RSA_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_RSA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_RSA_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_RSA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_RSASSA_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_RSASSA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_RSASSA_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_RSASSA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_RSAPSS_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_RSAPSS_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_RSAPSS_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_RSAPSS_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_ECC_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_ECC_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_ECC_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_ECDAA_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_ECDAA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_ECDAA_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_ECDAA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_ECDSA_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_ECDSA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_ECDSA_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_ECDSA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_SM2_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_SM2_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_SM2_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_SM2_MARSHAL_REF, (source), (buffer), (size))#define TPMS_SIGNATURE_ECSCHNORR_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF, (target), (buffer), (size))#define TPMS_SIGNATURE_ECSCHNORR_Marshal(source, buffer, size)\
Marshal(TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF, (source), (buffer), (size))#define TPMU_SIGNATURE_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_SIGNATURE_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_SIGNATURE_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_SIGNATURE_MARSHAL_REF, (source), (buffer), (size), (selector))#define TPMT_SIGNATURE_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMT_SIGNATURE_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),\(size))#define TPMT_SIGNATURE_Marshal(source, buffer, size)\
Marshal(TPMT_SIGNATURE_MARSHAL_REF, (source), (buffer), (size))#define TPMU_ENCRYPTED_SECRET_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_ENCRYPTED_SECRET_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_ENCRYPTED_SECRET_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_ENCRYPTED_SECRET_MARSHAL_REF, (source), (buffer), (size),\(selector))#define TPM2B_ENCRYPTED_SECRET_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_ENCRYPTED_SECRET_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_ENCRYPTED_SECRET_Marshal(source, buffer, size)\
Marshal(TPM2B_ENCRYPTED_SECRET_MARSHAL_REF, (source), (buffer), (size))#define TPMI_ALG_PUBLIC_Unmarshal(target, buffer, size)\
Unmarshal(TPMI_ALG_PUBLIC_MARSHAL_REF, (target), (buffer), (size))#define TPMI_ALG_PUBLIC_Marshal(source, buffer, size)\
Marshal(TPMI_ALG_PUBLIC_MARSHAL_REF, (source), (buffer), (size))#define TPMU_PUBLIC_ID_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_PUBLIC_ID_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_PUBLIC_ID_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_PUBLIC_ID_MARSHAL_REF, (source), (buffer), (size), (selector))#define TPMS_KEYEDHASH_PARMS_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_KEYEDHASH_PARMS_MARSHAL_REF, (target), (buffer), (size))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 478
December 24, 2020

Part 4: Supporting Routines
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
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382

Trusted Platform Module Library#define TPMS_KEYEDHASH_PARMS_Marshal(source, buffer, size)\
Marshal(TPMS_KEYEDHASH_PARMS_MARSHAL_REF, (source), (buffer), (size))#define TPMS_RSA_PARMS_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_RSA_PARMS_MARSHAL_REF, (target), (buffer), (size))#define TPMS_RSA_PARMS_Marshal(source, buffer, size)\
Marshal(TPMS_RSA_PARMS_MARSHAL_REF, (source), (buffer), (size))#define TPMS_ECC_PARMS_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_ECC_PARMS_MARSHAL_REF, (target), (buffer), (size))#define TPMS_ECC_PARMS_Marshal(source, buffer, size)\
Marshal(TPMS_ECC_PARMS_MARSHAL_REF, (source), (buffer), (size))#define TPMU_PUBLIC_PARMS_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_PUBLIC_PARMS_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_PUBLIC_PARMS_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_PUBLIC_PARMS_MARSHAL_REF, (source), (buffer), (size),\(selector))#define TPMT_PUBLIC_PARMS_Unmarshal(target, buffer, size)\
Unmarshal(TPMT_PUBLIC_PARMS_MARSHAL_REF, (target), (buffer), (size))#define TPMT_PUBLIC_PARMS_Marshal(source, buffer, size)\
Marshal(TPMT_PUBLIC_PARMS_MARSHAL_REF, (source), (buffer), (size))#define TPMT_PUBLIC_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPMT_PUBLIC_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer),\(size))#define TPMT_PUBLIC_Marshal(source, buffer, size)\
Marshal(TPMT_PUBLIC_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_PUBLIC_Unmarshal(target, buffer, size, flag)\
Unmarshal(TPM2B_PUBLIC_MARSHAL_REF|(flag ? NULL_FLAG : 0), (target), (buffer), \(size))#define TPM2B_PUBLIC_Marshal(source, buffer, size)\
Marshal(TPM2B_PUBLIC_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_TEMPLATE_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_TEMPLATE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_TEMPLATE_Marshal(source, buffer, size)\
Marshal(TPM2B_TEMPLATE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_PRIVATE_VENDOR_SPECIFIC_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_PRIVATE_VENDOR_SPECIFIC_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_PRIVATE_VENDOR_SPECIFIC_Marshal(source, buffer, size)\
Marshal(TPM2B_PRIVATE_VENDOR_SPECIFIC_MARSHAL_REF, (source), (buffer), (size))#define TPMU_SENSITIVE_COMPOSITE_Unmarshal(target, buffer, size, selector)\
UnmarshalUnion(TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF, (target), (buffer), (size),\(selector))#define TPMU_SENSITIVE_COMPOSITE_Marshal(source, buffer, size, selector)\
MarshalUnion(TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF, (source), (buffer), (size), \(selector))#define TPMT_SENSITIVE_Unmarshal(target, buffer, size)\
Unmarshal(TPMT_SENSITIVE_MARSHAL_REF, (target), (buffer), (size))#define TPMT_SENSITIVE_Marshal(source, buffer, size)\
Marshal(TPMT_SENSITIVE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_SENSITIVE_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_SENSITIVE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_SENSITIVE_Marshal(source, buffer, size)\
Marshal(TPM2B_SENSITIVE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_PRIVATE_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_PRIVATE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_PRIVATE_Marshal(source, buffer, size)\
Marshal(TPM2B_PRIVATE_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_ID_OBJECT_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_ID_OBJECT_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_ID_OBJECT_Marshal(source, buffer, size)\
Marshal(TPM2B_ID_OBJECT_MARSHAL_REF, (source), (buffer), (size))#define TPM_NV_INDEX_Marshal(source, buffer, size)\
Marshal(TPM_NV_INDEX_MARSHAL_REF, (source), (buffer), (size))#define TPMS_NV_PIN_COUNTER_PARAMETERS_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_NV_PIN_COUNTER_PARAMETERS_MARSHAL_REF, (target), (buffer),\(size))#define TPMS_NV_PIN_COUNTER_PARAMETERS_Marshal(source, buffer, size)\

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 479
December 24, 2020

Part 4: Supporting Routines
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
1420
1421
1422
1423
1424
1425
1426
1427

Marshal(TPMS_NV_PIN_COUNTER_PARAMETERS_MARSHAL_REF, (source), (buffer), (size))#define TPMA_NV_Unmarshal(target, buffer, size)\
Unmarshal(TPMA_NV_MARSHAL_REF, (target), (buffer), (size))#define TPMA_NV_Marshal(source, buffer, size)\
Marshal(TPMA_NV_MARSHAL_REF, (source), (buffer), (size))#define TPMS_NV_PUBLIC_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_NV_PUBLIC_MARSHAL_REF, (target), (buffer), (size))#define TPMS_NV_PUBLIC_Marshal(source, buffer, size)\
Marshal(TPMS_NV_PUBLIC_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_NV_PUBLIC_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_NV_PUBLIC_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_NV_PUBLIC_Marshal(source, buffer, size)\
Marshal(TPM2B_NV_PUBLIC_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_CONTEXT_SENSITIVE_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_CONTEXT_SENSITIVE_Marshal(source, buffer, size)\
Marshal(TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF, (source), (buffer), (size))#define TPMS_CONTEXT_DATA_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_CONTEXT_DATA_MARSHAL_REF, (target), (buffer), (size))#define TPMS_CONTEXT_DATA_Marshal(source, buffer, size)\
Marshal(TPMS_CONTEXT_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_CONTEXT_DATA_Unmarshal(target, buffer, size)\
Unmarshal(TPM2B_CONTEXT_DATA_MARSHAL_REF, (target), (buffer), (size))#define TPM2B_CONTEXT_DATA_Marshal(source, buffer, size)\
Marshal(TPM2B_CONTEXT_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPMS_CONTEXT_Unmarshal(target, buffer, size)\
Unmarshal(TPMS_CONTEXT_MARSHAL_REF, (target), (buffer), (size))#define TPMS_CONTEXT_Marshal(source, buffer, size)\
Marshal(TPMS_CONTEXT_MARSHAL_REF, (source), (buffer), (size))#define TPMS_CREATION_DATA_Marshal(source, buffer, size)\
Marshal(TPMS_CREATION_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPM2B_CREATION_DATA_Marshal(source, buffer, size)\
Marshal(TPM2B_CREATION_DATA_MARSHAL_REF, (source), (buffer), (size))#define TPM_AT_Unmarshal(target, buffer, size)\
Unmarshal(TPM_AT_MARSHAL_REF, (target), (buffer), (size))#define TPM_AT_Marshal(source, buffer, size)\
Marshal(TPM_AT_MARSHAL_REF, (source), (buffer), (size))#define TPM_AE_Marshal(source, buffer, size)\
Marshal(TPM_AE_MARSHAL_REF, (source), (buffer), (size))#define TPMS_AC_OUTPUT_Marshal(source, buffer, size)\
Marshal(TPMS_AC_OUTPUT_MARSHAL_REF, (source), (buffer), (size))#define TPML_AC_CAPABILITIES_Marshal(source, buffer, size)\
Marshal(TPML_AC_CAPABILITIES_MARSHAL_REF, (source), (buffer), (size))#endif // _TABLE_MARSHAL_DEFINES_H_

9.10.7.3
1
2
3
4

Trusted Platform Module Library

TableMarshalTypes.h#ifndef _TABLE_MARSHAL_TYPES_H_#define _TABLE_MARSHAL_TYPES_H_
typedef UINT16

marshalIndex_t;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 480
December 24, 2020

Part 4: Supporting Routines

9.10.7.3.1.1

Trusted Platform Module Library

Structure Entries

A structure contains a list of elements to unmarshal. Each of the entries is a UINT16. The structure
descriptor is:
The values array contains indicators for the things to marshal. The elements parameter indicates how
many different entities are unmarshaled. This number nominally corresponds to the number of rows in thePart 2 table that describes the structure (the number of rows minus the title row and any error code rows).
A schematic of a simple structure entry is shown here but the values are not actually in a structure. As
shown, the third value is the offset in the structure where the value is placed when unmarshaled, or
fetched from when marshaling. This is sufficient when the element type indicated by index is always asimple type and never a union or array.This is just shown for illustrative purposes.
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

typedef struct simpleStructureEntry_t {UINT16
qualifiers;// indicates the type of entry (array, union// etc.)marshalIndex_t index;// the index into the appropriate array of// the descriptor of this type
UINT16
offset;// where this comes from or is placed} simpleStructureEntry_t;
typedef const struct UintMarshal_mst{
UINT8
marshalType;UINT8
modifiers;} UintMarshal_mst;// UINT_MTYPE// size and signed indicator.

typedef struct UnionMarshal_mst{
UINT8
countOfselectors;
UINT8
modifiers;// NULL_SELECTORUINT16
offsetOfUnmarshalTypes;
UINT32
selectors[1];//UINT16
marshalingTypes[1]; // This is not part of the prototypical//entry. It is here to show where the//marshaling types will be in a union} UnionMarshal_mst;
typedef struct NullUnionMarshal_mst{
UINT8
count;} NullUnionMarshal_mst;
typedef struct MarshalHeader_mst{
UINT8
marshalType;UINT8
modifiers;
UINT8
errorCode;} MarshalHeader_mst;// VALUES_MTYPE

typedef const struct ArrayMarshal_mst{
marshalIndex_t type;
UINT16
stride;} ArrayMarshal_mst;
typedef const struct StructMarshal_mst{
UINT8
marshalType;UINT8elements;
UINT16values[1];} StructMarshal_mst;

Family “2.0”Level 00 Revision 01.64// used in a structure// STRUCTURE_MTYPE// three times elements

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 481
December 24, 2020

Part 4: Supporting Routines
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
119
120

Trusted Platform Module Library

typedef const struct ValuesMarshal_mst{
UINT8
marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[1];} ValuesMarshal_mst;
typedef const struct TableMarshal_mst{
UINT8
marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8singles;
UINT32
values[1];} TableMarshal_mst;// VALUES_MTYPE

typedef const struct MinMaxMarshal_mst{
UINT8
marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} MinMaxMarshal_mst;// TABLE_MTYPE

typedef const struct Tpm2bMarshal_mst{
UINT8
unmarshalType;UINT16
sizeIndex;} Tpm2bMarshal_mst;// MIN_MAX_MTYPE

typedef const struct Tpm2bsMarshal_mst{
UINT8
unmarshalType;UINT8
modifiers;
UINT16
sizeIndex;
UINT16
dataIndex;} Tpm2bsMarshal_mst;// TPM2B_MTYPE// reference to type for this size value

typedef const struct ListMarshal_mst{
UINT8
unmarshalType;UINT8
modifiers;
UINT16
sizeIndex;// TPM2BS_MTYPE// size= and offset (2 - 7)// index of the size value;// the structure

UINT16arrayRef;// LIST_MTYPE (for TPML)// size offset 2-7// reference to the minmax structure that//
unmarshals the size parameter// reference to an array definition (type// and stride)} ListMarshal_mst;
typedef const struct AttributesMarshal_mst{
UINT8
unmarashalType;// ATTRIBUTE_MTYPE
UINT8
modifiers;// size (ONE_BYTES, TWO_BYTES, or FOUR_BYTESUINT32attributeMask;// the values that must be zero.
} AttributesMarshal_mst;
typedef const struct CompositeMarshal_mst{
UINT8
unmashalType;// COMPOSITE_MTYPE
UINT8
modifiers;// number of entries and size
marshalIndex_t types[1];// array of unmarshaling types} CompositeMarshal_mst;
typedef const struct TPM_ECC_CURVE_mst {Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 482
December 24, 2020

Part 4: Supporting Routines
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
185
186

Trusted Platform Module Library

UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPM_ECC_CURVE_mst;
typedef const struct TPM_CLOCK_ADJUST_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPM_CLOCK_ADJUST_mst;
typedef const struct TPM_EO_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPM_EO_mst;
typedef const struct TPM_SU_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} TPM_SU_mst;
typedef const struct TPM_SE_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[3];} TPM_SE_mst;
typedef const struct TPM_CAP_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[3];} TPM_CAP_mst;
typedef const struct TPMI_YES_NO_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} TPMI_YES_NO_mst;
typedef const struct TPMI_DH_OBJECT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[5];} TPMI_DH_OBJECT_mst;
typedef const struct TPMI_DH_PARENT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 483
December 24, 2020

Part 4: Supporting Routines
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
252

Trusted Platform Module Library

UINT8ranges;UINT8singles;
UINT32
values[8];} TPMI_DH_PARENT_mst;
typedef const struct TPMI_DH_PERSISTENT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPMI_DH_PERSISTENT_mst;
typedef const struct TPMI_DH_ENTITY_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[15];} TPMI_DH_ENTITY_mst;
typedef const struct TPMI_DH_PCR_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[3];} TPMI_DH_PCR_mst;
typedef const struct TPMI_SH_AUTH_SESSION_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[5];} TPMI_SH_AUTH_SESSION_mst;
typedef const struct TPMI_SH_HMAC_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPMI_SH_HMAC_mst;
typedef const struct TPMI_SH_POLICY_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPMI_SH_POLICY_mst;
typedef const struct TPMI_DH_CONTEXT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[6];} TPMI_DH_CONTEXT_mst;
typedef const struct TPMI_DH_SAVED_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 484
December 24, 2020

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

UINT32
values[7];} TPMI_DH_SAVED_mst;
typedef const struct TPMI_RH_HIERARCHY_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[4];} TPMI_RH_HIERARCHY_mst;
typedef const struct TPMI_RH_ENABLES_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[5];} TPMI_RH_ENABLES_mst;
typedef const struct TPMI_RH_HIERARCHY_AUTH_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[4];} TPMI_RH_HIERARCHY_AUTH_mst;
typedef const struct TPMI_RH_HIERARCHY_POLICY_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[6];} TPMI_RH_HIERARCHY_POLICY_mst;
typedef const struct TPMI_RH_PLATFORM_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} TPMI_RH_PLATFORM_mst;
typedef const struct TPMI_RH_OWNER_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} TPMI_RH_OWNER_mst;
typedef const struct TPMI_RH_ENDORSEMENT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} TPMI_RH_ENDORSEMENT_mst;
typedef const struct TPMI_RH_PROVISION_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 485
December 24, 2020

Part 4: Supporting Routines
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
383
384

Trusted Platform Module Library} TPMI_RH_PROVISION_mst;
typedef const struct TPMI_RH_CLEAR_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} TPMI_RH_CLEAR_mst;
typedef const struct TPMI_RH_NV_AUTH_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[4];} TPMI_RH_NV_AUTH_mst;
typedef const struct TPMI_RH_LOCKOUT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} TPMI_RH_LOCKOUT_mst;
typedef const struct TPMI_RH_NV_INDEX_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPMI_RH_NV_INDEX_mst;
typedef const struct TPMI_RH_AC_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPMI_RH_AC_mst;
typedef const struct TPMI_RH_ACT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} TPMI_RH_ACT_mst;
typedef const struct TPMI_ALG_HASH_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[5];} TPMI_ALG_HASH_mst;
typedef const struct TPMI_ALG_ASYM_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[5];} TPMI_ALG_ASYM_mst;
typedef const struct TPMI_ALG_SYM_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 486
December 24, 2020

Part 4: Supporting Routines
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
449
450

Trusted Platform Module Library

UINT32
values[5];} TPMI_ALG_SYM_mst;
typedef const struct TPMI_ALG_SYM_OBJECT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[5];} TPMI_ALG_SYM_OBJECT_mst;
typedef const struct TPMI_ALG_SYM_MODE_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_SYM_MODE_mst;
typedef const struct TPMI_ALG_KDF_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_KDF_mst;
typedef const struct TPMI_ALG_SIG_SCHEME_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_SIG_SCHEME_mst;
typedef const struct TPMI_ECC_KEY_EXCHANGE_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ECC_KEY_EXCHANGE_mst;
typedef const struct TPMI_ST_COMMAND_TAG_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} TPMI_ST_COMMAND_TAG_mst;
typedef const struct TPMI_ALG_MAC_SCHEME_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[5];} TPMI_ALG_MAC_SCHEME_mst;
typedef const struct TPMI_ALG_CIPHER_MODE_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_CIPHER_MODE_mst;
typedef const struct TPMS_EMPTY_mst{
UINT8
marshalType;UINT8elements;
UINT16values[3];} TPMS_EMPTY_mst;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 487
December 24, 2020

Part 4: Supporting Routines
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
515
516

Trusted Platform Module Library

typedef const struct TPMS_ALGORITHM_DESCRIPTION_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_ALGORITHM_DESCRIPTION_mst;
typedef struct TPMU_HA_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[9];UINT16
marshalingTypes[9];} TPMU_HA_mst;
typedef const struct TPMT_HA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_HA_mst;
typedef const struct TPMS_PCR_SELECT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_PCR_SELECT_mst;
typedef const struct TPMS_PCR_SELECTION_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMS_PCR_SELECTION_mst;
typedef const struct TPMT_TK_CREATION_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMT_TK_CREATION_mst;
typedef const struct TPMT_TK_VERIFIED_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMT_TK_VERIFIED_mst;
typedef const struct TPMT_TK_AUTH_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMT_TK_AUTH_mst;
typedef const struct TPMT_TK_HASHCHECK_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMT_TK_HASHCHECK_mst;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 488
December 24, 2020

Part 4: Supporting Routines
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
581
582

Trusted Platform Module Library

typedef const struct TPMS_ALG_PROPERTY_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_ALG_PROPERTY_mst;
typedef const struct TPMS_TAGGED_PROPERTY_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_TAGGED_PROPERTY_mst;
typedef const struct TPMS_TAGGED_PCR_SELECT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMS_TAGGED_PCR_SELECT_mst;
typedef const struct TPMS_TAGGED_POLICY_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_TAGGED_POLICY_mst;
typedef const struct TPMS_ACT_DATA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMS_ACT_DATA_mst;
typedef struct TPMU_CAPABILITIES_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[11];UINT16
marshalingTypes[11];} TPMU_CAPABILITIES_mst;
typedef const struct TPMS_CAPABILITY_DATA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_CAPABILITY_DATA_mst;
typedef const struct TPMS_CLOCK_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMS_CLOCK_INFO_mst;
typedef const struct TPMS_TIME_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_TIME_INFO_mst;
typedef const struct TPMS_TIME_ATTEST_INFO_mst

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 489
December 24, 2020

Part 4: Supporting Routines
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
647
648

Trusted Platform Module Library{
UINT8marshalType;UINT8elements;
UINT16values[6];} TPMS_TIME_ATTEST_INFO_mst;
typedef const struct TPMS_CERTIFY_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_CERTIFY_INFO_mst;
typedef const struct TPMS_QUOTE_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_QUOTE_INFO_mst;
typedef const struct TPMS_COMMAND_AUDIT_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMS_COMMAND_AUDIT_INFO_mst;
typedef const struct TPMS_SESSION_AUDIT_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_SESSION_AUDIT_INFO_mst;
typedef const struct TPMS_CREATION_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_CREATION_INFO_mst;
typedef const struct TPMS_NV_CERTIFY_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMS_NV_CERTIFY_INFO_mst;
typedef const struct TPMS_NV_DIGEST_CERTIFY_INFO_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_NV_DIGEST_CERTIFY_INFO_mst;
typedef const struct TPMI_ST_ATTEST_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
ranges;UINT8singles;
UINT32
values[3];} TPMI_ST_ATTEST_mst;
typedef struct TPMU_ATTEST_mst{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 490
December 24, 2020

Part 4: Supporting Routines
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
713
714

Trusted Platform Module Library

BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[8];UINT16
marshalingTypes[8];} TPMU_ATTEST_mst;
typedef const struct TPMS_ATTEST_mst{
UINT8
marshalType;UINT8elements;
UINT16values[21];} TPMS_ATTEST_mst;
typedef const struct TPMS_AUTH_COMMAND_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMS_AUTH_COMMAND_mst;
typedef const struct TPMS_AUTH_RESPONSE_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMS_AUTH_RESPONSE_mst;
typedef const struct TPMI_TDES_KEY_BITS_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} TPMI_TDES_KEY_BITS_mst;
typedef const struct TPMI_AES_KEY_BITS_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[3];} TPMI_AES_KEY_BITS_mst;
typedef const struct TPMI_SM4_KEY_BITS_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} TPMI_SM4_KEY_BITS_mst;
typedef const struct TPMI_CAMELLIA_KEY_BITS_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[3];} TPMI_CAMELLIA_KEY_BITS_mst;
typedef struct TPMU_SYM_KEY_BITS_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[6];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 491
December 24, 2020

Part 4: Supporting Routines
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
779
780

Trusted Platform Module Library

UINT16
marshalingTypes[6];} TPMU_SYM_KEY_BITS_mst;
typedef struct TPMU_SYM_MODE_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[6];UINT16
marshalingTypes[6];} TPMU_SYM_MODE_mst;
typedef const struct TPMT_SYM_DEF_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMT_SYM_DEF_mst;
typedef const struct TPMT_SYM_DEF_OBJECT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMT_SYM_DEF_OBJECT_mst;
typedef const struct TPMS_SYMCIPHER_PARMS_mst{
UINT8
marshalType;UINT8elements;
UINT16values[3];} TPMS_SYMCIPHER_PARMS_mst;
typedef const struct TPMS_DERIVE_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_DERIVE_mst;
typedef const struct TPMS_SENSITIVE_CREATE_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_SENSITIVE_CREATE_mst;
typedef const struct TPMS_SCHEME_HASH_mst{
UINT8
marshalType;UINT8elements;
UINT16values[3];} TPMS_SCHEME_HASH_mst;
typedef const struct TPMS_SCHEME_ECDAA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_SCHEME_ECDAA_mst;
typedef const struct TPMI_ALG_KEYEDHASH_SCHEME_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 492
December 24, 2020

Part 4: Supporting Routines
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
845
846

Trusted Platform Module Library} TPMI_ALG_KEYEDHASH_SCHEME_mst;
typedef const struct TPMS_SCHEME_XOR_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_SCHEME_XOR_mst;
typedef struct TPMU_SCHEME_KEYEDHASH_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[3];UINT16
marshalingTypes[3];} TPMU_SCHEME_KEYEDHASH_mst;
typedef const struct TPMT_KEYEDHASH_SCHEME_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_KEYEDHASH_SCHEME_mst;
typedef struct TPMU_SIG_SCHEME_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[8];UINT16
marshalingTypes[8];} TPMU_SIG_SCHEME_mst;
typedef const struct TPMT_SIG_SCHEME_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_SIG_SCHEME_mst;
typedef struct TPMU_KDF_SCHEME_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[5];UINT16
marshalingTypes[5];} TPMU_KDF_SCHEME_mst;
typedef const struct TPMT_KDF_SCHEME_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_KDF_SCHEME_mst;
typedef const struct TPMI_ALG_ASYM_SCHEME_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_ASYM_SCHEME_mst;
typedef struct TPMU_ASYM_SCHEME_mst{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 493
December 24, 2020

Part 4: Supporting Routines
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
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912

Trusted Platform Module Library

BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[11];UINT16
marshalingTypes[11];} TPMU_ASYM_SCHEME_mst;
typedef const struct TPMI_ALG_RSA_SCHEME_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_RSA_SCHEME_mst;
typedef const struct TPMT_RSA_SCHEME_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_RSA_SCHEME_mst;
typedef const struct TPMI_ALG_RSA_DECRYPT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_RSA_DECRYPT_mst;
typedef const struct TPMT_RSA_DECRYPT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_RSA_DECRYPT_mst;
typedef const struct TPMI_RSA_KEY_BITS_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[3];} TPMI_RSA_KEY_BITS_mst;
typedef const struct TPMS_ECC_POINT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_ECC_POINT_mst;
typedef const struct TPMI_ALG_ECC_SCHEME_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_ECC_SCHEME_mst;
typedef const struct TPMI_ECC_CURVE_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[3];} TPMI_ECC_CURVE_mst;
typedef const struct TPMT_ECC_SCHEME_mst{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 494
December 24, 2020

Part 4: Supporting Routines
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
977
978

Trusted Platform Module Library

UINT8marshalType;UINT8elements;
UINT16values[6];} TPMT_ECC_SCHEME_mst;
typedef const struct TPMS_ALGORITHM_DETAIL_ECC_mst{
UINT8
marshalType;UINT8elements;
UINT16values[33];} TPMS_ALGORITHM_DETAIL_ECC_mst;
typedef const struct TPMS_SIGNATURE_RSA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_SIGNATURE_RSA_mst;
typedef const struct TPMS_SIGNATURE_ECC_mst{
UINT8
marshalType;UINT8elements;
UINT16values[9];} TPMS_SIGNATURE_ECC_mst;
typedef struct TPMU_SIGNATURE_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[8];UINT16
marshalingTypes[8];} TPMU_SIGNATURE_mst;
typedef const struct TPMT_SIGNATURE_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_SIGNATURE_mst;
typedef struct TPMU_ENCRYPTED_SECRET_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[4];UINT16
marshalingTypes[4];} TPMU_ENCRYPTED_SECRET_mst;
typedef const struct TPMI_ALG_PUBLIC_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[4];} TPMI_ALG_PUBLIC_mst;
typedef struct TPMU_PUBLIC_ID_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[4];UINT16
marshalingTypes[4];} TPMU_PUBLIC_ID_mst;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 495
December 24, 2020

Part 4: Supporting Routines
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
1036
1037
1038
1039
1040
1041
1042
1043
1044

Trusted Platform Module Library

typedef const struct TPMS_KEYEDHASH_PARMS_mst{
UINT8
marshalType;UINT8elements;
UINT16values[3];} TPMS_KEYEDHASH_PARMS_mst;
typedef const struct TPMS_RSA_PARMS_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMS_RSA_PARMS_mst;
typedef const struct TPMS_ECC_PARMS_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMS_ECC_PARMS_mst;
typedef struct TPMU_PUBLIC_PARMS_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[4];UINT16
marshalingTypes[4];} TPMU_PUBLIC_PARMS_mst;
typedef const struct TPMT_PUBLIC_PARMS_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMT_PUBLIC_PARMS_mst;
typedef const struct TPMT_PUBLIC_mst{
UINT8
marshalType;UINT8elements;
UINT16values[18];} TPMT_PUBLIC_mst;
typedef struct TPMU_SENSITIVE_COMPOSITE_mst{
BYTE
countOfselectors;
BYTE
modifiers;
UINT16
offsetOfUnmarshalTypes;
UINT32
selectors[4];UINT16
marshalingTypes[4];} TPMU_SENSITIVE_COMPOSITE_mst;
typedef const struct TPMT_SENSITIVE_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMT_SENSITIVE_mst;
typedef const struct TPMS_NV_PIN_COUNTER_PARAMETERS_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 496
December 24, 2020

Part 4: Supporting Routines
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
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

Trusted Platform Module Library} TPMS_NV_PIN_COUNTER_PARAMETERS_mst;
typedef const struct TPMS_NV_PUBLIC_mst{
UINT8
marshalType;UINT8elements;
UINT16values[15];} TPMS_NV_PUBLIC_mst;
typedef const struct TPMS_CONTEXT_DATA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_CONTEXT_DATA_mst;
typedef const struct TPMS_CONTEXT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[12];} TPMS_CONTEXT_mst;
typedef const struct TPMS_CREATION_DATA_mst{
UINT8
marshalType;UINT8elements;
UINT16values[21];} TPMS_CREATION_DATA_mst;
typedef const struct TPM_AT_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[4];} TPM_AT_mst;
typedef const struct TPMS_AC_OUTPUT_mst{
UINT8
marshalType;UINT8elements;
UINT16values[6];} TPMS_AC_OUTPUT_mst;
typedef const struct Type02_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type02_mst;
typedef const struct Type03_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type03_mst;
typedef const struct Type04_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type04_mst;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 497
December 24, 2020

Part 4: Supporting Routines
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
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

Trusted Platform Module Library

typedef const struct Type06_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type06_mst;
typedef const struct Type08_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type08_mst;
typedef const struct Type10_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} Type10_mst;
typedef const struct Type11_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} Type11_mst;
typedef const struct Type12_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[2];} Type12_mst;
typedef const struct Type13_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT8
entries;
UINT32
values[1];} Type13_mst;
typedef const struct Type15_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type15_mst;
typedef const struct Type17_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type17_mst;
typedef const struct Type18_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type18_mst;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 498
December 24, 2020

Part 4: Supporting Routines
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
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242

Trusted Platform Module Library

typedef const struct Type19_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type19_mst;
typedef const struct Type20_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type20_mst;
typedef const struct Type22_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type22_mst;
typedef const struct Type23_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type23_mst;
typedef const struct Type24_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type24_mst;
typedef const struct Type25_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type25_mst;
typedef const struct Type26_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type26_mst;
typedef const struct Type27_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type27_mst;
typedef const struct Type29_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type29_mst;
typedef const struct Type30_mst {UINT8marshalType;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 499
December 24, 2020

Part 4: Supporting Routines
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

UINT8
UINT8
UINT32} Type30_mst;

Trusted Platform Module Librarymodifiers;
errorCode;values[2];typedef const struct Type33_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type33_mst;
typedef const struct Type34_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type34_mst;
typedef const struct Type35_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type35_mst;
typedef const struct Type38_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type38_mst;
typedef const struct Type41_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type41_mst;
typedef const struct Type42_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type42_mst;
typedef const struct Type44_mst {UINT8marshalType;UINT8
modifiers;
UINT8
errorCode;UINT32
values[2];} Type44_mst;

This structure combines all the individual marshaling structures to build something that can be referenced
by offset rather than full address
1296
1297
1298
1299
1300
1301
1302
1303

typedef const struct MarshalData_st {UintMarshal_mst
UINT8_DATA;UintMarshal_mst
UINT16_DATA;UintMarshal_mst
UINT32_DATA;UintMarshal_mst
UINT64_DATA;UintMarshal_mst
INT8_DATA;UintMarshal_mst
INT16_DATA;UintMarshal_mst
INT32_DATA;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 500
December 24, 2020

Part 4: Supporting Routines
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
1362
1363
1364
1365
1366
1367
1368
1369

Trusted Platform Module Library

UintMarshal_mst
UintMarshal_mst
TPM_ECC_CURVE_mst
TPM_CLOCK_ADJUST_mst
TPM_EO_mst
TPM_SU_mst
TPM_SE_mst
TPM_CAP_mst
AttributesMarshal_mst
AttributesMarshal_mst
AttributesMarshal_mst
AttributesMarshal_mst
TPMI_YES_NO_mst
TPMI_DH_OBJECT_mst
TPMI_DH_PARENT_mst
TPMI_DH_PERSISTENT_mst
TPMI_DH_ENTITY_mst
TPMI_DH_PCR_mst
TPMI_SH_AUTH_SESSION_mst
TPMI_SH_HMAC_mst
TPMI_SH_POLICY_mst
TPMI_DH_CONTEXT_mst
TPMI_DH_SAVED_mst
TPMI_RH_HIERARCHY_mst
TPMI_RH_ENABLES_mst
TPMI_RH_HIERARCHY_AUTH_mst
TPMI_RH_HIERARCHY_POLICY_mst
TPMI_RH_PLATFORM_mst
TPMI_RH_OWNER_mst
TPMI_RH_ENDORSEMENT_mst
TPMI_RH_PROVISION_mst
TPMI_RH_CLEAR_mst
TPMI_RH_NV_AUTH_mst
TPMI_RH_LOCKOUT_mst
TPMI_RH_NV_INDEX_mst
TPMI_RH_AC_mst
TPMI_RH_ACT_mst
TPMI_ALG_HASH_mst
TPMI_ALG_ASYM_mst
TPMI_ALG_SYM_mst
TPMI_ALG_SYM_OBJECT_mst
TPMI_ALG_SYM_MODE_mst
TPMI_ALG_KDF_mst
TPMI_ALG_SIG_SCHEME_mst
TPMI_ECC_KEY_EXCHANGE_mst
TPMI_ST_COMMAND_TAG_mst
TPMI_ALG_MAC_SCHEME_mst
TPMI_ALG_CIPHER_MODE_mst
TPMS_EMPTY_mst
TPMS_ALGORITHM_DESCRIPTION_mst
TPMU_HA_mst
TPMT_HA_mst
Tpm2bMarshal_mst
Tpm2bMarshal_mst
Tpm2bMarshal_mst
Tpm2bMarshal_mst
Tpm2bMarshal_mst
Tpm2bMarshal_mst
Tpm2bMarshal_mst
NullUnionMarshal_mst
Tpm2bMarshal_mst
TPMS_PCR_SELECT_mst
TPMS_PCR_SELECTION_mst
TPMT_TK_CREATION_mst
TPMT_TK_VERIFIED_mst
TPMT_TK_AUTH_mst

Family “2.0”Level 00 Revision 01.64

INT64_DATA;UINT0_DATA;TPM_ECC_CURVE_DATA;TPM_CLOCK_ADJUST_DATA;TPM_EO_DATA;TPM_SU_DATA;TPM_SE_DATA;TPM_CAP_DATA;
TPMA_ALGORITHM_DATA;
TPMA_OBJECT_DATA;
TPMA_SESSION_DATA;
TPMA_ACT_DATA;TPMI_YES_NO_DATA;TPMI_DH_OBJECT_DATA;TPMI_DH_PARENT_DATA;TPMI_DH_PERSISTENT_DATA;TPMI_DH_ENTITY_DATA;TPMI_DH_PCR_DATA;TPMI_SH_AUTH_SESSION_DATA;TPMI_SH_HMAC_DATA;TPMI_SH_POLICY_DATA;TPMI_DH_CONTEXT_DATA;TPMI_DH_SAVED_DATA;TPMI_RH_HIERARCHY_DATA;TPMI_RH_ENABLES_DATA;TPMI_RH_HIERARCHY_AUTH_DATA;TPMI_RH_HIERARCHY_POLICY_DATA;TPMI_RH_PLATFORM_DATA;TPMI_RH_OWNER_DATA;TPMI_RH_ENDORSEMENT_DATA;TPMI_RH_PROVISION_DATA;TPMI_RH_CLEAR_DATA;TPMI_RH_NV_AUTH_DATA;TPMI_RH_LOCKOUT_DATA;TPMI_RH_NV_INDEX_DATA;TPMI_RH_AC_DATA;TPMI_RH_ACT_DATA;TPMI_ALG_HASH_DATA;TPMI_ALG_ASYM_DATA;TPMI_ALG_SYM_DATA;TPMI_ALG_SYM_OBJECT_DATA;TPMI_ALG_SYM_MODE_DATA;TPMI_ALG_KDF_DATA;TPMI_ALG_SIG_SCHEME_DATA;TPMI_ECC_KEY_EXCHANGE_DATA;TPMI_ST_COMMAND_TAG_DATA;TPMI_ALG_MAC_SCHEME_DATA;TPMI_ALG_CIPHER_MODE_DATA;TPMS_EMPTY_DATA;TPMS_ALGORITHM_DESCRIPTION_DATA;TPMU_HA_DATA;TPMT_HA_DATA;
TPM2B_DIGEST_DATA;
TPM2B_DATA_DATA;
TPM2B_EVENT_DATA;
TPM2B_MAX_BUFFER_DATA;
TPM2B_MAX_NV_BUFFER_DATA;
TPM2B_TIMEOUT_DATA;
TPM2B_IV_DATA;NULL_UNION_DATA;
TPM2B_NAME_DATA;TPMS_PCR_SELECT_DATA;TPMS_PCR_SELECTION_DATA;TPMT_TK_CREATION_DATA;TPMT_TK_VERIFIED_DATA;TPMT_TK_AUTH_DATA;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 501
December 24, 2020

Part 4: Supporting Routines
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
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435

Trusted Platform Module Library

TPMT_TK_HASHCHECK_mst
TPMT_TK_HASHCHECK_DATA;TPMS_ALG_PROPERTY_mst
TPMS_ALG_PROPERTY_DATA;TPMS_TAGGED_PROPERTY_mst
TPMS_TAGGED_PROPERTY_DATA;TPMS_TAGGED_PCR_SELECT_mst
TPMS_TAGGED_PCR_SELECT_DATA;TPMS_TAGGED_POLICY_mst
TPMS_TAGGED_POLICY_DATA;TPMS_ACT_DATA_mst
TPMS_ACT_DATA_DATA;
ListMarshal_mst
TPML_CC_DATA;
ListMarshal_mst
TPML_CCA_DATA;
ListMarshal_mst
TPML_ALG_DATA;
ListMarshal_mst
TPML_HANDLE_DATA;
ListMarshal_mst
TPML_DIGEST_DATA;
ListMarshal_mst
TPML_DIGEST_VALUES_DATA;
ListMarshal_mst
TPML_PCR_SELECTION_DATA;
ListMarshal_mst
TPML_ALG_PROPERTY_DATA;
ListMarshal_mst
TPML_TAGGED_TPM_PROPERTY_DATA;
ListMarshal_mst
TPML_TAGGED_PCR_PROPERTY_DATA;
ListMarshal_mst
TPML_ECC_CURVE_DATA;
ListMarshal_mst
TPML_TAGGED_POLICY_DATA;
ListMarshal_mst
TPML_ACT_DATA_DATA;TPMU_CAPABILITIES_mst
TPMU_CAPABILITIES_DATA;TPMS_CAPABILITY_DATA_mst
TPMS_CAPABILITY_DATA_DATA;TPMS_CLOCK_INFO_mst
TPMS_CLOCK_INFO_DATA;TPMS_TIME_INFO_mst
TPMS_TIME_INFO_DATA;TPMS_TIME_ATTEST_INFO_mst
TPMS_TIME_ATTEST_INFO_DATA;TPMS_CERTIFY_INFO_mst
TPMS_CERTIFY_INFO_DATA;TPMS_QUOTE_INFO_mst
TPMS_QUOTE_INFO_DATA;TPMS_COMMAND_AUDIT_INFO_mst
TPMS_COMMAND_AUDIT_INFO_DATA;TPMS_SESSION_AUDIT_INFO_mst
TPMS_SESSION_AUDIT_INFO_DATA;TPMS_CREATION_INFO_mst
TPMS_CREATION_INFO_DATA;TPMS_NV_CERTIFY_INFO_mst
TPMS_NV_CERTIFY_INFO_DATA;TPMS_NV_DIGEST_CERTIFY_INFO_mst TPMS_NV_DIGEST_CERTIFY_INFO_DATA;TPMI_ST_ATTEST_mst
TPMI_ST_ATTEST_DATA;TPMU_ATTEST_mst
TPMU_ATTEST_DATA;TPMS_ATTEST_mst
TPMS_ATTEST_DATA;
Tpm2bMarshal_mst
TPM2B_ATTEST_DATA;TPMS_AUTH_COMMAND_mst
TPMS_AUTH_COMMAND_DATA;TPMS_AUTH_RESPONSE_mst
TPMS_AUTH_RESPONSE_DATA;TPMI_TDES_KEY_BITS_mst
TPMI_TDES_KEY_BITS_DATA;TPMI_AES_KEY_BITS_mst
TPMI_AES_KEY_BITS_DATA;TPMI_SM4_KEY_BITS_mst
TPMI_SM4_KEY_BITS_DATA;TPMI_CAMELLIA_KEY_BITS_mst
TPMI_CAMELLIA_KEY_BITS_DATA;TPMU_SYM_KEY_BITS_mst
TPMU_SYM_KEY_BITS_DATA;TPMU_SYM_MODE_mst
TPMU_SYM_MODE_DATA;TPMT_SYM_DEF_mst
TPMT_SYM_DEF_DATA;TPMT_SYM_DEF_OBJECT_mst
TPMT_SYM_DEF_OBJECT_DATA;
Tpm2bMarshal_mst
TPM2B_SYM_KEY_DATA;TPMS_SYMCIPHER_PARMS_mst
TPMS_SYMCIPHER_PARMS_DATA;
Tpm2bMarshal_mst
TPM2B_LABEL_DATA;TPMS_DERIVE_mst
TPMS_DERIVE_DATA;
Tpm2bMarshal_mst
TPM2B_DERIVE_DATA;
Tpm2bMarshal_mst
TPM2B_SENSITIVE_DATA_DATA;TPMS_SENSITIVE_CREATE_mst
TPMS_SENSITIVE_CREATE_DATA;
Tpm2bsMarshal_mst
TPM2B_SENSITIVE_CREATE_DATA;TPMS_SCHEME_HASH_mst
TPMS_SCHEME_HASH_DATA;TPMS_SCHEME_ECDAA_mst
TPMS_SCHEME_ECDAA_DATA;TPMI_ALG_KEYEDHASH_SCHEME_mst
TPMI_ALG_KEYEDHASH_SCHEME_DATA;TPMS_SCHEME_XOR_mst
TPMS_SCHEME_XOR_DATA;TPMU_SCHEME_KEYEDHASH_mst
TPMU_SCHEME_KEYEDHASH_DATA;TPMT_KEYEDHASH_SCHEME_mst
TPMT_KEYEDHASH_SCHEME_DATA;TPMU_SIG_SCHEME_mst
TPMU_SIG_SCHEME_DATA;TPMT_SIG_SCHEME_mst
TPMT_SIG_SCHEME_DATA;TPMU_KDF_SCHEME_mst
TPMU_KDF_SCHEME_DATA;TPMT_KDF_SCHEME_mst
TPMT_KDF_SCHEME_DATA;TPMI_ALG_ASYM_SCHEME_mst
TPMI_ALG_ASYM_SCHEME_DATA;TPMU_ASYM_SCHEME_mst
TPMU_ASYM_SCHEME_DATA;TPMI_ALG_RSA_SCHEME_mst
TPMI_ALG_RSA_SCHEME_DATA;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 502
December 24, 2020

Part 4: Supporting Routines
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
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501

Trusted Platform Module Library

TPMT_RSA_SCHEME_mst
TPMT_RSA_SCHEME_DATA;TPMI_ALG_RSA_DECRYPT_mst
TPMI_ALG_RSA_DECRYPT_DATA;TPMT_RSA_DECRYPT_mst
TPMT_RSA_DECRYPT_DATA;
Tpm2bMarshal_mst
TPM2B_PUBLIC_KEY_RSA_DATA;TPMI_RSA_KEY_BITS_mst
TPMI_RSA_KEY_BITS_DATA;
Tpm2bMarshal_mst
TPM2B_PRIVATE_KEY_RSA_DATA;
Tpm2bMarshal_mst
TPM2B_ECC_PARAMETER_DATA;TPMS_ECC_POINT_mst
TPMS_ECC_POINT_DATA;
Tpm2bsMarshal_mst
TPM2B_ECC_POINT_DATA;TPMI_ALG_ECC_SCHEME_mst
TPMI_ALG_ECC_SCHEME_DATA;TPMI_ECC_CURVE_mst
TPMI_ECC_CURVE_DATA;TPMT_ECC_SCHEME_mst
TPMT_ECC_SCHEME_DATA;TPMS_ALGORITHM_DETAIL_ECC_mst
TPMS_ALGORITHM_DETAIL_ECC_DATA;TPMS_SIGNATURE_RSA_mst
TPMS_SIGNATURE_RSA_DATA;TPMS_SIGNATURE_ECC_mst
TPMS_SIGNATURE_ECC_DATA;TPMU_SIGNATURE_mst
TPMU_SIGNATURE_DATA;TPMT_SIGNATURE_mst
TPMT_SIGNATURE_DATA;TPMU_ENCRYPTED_SECRET_mst
TPMU_ENCRYPTED_SECRET_DATA;
Tpm2bMarshal_mst
TPM2B_ENCRYPTED_SECRET_DATA;TPMI_ALG_PUBLIC_mst
TPMI_ALG_PUBLIC_DATA;TPMU_PUBLIC_ID_mst
TPMU_PUBLIC_ID_DATA;TPMS_KEYEDHASH_PARMS_mst
TPMS_KEYEDHASH_PARMS_DATA;TPMS_RSA_PARMS_mst
TPMS_RSA_PARMS_DATA;TPMS_ECC_PARMS_mst
TPMS_ECC_PARMS_DATA;TPMU_PUBLIC_PARMS_mst
TPMU_PUBLIC_PARMS_DATA;TPMT_PUBLIC_PARMS_mst
TPMT_PUBLIC_PARMS_DATA;TPMT_PUBLIC_mst
TPMT_PUBLIC_DATA;
Tpm2bsMarshal_mst
TPM2B_PUBLIC_DATA;
Tpm2bMarshal_mst
TPM2B_TEMPLATE_DATA;
Tpm2bMarshal_mst
TPM2B_PRIVATE_VENDOR_SPECIFIC_DATA;TPMU_SENSITIVE_COMPOSITE_mst
TPMU_SENSITIVE_COMPOSITE_DATA;TPMT_SENSITIVE_mst
TPMT_SENSITIVE_DATA;
Tpm2bsMarshal_mst
TPM2B_SENSITIVE_DATA;
Tpm2bMarshal_mst
TPM2B_PRIVATE_DATA;
Tpm2bMarshal_mst
TPM2B_ID_OBJECT_DATA;TPMS_NV_PIN_COUNTER_PARAMETERS_mst TPMS_NV_PIN_COUNTER_PARAMETERS_DATA;
AttributesMarshal_mst
TPMA_NV_DATA;TPMS_NV_PUBLIC_mst
TPMS_NV_PUBLIC_DATA;
Tpm2bsMarshal_mst
TPM2B_NV_PUBLIC_DATA;
Tpm2bMarshal_mst
TPM2B_CONTEXT_SENSITIVE_DATA;TPMS_CONTEXT_DATA_mst
TPMS_CONTEXT_DATA_DATA;
Tpm2bMarshal_mst
TPM2B_CONTEXT_DATA_DATA;TPMS_CONTEXT_mst
TPMS_CONTEXT_DATA;TPMS_CREATION_DATA_mst
TPMS_CREATION_DATA_DATA;
Tpm2bsMarshal_mst
TPM2B_CREATION_DATA_DATA;TPM_AT_mst
TPM_AT_DATA;TPMS_AC_OUTPUT_mst
TPMS_AC_OUTPUT_DATA;
ListMarshal_mst
TPML_AC_CAPABILITIES_DATA;
MinMaxMarshal_mst
Type00_DATA;
MinMaxMarshal_mst
Type01_DATA;
Type02_mst
Type02_DATA;
Type03_mst
Type03_DATA;
Type04_mst
Type04_DATA;
MinMaxMarshal_mst
Type05_DATA;
Type06_mst
Type06_DATA;
MinMaxMarshal_mst
Type07_DATA;
Type08_mst
Type08_DATA;
Type10_mst
Type10_DATA;
Type11_mst
Type11_DATA;
Type12_mst
Type12_DATA;
Type13_mst
Type13_DATA;
Type15_mst
Type15_DATA;
Type17_mst
Type17_DATA;
Type18_mst
Type18_DATA;
Type19_mst
Type19_DATA;
Type20_mst
Type20_DATA;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 503
December 24, 2020

Part 4: Supporting Routines
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

Type22_mst
Type23_mst
Type24_mst
Type25_mst
Type26_mst
Type27_mst
MinMaxMarshal_mst
Type29_mst
Type30_mst
MinMaxMarshal_mst
MinMaxMarshal_mst
Type33_mst
Type34_mst
Type35_mst
MinMaxMarshal_mst
MinMaxMarshal_mst
Type38_mst
MinMaxMarshal_mst
MinMaxMarshal_mst
Type41_mst
Type42_mst
MinMaxMarshal_mst
Type44_mst} MarshalData_st;

Type22_DATA;
Type23_DATA;
Type24_DATA;
Type25_DATA;
Type26_DATA;
Type27_DATA;
Type28_DATA;
Type29_DATA;
Type30_DATA;
Type31_DATA;
Type32_DATA;
Type33_DATA;
Type34_DATA;
Type35_DATA;
Type36_DATA;
Type37_DATA;
Type38_DATA;
Type39_DATA;
Type40_DATA;
Type41_DATA;
Type42_DATA;
Type43_DATA;
Type44_DATA;#endif // _TABLE_MARSHAL_TYPES_H_

9.10.89.10.8.1
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

Trusted Platform Module Library

Table Marshal Source
TableDrivenMarshal.c#include <assert.h>#include "Tpm.h"#include "Marshal.h"#include "TableMarshal.h"#if TABLE_DRIVEN_MARSHAL
extern ArrayMarshal_mst ArrayLookupTable[];extern UINT16 MarshalLookupTable[];typedef struct { int a; } External_Structure_t;
extern struct Exernal_Structure_t MarshalData;#define IS_SUCCESS(UNMARSHAL_FUNCTION)(TPM_RC_SUCCESS == (result = (UNMARSHAL_FUNCTION)))\

marshalIndex_t IntegerDispatch[] = {UINT8_MARSHAL_REF, UINT16_MARSHAL_REF, UINT32_MARSHAL_REF, UINT64_MARSHAL_REF,
INT8_MARSHAL_REF, INT16_MARSHAL_REF, INT32_MARSHAL_REF, INT64_MARSHAL_REF};#if 1#define GetDescriptor(reference)((MarshalHeader_mst *)(((BYTE *)(&MarshalData)) + (reference & NULL_MASK)))#else
static const MarshalHeader_mst *GetDescriptor(marshalIndex_t index){
const MarshalHeader_mst*mst = MarshalLookupTable[index & NULL_MASK];
return mst;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 504
December 24, 2020

Part 4: Supporting Routines
34
35
36
37
38
39

Trusted Platform Module Library#endif#define GetUnionDescriptor(_index_)((UnionMarshal_mst *)GetDescriptor(_index_))#define GetArrayDescriptor(_index_)((ArrayMarshal_mst *))(ArrayLookupTable[_index_ & NULL_MASK])

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 505
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.1

Trusted Platform Module Library

GetUnmarshaledInteger()

Gets the unmarshaled value and normalizes it to a UIN32 for other processing (comparisons and such).
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

static UINT32 GetUnmarshaledInteger(
marshalIndex_t
const void

type,
*target){int

size = (type & SIZE_MASK);//
if(size == FOUR_BYTES)
return *((UINT32 *)target);if(type & IS_SIGNED){
if(size == TWO_BYTES)
return (UINT32)*((int16_t *)target);return (UINT32)*((int8_t *)target);}if(size == TWO_BYTES)
return (UINT32)*((UINT16 *)target);return (UINT32)*((UINT8 *)target);}static UINT32 GetSelector(
void*structure,
const UINT16*values,
UINT16
descriptor){
unsignedsel = GET_ELEMENT_NUMBER(descriptor);// Get the offset of the value in the unmarshaled structure
const UINT16*entry = &values[(sel * 3)];//return GetUnmarshaledInteger(GET_ELEMENT_SIZE(entry[0]),((UINT8 *)structure) + entry[2]);}static TPM_RC UnmarshalBytes(
UINT8*target,// IN/OUT: place to put the bytes
UINT8**buffer,// IN/OUT: source of the input data
INT32
*size,// IN/OUT: remaining bytes in the input buffer
int
count
// IN: number of bytes to get){if((*size -= count) >= 0){
memcpy(target, *buffer, count);*buffer += count;return TPM_RC_SUCCESS;}
return TPM_RC_INSUFFICIENT;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 506
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.2

Trusted Platform Module Library

MarshalBytes()

Marshal an array of bytes.
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

static UINT16 MarshalBytes(
UINT8
UINT8
INT32
int32_t*source,**buffer,*size,count){if(buffer != NULL){
if(size != NULL && (size -= count) < 0)return 0;
memcpy(*buffer, source, count);*buffer += count;}return (UINT16)count;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 507
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.3

Trusted Platform Module Library

ArrayUnmarshal()Unmarshal an array. The index is of the form: type_ARRAY_MARSHAL_INDEX.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

static TPM_RC ArrayUnmarshal(
UINT16
UINT8
UINT8
INT32
UINT32index,*target,**buffer,*size,
count// IN: the type of the array// IN: target for the data// IN/OUT: place to get the data// IN/OUT: remaining unmarshal data// IN: number of values of 'index' to//unmarshal

marshalIndex_t
UINT16
TPM_RC

which = ArrayLookupTable[index & NULL_MASK].type;stride = ArrayLookupTable[index & NULL_MASK].stride;
result;){//if(stride == 1) // A byte array
result = UnmarshalBytes(target, buffer, size, count);else{
which |= index & NULL_FLAG;
for(result = TPM_RC_SUCCESS; count > 0; target += stride, count--)
if(!IS_SUCCESS(Unmarshal(which, target, buffer, size)))
break;}
return result;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 508
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.4
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

Trusted Platform Module Library

ArrayMarshal()static UINT16 ArrayMarshal(
UINT16
UINT8
UINT8
INT32
UINT32index,*source,**buffer,*size,
count// IN: the type of the array// IN: source of the data// IN/OUT: place to put the data// IN/OUT: amount of space for the data// IN: number of values of 'index' to marshal

marshalIndex_t
UINT16
UINT16

which = ArrayLookupTable[index & NULL_MASK].type;stride = ArrayLookupTable[index & NULL_MASK].stride;
retVal;){//if(stride == 1) // A byte array
return MarshalBytes(source, buffer, size, count);which |= index & NULL_FLAG;
for(retVal = 0; count > 0; source += stride, count--)
retVal += Marshal(which, source, buffer, size);
return retVal;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 509
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.5
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

Trusted Platform Module Library

UnmarshalUnion()

TPM_RC
UnmarshalUnion(
UINT16
void
UINT8
INT32
UINT32

typeIndex,*target,**buffer,*size,
selector// IN: the thing to unmarshal// IN: were the data goes to// IN/OUT: the data source buffer// IN/OUT: the remaining size

intUnionMarshal_mst
marshalIndex_ti;*ut = GetUnionDescriptor(typeIndex);
selected;){//for(i = 0; i < ut->countOfselectors; i++){if(selector == ut->selectors[i]){UINT8*offset = ((UINT8 *)ut) + ut->offsetOfUnmarshalTypes;// Get the selected thing to unmarshal
selected = ((marshalIndex_t *)offset)[i];if(ut->modifiers & IS_ARRAY_UNION)
return UnmarshalBytes(target, buffer, size, selected);else{// Propagate NULL_FLAG if the null flag was// propagated to the structure containing the union
selected |= (typeIndex & NULL_FLAG);
return Unmarshal(selected, target, buffer, size);}}}// Didn't find the value.
return TPM_RC_SELECTOR;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 510
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.6
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

Trusted Platform Module Library

MarshalUnion()

UINT16
MarshalUnion(
UINT16
void
UINT8
INT32
UINT32

typeIndex,*source,**buffer,*size,
selector// IN: the thing to marshal// IN: were the data comes from// IN/OUT: the data source buffer// IN/OUT: the remaining size// IN: the union selector

intUnionMarshal_mst
marshalIndex_ti;*ut = GetUnionDescriptor(typeIndex);
selected;){//for(i = 0; i < ut->countOfselectors; i++){if(selector == ut->selectors[i]){UINT8*offset = ((UINT8 *)ut) + ut->offsetOfUnmarshalTypes;// Get the selected thing to unmarshal
selected = ((marshalIndex_t *)offset)[i];if(ut->modifiers & IS_ARRAY_UNION)
return MarshalBytes(source, buffer, size, selected);else
return Marshal(selected, source, buffer, size);}}if(size != NULL)*size = -1;
return 0;}
TPM_RC
UnmarshalInteger(
int
iSize,// IN: Number of bytes in the integer
void*target,// OUT: receives the integer
UINT8**buffer,// IN/OUT: source of the data
INT32
*size,// IN/OUT: amount of data available
UINT32*value// OUT: optional copy of 'target'){// This is just to save typing#define _MB_ (*buffer)// The size is a power of two so convert to regular integer
int
bytes = (1 << (iSize & SIZE_MASK));//// Check to see if there is enough data to fulfill the requestif((*size -= bytes) >= 0){// The most comon size
if(bytes == 4){*((UINT32 *)target) = (UINT32)((((((_MB_[0] << 8) | _MB_[1]) << 8)| _MB_[2]) << 8) | _MB_[3]);// If a copy is needed, copy it.
if(value != NULL)*value = *((UINT32 *)target);}else if(bytes == 2){*((UINT16 *)target) = (UINT16)((_MB_[0] << 8) | _MB_[1]);// If a copy is needed, copy with the appropriate sign extensionif(value != NULL){
if(iSize & IS_SIGNED)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 511
December 24, 2020

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

Trusted Platform Module Library*value = (UINT32)(*((INT16 *)target));else*value = (UINT32)(*((UINT16 *)target));}}else if(bytes == 1){*((UINT8*)target) = (UINT8)_MB_[0];// If a copy is needed, copy with the appropriate sign extensionif(value != NULL){
if(iSize & IS_SIGNED)*value = (UINT32)(*((INT8 *)target));else*value = (UINT32)(*((UINT8 *)target));
}
}
else
{
// There is no input type that is a 64-bit value other than a UINT64. So// there is no reason to do anything other than unmarshal it.
*((UINT64 *)target) = BYTE_ARRAY_TO_UINT64(*buffer);}*buffer += bytes;
return TPM_RC_SUCCESS;#undef _MB_}
return TPM_RC_INSUFFICIENT;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 512
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.7

Trusted Platform Module Library

Unmarshal()This is the function that performs unmarshaling of different numbered types. Each TPM type has anumber. The number is used to lookup the address of the data structure that describes how to unmarshal
that data type.
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
331
332

TPM_RC
Unmarshal(
UINT16
void
UINT8
INT32

typeIndex,*target,**buffer,*size// IN: the thing to marshal// IN: were the data goes from// IN/OUT: the data source buffer// IN/OUT: the remaining size){
const MarshalHeader_mst
TPM_RC*sel;
result;//sel = GetDescriptor(typeIndex);
switch(sel->marshalType){case UINT_MTYPE:{// A simple signed or unsigned integer value.
return UnmarshalInteger(sel->modifiers, target,
buffer, size, NULL);}
case VALUES_MTYPE:{// This is the general-purpose structure that can handle things like// TPMI_DH_PARENT that has multiple ranges, multiple singles and a// 'null' value. When things cover a large range with holes in the range// they can be turned into multiple ranges. There is no option for a bit// field.
// The structure is:// typedef const struct ValuesMarshal_mst
// {
//
UINT8
marshalType;// VALUES_MTYPE//
UINT8
modifiers;//
UINT8
errorCode;//UINT8
ranges;//UINT8singles;//
UINT32
values[1];// } ValuesMarshal_mst;// Unmarshal the base type
UINT32val;
if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
buffer, size, &val))){ValuesMarshal_mst*vmt = ((ValuesMarshal_mst *)sel);const UINT32*check = vmt->values;//// if the TAKES_NULL flag is set, then the first entry in the values// list is the NULL value. Iy is not included in the 'ranges' or// 'singles' count.
if((vmt->modifiers & TAKES_NULL) && (val == *check++)){if((typeIndex & NULL_FLAG) == 0)
result = (TPM_RC)(sel->errorCode);}// No NULL value or input is not the NULL value
else
{
int
i;
//

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 513
December 24, 2020

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
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

Trusted Platform Module Library// Check all the min-max ranges.
for(i = vmt->ranges - 1; i >= 0; check = &check[2], i--)if((UINT32)(val - check[0]) <= check[1])break;// if the input is in a selected range, then i >= 0
if(i < 0){// Not in any range, so check sigles
for(i = vmt->singles - 1; i >= 0; i--)if(val == check[i])break;}// If input not in range and not in any single so return error
if(i < 0)result = (TPM_RC)(sel->errorCode);}}
break;}
case TABLE_MTYPE:{// This is a table with or without bit checking. The input is checked// against each value in the table. If the value is in the table, and// a bits table is present, then the bit field is checked to see if the// indicated value is implemented. For example, if there is a table of// allowed RSA key sizes and the 2nd entry matches, then the 2nd bit in// the bit field is checked to see if that allowed size is implemented// in this TPM.
// typedef const struct TableMarshal_mst
// {
//
UINT8
marshalType;// TABLE_MTYPE//
UINT8
modifiers;//
UINT8
errorCode;//UINT8singles;//
UINT32
values[singles + 1 if TAKES_NULL];// } TableMarshal_mst;
UINT32val;//// Unmarshal the base typeif(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
buffer, size, &val))){TableMarshal_mst*tmt = ((TableMarshal_mst *)sel);const UINT32*check = tmt->values;//// If this type has a null value, then it is the first value in the// list of values. It does not count in the count of values
if((tmt->modifiers & TAKES_NULL) && (val == *check++)){if((typeIndex & NULL_FLAG) == 0)
result = (TPM_RC)(sel->errorCode);
}
else
{
int
i;
//
// Process the singles
for(i = tmt->singles - 1; i >= 0; i--){// does the input value match the value in the tableif(val == check[i]){// If there is an associated bit table, make sure that// the corresponding bit is SET
if((HAS_BITS & tmt->modifiers)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 514
December 24, 2020

Part 4: Supporting Routines
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
463
464

Trusted Platform Module Library&& (!IS_BIT_SET32(i, &(check[tmt->singles]))))// if not SET, then this is a failure.
i = -1;break;}}// error if not found or bit not SET
if(i < 0)result = (TPM_RC)(sel->errorCode);}}
break;}
case MIN_MAX_MTYPE:{// A MIN_MAX is a range. It can have a bit field and a NULL value that is// outside of the range. If the input value is in the min-max range then// it is valid unless there is an associated bit field. Otherwise, it// it is only valid if the corresponding value in the bit field is SET.
// The min value is 'values[0]' or 'values[1]' if there is a NULL value.
// The max value is the value after min. The max value is in the table as// max minus min. This allows 'val' to be subtracted from min and then// checked against max with one unsigned comparison. If present, the bit// field will be the first 'values' after max.
// typedef const struct MinMaxMarshal_mst
// {
//
UINT8
marshalType;// MIN_MAX_MTYPE//
UINT8
modifiers;//
UINT8
errorCode;//UINT32
values[2 + 1 if TAKES_NULL];// } MinMaxMarshal_mst;
UINT32val;//// A min-max has a range. It can have a bit-field that is indexed to the// min value (something that matches min has a bit at 0. This is useful// for algorithms. The min-max define a range of algorithms to be checked// and the bit field can check to see if the algorithm in that range is// allowed.
if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
buffer, size, &val))){MinMaxMarshal_mst*mmt = (MinMaxMarshal_mst *)sel;const UINT32*check = mmt->values;//// If this type takes a NULL, see if it matches. Thisif((mmt->modifiers & TAKES_NULL) && (val == *check++)){if((typeIndex & NULL_FLAG) == 0)
result = (TPM_RC)(mmt->errorCode);}else{
val -= *check;if((val > check[1])|| ((mmt->modifiers & HAS_BITS) &&!IS_BIT_SET32(val, &check[2])))
result = (TPM_RC)(mmt->errorCode);}}
break;}
case ATTRIBUTES_MTYPE:{// This is used for TPMA values.
UINT32mask;
AttributesMarshal_mst*amt = (AttributesMarshal_mst *)sel;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 515
December 24, 2020

Part 4: Supporting Routines
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
529
530

Trusted Platform Module Library//if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
buffer, size, &mask))){if((mask & amt->attributeMask) != 0)
result = TPM_RC_RESERVED_BITS;}
break;}
case STRUCTURE_MTYPE:{// A structure (not a union). A structure has elements (one defined per// row). Three UINT16 values are used for each row. The first indicates// the type of the entry. They choices are: simple, union, or array. A// simple type can be a simple integer or another structure. It can also// be a specific "interface type." For example, when a structure entry is// a value that is used define the dimension of an array, the entry of// the structure will reference a "synthetic" interface type, most often// a min-max value. If the type of the entry is union or array, then the// first value indicates which of the previous elements provides the union// selector or the array dimension. That previous entry is referenced in// the unmarshaled structure in memory (Not the marshaled buffer). The// previous entry indicates the location in the structure of the value.
// The second entry of each structure entry indicated the index of the// type associated with the entry. This is an index into the array of// arrays or the union table (merged with the normal table in this// implementation). The final entry is the offset in the unmarshaled// structure where the value is located. This is the offsetof(STRUcTURE,// element). This value is added to the input 'target' or 'source' value// to determine where the value goes.
StructMarshal_mst*mst = (StructMarshal_mst *)sel;int
i;
const UINT16*value = mst->values;//for(result = TPM_RC_SUCCESS, i = mst->elements; (TPM_RC_SUCCESS == result) && (i > 0)
; value = &value[3], i--){UINT16
descriptor = value[0];marshalIndex_t
index = value[1];// The offset of the object in the structure is in the last value in// the triplet. Add that value to the start of the structure
UINT8*offset = ((UINT8 *)target) + value[2];//if ((ELEMENT_PROPAGATE & descriptor)&& (typeIndex & NULL_FLAG))
index |= NULL_FLAG;
switch(GET_ELEMENT_TYPE(descriptor)){case SIMPLE_STYPE:{
result = Unmarshal(index, offset, buffer, size);break;}
case UNION_STYPE:{UINT32
choice;//// Get the selector or array dimension value
choice = GetSelector(target, mst->values, descriptor);
result = UnmarshalUnion(index, offset, buffer, size, choice);
break;}
case ARRAY_STYPE:{UINT32dimension;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 516
December 24, 2020

Part 4: Supporting Routines
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
595
596

Trusted Platform Module Library//dimension = GetSelector(target, mst->values, descriptor);
result = ArrayUnmarshal(index, offset, buffer,size, dimension);break;}
default:
result = TPM_RC_FAILURE;
break;}}
break;}
case TPM2B_MTYPE:{// A primitive TPM2B. A size and byte buffer. The single value (other than// the tag) references the synthetic 'interface' value for the size// parameter.
Tpm2bMarshal_mst*m2bt = (Tpm2bMarshal_mst *)sel;//
if(IS_SUCCESS(Unmarshal(m2bt->sizeIndex, target, buffer, size)))
result = UnmarshalBytes(((TPM2B *)target)->buffer,buffer, size, *((UINT16 *)target));break;}
case TPM2BS_MTYPE:{// This is used when a TPM2B contains a structure.
Tpm2bsMarshal_mst*m2bst = (Tpm2bsMarshal_mst *)sel;
INT32
count;//
if(IS_SUCCESS(Unmarshal(m2bst->sizeIndex, target, buffer, size))){// fetch the size value and convert it to a 32-bit count value
count = (int32_t)*((UINT16 *)target);if(count == 0){if(m2bst->modifiers & SIZE_EQUAL)
result = TPM_RC_SIZE;}
else if((*size -= count) >= 0){
marshalIndex_t index = m2bst->dataIndex;//// If this type propigates a null (PROPIGATE_NULL), propigate itif ((m2bst->modifiers & PROPAGATE_NULL)&& (typeIndex & typeIndex))
index |= NULL_FLAG;// The structure might not start two bytes after the start of the// size field. The offset to the start of the structure is between// 2 and 8 bytes. This is encoded into the low 4 bits of the// modifiers byte byte
if(IS_SUCCESS(Unmarshal(index,((UINT8 *)target) + (m2bst->modifiers & OFFSET_MASK),
buffer, &count))){
if(count != 0)
result = TPM_RC_SIZE;}}
else
result = TPM_RC_INSUFFICIENT;}
break;}
case LIST_MTYPE:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 517
December 24, 2020

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

Trusted Platform Module Library{// Used for a list. A list is a qualified 32-bit 'count' value followed// by a type indicator.
ListMarshal_mst*mlt = (ListMarshal_mst *)sel;
marshalIndex_t
index = mlt->arrayRef;//
if(IS_SUCCESS(Unmarshal(mlt->sizeIndex, target, buffer, size))){// If this type propigates a null (PROPIGATE_NULL), propigate itif ((mlt->modifiers & PROPAGATE_NULL)&& (typeIndex & NULL_FLAG))
index |= NULL_FLAG;
result = ArrayUnmarshal(index,((UINT8 *)target) +(mlt->modifiers & OFFSET_MASK),
buffer, size, *((UINT32 *)target));}break;}
case NULL_MTYPE:{
result = TPM_RC_SUCCESS;
break;}#if 0case COMPOSITE_MTYPE:{
CompositeMarshal_mst*mct = (CompositeMarshal_mst *)sel;
int
i;
UINT8
*buf = *buffer;
INT32
sz = *size;//
result = TPM_RC_VALUE;
for(i = GET_ELEMENT_COUNT(mct->modifiers) - 1; i <= 0; i--){marshalIndex_t
index = mct->types[i];//// This type might take a null so set it in each called value, just// in case it is needed in that value. Only one value in each// composite should have the takes null SET.
index |= typeIndex & NULL_MASK;
result = Unmarshal(index, target, buffer, size);if(result == TPM_RC_SUCCESS)
break;// Each of the composite values does its own unmarshaling. This// has some execution overhead if it is unmarshaled multiple times// but it saves code size in not having to reproduce the various// unmarshaling types that can be in a composite. So, what this means// is that the buffer pointer and size have to be reset for each// unmarshaled value.
*buffer = buf;
*size = sz;}
break;}#endif // 0
default:{
result = TPM_RC_FAILURE;
break;}}
return result;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 518
December 24, 2020

Part 4: Supporting Routines

9.10.8.1.1.8

Trusted Platform Module Library

Marshal()This is the function that drives marshaling of output. Because there is no validation of the output, there isa lot less code.
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

UINT16 Marshal(
UINT16
void
UINT8
INT32
)
{
#define _source

typeIndex,*source,**buffer,*size// IN: the thing to marshal// IN: were the data comes from// IN/OUT: the data source buffer// IN/OUT: the remaining size((UINT8 *)source)

const MarshalHeader_mst
UINT16*sel;
retVal;//sel = GetDescriptor(typeIndex);
switch(sel->marshalType){case VALUES_MTYPE:
case UINT_MTYPE:
case TABLE_MTYPE:
case MIN_MAX_MTYPE:
case ATTRIBUTES_MTYPE:
case COMPOSITE_MTYPE:{#if BIG_ENDIAN_TPM#define MM16
0
#define MM32
0#define MM64
0#else// These flip the constant index values so that they count in reverse order when doing// little-endian stuff#define MM16
1
#define MM32
3
#define MM64
7
#endif// Just change the name and cast the type of the input parameters for typing purposes#define mb (*buffer)#define _source ((UINT8 *)source)
retVal = (1 << (sel->modifiers & SIZE_MASK));if(buffer != NULL){
if((size == NULL) || ((*size -= retVal) >= 0)){if(retVal == 4){mb[0 ^ MM32] = _source[0];mb[1 ^ MM32] = _source[1];mb[2 ^ MM32] = _source[2];mb[3 ^ MM32] = _source[3];}else if(retVal == 2){
mb[0 ^ MM16] = _source[0];mb[1 ^ MM16] = _source[1];}else if(retVal == 1)
mb[0] = _source[0];else{
mb[0 ^ MM64] = _source[0];mb[1 ^ MM64] = _source[1];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 519
December 24, 2020

Part 4: Supporting Routines
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
779
780
781
782
783
784

Trusted Platform Module Librarymb[2 ^ MM64] = _source[2];mb[3 ^ MM64] = _source[3];mb[4 ^ MM64] = _source[4];mb[5 ^ MM64] = _source[5];mb[6 ^ MM64] = _source[6];mb[7 ^ MM64] = _source[7];}*buffer += retVal;}}
break;}
case STRUCTURE_MTYPE:{//#define _mst ((StructMarshal_mst *)sel)
StructMarshal_mst *mst = ((StructMarshal_mst *)sel);int
i;const UINT16 *value = mst->values;//for(retVal = 0, i = mst->elements; i > 0; value = &value[3], i--){UINT16
des = value[0];marshalIndex_t
index = value[1];UINT8*offset = _source + value[2];//switch(GET_ELEMENT_TYPE(des)){case UNION_STYPE:{UINT32
choice;//choice = GetSelector(source, mst->values, des);retVal += MarshalUnion(index, offset, buffer, size, choice);
break;}
case ARRAY_STYPE:{UINT32
count;//
count = GetSelector(source, mst->values, des);retVal += ArrayMarshal(index, offset, buffer, size, count);
break;}
case SIMPLE_STYPE:
default:{// This is either another structure or a simple typeretVal += Marshal(index, offset, buffer, size);break;}}}
break;}
case TPM2B_MTYPE:{// Get the number of bytes being marshaled
INT32
val = (int32_t)*((UINT16 *)source);//
retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size);// This is a standard 2B with a byte buffer
retVal += MarshalBytes(((TPM2B *)_source)->buffer, buffer, size, val);
break;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 520
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarycase TPM2BS_MTYPE: // A structure in a TPM2B{
Tpm2bsMarshal_mst*m2bst = (Tpm2bsMarshal_mst *)sel;
UINT8*offset;UINT16amount;UINT8*marshaledSize;//// Save the address of where the size should go
marshaledSize = *buffer;// marshal the size (checks the space and advanced the pointer)
retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size);// This gets the 'offsetof' the structure to marshal. It was placed in the// modifiers byte because the offset from the start of the TPM2B to the// start of the structure is going to be less than 8 and the modifiers// byte isn't needed for anything else.
offset = _source + (m2bst->modifiers & SIGNED_MASK);// Marshal the structure and get its sizeamount = Marshal(m2bst->dataIndex, offset, buffer, size);// put the size in the space used when the size was marshaled.
if(buffer != NULL)UINT16_TO_BYTE_ARRAY(amount, marshaledSize);
retVal += amount;break;}
case LIST_MTYPE:{
ListMarshal_mst *mlt = ((ListMarshal_mst *)sel);
UINT8*offset = _source + (mlt->modifiers & SIGNED_MASK);
retVal = Marshal(UINT32_MARSHAL_REF, source, buffer, size);
retVal += ArrayMarshal((marshalIndex_t)(mlt->arrayRef), offset,
buffer, size, *((UINT32 *)source));break;}
case NULL_MTYPE:
retVal = 0;
break;
case ERROR_MTYPE:
default:{if(size != NULL)*size = -1;
retVal = 0;
break;}}
return retVal;}#endif // TABLE_DRIVEN_MARSHAL

9.10.8.2

TableMarshalData.c

This file contains the data initializer used for the table-driven marshaling code.
1
2
3
4
5

#include "Tpm.h"#if TABLE_DRIVEN_MARSHAL#include "TableMarshal.h"#include "Marshal.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 521
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

The array marshaling table
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

ArrayMarshal_mst
ArrayLookupTable[] = {ARRAY_MARSHAL_ENTRY(UINT8),
ARRAY_MARSHAL_ENTRY(TPM_CC),
ARRAY_MARSHAL_ENTRY(TPMA_CC),
ARRAY_MARSHAL_ENTRY(TPM_ALG_ID),
ARRAY_MARSHAL_ENTRY(TPM_HANDLE),
ARRAY_MARSHAL_ENTRY(TPM2B_DIGEST),ARRAY_MARSHAL_ENTRY(TPMT_HA),
ARRAY_MARSHAL_ENTRY(TPMS_PCR_SELECTION),ARRAY_MARSHAL_ENTRY(TPMS_ALG_PROPERTY),
ARRAY_MARSHAL_ENTRY(TPMS_TAGGED_PROPERTY),
ARRAY_MARSHAL_ENTRY(TPMS_TAGGED_PCR_SELECT),ARRAY_MARSHAL_ENTRY(TPM_ECC_CURVE),ARRAY_MARSHAL_ENTRY(TPMS_TAGGED_POLICY),ARRAY_MARSHAL_ENTRY(TPMS_ACT_DATA),ARRAY_MARSHAL_ENTRY(TPMS_AC_OUTPUT)};The main marshaling structure
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
62
63
64
65

MarshalData_st MarshalData = {// UINT8_DATA{UINT_MTYPE, 0},// UINT16_DATA{UINT_MTYPE, 1},// UINT32_DATA{UINT_MTYPE, 2},// UINT64_DATA{UINT_MTYPE, 3},// INT8_DATA{UINT_MTYPE, 0 + IS_SIGNED},// INT16_DATA{UINT_MTYPE, 1 + IS_SIGNED},// INT32_DATA{UINT_MTYPE, 2 + IS_SIGNED},// INT64_DATA{UINT_MTYPE, 3 + IS_SIGNED},// UINT0_DATA{NULL_MTYPE, 0},// TPM_ECC_CURVE_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_CURVE,{TPM_ECC_NONE,
RANGE(1, 32, UINT16),(UINT32)((ECC_NIST_P192 << 0) | (ECC_NIST_P224 << 1) | (ECC_NIST_P256 << 2) |(ECC_NIST_P384 << 3) | (ECC_NIST_P521 << 4) | (ECC_BN_P256 << 15) |(ECC_BN_P638 << 16) | (ECC_SM2_P256 << 31))}},// TPM_CLOCK_ADJUST_DATA{MIN_MAX_MTYPE, ONE_BYTES|IS_SIGNED, (UINT8)TPM_RC_VALUE,{RANGE(TPM_CLOCK_COARSE_SLOWER, TPM_CLOCK_COARSE_FASTER, INT8)}},// TPM_EO_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(TPM_EO_EQ, TPM_EO_BITCLEAR, UINT16)}},// TPM_SU_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 2,{TPM_SU_CLEAR, TPM_SU_STATE}},// TPM_SE_DATA{TABLE_MTYPE, ONE_BYTES, (UINT8)TPM_RC_VALUE, 3,{TPM_SE_HMAC, TPM_SE_POLICY, TPM_SE_TRIAL}},// TPM_CAP_DATA{VALUES_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1, 1,{RANGE(TPM_CAP_ALGS, TPM_CAP_ACT, UINT32),
TPM_CAP_VENDOR_PROPERTY}},// TPMA_ALGORITHM_DATA{ATTRIBUTES_MTYPE, FOUR_BYTES, 0xFFFFF8F0},

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 522
December 24, 2020

Part 4: Supporting Routines
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
128
129
130
131

Trusted Platform Module Library// TPMA_OBJECT_DATA{ATTRIBUTES_MTYPE, FOUR_BYTES, 0xFFF0F309},// TPMA_SESSION_DATA{ATTRIBUTES_MTYPE, ONE_BYTES, 0x00000018},// TPMA_ACT_DATA{ATTRIBUTES_MTYPE, FOUR_BYTES, 0xFFFFFFFC},// TPMI_YES_NO_DATA{TABLE_MTYPE, ONE_BYTES, (UINT8)TPM_RC_VALUE, 2,{NO, YES}},// TPMI_DH_OBJECT_DATA{VALUES_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 2, 0,{TPM_RH_NULL,RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32),
RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32)}},// TPMI_DH_PARENT_DATA{VALUES_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 2, 3,{TPM_RH_NULL,RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32),
RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32),
TPM_RH_OWNER, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}},// TPMI_DH_PERSISTENT_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32)}},// TPMI_DH_ENTITY_DATA{VALUES_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 5, 4,{TPM_RH_NULL,RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32),
RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32),
RANGE(NV_INDEX_FIRST, NV_INDEX_LAST, UINT32),
RANGE(PCR_FIRST, PCR_LAST, UINT32),
RANGE(TPM_RH_AUTH_00, TPM_RH_AUTH_FF, UINT32),
TPM_RH_OWNER, TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}},// TPMI_DH_PCR_DATA{MIN_MAX_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE,{TPM_RH_NULL,RANGE(PCR_FIRST, PCR_LAST, UINT32)}},// TPMI_SH_AUTH_SESSION_DATA{VALUES_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 2, 0,{TPM_RS_PW,
RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32),
RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32)}},// TPMI_SH_HMAC_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32)}},// TPMI_SH_POLICY_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32)}},// TPMI_DH_CONTEXT_DATA{VALUES_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 3, 0,{RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32),
RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32),
RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32)}},// TPMI_DH_SAVED_DATA{VALUES_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 2, 3,{RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32),
RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32),
0x80000000, 0x80000001, 0x80000002}},// TPMI_RH_HIERARCHY_DATA{TABLE_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 3,{TPM_RH_NULL,
TPM_RH_OWNER, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}},// TPMI_RH_ENABLES_DATA{TABLE_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 4,{TPM_RH_NULL,
TPM_RH_OWNER, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM, TPM_RH_PLATFORM_NV}},// TPMI_RH_HIERARCHY_AUTH_DATA

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 523
December 24, 2020

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 Library{TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 4,{TPM_RH_OWNER, TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}},// TPMI_RH_HIERARCHY_POLICY_DATA{VALUES_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1, 4,{RANGE(TPM_RH_ACT_0, TPM_RH_ACT_F, UINT32),
TPM_RH_OWNER, TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}},// TPMI_RH_PLATFORM_DATA{TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1,{TPM_RH_PLATFORM}},// TPMI_RH_OWNER_DATA{TABLE_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 1,{TPM_RH_NULL,
TPM_RH_OWNER}},// TPMI_RH_ENDORSEMENT_DATA{TABLE_MTYPE, FOUR_BYTES|TAKES_NULL, (UINT8)TPM_RC_VALUE, 1,{TPM_RH_NULL,
TPM_RH_ENDORSEMENT}},// TPMI_RH_PROVISION_DATA{TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 2,{TPM_RH_OWNER, TPM_RH_PLATFORM}},// TPMI_RH_CLEAR_DATA{TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 2,{TPM_RH_LOCKOUT, TPM_RH_PLATFORM}},// TPMI_RH_NV_AUTH_DATA{VALUES_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1, 2,{RANGE(NV_INDEX_FIRST, NV_INDEX_LAST, UINT32),
TPM_RH_OWNER, TPM_RH_PLATFORM}},// TPMI_RH_LOCKOUT_DATA{TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1,{TPM_RH_LOCKOUT}},// TPMI_RH_NV_INDEX_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(NV_INDEX_FIRST, NV_INDEX_LAST, UINT32)}},// TPMI_RH_AC_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(AC_FIRST, AC_LAST, UINT32)}},// TPMI_RH_ACT_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(TPM_RH_ACT_0, TPM_RH_ACT_F, UINT32)}},// TPMI_ALG_HASH_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_HASH,{TPM_ALG_NULL,RANGE(4, 41, UINT16),(UINT32)((ALG_SHA1 << 0)| (ALG_SHA256 << 7) | (ALG_SHA384 << 8) |(ALG_SHA512 << 9) | (ALG_SM3_256 << 14)),(UINT32)((ALG_SHA3_256 << 3)|(ALG_SHA3_384 << 4)|(ALG_SHA3_512 << 5))}},// TPMI_ALG_ASYM_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_ASYMMETRIC,{TPM_ALG_NULL,RANGE(1, 35, UINT16),(UINT32)((ALG_RSA << 0)),(UINT32)((ALG_ECC << 2))}},// TPMI_ALG_SYM_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_SYMMETRIC,{TPM_ALG_NULL,RANGE(3, 38, UINT16),(UINT32)((ALG_TDES << 0)|(ALG_AES << 3)|(ALG_XOR << 7)|(ALG_SM4 << 16)),(UINT32)((ALG_CAMELLIA << 3))}},// TPMI_ALG_SYM_OBJECT_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_SYMMETRIC,{TPM_ALG_NULL,RANGE(3, 38, UINT16),(UINT32)((ALG_TDES << 0)|(ALG_AES << 3)|(ALG_SM4 << 16)),(UINT32)((ALG_CAMELLIA << 3))}},// TPMI_ALG_SYM_MODE_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_MODE,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 524
December 24, 2020

Part 4: Supporting Routines
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
260
261
262
263

Trusted Platform Module Library{TPM_ALG_NULL,RANGE(63, 68, UINT16),(UINT32)((ALG_CMAC << 0) | (ALG_CTR << 1) | (ALG_OFB << 2) |(ALG_CBC << 3) | (ALG_CFB << 4) | (ALG_ECB << 5))}},// TPMI_ALG_KDF_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_KDF,{TPM_ALG_NULL,RANGE(7, 34, UINT16),(UINT32)((ALG_MGF1 << 0)| (ALG_KDF1_SP800_56A << 25) |(ALG_KDF2 << 26)| (ALG_KDF1_SP800_108 << 27))}},// TPMI_ALG_SIG_SCHEME_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_SCHEME,{TPM_ALG_NULL,RANGE(5, 28, UINT16),(UINT32)((ALG_HMAC << 0)| (ALG_RSASSA << 15) | (ALG_RSAPSS << 17) |(ALG_ECDSA << 19) | (ALG_ECDAA << 21) | (ALG_SM2 << 22)|(ALG_ECSCHNORR << 23))}},// TPMI_ECC_KEY_EXCHANGE_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_SCHEME,{TPM_ALG_NULL,RANGE(25, 29, UINT16),(UINT32)((ALG_ECDH << 0)|(ALG_SM2 << 2)|(ALG_ECMQV << 4))}},// TPMI_ST_COMMAND_TAG_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_BAD_TAG, 2,{TPM_ST_NO_SESSIONS, TPM_ST_SESSIONS}},// TPMI_ALG_MAC_SCHEME_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_SYMMETRIC,{TPM_ALG_NULL,RANGE(4, 63, UINT16),(UINT32)((ALG_SHA1 << 0)| (ALG_SHA256 << 7) | (ALG_SHA384 << 8) |(ALG_SHA512 << 9) | (ALG_SM3_256 << 14)),(UINT32)((ALG_SHA3_256 << 3) | (ALG_SHA3_384 << 4) | (ALG_SHA3_512 << 5) |(ALG_CMAC << 27))}},// TPMI_ALG_CIPHER_MODE_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_MODE,{TPM_ALG_NULL,RANGE(64, 68, UINT16),(UINT32)((ALG_CTR << 0) | (ALG_OFB << 1) | (ALG_CBC << 2) | (ALG_CFB << 3) |(ALG_ECB << 4))}},// TPMS_EMPTY_DATA{STRUCTURE_MTYPE, 1,{SET_ELEMENT_TYPE(SIMPLE_STYPE), UINT0_MARSHAL_REF, 0}},// TPMS_ALGORITHM_DESCRIPTION_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPM_ALG_ID_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DESCRIPTION, alg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPMA_ALGORITHM_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DESCRIPTION, attributes))}},// TPMU_HA_DATA{9, IS_ARRAY_UNION, (UINT16)(offsetof(TPMU_HA_mst, marshalingTypes)),{(UINT32)TPM_ALG_SHA1,(UINT32)TPM_ALG_SHA256,(UINT32)TPM_ALG_SHA384,(UINT32)TPM_ALG_SHA512,(UINT32)TPM_ALG_SM3_256, (UINT32)TPM_ALG_SHA3_256,(UINT32)TPM_ALG_SHA3_384, (UINT32)TPM_ALG_SHA3_512, (UINT32)TPM_ALG_NULL},{(UINT16)(SHA1_DIGEST_SIZE),(UINT16)(SHA256_DIGEST_SIZE),(UINT16)(SHA384_DIGEST_SIZE),(UINT16)(SHA512_DIGEST_SIZE),(UINT16)(SM3_256_DIGEST_SIZE), (UINT16)(SHA3_256_DIGEST_SIZE),(UINT16)(SHA3_384_DIGEST_SIZE), (UINT16)(SHA3_512_DIGEST_SIZE),(UINT16)(0)}},// TPMT_HA_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMT_HA, hashAlg)),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 525
December 24, 2020

Part 4: Supporting Routines
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
326
327
328
329

Trusted Platform Module Library

SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_HA_MARSHAL_REF,(UINT16)(offsetof(TPMT_HA, digest))}},// TPM2B_DIGEST_DATA{TPM2B_MTYPE, Type00_MARSHAL_REF},// TPM2B_DATA_DATA{TPM2B_MTYPE, Type01_MARSHAL_REF},// TPM2B_EVENT_DATA{TPM2B_MTYPE, Type02_MARSHAL_REF},// TPM2B_MAX_BUFFER_DATA{TPM2B_MTYPE, Type03_MARSHAL_REF},// TPM2B_MAX_NV_BUFFER_DATA{TPM2B_MTYPE, Type04_MARSHAL_REF},// TPM2B_TIMEOUT_DATA{TPM2B_MTYPE, Type05_MARSHAL_REF},// TPM2B_IV_DATA{TPM2B_MTYPE, Type06_MARSHAL_REF},// NULL_UNION_DATA{0},// TPM2B_NAME_DATA{TPM2B_MTYPE, Type07_MARSHAL_REF},// TPMS_PCR_SELECT_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),
Type08_MARSHAL_REF,(UINT16)(offsetof(TPMS_PCR_SELECT, sizeofSelect)),
SET_ELEMENT_TYPE(ARRAY_STYPE)|SET_ELEMENT_NUMBER(0),UINT8_ARRAY_MARSHAL_INDEX,(UINT16)(offsetof(TPMS_PCR_SELECT, pcrSelect))}},// TPMS_PCR_SELECTION_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_PCR_SELECTION, hash)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),
Type08_MARSHAL_REF,(UINT16)(offsetof(TPMS_PCR_SELECTION, sizeofSelect)),
SET_ELEMENT_TYPE(ARRAY_STYPE)|SET_ELEMENT_NUMBER(1),UINT8_ARRAY_MARSHAL_INDEX,(UINT16)(offsetof(TPMS_PCR_SELECTION, pcrSelect))}},// TPMT_TK_CREATION_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),
Type10_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_CREATION, tag)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_RH_HIERARCHY_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMT_TK_CREATION, hierarchy)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_CREATION, digest))}},// TPMT_TK_VERIFIED_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),
Type11_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_VERIFIED, tag)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_RH_HIERARCHY_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMT_TK_VERIFIED, hierarchy)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_VERIFIED, digest))}},// TPMT_TK_AUTH_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),
Type12_MARSHAL_REF,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 526
December 24, 2020

Part 4: Supporting Routines
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
393
394
395

Trusted Platform Module Library(UINT16)(offsetof(TPMT_TK_AUTH, tag)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_RH_HIERARCHY_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMT_TK_AUTH, hierarchy)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_AUTH, digest))}},// TPMT_TK_HASHCHECK_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),
Type13_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_HASHCHECK, tag)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_RH_HIERARCHY_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMT_TK_HASHCHECK, hierarchy)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMT_TK_HASHCHECK, digest))}},// TPMS_ALG_PROPERTY_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPM_ALG_ID_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALG_PROPERTY, alg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPMA_ALGORITHM_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALG_PROPERTY, algProperties))}},// TPMS_TAGGED_PROPERTY_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPM_PT_MARSHAL_REF,(UINT16)(offsetof(TPMS_TAGGED_PROPERTY, property)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_TAGGED_PROPERTY, value))}},// TPMS_TAGGED_PCR_SELECT_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPM_PT_PCR_MARSHAL_REF,(UINT16)(offsetof(TPMS_TAGGED_PCR_SELECT, tag)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),
Type08_MARSHAL_REF,(UINT16)(offsetof(TPMS_TAGGED_PCR_SELECT, sizeofSelect)),
SET_ELEMENT_TYPE(ARRAY_STYPE)|SET_ELEMENT_NUMBER(1),UINT8_ARRAY_MARSHAL_INDEX,(UINT16)(offsetof(TPMS_TAGGED_PCR_SELECT, pcrSelect))}},// TPMS_TAGGED_POLICY_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPM_HANDLE_MARSHAL_REF,(UINT16)(offsetof(TPMS_TAGGED_POLICY, handle)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_HA_MARSHAL_REF,(UINT16)(offsetof(TPMS_TAGGED_POLICY, policyHash))}},// TPMS_ACT_DATA_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPM_HANDLE_MARSHAL_REF,(UINT16)(offsetof(TPMS_ACT_DATA, handle)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_ACT_DATA, timeout)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPMA_ACT_MARSHAL_REF,(UINT16)(offsetof(TPMS_ACT_DATA, attributes))}},// TPML_CC_DATA{LIST_MTYPE,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 527
December 24, 2020

Part 4: Supporting Routines
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
454
455
456
457
458
459
460
461

Trusted Platform Module Library(UINT8)(offsetof(TPML_CC, commandCodes)),
Type15_MARSHAL_REF,
TPM_CC_ARRAY_MARSHAL_INDEX},// TPML_CCA_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_CCA, commandAttributes)),
Type15_MARSHAL_REF,
TPMA_CC_ARRAY_MARSHAL_INDEX},// TPML_ALG_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_ALG, algorithms)),
Type17_MARSHAL_REF,
TPM_ALG_ID_ARRAY_MARSHAL_INDEX},// TPML_HANDLE_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_HANDLE, handle)),Type18_MARSHAL_REF,
TPM_HANDLE_ARRAY_MARSHAL_INDEX},// TPML_DIGEST_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_DIGEST, digests)),
Type19_MARSHAL_REF,
TPM2B_DIGEST_ARRAY_MARSHAL_INDEX},// TPML_DIGEST_VALUES_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_DIGEST_VALUES, digests)),
Type20_MARSHAL_REF,
TPMT_HA_ARRAY_MARSHAL_INDEX},// TPML_PCR_SELECTION_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_PCR_SELECTION, pcrSelections)),
Type20_MARSHAL_REF,
TPMS_PCR_SELECTION_ARRAY_MARSHAL_INDEX},// TPML_ALG_PROPERTY_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_ALG_PROPERTY, algProperties)),
Type22_MARSHAL_REF,
TPMS_ALG_PROPERTY_ARRAY_MARSHAL_INDEX},// TPML_TAGGED_TPM_PROPERTY_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_TAGGED_TPM_PROPERTY, tpmProperty)),
Type23_MARSHAL_REF,
TPMS_TAGGED_PROPERTY_ARRAY_MARSHAL_INDEX},// TPML_TAGGED_PCR_PROPERTY_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_TAGGED_PCR_PROPERTY, pcrProperty)),
Type24_MARSHAL_REF,
TPMS_TAGGED_PCR_SELECT_ARRAY_MARSHAL_INDEX},// TPML_ECC_CURVE_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_ECC_CURVE, eccCurves)),
Type25_MARSHAL_REF,
TPM_ECC_CURVE_ARRAY_MARSHAL_INDEX},// TPML_TAGGED_POLICY_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_TAGGED_POLICY, policies)),
Type26_MARSHAL_REF,
TPMS_TAGGED_POLICY_ARRAY_MARSHAL_INDEX},// TPML_ACT_DATA_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_ACT_DATA, actData)),
Type27_MARSHAL_REF,
TPMS_ACT_DATA_ARRAY_MARSHAL_INDEX},// TPMU_CAPABILITIES_DATA{11, 0, (UINT16)(offsetof(TPMU_CAPABILITIES_mst, marshalingTypes)),{(UINT32)TPM_CAP_ALGS,(UINT32)TPM_CAP_HANDLES,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 528
December 24, 2020

Part 4: Supporting Routines
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
515
516
517
518
519
520
521
522
523
524
525
526
527

Trusted Platform Module Library(UINT32)TPM_CAP_COMMANDS,(UINT32)TPM_CAP_PP_COMMANDS,(UINT32)TPM_CAP_AUDIT_COMMANDS, (UINT32)TPM_CAP_PCRS,(UINT32)TPM_CAP_TPM_PROPERTIES, (UINT32)TPM_CAP_PCR_PROPERTIES,(UINT32)TPM_CAP_ECC_CURVES,(UINT32)TPM_CAP_AUTH_POLICIES,(UINT32)TPM_CAP_ACT},{(UINT16)(TPML_ALG_PROPERTY_MARSHAL_REF),(UINT16)(TPML_HANDLE_MARSHAL_REF),(UINT16)(TPML_CCA_MARSHAL_REF),(UINT16)(TPML_CC_MARSHAL_REF),(UINT16)(TPML_CC_MARSHAL_REF),(UINT16)(TPML_PCR_SELECTION_MARSHAL_REF),(UINT16)(TPML_TAGGED_TPM_PROPERTY_MARSHAL_REF),(UINT16)(TPML_TAGGED_PCR_PROPERTY_MARSHAL_REF),(UINT16)(TPML_ECC_CURVE_MARSHAL_REF),(UINT16)(TPML_TAGGED_POLICY_MARSHAL_REF),(UINT16)(TPML_ACT_DATA_MARSHAL_REF)}},// TPMS_CAPABILITY_DATA_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPM_CAP_MARSHAL_REF,(UINT16)(offsetof(TPMS_CAPABILITY_DATA, capability)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_CAPABILITIES_MARSHAL_REF,(UINT16)(offsetof(TPMS_CAPABILITY_DATA, data))}},// TPMS_CLOCK_INFO_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(EIGHT_BYTES),UINT64_MARSHAL_REF,(UINT16)(offsetof(TPMS_CLOCK_INFO, clock)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_CLOCK_INFO, resetCount)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_CLOCK_INFO, restartCount)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),TPMI_YES_NO_MARSHAL_REF,(UINT16)(offsetof(TPMS_CLOCK_INFO, safe))}},// TPMS_TIME_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(EIGHT_BYTES),UINT64_MARSHAL_REF,(UINT16)(offsetof(TPMS_TIME_INFO, time)),SET_ELEMENT_TYPE(SIMPLE_STYPE),TPMS_CLOCK_INFO_MARSHAL_REF,(UINT16)(offsetof(TPMS_TIME_INFO, clockInfo))}},// TPMS_TIME_ATTEST_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),TPMS_TIME_INFO_MARSHAL_REF,(UINT16)(offsetof(TPMS_TIME_ATTEST_INFO, time)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(EIGHT_BYTES),UINT64_MARSHAL_REF,(UINT16)(offsetof(TPMS_TIME_ATTEST_INFO, firmwareVersion))}},// TPMS_CERTIFY_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_CERTIFY_INFO, name)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_CERTIFY_INFO, qualifiedName))}},// TPMS_QUOTE_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 529
December 24, 2020

Part 4: Supporting Routines
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
581
582
583
584
585
586
587
588
589
590
591
592
593

Trusted Platform Module Library

TPML_PCR_SELECTION_MARSHAL_REF,(UINT16)(offsetof(TPMS_QUOTE_INFO, pcrSelect)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_QUOTE_INFO, pcrDigest))}},// TPMS_COMMAND_AUDIT_INFO_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(EIGHT_BYTES),UINT64_MARSHAL_REF,(UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, auditCounter)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPM_ALG_ID_MARSHAL_REF,(UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, digestAlg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, auditDigest)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, commandDigest))}},// TPMS_SESSION_AUDIT_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),TPMI_YES_NO_MARSHAL_REF,(UINT16)(offsetof(TPMS_SESSION_AUDIT_INFO, exclusiveSession)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_SESSION_AUDIT_INFO, sessionDigest))}},// TPMS_CREATION_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_INFO, objectName)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_INFO, creationHash))}},// TPMS_NV_CERTIFY_INFO_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_CERTIFY_INFO, indexName)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),UINT16_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_CERTIFY_INFO, offset)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_MAX_NV_BUFFER_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_CERTIFY_INFO, nvContents))}},// TPMS_NV_DIGEST_CERTIFY_INFO_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_DIGEST_CERTIFY_INFO, indexName)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_DIGEST_CERTIFY_INFO, nvDigest))}},// TPMI_ST_ATTEST_DATA{VALUES_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 1, 1,{RANGE(TPM_ST_ATTEST_NV, TPM_ST_ATTEST_CREATION, UINT16),
TPM_ST_ATTEST_NV_DIGEST}},// TPMU_ATTEST_DATA{8, 0, (UINT16)(offsetof(TPMU_ATTEST_mst, marshalingTypes)),{(UINT32)TPM_ST_ATTEST_CERTIFY,(UINT32)TPM_ST_ATTEST_CREATION,(UINT32)TPM_ST_ATTEST_QUOTE,(UINT32)TPM_ST_ATTEST_COMMAND_AUDIT,(UINT32)TPM_ST_ATTEST_SESSION_AUDIT, (UINT32)TPM_ST_ATTEST_TIME,(UINT32)TPM_ST_ATTEST_NV,(UINT32)TPM_ST_ATTEST_NV_DIGEST},{(UINT16)(TPMS_CERTIFY_INFO_MARSHAL_REF),(UINT16)(TPMS_CREATION_INFO_MARSHAL_REF),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 530
December 24, 2020

Part 4: Supporting Routines
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
650
651
652
653
654
655
656
657
658
659

Trusted Platform Module Library(UINT16)(TPMS_QUOTE_INFO_MARSHAL_REF),(UINT16)(TPMS_COMMAND_AUDIT_INFO_MARSHAL_REF),(UINT16)(TPMS_SESSION_AUDIT_INFO_MARSHAL_REF),(UINT16)(TPMS_TIME_ATTEST_INFO_MARSHAL_REF),(UINT16)(TPMS_NV_CERTIFY_INFO_MARSHAL_REF),(UINT16)(TPMS_NV_DIGEST_CERTIFY_INFO_MARSHAL_REF)}},// TPMS_ATTEST_DATA{STRUCTURE_MTYPE, 7, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPM_CONSTANTS32_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, magic)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ST_ATTEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, type)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, qualifiedSigner)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DATA_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, extraData)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),TPMS_CLOCK_INFO_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, clockInfo)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(EIGHT_BYTES),UINT64_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, firmwareVersion)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(1),TPMU_ATTEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_ATTEST, attested))}},// TPM2B_ATTEST_DATA{TPM2B_MTYPE, Type28_MARSHAL_REF},// TPMS_AUTH_COMMAND_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_SH_AUTH_SESSION_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_AUTH_COMMAND, sessionHandle)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NONCE_MARSHAL_REF,(UINT16)(offsetof(TPMS_AUTH_COMMAND, nonce)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),
TPMA_SESSION_MARSHAL_REF,(UINT16)(offsetof(TPMS_AUTH_COMMAND, sessionAttributes)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_AUTH_MARSHAL_REF,(UINT16)(offsetof(TPMS_AUTH_COMMAND, hmac))}},// TPMS_AUTH_RESPONSE_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NONCE_MARSHAL_REF,(UINT16)(offsetof(TPMS_AUTH_RESPONSE, nonce)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),
TPMA_SESSION_MARSHAL_REF,(UINT16)(offsetof(TPMS_AUTH_RESPONSE, sessionAttributes)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_AUTH_MARSHAL_REF,(UINT16)(offsetof(TPMS_AUTH_RESPONSE, hmac))}},// TPMI_TDES_KEY_BITS_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 1,{128*TDES_128}},// TPMI_AES_KEY_BITS_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 3,{192*AES_192, 128*AES_128, 256*AES_256}},// TPMI_SM4_KEY_BITS_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 1,{128*SM4_128}},

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 531
December 24, 2020

Part 4: Supporting Routines
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
724
725

Trusted Platform Module Library// TPMI_CAMELLIA_KEY_BITS_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 3,{192*CAMELLIA_192, 128*CAMELLIA_128, 256*CAMELLIA_256}},// TPMU_SYM_KEY_BITS_DATA{6, 0, (UINT16)(offsetof(TPMU_SYM_KEY_BITS_mst, marshalingTypes)),{(UINT32)TPM_ALG_TDES,(UINT32)TPM_ALG_AES,(UINT32)TPM_ALG_SM4,(UINT32)TPM_ALG_CAMELLIA, (UINT32)TPM_ALG_XOR,(UINT32)TPM_ALG_NULL},{(UINT16)(TPMI_TDES_KEY_BITS_MARSHAL_REF),(UINT16)(TPMI_AES_KEY_BITS_MARSHAL_REF),(UINT16)(TPMI_SM4_KEY_BITS_MARSHAL_REF),(UINT16)(TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF),(UINT16)(TPMI_ALG_HASH_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMU_SYM_MODE_DATA{6, 0, (UINT16)(offsetof(TPMU_SYM_MODE_mst, marshalingTypes)),{(UINT32)TPM_ALG_TDES,(UINT32)TPM_ALG_AES,(UINT32)TPM_ALG_SM4,(UINT32)TPM_ALG_CAMELLIA, (UINT32)TPM_ALG_XOR,(UINT32)TPM_ALG_NULL},{(UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF|NULL_FLAG),(UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF|NULL_FLAG),(UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF|NULL_FLAG),(UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF|NULL_FLAG),(UINT16)(UINT0_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMT_SYM_DEF_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_SYM_MARSHAL_REF,(UINT16)(offsetof(TPMT_SYM_DEF, algorithm)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SYM_KEY_BITS_MARSHAL_REF,(UINT16)(offsetof(TPMT_SYM_DEF, keyBits)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SYM_MODE_MARSHAL_REF,(UINT16)(offsetof(TPMT_SYM_DEF, mode))}},// TPMT_SYM_DEF_OBJECT_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_SYM_OBJECT_MARSHAL_REF,(UINT16)(offsetof(TPMT_SYM_DEF_OBJECT, algorithm)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SYM_KEY_BITS_MARSHAL_REF,(UINT16)(offsetof(TPMT_SYM_DEF_OBJECT, keyBits)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SYM_MODE_MARSHAL_REF,(UINT16)(offsetof(TPMT_SYM_DEF_OBJECT, mode))}},// TPM2B_SYM_KEY_DATA{TPM2B_MTYPE, Type29_MARSHAL_REF},// TPMS_SYMCIPHER_PARMS_DATA{STRUCTURE_MTYPE, 1, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_SYM_DEF_OBJECT_MARSHAL_REF,(UINT16)(offsetof(TPMS_SYMCIPHER_PARMS, sym))}},// TPM2B_LABEL_DATA{TPM2B_MTYPE, Type30_MARSHAL_REF},// TPMS_DERIVE_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_LABEL_MARSHAL_REF,(UINT16)(offsetof(TPMS_DERIVE, label)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_LABEL_MARSHAL_REF,(UINT16)(offsetof(TPMS_DERIVE, context))}},// TPM2B_DERIVE_DATA{TPM2B_MTYPE, Type31_MARSHAL_REF},

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 532
December 24, 2020

Part 4: Supporting Routines
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
790
791

Trusted Platform Module Library// TPM2B_SENSITIVE_DATA_DATA{TPM2B_MTYPE, Type32_MARSHAL_REF},// TPMS_SENSITIVE_CREATE_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_AUTH_MARSHAL_REF,(UINT16)(offsetof(TPMS_SENSITIVE_CREATE, userAuth)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_SENSITIVE_DATA_MARSHAL_REF,(UINT16)(offsetof(TPMS_SENSITIVE_CREATE, data))}},// TPM2B_SENSITIVE_CREATE_DATA{TPM2BS_MTYPE,(UINT8)(offsetof(TPM2B_SENSITIVE_CREATE, sensitive))|SIZE_EQUAL,UINT16_MARSHAL_REF,
TPMS_SENSITIVE_CREATE_MARSHAL_REF},// TPMS_SCHEME_HASH_DATA{STRUCTURE_MTYPE, 1, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_SCHEME_HASH, hashAlg))}},// TPMS_SCHEME_ECDAA_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_SCHEME_ECDAA, hashAlg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),UINT16_MARSHAL_REF,(UINT16)(offsetof(TPMS_SCHEME_ECDAA, count))}},// TPMI_ALG_KEYEDHASH_SCHEME_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_VALUE,{TPM_ALG_NULL,RANGE(5, 10, UINT16),(UINT32)((ALG_HMAC << 0)|(ALG_XOR << 5))}},// TPMS_SCHEME_XOR_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_SCHEME_XOR, hashAlg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_KDF_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_SCHEME_XOR, kdf))}},// TPMU_SCHEME_KEYEDHASH_DATA{3, 0, (UINT16)(offsetof(TPMU_SCHEME_KEYEDHASH_mst, marshalingTypes)),{(UINT32)TPM_ALG_HMAC, (UINT32)TPM_ALG_XOR, (UINT32)TPM_ALG_NULL},{(UINT16)(TPMS_SCHEME_HMAC_MARSHAL_REF),(UINT16)(TPMS_SCHEME_XOR_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMT_KEYEDHASH_SCHEME_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_KEYEDHASH_SCHEME, scheme)),SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SCHEME_KEYEDHASH_MARSHAL_REF,(UINT16)(offsetof(TPMT_KEYEDHASH_SCHEME, details))}},// TPMU_SIG_SCHEME_DATA{8, 0, (UINT16)(offsetof(TPMU_SIG_SCHEME_mst, marshalingTypes)),{(UINT32)TPM_ALG_ECDAA,(UINT32)TPM_ALG_RSASSA,(UINT32)TPM_ALG_RSAPSS,(UINT32)TPM_ALG_ECDSA,(UINT32)TPM_ALG_SM2,(UINT32)TPM_ALG_ECSCHNORR,(UINT32)TPM_ALG_HMAC,(UINT32)TPM_ALG_NULL},{(UINT16)(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 533
December 24, 2020

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

Trusted Platform Module Library(UINT16)(TPMS_SIG_SCHEME_SM2_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF),(UINT16)(TPMS_SCHEME_HMAC_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMT_SIG_SCHEME_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_SIG_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_SIG_SCHEME, scheme)),SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SIG_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_SIG_SCHEME, details))}},// TPMU_KDF_SCHEME_DATA{5, 0, (UINT16)(offsetof(TPMU_KDF_SCHEME_mst, marshalingTypes)),{(UINT32)TPM_ALG_MGF1,(UINT32)TPM_ALG_KDF1_SP800_56A,(UINT32)TPM_ALG_KDF2,(UINT32)TPM_ALG_KDF1_SP800_108,(UINT32)TPM_ALG_NULL},{(UINT16)(TPMS_KDF_SCHEME_MGF1_MARSHAL_REF),(UINT16)(TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF),(UINT16)(TPMS_KDF_SCHEME_KDF2_MARSHAL_REF),(UINT16)(TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMT_KDF_SCHEME_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_KDF_MARSHAL_REF,(UINT16)(offsetof(TPMT_KDF_SCHEME, scheme)),SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_KDF_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_KDF_SCHEME, details))}},// TPMI_ALG_ASYM_SCHEME_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_VALUE,{TPM_ALG_NULL,RANGE(20, 29, UINT16),(UINT32)((ALG_RSASSA << 0)| (ALG_RSAES << 1)| (ALG_RSAPSS << 2)|(ALG_OAEP << 3)| (ALG_ECDSA << 4)| (ALG_ECDH << 5)|(ALG_ECDAA << 6)| (ALG_SM2 << 7)| (ALG_ECSCHNORR << 8) |(ALG_ECMQV << 9))}},// TPMU_ASYM_SCHEME_DATA{11, 0, (UINT16)(offsetof(TPMU_ASYM_SCHEME_mst, marshalingTypes)),{(UINT32)TPM_ALG_ECDH,(UINT32)TPM_ALG_ECMQV,(UINT32)TPM_ALG_ECDAA,(UINT32)TPM_ALG_RSASSA,(UINT32)TPM_ALG_RSAPSS,(UINT32)TPM_ALG_ECDSA,(UINT32)TPM_ALG_SM2,(UINT32)TPM_ALG_ECSCHNORR,(UINT32)TPM_ALG_RSAES,(UINT32)TPM_ALG_OAEP,(UINT32)TPM_ALG_NULL},{(UINT16)(TPMS_KEY_SCHEME_ECDH_MARSHAL_REF),(UINT16)(TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_SM2_MARSHAL_REF),(UINT16)(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF),(UINT16)(TPMS_ENC_SCHEME_RSAES_MARSHAL_REF),(UINT16)(TPMS_ENC_SCHEME_OAEP_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMI_ALG_RSA_SCHEME_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_VALUE,{TPM_ALG_NULL,RANGE(20, 23, UINT16),(UINT32)((ALG_RSASSA << 0)|(ALG_RSAES << 1)|(ALG_RSAPSS << 2)|(ALG_OAEP << 3))}},// TPMT_RSA_SCHEME_DATA

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 534
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_RSA_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_RSA_SCHEME, scheme)),SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_ASYM_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_RSA_SCHEME, details))}},// TPMI_ALG_RSA_DECRYPT_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_VALUE,{TPM_ALG_NULL,RANGE(21, 23, UINT16),(UINT32)((ALG_RSAES << 0)|(ALG_OAEP << 2))}},// TPMT_RSA_DECRYPT_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_RSA_DECRYPT_MARSHAL_REF,(UINT16)(offsetof(TPMT_RSA_DECRYPT, scheme)),SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_ASYM_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_RSA_DECRYPT, details))}},// TPM2B_PUBLIC_KEY_RSA_DATA{TPM2B_MTYPE, Type33_MARSHAL_REF},// TPMI_RSA_KEY_BITS_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 3,{3072*RSA_3072, 1024*RSA_1024, 2048*RSA_2048}},// TPM2B_PRIVATE_KEY_RSA_DATA{TPM2B_MTYPE, Type34_MARSHAL_REF},// TPM2B_ECC_PARAMETER_DATA{TPM2B_MTYPE, Type35_MARSHAL_REF},// TPMS_ECC_POINT_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ECC_POINT, x)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ECC_POINT, y))}},// TPM2B_ECC_POINT_DATA{TPM2BS_MTYPE,(UINT8)(offsetof(TPM2B_ECC_POINT, point))|SIZE_EQUAL,UINT16_MARSHAL_REF,
TPMS_ECC_POINT_MARSHAL_REF},// TPMI_ALG_ECC_SCHEME_DATA{MIN_MAX_MTYPE, TWO_BYTES|TAKES_NULL|HAS_BITS, (UINT8)TPM_RC_SCHEME,{TPM_ALG_NULL,RANGE(24, 29, UINT16),(UINT32)((ALG_ECDSA << 0)| (ALG_ECDH << 1)| (ALG_ECDAA << 2)|(ALG_SM2 << 3)| (ALG_ECSCHNORR << 4) | (ALG_ECMQV << 5))}},// TPMI_ECC_CURVE_DATA{MIN_MAX_MTYPE, TWO_BYTES|HAS_BITS, (UINT8)TPM_RC_CURVE,{RANGE(1, 32, UINT16),(UINT32)((ECC_NIST_P192 << 0) | (ECC_NIST_P224 << 1) | (ECC_NIST_P256 << 2) |(ECC_NIST_P384 << 3) | (ECC_NIST_P521 << 4) | (ECC_BN_P256 << 15) |(ECC_BN_P638 << 16) | (ECC_SM2_P256 << 31))}},// TPMT_ECC_SCHEME_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_ECC_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_ECC_SCHEME, scheme)),SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_ASYM_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_ECC_SCHEME, details))}},// TPMS_ALGORITHM_DETAIL_ECC_DATA{STRUCTURE_MTYPE, 11, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),
TPM_ECC_CURVE_MARSHAL_REF,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 535
December 24, 2020

Part 4: Supporting Routines
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
981
982
983
984
985
986
987
988
989

Trusted Platform Module Library(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, curveID)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),UINT16_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, keySize)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_KDF_SCHEME_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, kdf)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_ECC_SCHEME_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, sign)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, p)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, a)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, b)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, gX)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, gY)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, n)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, h))}},// TPMS_SIGNATURE_RSA_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_SIGNATURE_RSA, hash)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF,(UINT16)(offsetof(TPMS_SIGNATURE_RSA, sig))}},// TPMS_SIGNATURE_ECC_DATA{STRUCTURE_MTYPE, 3, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_SIGNATURE_ECC, hash)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_SIGNATURE_ECC, signatureR)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_ECC_PARAMETER_MARSHAL_REF,(UINT16)(offsetof(TPMS_SIGNATURE_ECC, signatureS))}},// TPMU_SIGNATURE_DATA{8, 0, (UINT16)(offsetof(TPMU_SIGNATURE_mst, marshalingTypes)),{(UINT32)TPM_ALG_ECDAA,(UINT32)TPM_ALG_RSASSA,(UINT32)TPM_ALG_RSAPSS,(UINT32)TPM_ALG_ECDSA,(UINT32)TPM_ALG_SM2,(UINT32)TPM_ALG_ECSCHNORR,(UINT32)TPM_ALG_HMAC,(UINT32)TPM_ALG_NULL},{(UINT16)(TPMS_SIGNATURE_ECDAA_MARSHAL_REF),(UINT16)(TPMS_SIGNATURE_RSASSA_MARSHAL_REF),(UINT16)(TPMS_SIGNATURE_RSAPSS_MARSHAL_REF),(UINT16)(TPMS_SIGNATURE_ECDSA_MARSHAL_REF),(UINT16)(TPMS_SIGNATURE_SM2_MARSHAL_REF),(UINT16)(TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF),(UINT16)(TPMT_HA_MARSHAL_REF),(UINT16)(UINT0_MARSHAL_REF)}},// TPMT_SIGNATURE_DATA

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 536
December 24, 2020

Part 4: Supporting Routines
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
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055

Trusted Platform Module Library{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_SIG_SCHEME_MARSHAL_REF,(UINT16)(offsetof(TPMT_SIGNATURE, sigAlg)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SIGNATURE_MARSHAL_REF,(UINT16)(offsetof(TPMT_SIGNATURE, signature))}},// TPMU_ENCRYPTED_SECRET_DATA{4, IS_ARRAY_UNION, (UINT16)(offsetof(TPMU_ENCRYPTED_SECRET_mst, marshalingTypes)),{(UINT32)TPM_ALG_ECC,(UINT32)TPM_ALG_RSA,(UINT32)TPM_ALG_SYMCIPHER, (UINT32)TPM_ALG_KEYEDHASH},{(UINT16)(sizeof(TPMS_ECC_POINT)), (UINT16)(MAX_RSA_KEY_BYTES),(UINT16)(sizeof(TPM2B_DIGEST)),(UINT16)(sizeof(TPM2B_DIGEST))}},// TPM2B_ENCRYPTED_SECRET_DATA{TPM2B_MTYPE, Type36_MARSHAL_REF},// TPMI_ALG_PUBLIC_DATA{MIN_MAX_MTYPE, TWO_BYTES|HAS_BITS, (UINT8)TPM_RC_TYPE,{RANGE(1, 37, UINT16),(UINT32)((ALG_RSA << 0)|(ALG_KEYEDHASH << 7)),(UINT32)((ALG_ECC << 2)|(ALG_SYMCIPHER << 4))}},// TPMU_PUBLIC_ID_DATA{4, 0, (UINT16)(offsetof(TPMU_PUBLIC_ID_mst, marshalingTypes)),{(UINT32)TPM_ALG_KEYEDHASH, (UINT32)TPM_ALG_SYMCIPHER,(UINT32)TPM_ALG_RSA,(UINT32)TPM_ALG_ECC},{(UINT16)(TPM2B_DIGEST_MARSHAL_REF),(UINT16)(TPM2B_DIGEST_MARSHAL_REF),(UINT16)(TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF),(UINT16)(TPMS_ECC_POINT_MARSHAL_REF)}},// TPMS_KEYEDHASH_PARMS_DATA{STRUCTURE_MTYPE, 1, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_KEYEDHASH_SCHEME_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_KEYEDHASH_PARMS, scheme))}},// TPMS_RSA_PARMS_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_SYM_DEF_OBJECT_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_RSA_PARMS, symmetric)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_RSA_SCHEME_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_RSA_PARMS, scheme)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_RSA_KEY_BITS_MARSHAL_REF,(UINT16)(offsetof(TPMS_RSA_PARMS, keyBits)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_RSA_PARMS, exponent))}},// TPMS_ECC_PARMS_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_SYM_DEF_OBJECT_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_ECC_PARMS, symmetric)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_ECC_SCHEME_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_ECC_PARMS, scheme)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ECC_CURVE_MARSHAL_REF,(UINT16)(offsetof(TPMS_ECC_PARMS, curveID)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPMT_KDF_SCHEME_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_ECC_PARMS, kdf))}},// TPMU_PUBLIC_PARMS_DATA{4, 0, (UINT16)(offsetof(TPMU_PUBLIC_PARMS_mst, marshalingTypes)),{(UINT32)TPM_ALG_KEYEDHASH, (UINT32)TPM_ALG_SYMCIPHER,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 537
December 24, 2020

Part 4: Supporting Routines
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
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

Trusted Platform Module Library(UINT32)TPM_ALG_RSA,(UINT32)TPM_ALG_ECC},{(UINT16)(TPMS_KEYEDHASH_PARMS_MARSHAL_REF),(UINT16)(TPMS_SYMCIPHER_PARMS_MARSHAL_REF),(UINT16)(TPMS_RSA_PARMS_MARSHAL_REF),(UINT16)(TPMS_ECC_PARMS_MARSHAL_REF)}},// TPMT_PUBLIC_PARMS_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_PUBLIC_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC_PARMS, type)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_PUBLIC_PARMS_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC_PARMS, parameters))}},// TPMT_PUBLIC_DATA{STRUCTURE_MTYPE, 6, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_PUBLIC_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC, type)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES)|ELEMENT_PROPAGATE,TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC, nameAlg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPMA_OBJECT_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC, objectAttributes)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC, authPolicy)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_PUBLIC_PARMS_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC, parameters)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_PUBLIC_ID_MARSHAL_REF,(UINT16)(offsetof(TPMT_PUBLIC, unique))}},// TPM2B_PUBLIC_DATA{TPM2BS_MTYPE,(UINT8)(offsetof(TPM2B_PUBLIC, publicArea))|SIZE_EQUAL|ELEMENT_PROPAGATE,UINT16_MARSHAL_REF,
TPMT_PUBLIC_MARSHAL_REF},// TPM2B_TEMPLATE_DATA{TPM2B_MTYPE, Type37_MARSHAL_REF},// TPM2B_PRIVATE_VENDOR_SPECIFIC_DATA{TPM2B_MTYPE, Type38_MARSHAL_REF},// TPMU_SENSITIVE_COMPOSITE_DATA{4, 0, (UINT16)(offsetof(TPMU_SENSITIVE_COMPOSITE_mst, marshalingTypes)),{(UINT32)TPM_ALG_RSA,(UINT32)TPM_ALG_ECC,(UINT32)TPM_ALG_KEYEDHASH, (UINT32)TPM_ALG_SYMCIPHER},{(UINT16)(TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF),(UINT16)(TPM2B_ECC_PARAMETER_MARSHAL_REF),(UINT16)(TPM2B_SENSITIVE_DATA_MARSHAL_REF),(UINT16)(TPM2B_SYM_KEY_MARSHAL_REF)}},// TPMT_SENSITIVE_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_PUBLIC_MARSHAL_REF,(UINT16)(offsetof(TPMT_SENSITIVE, sensitiveType)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_AUTH_MARSHAL_REF,(UINT16)(offsetof(TPMT_SENSITIVE, authValue)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMT_SENSITIVE, seedValue)),
SET_ELEMENT_TYPE(UNION_STYPE)|SET_ELEMENT_NUMBER(0),TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF,(UINT16)(offsetof(TPMT_SENSITIVE, sensitive))}},

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 538
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library// TPM2B_SENSITIVE_DATA{TPM2BS_MTYPE,(UINT8)(offsetof(TPM2B_SENSITIVE, sensitiveArea)),
UINT16_MARSHAL_REF,
TPMT_SENSITIVE_MARSHAL_REF},// TPM2B_PRIVATE_DATA{TPM2B_MTYPE, Type39_MARSHAL_REF},// TPM2B_ID_OBJECT_DATA{TPM2B_MTYPE, Type40_MARSHAL_REF},// TPMS_NV_PIN_COUNTER_PARAMETERS_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PIN_COUNTER_PARAMETERS, pinCount)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PIN_COUNTER_PARAMETERS, pinLimit))}},// TPMA_NV_DATA{ATTRIBUTES_MTYPE, FOUR_BYTES, 0x01F00300},// TPMS_NV_PUBLIC_DATA{STRUCTURE_MTYPE, 5, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_RH_NV_INDEX_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PUBLIC, nvIndex)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPMI_ALG_HASH_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PUBLIC, nameAlg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),
TPMA_NV_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PUBLIC, attributes)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PUBLIC, authPolicy)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),
Type41_MARSHAL_REF,(UINT16)(offsetof(TPMS_NV_PUBLIC, dataSize))}},// TPM2B_NV_PUBLIC_DATA{TPM2BS_MTYPE,(UINT8)(offsetof(TPM2B_NV_PUBLIC, nvPublic))|SIZE_EQUAL,UINT16_MARSHAL_REF,
TPMS_NV_PUBLIC_MARSHAL_REF},// TPM2B_CONTEXT_SENSITIVE_DATA{TPM2B_MTYPE, Type42_MARSHAL_REF},// TPMS_CONTEXT_DATA_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_CONTEXT_DATA, integrity)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF,(UINT16)(offsetof(TPMS_CONTEXT_DATA, encrypted))}},// TPM2B_CONTEXT_DATA_DATA{TPM2B_MTYPE, Type43_MARSHAL_REF},// TPMS_CONTEXT_DATA{STRUCTURE_MTYPE, 4, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(EIGHT_BYTES),UINT64_MARSHAL_REF,(UINT16)(offsetof(TPMS_CONTEXT, sequence)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_DH_SAVED_MARSHAL_REF,(UINT16)(offsetof(TPMS_CONTEXT, savedHandle)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPMI_RH_HIERARCHY_MARSHAL_REF|NULL_FLAG,(UINT16)(offsetof(TPMS_CONTEXT, hierarchy)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_CONTEXT_DATA_MARSHAL_REF,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 539
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library(UINT16)(offsetof(TPMS_CONTEXT, contextBlob))}},// TPMS_CREATION_DATA_DATA{STRUCTURE_MTYPE, 7, {SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPML_PCR_SELECTION_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, pcrSelect)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DIGEST_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, pcrDigest)),SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(ONE_BYTES),
TPMA_LOCALITY_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, locality)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(TWO_BYTES),TPM_ALG_ID_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, parentNameAlg)),
SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, parentName)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_NAME_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, parentQualifiedName)),SET_ELEMENT_TYPE(SIMPLE_STYPE),
TPM2B_DATA_MARSHAL_REF,(UINT16)(offsetof(TPMS_CREATION_DATA, outsideInfo))}},// TPM2B_CREATION_DATA_DATA{TPM2BS_MTYPE,(UINT8)(offsetof(TPM2B_CREATION_DATA, creationData))|SIZE_EQUAL,UINT16_MARSHAL_REF,
TPMS_CREATION_DATA_MARSHAL_REF},// TPM_AT_DATA{TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 4,{TPM_AT_ANY, TPM_AT_ERROR, TPM_AT_PV1, TPM_AT_VEND}},// TPMS_AC_OUTPUT_DATA{STRUCTURE_MTYPE, 2, {SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),TPM_AT_MARSHAL_REF,(UINT16)(offsetof(TPMS_AC_OUTPUT, tag)),
SET_ELEMENT_TYPE(SIMPLE_STYPE)|SET_ELEMENT_SIZE(FOUR_BYTES),UINT32_MARSHAL_REF,(UINT16)(offsetof(TPMS_AC_OUTPUT, data))}},// TPML_AC_CAPABILITIES_DATA{LIST_MTYPE,(UINT8)(offsetof(TPML_AC_CAPABILITIES, acCapabilities)),
Type44_MARSHAL_REF,
TPMS_AC_OUTPUT_ARRAY_MARSHAL_INDEX},// Type00_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMU_HA), UINT16)}},// Type01_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMT_HA), UINT16)}},// Type02_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, 1024, UINT16)}},// Type03_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_DIGEST_BUFFER, UINT16)}},// Type04_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_NV_BUFFER_SIZE, UINT16)}},// Type05_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(UINT64), UINT16)}},// Type06_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_SYM_BLOCK_SIZE, UINT16)}},

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 540
December 24, 2020

Part 4: Supporting Routines
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
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319

Trusted Platform Module Library// Type07_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMU_NAME), UINT16)}},// Type08_DATA{MIN_MAX_MTYPE, ONE_BYTES, (UINT8)TPM_RC_VALUE,{RANGE(PCR_SELECT_MIN, PCR_SELECT_MAX, UINT8)}},// Type10_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 1,{TPM_ST_CREATION}},// Type11_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 1,{TPM_ST_VERIFIED}},// Type12_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 2,{TPM_ST_AUTH_SECRET, TPM_ST_AUTH_SIGNED}},// Type13_DATA{TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 1,{TPM_ST_HASHCHECK}},// Type15_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_CAP_CC, UINT32)}},// Type17_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_ALG_LIST_SIZE, UINT32)}},// Type18_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_CAP_HANDLES, UINT32)}},// Type19_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(2, 8, UINT32)}},// Type20_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, HASH_COUNT, UINT32)}},// Type22_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_CAP_ALGS, UINT32)}},// Type23_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_TPM_PROPERTIES, UINT32)}},// Type24_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_PCR_PROPERTIES, UINT32)}},// Type25_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_ECC_CURVES, UINT32)}},// Type26_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_TAGGED_POLICIES, UINT32)}},// Type27_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_ACT_DATA, UINT32)}},// Type28_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMS_ATTEST), UINT16)}},// Type29_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_SYM_KEY_BYTES, UINT16)}},// Type30_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, LABEL_MAX_BUFFER, UINT16)}},// Type31_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMS_DERIVE), UINT16)}},// Type32_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMU_SENSITIVE_CREATE), UINT16)}},

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 541
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// Type33_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_RSA_KEY_BYTES, UINT16)}},// Type34_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, RSA_PRIVATE_SIZE, UINT16)}},// Type35_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_ECC_KEY_BYTES, UINT16)}},// Type36_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMU_ENCRYPTED_SECRET), UINT16)}},// Type37_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMT_PUBLIC), UINT16)}},// Type38_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, PRIVATE_VENDOR_SPECIFIC_BYTES, UINT16)}},// Type39_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(_PRIVATE), UINT16)}},// Type40_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMS_ID_OBJECT), UINT16)}},// Type41_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_NV_INDEX_SIZE, UINT16)}},// Type42_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_CONTEXT_SIZE, UINT16)}},// Type43_DATA{MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, sizeof(TPMS_CONTEXT_DATA), UINT16)}},// Type44_DATA{MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE,{RANGE(0, MAX_AC_CAPABILITIES, UINT32)}}};#endif // TABLE_DRIVEN_MARSHALFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 542
December 24, 2020

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
UnsignedCmpB()

This 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 543
December 24, 2020

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
46
47
48
49
50
51
52
53

Trusted Platform Module Library

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 Return

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,

Family “2.0”Level 00 Revision 01.64// 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-2021

Page 544
December 24, 2020

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 Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 545
December 24, 2020

Part 4: Supporting Routines
117

Trusted Platform Module Library}

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 546
December 24, 2020

Part 4: Supporting Routines
166
167
168

Trusted Platform Module Library}
return value;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 547
December 24, 2020

Part 4: Supporting Routines

9.12

Trusted Platform Module Library

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

Functions
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.
Return Value

13
14
15
16
17
18
19
20
21
22
23
24
25
26

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 548
December 24, 2020

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 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.
Return Value

61
62

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 549
December 24, 2020

Part 4: Supporting Routines
63
64
65
66
67
68
69
70

const TPM2B
const TPM2B)

Trusted Platform Module Library

*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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 550
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 551
December 24, 2020

Part 4: Supporting Routines
138
139
140
141
142
143
144

Trusted Platform Module Library

UINT32
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]);}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 552
December 24, 2020

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).
Return Value

20
21
22
23
24

Meaning

TRUE(1)

TPM has been initialized

FALSE(0)TPM has not been initialized

BOOL
TPMIsStarted(
void
)
{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 553
December 24, 2020

Part 4: Supporting Routines
25
26

Trusted Platform Module Library

return g_initialized;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 554
December 24, 2020

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.3Functions9.14.3.1

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.
Return Value

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 555
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 556
December 24, 2020

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 = { TPMA_ZERO_INITIALIZER() };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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 557
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 558
December 24, 2020

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

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;
#if 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 559
December 24, 2020

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
367

Trusted Platform Module Library

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 = { TPMA_ZERO_INITIALIZER() };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_CLEAR attr;
UINT32u32;} flags = { TPMA_ZERO_INITIALIZER() };//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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 560
December 24, 2020

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;}
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:#if ALG_ECC// number of loaded ECC curves*value = ECC_CURVE_COUNT;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 561
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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.
Return Value

479
480
481
482
483
484

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

Family “2.0”Level 00 Revision 01.64// IN: the starting TPM property// IN: maximum number of returned//
properties// OUT: property list

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 562
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 563
December 24, 2020

Part 4: Supporting Routines

9.15

Trusted Platform Module Library

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 564
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 565
December 24, 2020

Part 4: Supporting Routines

9.17

TpmFail.c

9.17.1
1
2
3

Trusted Platform Module Library

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_STUINT32
TPM_RC} HEADER;
typedef struct
{
BYTE
BYTE
BYTE
} PACKED_HEADER;

tag;
size;
code;

tag[sizeof(TPM_ST)];size[sizeof(UINT32)];
code[sizeof(TPM_RC)];

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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 566
December 24, 2020

Part 4: Supporting Routines
46
47
48
49
50
51
52
53
54

Trusted Platform Module Library

BYTE
header[sizeof(PACKED_HEADER)];
BYTE
getCap[sizeof(GET_CAPABILITY_PARAMETERS)];} CAPABILITY_RESPONSE;
typedef union
{
BYTE
BYTE
} RESPONSES;

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

55
56
57

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

Local Functions

9.17.3.1

MarshalUint16()

Function to marshal a 16 bit value to the output buffer.
58
59
60
61
62
63
64
65
66
67

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.
68
69
70
71
72
73
74
75
76
77

static INT32
MarshalUint32(
UINT32BYTE){
UINT32_TO_BYTE_ARRAY(integer, *buffer);*buffer += 4;
return 4;}

9.17.3.3
78
79
80
81
82

integer,**buffer

Unmarshal32()

static BOOL Unmarshal32(
UINT32
BYTE
INT32
)

*target,**buffer,*size

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 567
December 24, 2020

Part 4: Supporting Routines
83
84
85
86
87
88
89

{
if((*size -= 4) < 0)return FALSE;*target = BYTE_ARRAY_TO_UINT32(*buffer);*buffer += 4;
return TRUE;}

9.17.3.4
90
91
92
93
94
95
96
97
98
99
100
101

Trusted Platform Module Library

Unmarshal16()

static BOOL Unmarshal16(
UINT16BYTE
INT32*target,**buffer,
*size

)
{
if((*size -= 2) < 0)return FALSE;*target = BYTE_ARRAY_TO_UINT16(*buffer);*buffer += 2;
return TRUE;}

9.17.49.17.4.1

Public Functions
SetForceFailureMode()This function is called by the simulator to enable failure mode testing.
102
103
104
105
106
107
108
109
110
111

#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.
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)(ptrdiff_t)function;s_failLine = line;#else

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 568
December 24, 2020

Part 4: Supporting Routines
128
129
130
131
132
133
134
135
136
137

Trusted Platform Module Librarys_failFunction = 0;s_failLine = 0;
#endifs_failCode = code;// We are in failure mode
g_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().
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

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)(ptrdiff_t)function;s_failLine = line;#else
s_failFunction = (UINT32)(ptrdiff_t)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.
175
176
177
178
179

void
TpmFailureMode(
unsigned int
unsigned char
unsigned int

inRequestSize,*inRequest,*outResponseSize,

Family “2.0”Level 00 Revision 01.64// IN: command buffer size// IN: command buffer// OUT: response buffer size

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 569
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

unsigned char)**outResponse// OUT: response buffer

UINT32
UINT32HEADERUINT32
UINT32
UINT8
INT32

marshalSize;capability;
header;// unmarshaled command headerpt;// 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 570
December 24, 2020

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 Librarypt = 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)*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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 571
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarycase 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
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...
356
357
358
359
360
361
362
363
364
365
366
367

void
UnmarshalFail(
void
BYTE
INT32
)

*type,**buffer,*size{
NOT_REFERENCED(type);
NOT_REFERENCED(buffer);
NOT_REFERENCED(size);
FAIL(FATAL_ERROR_INTERNAL);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 572
December 24, 2020

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 a pointer to a structure. The structure has three fields. The last field is and array (d) of
crypt_uword_t. Each word is in machine format (big- or little-endian) with the words in ascending
significance (i.e. words in little-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

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)#define BYTES_TO_CRYPT_WORDS(bytes)#define SIZE_IN_CRYPT_WORDS(thing)

RADIX_DIV((bits) + (RADIX_BITS - 1))
BITS_TO_CRYPT_WORDS(bytes * 8)
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)#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 573
December 24, 2020

Part 4: Supporting Routines
35
36
37
38
39
40
41
42
43

Trusted Platform Module Library#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)

These are the basic big number formats. This is convertible to the library- specific format without too
much difficulty. For the math performed using these numbers, the value is always positive.
44
45
46
47
48
49
50
51
52
53
54
55

#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
56#define BnGetAllocated(x)(unsigned)((x)->allocated)

Get number of words used57

#define BnGetSize(x)((x)->size)

Get a pointer to the data array58#define BnGetArray(x)((crypt_uword_t *)&((x)->d[0]))Get the nth word of a BIGNUM (zero-based)
59#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 zero60

#define BnEqualZero(bn)(BnGetSize(bn) == 0)

Test to see if a bignum_t is equal to a word type61
62

#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 its
size is zero, all words of the number are 0 so this test works on zero.
63#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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 574
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryThis will call the initialization function for a defined bignum_t. This sets the allocated and used fields andclears the words of n.
64
65
66

#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_
67
68
69
70
71
72
73
74
75
76
77

#define BN_ADDRESS(name) (bigNum)&name##_#define BN_CONST(name, words, initializer)
typedef const struct name##_type {crypt_uword_t
allocated;
crypt_uword_t
size;
crypt_uword_td[words < 1 ? 1 : words];} name##_type;
name##_type name = {(words < 1 ? 1 : words), words, {initializer}};

\
\
\
\
\
\

#define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1)

Create a structure of the correct size.
78
79#define BN_STRUCT(bits)
BN_STRUCT_DEF(BN_STRUCT_ALLOCATION(bits))\

Define a BIGNUM type with a specific allocation
80
81#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.
82
83
84
85

#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
86
87
88

#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.
89
90
91

#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 useful92#define BN_WORD(name)

BN_VAR(name, RADIX_BITS)

This is used to create a word-size BIGNUM and initialize it with an input parameter to a function.
93
94#define BN_WORD_INITIALIZED(name, initial)
BN_STRUCT(RADIX_BITS) name##_;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 575
December 24, 2020

Part 4: Supporting Routines
95
96

Trusted Platform Module Library

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 as part 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 inline versions of the numbers. This is a relic of the days when there was no standard TPM format for thenumbers
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

typedef struct _bn_point_t{
bigNumx;
bigNumy;bigNumz;} bn_point_t;
typedef bn_point_t
typedef const bn_point_t*bigPoint;*pointConst;

typedef struct constant_point_t{
bigConst
x;
bigConst
y;bigConstz;} constant_point_t;#define ECC_BITS(MAX_ECC_KEY_BYTES * 8)
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
144
145
146

typedef struct{
bigConst

Family “2.0”Level 00 Revision 01.64

prime;// a prime number

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 576
December 24, 2020

Part 4: Supporting Routines
147
148
149
150
151
152

bigConst
bigConst
bigConst
bigConst
constant_point_t} ECC_CURVE_DATA;

Trusted Platform Module Libraryorder;
h;
a;
b;
base;

// 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 nothing.
153
154
155
156
157
158
159
160

#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 This is used for CryptEccData.c.
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

#define

BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d)(((UINT32)(a) << 24)+((UINT32)(b) << 16)+((UINT32)(c) << 8)+((UINT32)(d))
)

\
\
\
\
\

#define

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)+((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

These macros are used for data initialization of big number ECC constants These two macros combine amacro for data definition with a macro for structure initilization. The a parameter is a macro that gives
numbers to each of the bytes of the initializer and defines where each of the numberd bytes will show up
in the final structure. The b value is a structure that contains the requisite number of bytes in big endianorder. S, the MJOIN and JOIND macros will combine a macro defining a data layout with a macro defining
the data to be places. Generally, these macros will only need expansion when CryptEccData.c getscompiled.
188
189
190
191

#define JOINED(a,b) a b#define MJOIN(a,b) a b#define B4_TO_BN(a, b, c, d)

Family “2.0”Level 00 Revision 01.64(((((a << 8) + b) << 8) + c) + d)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 577
December 24, 2020

Part 4: Supporting Routines
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

Trusted Platform Module Library#if RADIX_BYTES == 64#define B8_TO_BN(a, b, c, d, e, f, g, h)\(UINT64)(((((((((((((((a) << 8) | b) << 8) | c) << 8) | d) << 8)\e) << 8) | f) << 8) | g) << 8) | h)#define B1_TO_BN(a)B8_TO_BN(0, 0, 0, 0, 0, 0, 0, a)#define B2_TO_BN(a, b)
B8_TO_BN(0, 0, 0, 0, 0, 0, a, b)#define B3_TO_BN(a, b, c)
B8_TO_BN(0, 0, 0, 0, 0, a, b, c)#define B4_TO_BN(a, b, c, d)
B8_TO_BN(0, 0, 0, 0, a, b, c, d)#define B5_TO_BN(a, b, c, d, e)
B8_TO_BN(0, 0, 0, a, b, c, d, e)#define B6_TO_BN(a, b, c, d, e, f)
B8_TO_BN(0, 0, a, b, c, d, e, f)#define B7_TO_BN(a, b, c, d, e, f, g)
B8_TO_BN(0, a, b, c, d, e, f, g)#else#define B1_TO_BN(a)B4_TO_BN(0, 0, 0, a)#define B2_TO_BN(a, b)
B4_TO_BN(0, 0, a, b)#define B3_TO_BN(a, b, c)
B4_TO_BN(0, a, b, c)#define B4_TO_BN(a, b, c, d)(((((a << 8) + b) << 8) + c) + d)
#define B5_TO_BN(a, b, c, d, e)
B4_TO_BN(b, c, d, e), B1_TO_BN(a)#define B6_TO_BN(a, b, c, d, e, f)
B4_TO_BN(c, d, e, f), B2_TO_BN(a, b)#define B7_TO_BN(a, b, c, d, e, f, g)
B4_TO_BN(d, e, f, g), B3_TO_BN(a, b, c)#define B8_TO_BN(a, b, c, d, e, f, g, h) B4_TO_BN(e, f, g, h), B4_TO_BN(a, b, c, d)#endif

Add implementation dependent definitions for other ECC Values and for linkages.
214
215
216

#include LIB_INCLUDE(MATH_LIB, Math)#endif // _BN_NUMBERS_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 578
December 24, 2020

Part 4: Supporting Routines

10.1.2Trusted Platform Module Library

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
3
4
5
6
7
8
9
10
11

Structures

typedef struct ECC_CURVE{
const TPM_ECC_CURVE
const UINT16
const TPMT_KDF_SCHEME
const TPMT_ECC_SCHEME
const ECC_CURVE_DATA
const BYTE
} ECC_CURVE;

10.1.2.2.1

curveId;
keySizeBits;
kdf;
sign;
*curveData; // the address of the curve data
*OID;

MacrosThis macro is used to instance an ECC_CURVE_DATA structure for the curve. This structure isreferenced by the ECC_CURVE structure
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#define CURVE_DATA_DEF(CURVE)
const ECC_CURVE_DATA CURVE = {(bigNum)&CURVE##_p_DATA, (bigNum)&CURVE##_n_DATA, (bigNum)&CURVE##_h_DATA,(bigNum)&CURVE##_a_DATA, (bigNum)&CURVE##_b_DATA,{(bigNum)&CURVE##_gX_DATA, (bigNum)&CURVE##_gY_DATA, (bigNum)&BN_ONE} };

\
\
\
\

extern const ECC_CURVE eccCurves[ECC_CURVE_COUNT];#define CURVE_DEF(CURVE){
TPM_ECC_##CURVE,
CURVE##_KEY_SIZE,CURVE##_KDF,
CURVE##_SIGN,&##CURVE,OID_ECC_##CURVE}#define CURVE_NAME(N)

\
\
\
\
\
\
\
\

#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 579
December 24, 2020

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
19
20
21

typedef void(* SMAC_DATA_METHOD)(
union SMAC_STATESUINT32const BYTE);

*state,size,*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.
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;#if ALG_SHA1#
define IF_IMPLEMENTED_SHA1(op)

Family “2.0”Level 00 Revision 01.64

op(SHA1, Sha1)

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 580
December 24, 2020

Part 4: Supporting Routines
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
104
105
106
107
108
109

Trusted Platform Module Library#else#
define IF_IMPLEMENTED_SHA1(op)#endif#if ALG_SHA256#
define IF_IMPLEMENTED_SHA256(op)#else#
define IF_IMPLEMENTED_SHA256(op)#endif#if ALG_SHA384#
define IF_IMPLEMENTED_SHA384(op)#else#
define IF_IMPLEMENTED_SHA384(op)#endif#if ALG_SHA512#
define IF_IMPLEMENTED_SHA512(op)#else#
define IF_IMPLEMENTED_SHA512(op)#endif#if ALG_SM3_256#
define IF_IMPLEMENTED_SM3_256(op)#else#
define IF_IMPLEMENTED_SM3_256(op)#endif#if ALG_SHA3_256#
define IF_IMPLEMENTED_SHA3_256(op)#else#
define IF_IMPLEMENTED_SHA3_256(op)#endif#if ALG_SHA3_384#
define IF_IMPLEMENTED_SHA3_384(op)#else#
define IF_IMPLEMENTED_SHA3_384(op)#endif#if ALG_SHA3_512#
define IF_IMPLEMENTED_SHA3_512(op)#else#
define IF_IMPLEMENTED_SHA3_512(op)#endifop(SHA256, Sha256)

op(SHA384, Sha384)

op(SHA512, Sha512)

op(SM3_256, Sm3_256)

op(SHA3_256, Sha3_256)

op(SHA3_384, Sha3_384)

op(SHA3_512, Sha3_512)#define FOR_EACH_HASH(op)\
IF_IMPLEMENTED_SHA1(op)\
IF_IMPLEMENTED_SHA256(op)\
IF_IMPLEMENTED_SHA384(op)\
IF_IMPLEMENTED_SM3_256(op) \IF_IMPLEMENTED_SHA3_256(op) \IF_IMPLEMENTED_SHA3_384(op) \IF_IMPLEMENTED_SHA3_512(op)#define HASH_TYPE(HASH, Hash)
tpmHashState##HASH##_t Hash;
typedef union{
FOR_EACH_HASH(HASH_TYPE)// 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 == 8
uint64_talign;#else
uint32_talign;#endif} ANY_HASH_STATE;
typedef ANY_HASH_STATE *PANY_HASH_STATE;
typedef const ANY_HASH_STATE*PCANY_HASH_STATE;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 581
December 24, 2020

Part 4: Supporting Routines
110
111

Trusted Platform Module Library#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
112
113
114

#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.
115

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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

#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.
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

typedef HASH_START_METHOD_DEF;
typedef HASH_DATA_METHOD_DEF;
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
HASH_DATA_METHOD
HASH_END_METHOD
HASH_STATE_COPY_METHOD
HASH_STATE_EXPORT_METHOD*start;*data;*end;*copy;*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;#define HASH_TPM2B(HASH, Hash)

Family “2.0”Level 00 Revision 01.64

TPM2B_TYPE(HASH##_DIGEST, HASH##_DIGEST_SIZE);TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 582
December 24, 2020

Part 4: Supporting Routines
155

Trusted Platform Module Library

FOR_EACH_HASH(HASH_TPM2B)

When 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.
156
157
158
159
160
161
162

#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.
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

#if ALG_ECDSA#define ECDSA_HASH_REF#define ECDSA_OID(NAME)#else#define ECDSA_HASH_REF#define ECDSA_OID(NAME)#endifconst BYTE *ECDSA;, OID_ECDSA_##NAME

typedef 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;

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.
182
183
184
185
186
187
188
189
190
191
192
193
194
195

#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.
196
197
198
199
200
201

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 583
December 24, 2020

Part 4: Supporting Routines
202

Trusted Platform Module Library#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

203
204
205
206
207
208
209
210

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.
211
212
213
214
215

typedef struct hmacState{
HASH_STATE
hashState;
TPM2B_HASH_BLOCK
hmacKey;} HMAC_STATE, *PHMAC_STATE;// the hash state// the HMAC key

This is for the external hash state. This implementation assumes that the size of the exported hash state
is no larger than the internal hash state.
216
217
218
219
220
221
222
223

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 584
December 24, 2020

Part 4: Supporting Routines

10.1.410.1.4.1

Trusted Platform Module Library

CryptRand.hIntroduction

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
18
19

#define DRBG_KEY_SIZE_BITS#define DRBG_IV_SIZE_BITS#define DRBG_ALGORITHM

AES_MAX_KEY_SIZE_BITS(AES_MAX_BLOCK_SIZE * 8)
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
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#define DRBG_MAX_REQUESTS_PER_RESEED (1 << 48)#define DRBG_MAX_REQEST_SIZE (1 << 32)#define pDRBG_KEY(seed)#define pDRBG_IV(seed)((DRBG_KEY *)&(((BYTE *)(seed))[0]))((DRBG_IV *)&(((BYTE *)(seed))[DRBG_KEY_SIZE_BYTES]))#define DRBG_KEY_SIZE_WORDS#define DRBG_KEY_SIZE_BYTES(BITS_TO_CRYPT_WORDS(DRBG_KEY_SIZE_BITS))(DRBG_KEY_SIZE_WORDS * RADIX_BYTES)#define DRBG_IV_SIZE_WORDS#define DRBG_IV_SIZE_BYTES(BITS_TO_CRYPT_WORDS(DRBG_IV_SIZE_BITS))(DRBG_IV_SIZE_WORDS * RADIX_BYTES)#define DRBG_SEED_SIZE_WORDS#define DRBG_SEED_SIZE_BYTES(DRBG_KEY_SIZE_WORDS + DRBG_IV_SIZE_WORDS)(DRBG_KEY_SIZE_BYTES + DRBG_IV_SIZE_BYTES)

typedef union{
BYTE
crypt_uword_t

bytes[DRBG_KEY_SIZE_BYTES];
words[DRBG_KEY_SIZE_WORDS];

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 585
December 24, 2020

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

Trusted Platform Module Library} DRBG_KEY;
typedef union{
BYTE
crypt_uword_t} DRBG_IV;
typedef union{
BYTE
crypt_uword_t} DRBG_SEED;

bytes[DRBG_IV_SIZE_BYTES];
words[DRBG_IV_SIZE_WORDS];

bytes[DRBG_SEED_SIZE_BYTES];
words[DRBG_SEED_SIZE_WORDS];#define CTR_DRBG_MAX_REQUESTS_PER_RESEED#define CTR_DRBG_MAX_BYTES_PER_REQUEST###((UINT64)1 << 20)(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#define#define#defineTESTINGENTROPYTESTED(1 << 0)
(1 << 1)
(1 << 2)

#define#define#define

IsTestStateSet(BIT)((g_cryptoSelfTestState.rng & BIT) != 0)
SetTestStateBit(BIT)(g_cryptoSelfTestState.rng |= BIT)
ClearTestStateBit(BIT) (g_cryptoSelfTestState.rng &= ~BIT)#define#define#defineIsSelfTest()
IsTestStateSet(TESTING)
SetSelfTest()
SetTestStateBit(TESTING)
ClearSelfTest() ClearTestStateBit(TESTING)#define#define#defineIsEntropyBad()
SetEntropyBad()
ClearEntropyBad()

IsTestStateSet(ENTROPY)
SetTestStateBit(ENTROPY)
ClearTestStateBit(ENTROPY)#define#define#define

IsDrbgTested()
SetDrbgTested()
ClearDrbgTested()

IsTestStateSet(TESTED)
SetTestStateBit(TESTED)
ClearTestStateBit(TESTED)

typedef struct{
UINT64
UINT32
DRBG_SEEDUINT32reseedCounter;magic;
seed; // contains the key and IV for the counter mode DRBG
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 KDF_STATE {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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 586
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Make sure that any other structures added to this union start with a 64-bit counter and a 32-bit magic
number
103
104
105
106
107

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

extern RAND_STATE*s_random;

When instrumenting RSA key sieve
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

#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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 587
December 24, 2020

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
27
28
29
30
31

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 588
December 24, 2020

Part 4: Supporting Routines

10.1.6

Trusted Platform Module Library

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
8

Since bit numbering starts at zero, when TPM_ALG_LAST is a multiple of 8, ALGORITHM_VECTOR will needto have byte for the single bit in the last byte. So, for example, when TPM_ALG_LAST is 8,
ALGORITHM_VECTOR will need 2 bytes.

#define ALGORITHM_VECTOR_BYTES ((TPM_ALG_LAST + 8) / 8)
typedef BYTE
ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES];#ifdef TEST_SELF_TEST
LIB_EXPORT
extern ALGORITHM_VECTOR#endif

LibToTest;

This 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.
9
10
11
12
13
14
15
16
17
18
19
20
21
22

typedef struct{
UINT32
rng;
UINT32
hash;
UINT32sym;#if ALG_RSAUINT32rsa;#endif#if ALG_ECCUINT32ecc;#endif} CRYPTO_SELF_TEST_STATE;#endif // _CRYPT_TEST_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 589
December 24, 2020

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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 590
December 24, 2020

Part 4: Supporting Routines
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

Trusted Platform Module Library

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}}};#endifTPM2B_TYPE(EMPTY, 1);#if ALG_SM3_256 == YES
TPM2B_EMPTY c_SM3_256_digest = {{0, {0}}};#endif#if ALG_SHA3_256 == YES
TPM2B_EMPTY c_SHA3_256_digest = {{0, {0}}};#endif#if ALG_SHA3_384 == YES
TPM2B_EMPTY c_SHA3_384_digest = {{0, {0}}};#endif#if ALG_SHA3_512 == YES
TPM2B_EMPTY c_SHA3_512_digest = {{0, {0}}};#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 591
December 24, 2020

Part 4: Supporting Routines

10.1.8Trusted Platform Module Library

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
36
37
38
39
40
41
42
43

#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#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 592
December 24, 2020

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};

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 593
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 594
December 24, 2020

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

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,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 595
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 596
December 24, 2020

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

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,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 597
December 24, 2020

Part 4: Supporting Routines
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
383
384
385

Trusted Platform Module Library

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,
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 598
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.10 SelfTest.h
10.1.10.1 Introduction
This file contains the structure definitions for the self-test. It also contains macros for use when the selftest is implemented.
12#ifndef#define_SELF_TEST_H__SELF_TEST_H_

10.1.10.2 Defines
Was 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
10
11

#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 SYM_MODE_FIRST and SYM_MODE_LAST
12
13
14
15

#define SYM_MODE_FIRST#define SYM_MODE_LAST#define NUM_SYM_MODES

ALG_CTR_VALUE
ALG_ECB_VALUE(SYM_MODE_LAST - SYM_MODE_FIRST + 1)

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

#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#
defineDEFAULT_TEST_HASH

Family “2.0”Level 00 Revision 01.64

ALG_SHA512_VALUE

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 599
December 24, 2020

Part 4: Supporting Routines
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

Trusted Platform Module Library#define DEFAULT_TEST_DIGEST_SIZE#
define DEFAULT_TEST_HASH_BLOCK_SIZE#elif ALG_SHA384#
define DEFAULT_TEST_HASH#
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

SHA512_DIGEST_SIZESHA512_BLOCK_SIZE
ALG_SHA384_VALUESHA384_DIGEST_SIZESHA384_BLOCK_SIZE
ALG_SHA256_VALUE
SHA256_DIGEST_SIZESHA256_BLOCK_SIZE
ALG_SHA1_VALUE
SHA1_DIGEST_SIZE
SHA1_BLOCK_SIZE// _SELF_TEST_H_

10.1.11 SupportLibraryFunctionPrototypes_fp.h
10.1.11.1 Introduction
This file contains the function prototypes for the functions that need to be present in the selected mathlibrary. 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

10.1.11.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);

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

BOOL
MathLibraryCompatibilityCheck(void);

10.1.11.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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 600
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

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

10.1.11.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);

10.1.11.7 BnMod()16#define BnMod(a, b)

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

10.1.11.8 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);

10.1.11.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);

10.1.11.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);

10.1.11.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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 601
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.11.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);

10.1.11.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);

10.1.11.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);

10.1.11.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
36

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 602
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.12 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 [] = {Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 603
December 24, 2020

Part 4: Supporting Routines
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
123

Trusted Platform Module Library

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,
0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21,
0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a};

const BYTE

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};

const BYTE

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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 604
December 24, 2020

Part 4: Supporting Routines
124
125
126
127
128
129
130
131

Trusted Platform Module Library

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};#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 605
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.13 SymmetricTest.h
10.1.13.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
7

#ifndef
SELF_TEST_DATA#error "This file may only be included in AlgorithmTests.c"#endif#ifndef#define#include_SYMMETRIC_TEST_H_SYMMETRIC_TEST_H"SymmetricTestData.h"

10.1.13.2 Symmetric Test Structures
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

const SYMMETRIC_TEST_VECTOR
c_symTestValues[NUM_SYMS + 1] = {#if ALG_AES && AES_128{TPM_ALG_AES, 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{TPM_ALG_AES, 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{TPM_ALG_AES, 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// There are no SM4 test values yet so...
#if ALG_SM4 && SM4_128 && 0
{TPM_ALG_SM4, 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 606
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.14 EccTestData.h
This file contains the parameter data for ECC testing.
12
3
4#ifdef

SELF_TEST_DATA

TPM2B_TYPE(EC_TEST, 32);
const TPM_ECC_CURVE

c_testCurve = 00003;

The static key
5
6
7
8
9
10
11
12
13
14
15

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
16
17
18
19
20
21
22
23
24
25
26

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
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}}};

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 607
December 24, 2020

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

Trusted Platform Module Library

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,
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 608
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.15 CryptSym.h
10.1.15.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.15.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
23
24
25
26
27
28
29

#ifndef CRYPT_SYM_H#define CRYPT_SYM_H#if ALG_AES#
define IF_IMPLEMENTED_AES(op)op(AES, aes)
#else#
define IF_IMPLEMENTED_AES(op)#endif#if ALG_SM4#
define IF_IMPLEMENTED_SM4(op)op(SM4, sm4)
#else#
define IF_IMPLEMENTED_SM4(op)#endif#if ALG_CAMELLIA#
define IF_IMPLEMENTED_CAMELLIA(op)op(CAMELLIA, camellia)#else#
define IF_IMPLEMENTED_CAMELLIA(op)#endif#if ALG_TDES#
define IF_IMPLEMENTED_TDES(op)
op(TDES, tdes)#else#
define IF_IMPLEMENTED_TDES(op)#endif#define FOR_EACH_SYM(op)\
IF_IMPLEMENTED_AES(op)\
IF_IMPLEMENTED_SM4(op)\
IF_IMPLEMENTED_CAMELLIA(op) \IF_IMPLEMENTED_TDES(op)Macros for creating the key schedule union
30
31
32
33
34
35
36
37
38
39
40

#define
KEY_SCHEDULE(SYM, sym)
#defineTDES
DES[3]
typedef union tpmCryptKeySchedule_t {FOR_EACH_SYM(KEY_SCHEDULE)

tpmKeySchedule##SYM sym;

#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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 609
December 24, 2020

Part 4: Supporting Routines
41
42
43
44
45

Trusted Platform Module Library#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.
46
47
48
49
50
51
52
53
54
55
56
57

#define ENCRYPT_CASE(ALG, alg)case TPM_ALG_##ALG:
TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.alg);
encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG;
break;#define DECRYPT_CASE(ALG, alg)case TPM_ALG_##ALG:
TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.alg);
decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG;
break;

\
\
\
\
\
\
\
\

#endif // CRYPT_SYM_H

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 610
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.16 OIDs.h
12#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).
These macros allow OIDs to be defined (or not) depending on whether the associated hash algorithm isimplemented.
NOTE

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

When one of these macros is used, the NAME needs _" on each side. The exception is when the macro is used
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 SHA384_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##SM3_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)#else#define SHA3_256_OID(NAME)#endif#ifndef ALG_SHA3_384

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 611
December 24, 2020

Part 4: Supporting Routines
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

Trusted Platform Module Library#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 SHA3_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
67
68#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.
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

#define OID_SHA1_VALUE
0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
SHA1_OID(_);// Expands to://
MAKE_OID(_SHA1)// which expands to://
EXTERN const BYTE OID_SHA1[] INITIALIZER({OID_SHA1_VALUE})// which, depending on the setting of EXTERN and// INITIALIZER, expands to either://extern const 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_VALUESHA384_OID(_);

NIST_HASH, 2#define OID_SHA512_VALUESHA512_OID(_);

NIST_HASH, 3#define OID_SM3_256_VALUE
SM3_256_OID(_);

0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \0x83, 0x11// (1.2.156.10197.1.401)#define OID_SHA3_256_VALUE
SHA3_256_OID(_);

NIST_HASH, 8#define OID_SHA3_384_VALUE
SHA3_384_OID(_);

NIST_HASH, 9#define OID_SHA3_512_VALUE
SHA3_512_OID(_);

NIST_HASH, 10

These are used for RSA-PSS
103
104
105
106

#if ALG_RSA#define OID_MGF1_VALUE

Family “2.0”Level 00 Revision 01.64

0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \0x01, 0x01, 0x08

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 612
December 24, 2020

Part 4: Supporting Routines
107
108
109
110
111

Trusted Platform Module Library

MAKE_OID(_MGF1);#define OID_RSAPSS_VALUE

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.
112
113
114

#define OID_PKCS1_PUB_VALUE

0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \0x01, 0x01, 0x01

MAKE_OID(_PKCS1_PUB);

These are used for RSA PKCS1 signature Algorithms
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

#define OID_PKCS1_SHA1_VALUE
SHA1_OID(_PKCS1_);

0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x05// (1.2.840.113549.1.1.5)\#define OID_PKCS1_SHA256_VALUE
SHA256_OID(_PKCS1_);

0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0B// (1.2.840.113549.1.1.11)\#define OID_PKCS1_SHA384_VALUESHA384_OID(_PKCS1_);

0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0C// (1.2.840.113549.1.1.12)\#define OID_PKCS1_SHA512_VALUESHA512_OID(_PKCS1_);

0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0D//(1.2.840.113549.1.1.13)\#define OID_PKCS1_SM3_256_VALUE
SM3_256_OID(_PKCS1_);

0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55,
0x01, 0x83, 0x78// 1.2.156.10197.1.504#define OID_PKCS1_SHA3_256_VALUE
SHA3_256_OID(_PKCS1_);#define OID_PKCS1_SHA3_384_VALUE
SHA3_384_OID(_PKCS1_);#define OID_PKCS1_SHA3_512_VALUE
SHA3_512_OID(_PKCS1_);\

NIST_SIG, 14
NIST_SIG, 15
NIST_SIG, 16#endif // ALG_RSA#if ALG_ECDSA#define OID_ECDSA_SHA1_VALUE
SHA1_OID(_ECDSA_);

0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x01// (1.2.840.10045.4.1) SHA1 digest signed by an ECDSA key.

#define OID_ECDSA_SHA256_VALUE
SHA256_OID(_ECDSA_);

0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x03, 0x02// (1.2.840.10045.4.3.2) SHA256 digest signed by an ECDSA key.

#define OID_ECDSA_SHA384_VALUESHA384_OID(_ECDSA_);

0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x03, 0x03// (1.2.840.10045.4.3.3) SHA384 digest signed by an ECDSA key.

#define OID_ECDSA_SHA512_VALUESHA512_OID(_ECDSA_);

0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \0x03, 0x04// (1.2.840.10045.4.3.4) SHA512 digest signed by an ECDSA key.

#define OID_ECDSA_SM3_256_VALUE
SM3_256_OID(_ECDSA_);

Family “2.0”Level 00 Revision 01.64

0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01,
0x83, 0x75// 1.2.156.10197.1.501

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 613
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#define OID_ECDSA_SHA3_256_VALUE
SHA3_256_OID(_ECDSA_);#define OID_ECDSA_SHA3_384_VALUE
SHA3_384_OID(_ECDSA_);#define OID_ECDSA_SHA3_512_VALUE
SHA3_512_OID(_ECDSA_);NIST_SIG, 10
NIST_SIG, 11
NIST_SIG, 12#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#if ECC_NIST_P192
MAKE_OID(_ECC_NIST_P192);#endif // ECC_NIST_P192

0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \0x01, 0x01// (1.2.840.10045.3.1.1) 'nistP192'#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#if ECC_NIST_P256
MAKE_OID(_ECC_NIST_P256);#endif // ECC_NIST_P256

0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \0x01, 0x07// (1.2.840.10045.3.1.7)'nistP256'#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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

#define OID_ECC_BN_P256_VALUE#if ECC_BN_P256
MAKE_OID(_ECC_BN_P256);#endif // ECC_BN_P256

0x00#define OID_ECC_BN_P638_VALUE#if ECC_BN_P638
MAKE_OID(_ECC_BN_P638);#endif // ECC_BN_P638

0x00#define OID_ECC_SM2_P256_VALUE

0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \0x82, 0x2D

#if ECC_SM2_P256
MAKE_OID(_ECC_SM2_P256);#endif // ECC_SM2_P256// Don't know where I found this OID. It needs checking#if ECC_BN_P256#define OID_ECC_BN_P256#endif // ECC_BN_P256

NULL#endif // ALG_ECC

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 614
December 24, 2020

Part 4: Supporting Routines
228
229
230
231

#define OID_SIZE(OID)

Trusted Platform Module Library(OID[1] + 2)

#endif // !_OIDS_H_

10.1.17 PRNG_TestVectors.h
1
2
3
4
5

#ifndef#define_MSBN_DRBG_TEST_VECTORS_H_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 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
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

#

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 615
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.18 TpmAsn1.h
10.1.18.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.18.2 Includes
34#include "Tpm.h"#include "OIDs.h"

10.1.18.3 Defined Constants
10.1.18.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
37
38
39

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#define ASN1_SET
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// Primitive + Constructed + 0x10// Primitive + Constructed + 0x11

0xA0

#define ASN1_CONSTRUCTED_SEQUENCE (ASN1_SEQUENCE + ASN1_CONSTRUCTED)#define MAX_DEPTH

10// maximum push depth for marshaling context.

10.1.18.4 Macros
10.1.18.4.1
40

Unmarshaling Macros#ifndef VERIFYFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 616
December 24, 2020

Part 4: Supporting Routines
41
42

Trusted Platform Module Library#define VERIFY(_X_) {if(!(_X_)) goto Error; }#endifChecks the validity of the size making sure that there is no wrap around
43
44
45
46
47

#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.18.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.
48#define CHECK_SPACE(context, length)

VERIFY(context->offset > length)10.1.18.5 Structures
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

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_

10.1.19 X509.h
10.1.19.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.19.2 Includes
34#include "Tpm.h"#include "TpmASN1.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 617
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.1.19.3 Defined Constants
10.1.19.3.1
56
78X509 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

#define ENCODED_SIZE_REF#define VERSION_REF#define SERIAL_NUMBER_REF#define SIGNATURE_REF#define ISSUER_REF#define VALIDITY_REF#define SUBJECT_KEY_REF#define SUBJECT_PUBLIC_KEY_REF#define EXTENSIONS_REF#define REF_COUNT

0(ENCODED_SIZE_REF + 1)
(VERSION_REF + 1)
(SERIAL_NUMBER_REF + 1)
(SIGNATURE_REF + 1)
(ISSUER_REF + 1)
(VALIDITY_REF + 1)
(SUBJECT_KEY_REF + 1)
(SUBJECT_PUBLIC_KEY_REF + 1)
(EXTENSIONS_REF + 1)

10.1.19.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.
19
20
21
22
23

typedef struct stringRef
{
BYTE
*buf;
INT16
len;
} stringRef;

This is defined to avoid bit by bit comparisons within a UINT32
24
25
26
27

typedef union x509KeyUsageUnion {TPMA_X509_KEY_USAGE
x509;
UINT32integer;} x509KeyUsageUnion;

10.1.19.5 Global X509 Constants
These values are instanced by X509_spt.c and referenced by other X509-related files.
This is the DER-encoded value for the Key Usage OID (2.5.29.15). This is the full OID, not just thenumeric value
28
29#define OID_KEY_USAGE_EXTENSION_VALUE
MAKE_OID(_KEY_USAGE_EXTENSION);

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)
30
31
32
33
34

#define OID_TCG_TPMA_OBJECT_VALUE

0x06, 0x07, 0x67, 0x81, 0x05, 0x0a, 0x01,
0x01, 0x01\

MAKE_OID(_TCG_TPMA_OBJECT);#ifdef _X509_SPT_Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 618
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

If a bit is SET in KEY_USAGE_SIGN is also SET in keyUsage then the associated key has to have sign
SET.
35
36
37
38
39
40

const x509KeyUsageUnion KEY_USAGE_SIGN ={ TPMA_X509_KEY_USAGE_INITIALIZER(/* bits_at_0*/ 0, /* decipheronly*/ 0,/* crlsign*/ 1, /* keycertsign*/ 1,/* dataencipherment */ 0, /* keyencipherment */ 0,/* digitalsignature */ 1) };/* encipheronly*/ 0,/* keyagreement*/ 0,/* nonrepudiation */ 0,

If a bit is SET in KEY_USAGE_DECRYPT is also SET in keyUsage then the associated key has to havedecrypt SET.
41
42
43
44
45
46
47
48
49
50
51
52

const x509KeyUsageUnion KEY_USAGE_DECRYPT ={ TPMA_X509_KEY_USAGE_INITIALIZER(/* bits_at_0*/ 0, /* decipheronly*/ 1,/* crlsign*/ 0, /* keycertsign*/ 0,/* dataencipherment */ 1, /* keyencipherment */ 1,/* digitalsignature */ 0) };#else
extern x509KeyUsageUnion KEY_USAGE_SIGN;
extern x509KeyUsageUnion KEY_USAGE_DECRYPT;#endif/* encipheronly*/ 1,/* keyagreement*/ 1,/* nonrepudiation */ 0,#endif // _X509_H_

10.1.20 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_

TPM 2.0 Part 2: Table 3 - Definition of Base Types
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)

\
\
\
\
\
\
\

Vendor -Specific: Table 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

TCG Algorithm Registry: Table 3 - Defines for RSA Asymmetric Cipher Algorithm Constants
22
23#define RSA_KEY_SIZES_BITS(1024 * RSA_1024),

Family “2.0”Level 00 Revision 01.64\(2048 * RSA_2048), (3072 * RSA_3072),

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 619
December 24, 2020

Part 4: Supporting Routines
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Trusted Platform Module Library(4096 * RSA_4096), (16384 * RSA_16384)#if
RSA_16384#
define RSA_MAX_KEY_SIZE_BITS
16384#elif 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)

TCG Algorithm Registry: Table 13 - Defines for SHA1 Hash Values
40
41#define SHA1_DIGEST_SIZE#define SHA1_BLOCK_SIZE

2064

TCG Algorithm Registry: Table 14 - Defines for SHA256 Hash Values
4243#define SHA256_DIGEST_SIZE#define SHA256_BLOCK_SIZE

3264

TCG Algorithm Registry: Table 15 - Defines for SHA384 Hash Values
44
45#define SHA384_DIGEST_SIZE#define SHA384_BLOCK_SIZE48
128

TCG Algorithm Registry: Table 16 - Defines for SHA512 Hash Values
46
47#define SHA512_DIGEST_SIZE#define SHA512_BLOCK_SIZE64
128

TCG Algorithm Registry: Table 17 - Defines for SM3_256 Hash Values
48
49#define SM3_256_DIGEST_SIZE#define SM3_256_BLOCK_SIZE

3264

TCG Algorithm Registry: Table 18 - Defines for SHA3_256 Hash Values
50
51#define SHA3_256_DIGEST_SIZE#define SHA3_256_BLOCK_SIZE32
136

TCG Algorithm Registry: Table 19 - Defines for SHA3_384 Hash Values
5253#define SHA3_384_DIGEST_SIZE#define SHA3_384_BLOCK_SIZE

48
104

TCG Algorithm Registry: Table 20 - Defines for SHA3_512 Hash Values
54
55#define SHA3_512_DIGEST_SIZE#define SHA3_512_BLOCK_SIZE64
72

TCG Algorithm Registry: Table 21 - Defines for AES Symmetric Cipher Algorithm Constants
56
57#define AES_KEY_SIZES_BITS\(128 * AES_128), (192 * AES_192), (256 * AES_256)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 620
December 24, 2020

Part 4: Supporting Routines
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

Trusted Platform Module Library#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\

TCG Algorithm Registry: Table 22 - Defines for SM4 Symmetric Cipher Algorithm Constants
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

#define SM4_KEY_SIZES_BITS#if
SM4_128#
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 * SM4_128)
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

TCG Algorithm Registry: Table 23 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

#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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 621
December 24, 2020

Part 4: Supporting Routines
117
118
119
120
121

Trusted Platform Module Library#define CAMELLIA_MAX_BLOCK_SIZE#else#define CAMELLIA_MAX_BLOCK_SIZE#endif#define MAX_CAMELLIA_BLOCK_SIZE_BYTES

16
0CAMELLIA_MAX_BLOCK_SIZE

TCG Algorithm Registry: Table 24 - Defines for TDES Symmetric Cipher Algorithm Constants
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

#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_SIZE

Additional values for benefit of code
142
143
144
145
146
147
148
149

#define TPM_CC_FIRST#define TPM_CC_LAST#if COMPRESSED_LISTS#define ADD_FILL#else#define ADD_FILL#endif0x0000011F
0x0000019A
0
1

Size the array of library commands based on whether or not the array is packed (only defined commands)
or dense (having entries for unimplemented commands)
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

#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)

Family “2.0”Level 00 Revision 01.64\

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021/* 0x0000011F *//* 0x00000120 *//* 0x00000121 *//* 0x00000122 *//* 0x00000123 *//* 0x00000124 *//* 0x00000125 *//* 0x00000126 *//* 0x00000127 *//* 0x00000128 *//* 0x00000129 *//* 0x0000012A *//* 0x0000012B *//* 0x0000012C *//* 0x0000012D *//* 0x0000012E *//* 0x0000012F *//* 0x00000130 *//* 0x00000131 *//* 0x00000132 */

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 622
December 24, 2020

Part 4: Supporting Routines
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
236

Trusted Platform Module Library+ (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)+ (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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021/* 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 *//* 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 */

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

Page 623
December 24, 2020

Part 4: Supporting Routines
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
302

Trusted Platform Module Library+ 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)+ (ADD_FILL || CC_AC_GetCapability)+ (ADD_FILL || CC_AC_Send)+ (ADD_FILL || CC_Policy_AC_SendSelect)+ (ADD_FILL || CC_CertifyX509)+ (ADD_FILL || CC_ACT_SetTimeout)+ (ADD_FILL || CC_ECC_Encrypt)+ (ADD_FILL || CC_ECC_Decrypt))#define VENDOR_COMMAND_ARRAY_SIZE#define COMMAND_COUNT(LIBRARY_COMMAND_ARRAY_SIZE + VENDOR_COMMAND_ARRAY_SIZE)#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,

Level 00 Revision 01.64

\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\

(0 + CC_Vendor_TCG_Test)#define HASH_COUNT\(ALG_SHA1+ ALG_SHA256+ ALG_SHA384
ALG_SHA3_384 + ALG_SHA3_512 + ALG_SHA512

Family “2.0”/* 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 *//* 0x00000194 *//* 0x00000195 *//* 0x00000196 *//* 0x00000197 *//* 0x00000198 *//* 0x00000199 *//* 0x0000019A */TCG PUBLIC REVIEW
Copyright © TCG 2006-2021+ ALG_SHA3_256 ++ ALG_SM3_256)

\

\
\
\
\
\
\
\
\

\
\
\
\
\
\

Page 624
December 24, 2020

Part 4: Supporting Routines
303
304
305
306
307
308
309

MAX(ALG_SHA512
MAX(ALG_SM3_2560)))))))))

Trusted Platform Module Library* SHA512_DIGEST_SIZE,* SM3_256_DIGEST_SIZE,\\#if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0#error "Hash data not valid"#endifDefine the 2B structure that would hold any hash block310

TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE);

Following typedef is for some old code
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

typedef TPM2B_MAX_HASH_BLOCK

TPM2B_HASH_BLOCK;#define MAX_SYM_KEY_BITS\(MAX(AES_MAX_KEY_SIZE_BITS,
MAX(SM4_MAX_KEY_SIZE_BITS,0)))))#define MAX_SYM_KEY_BYTESMAX(CAMELLIA_MAX_KEY_SIZE_BITS,
MAX(TDES_MAX_KEY_SIZE_BITS,\\((MAX_SYM_KEY_BITS + 7) / 8)

#define MAX_SYM_BLOCK_SIZE\(MAX(AES_MAX_BLOCK_SIZE,MAX(SM4_MAX_BLOCK_SIZE,0)))))MAX(CAMELLIA_MAX_BLOCK_SIZE,
MAX(TDES_MAX_BLOCK_SIZE,\\#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_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 625
December 24, 2020

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
4
5

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.
6
7
8
9
10
11
12
13
14
15

#include#include#include#include#include#include"SelfTest.h""SymmetricTest.h""RsaTestData.h""EccTestData.h""HashTestData.h""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
16
17
18
19
20
21
22
23
24

#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.
25
26
27

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 626
December 24, 2020

Part 4: Supporting Routines

10.2.1.3.2

Trusted Platform Module Library

TestHash()

The hash test function.
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

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 != TPM_ALG_NULL);#define HASH_CASE_FOR_TEST(HASH, hash)case ALG_##HASH##_VALUE:
testDigest = &c_##HASH##_digest.b;
break;\\

switch(hashAlg){
FOR_EACH_HASH(HASH_CASE_FOR_TEST)
default:
FAIL(FATAL_ERROR_INTERNAL);}// Clear the to-test bits
CLEAR_BOTH(hashAlg);// If there is an algorithm without test vectors, then assume that things are OK.
if(testDigest == NULL || testDigest->size == 0)
return TPM_RC_SUCCESS;// 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;}

10.2.1.4

Symmetric Test Functions

10.2.1.4.1

MakeIv()

Internal function to make the appropriate IV depending on the mode.
71
72
73
74
75
76
77
78
79

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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 627
December 24, 2020

Part 4: Supporting Routines
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

Trusted Platform Module Libraryif(mode == TPM_ALG_ECB)
return 0;
if(mode == TPM_ALG_CTR){// 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.
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

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 - TPM_ALG_CTR],
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 - TPM_ALG_CTR]);// Make sure that it matches what we started withif(!MemoryEqual(decrypted, test->dataIn, test->dataInOutSize))
SELF_TEST_FAILURE;}

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.
Return Value

124
125

Meaning

TRUE(1)

all symmetric algorithms tested

FALSE(0)not all symmetric algorithms tested

static BOOL
AllSymsAreDone(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 628
December 24, 2020

Part 4: Supporting Routines
126
127
128
129
130

ALGORITHM_VECTOR)

Trusted Platform Module Library*toTest{return (!TEST_BOTH(TPM_ALG_AES) && !TEST_BOTH(TPM_ALG_SM4));}

10.2.1.4.4

AllModesAreDone()

Checks if all the modes have been tested.
Return Value

131
132
133
134
135
136
137
138
139
140
141

Meaning

TRUE(1)

all modes tested

FALSE(0)all modes not tested

static BOOL
AllModesAreDone(
ALGORITHM_VECTOR)*toTest{
TPM_ALG_IDalg;
for(alg = SYM_MODE_FIRST; alg <= 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.
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

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 == TPM_ALG_AES || alg == TPM_ALG_SM4 || alg == TPM_ALG_CAMELLIA){// 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 = SYM_MODE_FIRST;
mode <= SYM_MODE_LAST;
mode++){
if(TEST_BIT(mode, *toTest))
TestSymmetricAlgorithm(&c_symTestValues[index], mode);}}}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 629
December 24, 2020

Part 4: Supporting Routines
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

// if all the symmetric tests are doneif(AllSymsAreDone(toTest)){// all symmetric algorithms tested so no modes should be setfor(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++)
CLEAR_BOTH(alg);}}
else if(SYM_MODE_FIRST <= alg && alg <= 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(TPM_ALG_AES, *toTest)&& !TEST_BIT(TPM_ALG_SM4, *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(TPM_ALG_AES);
CLEAR_BOTH(TPM_ALG_SM4);}}
else
pAssert(alg == 0 && alg != 0);
return TPM_RC_SUCCESS;}

10.2.1.5
216

Trusted Platform Module Library

RSA Tests#if ALG_RSA

10.2.1.5.1

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 630
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.
217
218
219
220
221
222
223
224
225
226
227
228
229

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 tests are for a public key encryption that uses a random value.
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

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(TPM_ALG_NULL);
if(scheme == TPM_ALG_NULL){// 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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 631
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

}
else
{
// TPM_ALG_RSAES:// 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// TPM_ALG_OAEP:// 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 == TPM_ALG_OAEP){TEST_DEFAULT_TEST_HASH(toTest);
kvtValue = &c_OaepKvt;
testLabel = OAEP_TEST_STRING;}
else if(scheme == TPM_ALG_RSAES){
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,&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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 632
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarystatic 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(TPM_ALG_NULL);
CLEAR_BOTH(TPM_ALG_RSA);
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 forif(testSig.sigAlg == TPM_ALG_RSASSA){
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 signatureif(TPM_ALG_RSAPSS == scheme){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 633
December 24, 2020

Part 4: Supporting Routines
393
394
395
396
397
398
399
400

Trusted Platform Module Library

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

static TPM_RC
TestRsa(
TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest

TPM_RC

result = TPM_RC_SUCCESS;{//
switch(alg){case TPM_ALG_NULL:// 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(TPM_ALG_RSASSA, *toTest)&& !TEST_BIT(TPM_ALG_RSAES, *toTest)&& !TEST_BIT(TPM_ALG_RSAPSS, *toTest)&& !TEST_BIT(TPM_ALG_OAEP, *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 TPM_ALG_OAEP:
case TPM_ALG_RSAES:
result = TestRsaEncryptDecrypt(alg, toTest);
break;
case TPM_ALG_RSAPSS:
case TPM_ALG_RSASSA:
result = TestRsaSignAndVerify(alg, toTest);
break;
default:
SELF_TEST_FAILURE;}
return result;}#endif // ALG_RSA

10.2.1.6
442

ECC Tests#if ALG_ECC

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 634
December 24, 2020

Part 4: Supporting Routines

10.2.1.6.1

Trusted Platform Module Library

LoadEccParameter()This function is mostly for readability and type checking
443
444
445
446
447
448
449
450

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
451
452
453
454
455
456
457
458
459
460

*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.
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

static TPM_RC
TestECDH(
TPM_ALG_ID
ALGORITHM_VECTOR)// 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(TPM_ALG_ECDH);
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)|| !MemoryEqual2B(&c_ecTestEcdh_Y.b, &Z.y.b))
SELF_TEST_FAILURE;
return result;}10.2.1.6.4
484
485
486
487
488

scheme,*toTestTestEccSignAndVerify()

static TPM_RC
TestEccSignAndVerify(
TPM_ALG_ID
ALGORITHM_VECTOR)

Family “2.0”Level 00 Revision 01.64

scheme,*toTestTCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 635
December 24, 2020

Part 4: Supporting Routines
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
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

Trusted Platform Module Library{static 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(TPM_ALG_ECDH);// ECC signature verification testing uses a KVT.
switch(scheme){case TPM_ALG_ECDSA:
LoadEccParameter(&testSig.signature.ecdsa.signatureR, &c_TestEcDsa_r);
LoadEccParameter(&testSig.signature.ecdsa.signatureS, &c_TestEcDsa_s);
break;
case TPM_ALG_ECSCHNORR:
LoadEccParameter(&testSig.signature.ecschnorr.signatureR,&c_TestEcSchnorr_r);
LoadEccParameter(&testSig.signature.ecschnorr.signatureS,&c_TestEcSchnorr_s);
break;
case TPM_ALG_SM2:// 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
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 636
December 24, 2020

Part 4: Supporting Routines555
556

return TPM_RC_SUCCESS;}

10.2.1.6.5
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

TestKDFa()

static TPM_RC
TestKDFa(
ALGORITHM_VECTOR)*toTest{static TPM2B_KDF_TEST_KEY
UINT32

keyOut;counter = 0;//
CLEAR_BOTH(TPM_ALG_KDF1_SP800_108);
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
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

Trusted Platform Module Library

TestEcc()static TPM_RC
TestEcc(
TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest{
TPM_RC
result = TPM_RC_SUCCESS;NOT_REFERENCED(toTest);
switch(alg){case TPM_ALG_ECC:
case TPM_ALG_ECDH:// 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(TPM_ALG_ECDSA, *toTest)|| TEST_BIT(ALG_ECSCHNORR, *toTest)|| TEST_BIT(TPM_ALG_SM2, *toTest))){result = TestECDH(alg, toTest);}
break;
case TPM_ALG_ECDSA:
case TPM_ALG_ECSCHNORR:
case TPM_ALG_SM2:
result = TestEccSignAndVerify(alg, toTest);
break;
default:
SELF_TEST_FAILURE;
break;}
return result;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 637
December 24, 2020

Part 4: Supporting Routines
613

Trusted Platform Module Library#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

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

toTest will only ever have bits set for implemented algorithms but alg can be anything.

Error Return

Meaning

TPM_RC_CANCELED

test was canceled

LIB_EXPORTTPM_RC(TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest

TPM_ALG_ID
TPM_ALG_ID
BOOL
TPM_RC

first = (alg == TPM_ALG_ERROR) ? TPM_ALG_FIRST : alg;last = (alg == TPM_ALG_ERROR) ? TPM_ALG_LAST : alg;
doTest = (alg != TPM_ALG_ERROR);
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)){
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 TPM_ALG_AES:#endif // ALG_AES

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 638
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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 TPM_ALG_SM4:#endif // ALG_SM4#if ALG_CAMELLIA// no test vectors for camellia//case TPM_ALG_CAMELLIA:#endif// Symmetric modes#if!ALG_CFB#error
CFB is required in all TPM implementations#endif // !ALG_CFB
case TPM_ALG_CFB:
if(doTest)
result = TestSymmetric(alg, toTest);
break;#if ALG_CTR
case TPM_ALG_CTR:#endif // ALG_CRT#if ALG_OFB
case TPM_ALG_OFB:#endif // ALG_OFB#if ALG_CBC
case TPM_ALG_CBC:#endif // ALG_CBC#if ALG_ECB
case TPM_ALG_ECB:#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 TPM_ALG_HMAC:// 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);
break;// Have to use two arguments for the macro even though only the first is used in the// expansion.
#define HASH_CASE_TEST(HASH, hash)\case ALG_##HASH##_VALUE:
FOR_EACH_HASH(HASH_CASE_TEST)#undef HASH_CASE_TEST
if(doTest)
result = TestHash(alg, toTest);
break;// RSA-dependent#if ALG_RSA
case TPM_ALG_RSA:
CLEAR_BOTH(alg);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 639
December 24, 2020

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

Trusted Platform Module Libraryif(doTest)
result = TestRsa(TPM_ALG_NULL, toTest);
else
SET_BOTH(TPM_ALG_NULL);
break;
case TPM_ALG_RSASSA:
case TPM_ALG_RSAES:
case TPM_ALG_RSAPSS:
case TPM_ALG_OAEP:
case TPM_ALG_NULL:// used or RSADP
if(doTest)
result = TestRsa(alg, toTest);
break;#endif // ALG_RSA#if ALG_KDF1_SP800_108
case TPM_ALG_KDF1_SP800_108:
if(doTest)
result = TestKDFa(toTest);
break;#endif // ALG_KDF1_SP800_108#if ALG_ECC// ECC dependent but no tests//
case TPM_ALG_ECDAA://
case TPM_ALG_ECMQV://
case TPM_ALG_KDF1_SP800_56a://case TPM_ALG_KDF2://
case TPM_ALG_MGF1:
case TPM_ALG_ECC:
CLEAR_BOTH(alg);if(doTest)
result = TestEcc(TPM_ALG_ECDH, toTest);
else
SET_BOTH(TPM_ALG_ECDH);
break;
case TPM_ALG_ECDSA:
case TPM_ALG_ECDH:
case TPM_ALG_ECSCHNORR://
case TPM_ALG_SM2:
if(doTest)
result = TestEcc(alg, toTest);
break;#endif // ALG_ECC
default:
CLEAR_BIT(alg, *toTest);
break;}
if(result != TPM_RC_SUCCESS)
break;}
return result;}#endif // SELF_TESTSFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 640
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 641
December 24, 2020

Part 4: Supporting Routines
44
45
46

Trusted Platform Module Library

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 = (unsigned)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]);Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 642
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 643
December 24, 2020

Part 4: Supporting Routines
149
150
151
152
153
154
155

Trusted Platform Module Library// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 644
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 645
December 24, 2020

Part 4: Supporting Routines

10.2.3

Trusted Platform Module Library

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

carry = 0;i;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 646
December 24, 2020

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(
bigNumresult,
int
stop,
int
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 647
December 24, 2020

Part 4: Supporting Routines
66
67
68
69
70
71
72
73
74
75
76
77
78
79

Trusted Platform Module Library//if(n2->size > n1->size){
n1 = op2;
n2 = op1;}
pAssert(result->allocated >= n1->size);stop = MIN(n1->size, n2->allocated);carry = (int)AddSame(result->d, n1->d, n2->d, (int)stop);if(n1->size > stop)
carry = CarryProp(&result->d[stop], &n1->d[stop], (int)(n1->size - stop),
carry);
CarryResolve(result, (int)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], (int)(op->size - 1), carry);
CarryResolve(result, (int)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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 648
December 24, 2020

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
int

borrow;
stop = (int)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 > (crypt_uword_t)stop)
borrow = BorrowProp(&result->d[stop], &op1->d[stop], (int)(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(
bigNumbigConst
crypt_uword_t)

result,
op,
word

int

borrow;{//
pAssert(op->size > 1 || word <= op->d[0]);borrow = word > op->d[0];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 649
December 24, 2020

Part 4: Supporting Routines
157
158
159
160
161
162

Trusted Platform Module Library

result->d[0] = op->d[0] - word;borrow = BorrowProp(&result->d[1], &op->d[1], (int)(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).
Return Value

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

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 = (int)(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.
Return Value

187
188
189
190
191
192

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

{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 650
December 24, 2020

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,
Return Value

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 651
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

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 += (int)(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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 652
December 24, 2020

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] |= ((crypt_uword_t)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

There is a requirement that unused words of a bignum_t are set to zero.

Return Value

297
298
299
300
301
302
303
304
305
306
307

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 653
December 24, 2020

Part 4: Supporting Routines
308
309
310
311
312
313
314
315
316

Trusted Platform Module Libraryif(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).
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 654
December 24, 2020

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, (crypt_uword_t)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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 655
December 24, 2020

Part 4: Supporting Routines
398
399

Trusted Platform Module Library

return !g_inFailureMode;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 656
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 657
December 24, 2020

Part 4: Supporting Routines

10.2.4.3.3

Trusted Platform Module Library

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];Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 658
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 659
December 24, 2020

Part 4: Supporting Routines

10.2.5

Trusted Platform Module Library

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
5Includes, Defines, and Typedefs#define _CRYPT_HASH_C_#include "Tpm.h"#include "CryptSym.h"#if ALG_CMAC

10.2.5.3

Functions10.2.5.3.1

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

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 660
December 24, 2020

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

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;//// Set up the encryption values based on the algorithm
switch (algorithm){
FOR_EACH_SYM(ENCRYPT_CASE)
default:
FAIL(FATAL_ERROR_INTERNAL);}
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.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

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// Set up the encryption values based on the algorithm
switch (algorithm)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 661
December 24, 2020

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
119
120
121
122
123
124

Trusted Platform Module Library{
FOR_EACH_SYM(ENCRYPT_CASE)
default:
return 0;}
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.
// 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;}#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 662
December 24, 2020

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 Return

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 Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 663
December 24, 2020

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

TPMT_SIGNATURE
TPMT_KEYEDHASH_SCHEME

Trusted Platform Module Library
test;*keyScheme =&signKey->publicArea.parameters.keyedHashDetail.scheme;//if((signature->sigAlg != TPM_ALG_HMAC)|| (signature->signature.hmac.hashAlg == TPM_ALG_NULL))
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 != TPM_ALG_NULL)&& ((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 Return

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*scheme;hashAlg;
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 != TPM_ALG_KEYEDHASH)
return TPM_RC_FAILURE;// Pick the limiting hash algorithm
if(scheme->scheme == TPM_ALG_NULL)
hashAlg = publicArea->nameAlg;
else if(scheme->scheme == TPM_ALG_XOR)
hashAlg = scheme->details.xor.hashAlg;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 664
December 24, 2020

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

Trusted Platform Module Libraryelse
hashAlg = scheme->details.hmac.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 > CryptHashGetBlockSize(hashAlg))
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.
117
118
119
120
121
122
123

BOOL
CryptIsSchemeAnonymous(
TPM_ALG_ID)

scheme// IN: the scheme algorithm to test{
return scheme == TPM_ALG_ECDAA;}

10.2.6.4

Symmetric Functions

10.2.6.4.1

ParmDecryptSym()

This function performs parameter decryption using symmetric block cipher.
124
125
126
127

void
ParmDecryptSym(
TPM_ALG_ID
TPM_ALG_ID

symAlg,hash,

Family “2.0”Level 00 Revision 01.64// IN: the symmetric algorithm// IN: hash algorithm for KDFa

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 665
December 24, 2020

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

UINT16
TPM2B
TPM2B
TPM2B
UINT32BYTE)

Trusted Platform Module Library

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, TPM_ALG_CFB, dataSize, data);}
return;}10.2.6.4.2

ParmEncryptSym()

This function performs parameter encryption using symmetric block cipher.
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

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,
keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 666
December 24, 2020

Part 4: Supporting Routines
187
188
189
190
191
192

Trusted Platform Module Library

CryptSymmetricEncrypt(data, symAlg, keySizeInBits, symParmString, &iv,
TPM_ALG_CFB, 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

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

Error Return

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 thesensitive 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 == TPM_ALG_TDES){
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;}
return result;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 667
December 24, 2020

Part 4: Supporting Routines

10.2.6.4.4

Trusted Platform Module Library

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

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

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

271
272
273
274
275
276

Meaning

TRUE(1)

initializations succeeded

FALSE(0)initialization failed and caller should place the TPM into
Failure Mode

BOOL
CryptInit(
void
)
{
BOOL

ok;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 668
December 24, 2020

Part 4: Supporting Routines
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

Trusted Platform Module Library// 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.
Return Value

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

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));}#endif // ALG_ECC

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 669
December 24, 2020

Part 4: Supporting Routines
327
328

Trusted Platform Module Library

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.
Return Value

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348

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 TPM_ALG_RSA:#endif#if ALG_ECC
case TPM_ALG_ECC:#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().

349
350
351
352

Error Return

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_RCCryptSecretEncrypt(
OBJECT
const TPM2B

Family “2.0”Level 00 Revision 01.64*encryptKey,*label,// IN: encryption key object// IN: a null-terminated string as L

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 670
December 24, 2020

Part 4: Supporting Routines
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
418

Trusted Platform Module Library

TPM2B_DATA
TPM2B_ENCRYPTED_SECRET)*data,*secret// 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 = TPM_ALG_OAEP;
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 TPM_ALG_RSA:{// 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 TPM_ALG_ECC:{
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// parameters of input ECC encrypt key.
if(CryptEccPointMultiply(&eccSecret,encryptKey->publicArea.parameters.eccDetail.curveID,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 671
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library&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

453
454
455

Error Return

Meaning

TPM_RC_ATTRIBUTES

RSA key is not a decryption key

TPM_RC_BINDING

Invalid RSA key (public
cryptographically bound.

TPM_RC_ECC_POINT

ECC point in the secret is not on the curve

TPM_RC_INSUFFICIENT

failed to retrieve ECC point from the secret

TPM_RC_NO_RESULT

multiplication resulted in ECC point at infinity

TPM_RC_SIZE

data to decrypt is not of the same size as RSA key

TPM_RC_VALUEFor RSA key, numeric value of the encrypted data is greater thanthe modulus, or the recovered data is larger than the output
buffer. For keyedHash or symmetric key, the secret is larger than
the size of the digest produced by the name algorithm.

TPM_RC_FAILURE

internal error

andprivate

parts

are

not

TPM_RCCryptSecretDecrypt(
OBJECT

Family “2.0”Level 00 Revision 01.64*decryptKey,// IN: decrypt key

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 672
December 24, 2020

Part 4: Supporting Routines
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
515
516
517
518
519
520
521

Trusted Platform Module Library

TPM2B_NONCE*nonceCaller,

const TPM2B
TPM2B_ENCRYPTED_SECRETTPM2B_DATA)*label,*secret,*data// 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 TPM_ALG_RSA:{
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 TPM_ALG_NULL, set the scheme to OAEP and// set the algorithm to the name algorithm.
if(scheme.scheme == TPM_ALG_NULL){// Use OAEP scheme
scheme.scheme = TPM_ALG_OAEP;
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 != TPM_ALG_OAEP || digestSize == 0)
return TPM_RC_SCHEME;// 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 TPM_ALG_ECC:{
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){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 673
December 24, 2020

Part 4: Supporting Routines
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
581
582
583
584
585
586
587

Trusted Platform Module Library

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 TPM_ALG_KEYEDHASH:// 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{// 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 TPM_ALG_SYMCIPHER:{
TPM2B_IViv = {{0}};TPMT_SYM_DEF_OBJECT*symDef;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 674
December 24, 2020

Part 4: Supporting Routines
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// 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, TPM_ALG_CFB, secret->t.size,
secret->t.secret);}}
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return result;}10.2.6.6.5

CryptParameterEncryption()

This function does in-place encryption of a response parameter.
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 675
December 24, 2020

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

Trusted Platform Module Libraryif(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 == TPM_ALG_XOR)// 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;}10.2.6.6.6

CryptParameterDecryption()

This function does in-place decryption of a command parameter.

686
687
688
689
690
691
692
693
694
695
696
697
698
699
700

Error Return

Meaning

TPM_RC_SIZE

The number of bytes in the input buffer is less than the numberof bytes 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 676
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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 == TPM_ALG_XOR)// 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,
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.
748
749
750
751
752
753
754
755
756
757
758
759

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)){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 677
December 24, 2020

Part 4: Supporting Routines
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

Trusted Platform Module Library// 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.
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.

779
780
781
782
783

Error Return

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 thesensitive 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 akeyed hash object

TPM_RC_VALUE

exponent is not prime or could not find a prime using theprovided parameters for an RSA key; unsupported namealgorithm for an ECC key

TPM_RCCryptCreateObject(
OBJECT
TPMS_SENSITIVE_CREATERAND_STATE

Family “2.0”Level 00 Revision 01.64*object,*sensitiveCreate,*rand// IN: new object structure pointer// IN: sensitive creation// IN: the random number generator

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 678
December 24, 2020

Part 4: Supporting Routines
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
845
846
847
848
849

Trusted Platform Module Library//

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 TPM_ALG_RSA:// 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 TPM_ALG_ECC:
result = CryptEccGenerateKey(publicArea, sensitive, rand);break;#endif // ALG_ECC
case TPM_ALG_SYMCIPHER:
result = CryptGenerateKeySymmetric(publicArea, sensitive,
sensitiveCreate, rand);break;
case TPM_ALG_KEYEDHASH:
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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 679
December 24, 2020

Part 4: Supporting Routines
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

Trusted Platform Module Library

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 == TPM_ALG_SYMCIPHER|| publicArea->type == TPM_ALG_KEYEDHASH){
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
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

TPMI_ALG_HASH
CryptGetSignHashAlg(
TPMT_SIGNATURE
)

*auth

// IN: signature{if(auth->sigAlg == TPM_ALG_NULL)
FAIL(FATAL_ERROR_INTERNAL);// Get authHash algorithm based on signing scheme
switch(auth->sigAlg){#if ALG_RSA// If RSA is supported, both RSASSA and RSAPSS are required#
if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS#
error "RSASSA and RSAPSS are required for RSA"#
endifcase TPM_ALG_RSASSA:
return auth->signature.rsassa.hash;case TPM_ALG_RSAPSS:
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 TPM_ALG_ECDSA:// SM2 and ECSCHNORR are optional
#
#
#
#

if

ALG_SM2
case TPM_ALG_SM2:
endif
if ALG_ECSCHNORR
case TPM_ALG_ECSCHNORR:
endif//all ECC signatures look the same

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 680
December 24, 2020

Part 4: Supporting Routines
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

Trusted Platform Module Library

return auth->signature.ecdsa.hash;
#

#

if

ALG_ECDAA// Don't know how to verify an ECDAA signaturecase TPM_ALG_ECDAA:
break;
endif#endif // ALG_ECC
case TPM_ALG_HMAC:
return auth->signature.hmac.hashAlg;
default:
break;}
return TPM_ALG_NULL;}

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().
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942

BOOL
CryptIsSplitSign(
TPM_ALG_ID)

scheme// IN: the algorithm selector{##

switch(scheme){
if ALG_ECDAA
case TPM_ALG_ECDAA:
return TRUE;
break;
endif// ALG_ECDAA
default:
return FALSE;
break;}}

10.2.6.6.11

CryptIsAsymSignScheme()

This function indicates if a scheme algorithm is a sign algorithm.
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

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 TPM_ALG_RSA:
switch(scheme){#
if !ALG_RSASSA || !ALG_RSAPSS#
error "RSASSA and PSAPSS required if RSA used."#
endif

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 681
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Librarycase TPM_ALG_RSASSA:
case TPM_ALG_RSAPSS:
break;
default:
isSignScheme = FALSE;
break;}
break;#endif // ALG_RSA#if ALG_ECC// If ECC is implemented ECDSA is required
case TPM_ALG_ECC:
switch(scheme){// Support for ECDSA is required for ECC
case TPM_ALG_ECDSA:#if ALG_ECDAA // ECDAA is optionalcase TPM_ALG_ECDAA:#endif#if ALG_ECSCHNORR // Schnorr is also optionalcase TPM_ALG_ECSCHNORR:#endif#if ALG_SM2 // SM2 is optionalcase TPM_ALG_SM2:#endifbreak;
default:
isSignScheme = FALSE;
break;}
break;#endif // ALG_ECC
default:
isSignScheme = FALSE;
break;}
return isSignScheme;}

10.2.6.6.12

CryptIsAsymDecryptScheme()

This function indicate if a scheme algorithm is a decrypt algorithm.
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018

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 TPM_ALG_RSA:
switch(scheme){case TPM_ALG_RSAES:
case TPM_ALG_OAEP:
break;
default:
isDecryptScheme = FALSE;
break;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 682
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library}
break;#endif // ALG_RSA#if ALG_ECC// If ECC is implemented ECDH is required
case TPM_ALG_ECC:
switch(scheme){#if !ALG_ECDH#
error "ECDH is required for ECC"
#endifcase TPM_ALG_ECDH:#if ALG_SM2
case TPM_ALG_SM2:#endif#if ALG_ECMQVcase TPM_ALG_ECMQV:#endifbreak;
default:
isDecryptScheme = FALSE;
break;}
break;#endif // ALG_ECC
default:
isDecryptScheme = FALSE;
break;}
return isDecryptScheme;}

10.2.6.6.13

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.
Return Value

1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

Meaning

TRUE(1)scheme selected

FALSE(0)both scheme and key's default scheme are empty; orscheme is empty 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 683
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library{
OK = TRUE;
scheme->scheme = TPM_ALG_NULL;
scheme->details.any.hashAlg = TPM_ALG_NULL;}
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 == TPM_ALG_SYMCIPHER)
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 == TPM_ALG_NULL){// Input and default can't both be NULL
OK = (scheme->scheme != TPM_ALG_NULL);// Assume that the scheme is compatible with the key. If not,// an error will be generated in the signing operation.
}else if(scheme->scheme == TPM_ALG_NULL){// 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 684
December 24, 2020

Part 4: Supporting Routines

10.2.6.6.14

Trusted Platform Module Library

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 check if
the sign operation is allowed for restricted key. It should be checked before the function is called. The
function will assert if the key is not a signing key.

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
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172

Error Return

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 in'signScheme' (for an
RSA key); invalid commit status or failed to generate r value (foran 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 == TPM_ALG_NULL) || (signKey == NULL))
return TPM_RC_SUCCESS;// Initialize signature hash// 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 TPM_ALG_RSA:
result = CryptRsaSign(signature, signKey, digest, NULL);
break;#endif // ALG_RSA#if ALG_ECC
case TPM_ALG_ECC:// 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 TPM_ALG_KEYEDHASH:
result = CryptHmacSign(signature, signKey, digest);
break;
default:
FAIL(FATAL_ERROR_INTERNAL);
break;}
return result;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 685
December 24, 2020

Part 4: Supporting Routines

10.2.6.6.15

Trusted Platform Module Library

CryptValidateSignature()

This function is used to verify a signature.
It is called by TPM2_VerifySignature() andTPM2_PolicySigned(). Since this operation only requires use of a public key, no consistency checks arenecessary for the key to signature type because a caller can load any public key that they like with any
scheme that they like. This routine simply makes sure that the signature is correct, whatever the type.

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

Error Return

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;// The input unmarshaling should prevent any input signature from being// a NULL signature, but just in caseif(signature->sigAlg == TPM_ALG_NULL)
return TPM_RC_SIGNATURE;
switch(publicArea->type){#if ALG_RSA
case TPM_ALG_RSA:{//// Call RSA code to verify signature
result = CryptRsaValidateSignature(signature, signObject, digest);
break;}#endif // ALG_RSA#if ALG_ECC
case TPM_ALG_ECC:
result = CryptEccValidateSignature(signature, signObject, digest);
break;#endif // ALG_ECC
case TPM_ALG_KEYEDHASH:
if(signObject->attributes.publicOnly)
result = TPM_RCS_HANDLE;
elseresult = CryptHMACVerifySignature(signObject, digest, signature);
break;
default:
break;}
return result;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 686
December 24, 2020

Part 4: Supporting Routines

10.2.6.6.16

Trusted Platform Module Library

CryptGetTestResult()

This function returns the results of a self-test function.
NOTE

1222
1223
1224
1225
1226
1227
1228
1229

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 thepart 3 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

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.

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

Error Return

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
TPM_RCTPM_RC)*publicArea,*sensitive,
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 687
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library}switch(publicArea->type){#if ALG_RSA
case TPM_ALG_RSA:
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 TPM_ALG_ECC:{
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 != TPM_ALG_NULL){
if(!CryptEccIsPointOnCurve(curveId, &unique->ecc))
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 != TPM_ALG_NULL){// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 688
December 24, 2020

Part 4: Supporting Routines
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
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

Trusted Platform Module Library{// 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 == TPM_ALG_SYMCIPHER){
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// 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 == TPM_ALG_XOR){
maxSize = CryptHashGetBlockSize(scheme->details.xor.hashAlg);}else if(scheme->scheme == TPM_ALG_HMAC){
maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg);}else if(scheme->scheme == TPM_ALG_NULL){// 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 689
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

return TPM_RCS_KEY_SIZE + blameSensitive;}// If there is a nameAlg, check the binding
if(publicArea->nameAlg != TPM_ALG_NULL){
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 != TPM_ALG_NULL){
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.18

CryptSelectMac()

This function is used to set the MAC scheme based on the key parameters and the input scheme.

1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

Error Return

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 = TPM_ALG_NULL;
switch(publicArea->type){case TPM_ALG_KEYEDHASH:{// 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 != TPM_ALG_NULL)
macAlg = scheme->details.hmac.hashAlg;
break;}
case TPM_ALG_SYMCIPHER:{
TPMT_SYM_DEF_OBJECT*scheme;scheme = &publicArea->parameters.symDetail.sym;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 690
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// Expect that the scheme is either valid symmetric cipher or NULL
if(scheme->algorithm != TPM_ALG_NULL)
macAlg = scheme->mode.sym;
break;}
default:
return TPM_RCS_TYPE;}// If the input value is not TPM_ALG_NULL ...
if(*inMac != TPM_ALG_NULL){// ... then either the scheme in the key must be TPM_ALG_NULL or the input// value must matchif((macAlg != TPM_ALG_NULL) && (*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 == TPM_ALG_NULL)
return TPM_RCS_VALUE;*inMac = macAlg;}
if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE))
return TPM_RCS_SCHEME;
return TPM_RC_SUCCESS;}

10.2.6.6.19

CryptMacIsValidForKey()

Check to see if the key type is compatible with the mac type
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486

BOOL
CryptMacIsValidForKey(
TPM_ALG_ID
TPM_ALG_ID
BOOL

keyType,
macAlg,flag){
switch(keyType){case TPM_ALG_KEYEDHASH:
return CryptHashIsValidAlg(macAlg, flag);break;
case TPM_ALG_SYMCIPHER:
return CryptSmacIsValidAlg(macAlg, flag);break;
default:
break;}
return FALSE;}

10.2.6.6.20

CryptSmacIsValidAlg()

This function is used to test if an algorithm is a supported SMAC algorithm. It needs to be updated as newalgorithms are added.
1487
1488
1489
1490

BOOL
CryptSmacIsValidAlg(
TPM_ALG_ID
BOOL

alg,
FLAG

Family “2.0”Level 00 Revision 01.64// IN: Indicates if TPM_ALG_NULL is valid

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 691
December 24, 2020

Part 4: Supporting Routines
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506

Trusted Platform Module Library){switch (alg){#if ALG_CMAC
case TPM_ALG_CMAC:
return TRUE;
break;#endifcase TPM_ALG_NULL:
return FLAG;
break;
default:
return FALSE;}}

10.2.6.6.21

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

BOOL
CryptSymModeIsValid(
TPM_ALG_ID
BOOL

mode,
flag

)
{
switch(mode){#if ALG_CTR
case TPM_ALG_CTR:#endif // ALG_CTR#if ALG_OFB
case TPM_ALG_OFB:#endif // ALG_OFB#if ALG_CBC
case TPM_ALG_CBC:#endif // ALG_CBC#if ALG_CFB
case TPM_ALG_CFB:#endif // ALG_CFB#if ALG_ECB
case TPM_ALG_ECB:#endif // ALG_ECB
return TRUE;
case TPM_ALG_NULL:
return flag;
break;
default:
break;}
return FALSE;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 692
December 24, 2020

Part 4: Supporting Routines

10.2.7

CryptSelfTest.c

10.2.7.1

Introduction

Trusted Platform Module Library

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

Functions10.2.7.2.1

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 693
December 24, 2020

Part 4: Supporting Routines

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

Trusted Platform Module Library

Error Return

Meaning

TPM_RC_CANCELED

if the command is canceled

LIB_EXPORTTPM_RC(
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.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

Error Return

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))
return TPM_RC_VALUE;
SET_BIT(alg, toTestVector);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 694
December 24, 2020

Part 4: Supporting Routines
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

Trusted Platform Module Library}// 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

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.

98
99
100
101
102
103
104
105

Error Return

Meaning

TPM_RC_CANCELED

test was canceled

LIB_EXPORTTPM_RC(TPM_ALG_ID
ALGORITHM_VECTOR)

alg,*toTest{
TPM_RC#if SELF_TEST

Family “2.0”Level 00 Revision 01.64

result;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 695
December 24, 2020

Part 4: Supporting Routines
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

Trusted Platform Module Library

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 696
December 24, 2020

Part 4: Supporting Routines

10.2.81
2

Trusted Platform Module Library

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
41
42
43

#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
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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 697
December 24, 2020

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_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);#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(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 698
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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),
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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 699
December 24, 2020

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

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 = {(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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 700
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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#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),

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 701
December 24, 2020

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

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 = {(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}};

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 702
December 24, 2020

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#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(
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 703
December 24, 2020

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#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,{&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,{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&NIST_P192,
OID_ECC_NIST_P192
CURVE_NAME("NIST_P192")}#
undef comma#
define comma ,#endif // ECC_NIST_P192#if ECC_NIST_P224
comma

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 704
December 24, 2020

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{TPM_ECC_NIST_P224,
224,{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&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,{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&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,{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA384}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&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,{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA512}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&NIST_P521,
OID_ECC_NIST_P521
CURVE_NAME("NIST_P521")}#
undef comma#
define comma ,#endif // ECC_NIST_P521#if ECC_BN_P256
comma{TPM_ECC_BN_P256,
256,{TPM_ALG_NULL, {{TPM_ALG_NULL}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&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,{TPM_ALG_NULL, {{TPM_ALG_NULL}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&BN_P638,
OID_ECC_BN_P638

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 705
December 24, 2020

Part 4: Supporting Routines
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

Trusted Platform Module Library

CURVE_NAME("BN_P638")}#
undef comma#
define comma ,#endif // ECC_BN_P638#if ECC_SM2_P256
comma{TPM_ECC_SM2_P256,
256,{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SM3_256}}},{TPM_ALG_NULL, {{TPM_ALG_NULL}}},&SM2_P256,
OID_ECC_SM2_P256
CURVE_NAME("SM2_P256")}#
undef comma#
define comma ,#endif // ECC_SM2_P256};#endif // TPM_ALG_ECC

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 706
December 24, 2020

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
37
38

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.
39
40
41
42
43
44
45
46
47

UINT64
CryptSetOddByteParity(
UINT64)k{#define PMASK 0x0101010101010101ULLUINT64out;k |= PMASK;// set the parity bit
out = k;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 707
December 24, 2020

Part 4: Supporting Routines
48
49
50
51
52
53
54
55

k ^= k >> 4;
k ^= k >> 2;
k ^= k >> 1;
k &= PMASK;out ^= k;out ^= PMASK;
return out;

Trusted Platform Module Library// 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.
Return Value

56
57
58
59
60
61
62
63
64
65
66
67
68
69

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.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 708
December 24, 2020

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 709
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
3#include "Tpm.h"#if CC_ZGen_2Phase == YES

10.2.10.2 Functions
4#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).
5
6
7
8
9
10
11
12
13
14
15
16
17
18

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.

19
20
21
22
23
24
25

Error Return

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

Family “2.0”Level 00 Revision 01.64*outZ,
curveId,
*dsA,
*deA,
*QsB,

// 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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 710
December 24, 2020

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

TPMS_ECC_POINT)

Trusted Platform Module Library*QeB// IN: ephemeral public party B key{
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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 711
December 24, 2020

Part 4: Supporting Routines
92
93
94
95
96
97
98
99

Trusted Platform Module Library// Convert BIGNUM E to TPM2B E
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).
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

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 712
December 24, 2020

Part 4: Supporting Routines

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

Trusted Platform Module Library

Error Return

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 TPM_ALG_ECDH:
return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB);
break;#if ALG_ECMQVcase TPM_ALG_ECMQV:
return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB);
break;#endif#if ALG_SM2
case TPM_ALG_SM2:
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
185
186
187
188
189
190
191
192

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 713
December 24, 2020

Part 4: Supporting Routines

10.2.10.2.6

Trusted Platform Module Library

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.
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

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

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

Error Return

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 714
December 24, 2020

Part 4: Supporting Routines
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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 715
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.11 CryptEccMain.c
10.2.11.1 Includes and Defines
1
2
3#include "Tpm.h"#if ALG_ECC

This version requires that the new format for ECC data be used
4
5
6

#if !USE_BN_ECC_DATA#error "Need to SET USE_BN_ECC_DATA to YES in Implementaion.h"#endif10.2.11.2 Functions
7
8
9
10
11
12
13
14
15
16
17

#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
18
19
20
21
22
23
24

BOOL
CryptEccInit(
void){
return TRUE;}

10.2.11.2.2

CryptEccStartup()This function is called at TPM2_Startup().
25
26
27
28
29
30
31

BOOL
CryptEccStartup(
void){
return TRUE;}

10.2.11.2.3

ClearPoint2B(generic)Initialize the size values of a TPMS_ECC_POINT structure.
32
33

void
ClearPoint2B(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 716
December 24, 2020

Part 4: Supporting Routines
34
35
36
37
38
39
40
41
42

TPMS_ECC_POINT)

Trusted Platform Module Library*p// IN: the point{
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.
Return Value

43
44
45
46
47
48
49
50
51
52
53
54
55

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

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.
67
68
69
70

const ECC_CURVE_DATA *GetCurveData(
TPM_ECC_CURVE)

Family “2.0”Level 00 Revision 01.64

curveId// IN: the curveID

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 717
December 24, 2020

Part 4: Supporting Routines
71
72
73
74

{
const ECC_CURVE*curve = CryptEccGetParametersByCurveId(curveId);
return (curve != NULL) ? curve->curveData : NULL;}

10.2.11.2.7
75
76
77
78
79
80
81
82

Trusted Platform Module Library

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.
83
84
85
86
87
88
89
90
91

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".
Return Value

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

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':

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 718
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Libraryparameter = CurveGetOrder(curve);
break;
case '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.
Return Value

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

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){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 719
December 24, 2020

Part 4: Supporting Routines
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

Trusted Platform Module Library// If we have not filled up the return list, add more curves to// itcurveList->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.
178
179
180
181
182
183
184
185
186
187
188
189

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.
Return Value

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 720
December 24, 2020

Part 4: Supporting Routines
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
265
266

Trusted Platform Module Library//if(!CryptEccGetParameter(&n, 'n', curveID))
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,&name->b, &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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 721
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 722
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 723
December 24, 2020

Part 4: Supporting Routines
352
353
354
355
356
357
358
359
360
361
362
363
364

//

Trusted Platform Module Library

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*d,
TPM_ECC_CURVE
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
392

Error Return

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
bigCurve

Family “2.0”Level 00 Revision 01.64

R,
S,
d,
Q,
u,
E

// 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// IN: curve parameters

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 724
December 24, 2020

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

Trusted Platform Module Library

)
{
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
443

Return Value

Meaning

TRUE(1)success

FALSE(0)failure generating private key

BOOL
BnEccGetPrivate(
bigNumconst ECC_CURVE_DATA

dOut,
*C,

// OUT: the qualified random value// IN: curve for which the private key//
needs to be appropriate// IN: state for DRBGRAND_STATE
)

*rand

bigConst

order = CurveGetOrder(C);{Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 725
December 24, 2020

Part 4: Supporting Routines
444
445
446
447
448
449
450
451
452
453
454
455

Trusted Platform Module Library

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
493

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);
if(OK)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 726
December 24, 2020

Part 4: Supporting Routines
494
495
496
497
498
499
500
501
502
503
504

Trusted Platform Module Library{
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
532

Error Return

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);return retVal;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 727
December 24, 2020

Part 4: Supporting Routines
533

Trusted Platform Module Library}

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).
Return Value

534
535
536
537
538
539
540
541
542
543
544
545
546
547

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
563

Error Return

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);
ECC_NUM(bnD);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 728
December 24, 2020

Part 4: Supporting Routines
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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 729
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.12 CryptEccSignature.c
10.2.12.1 Includes and Defines
1
2
3
4#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.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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

28
29

Error Return

Meaning

TPM_RC_NO_RESULT

the result of the operation was zero or r (mod n) is zerostatic TPM_RC
BnSchnorrSign(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 730
December 24, 2020

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

bigNumbigConst
bigNumbigConst
bigConst)

Trusted Platform Module Library
bnS,
bnK,
bnR,
bnD,
bnN

// OUT: 's' component of the signature// 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.
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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 731
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 6. Compute s = (k^-1 * (e + d * r)) mod q. If s = 0, return to Step 1.2.
// 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 wherer 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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 732
December 24, 2020

Part 4: Supporting Routines

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

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 733
December 24, 2020

Part 4: Supporting Routines
190
191
192
193
194
195
196
197
198
199
200

Trusted Platform Module Library// 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.
201
202
203
204
205
206
207
208
209
210

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

211
212
213
214
215
216
217
218
219
220
221
222
223

Error Return

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_STATEUINT16

hashState;digestSize = CryptHashGetDigestSize(hashAlg);{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 734
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_KEY_BYTES));TPM2B_T
T2b;
TPM2B*e = &T2b.b;
TPM_RC
retVal = TPM_RC_NO_RESULT;
const ECC_CURVE_DATA*C;
bigConst
order;
bigConst
prime;
ECC_NUM(bnK);
POINT(ecR);//// 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.

276

Return Value

Meaning

TRUE(1)values equal

FALSE(0)values not equal

static BOOL

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 735
December 24, 2020

Part 4: Supporting Routines
277
278
279
280
281
282
283
284
285
286

Trusted Platform Module Library

BnHexEqual(
bigNumconst char
)

bn,
*c

//IN: big number value//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.

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

Error Return

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);Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 736
December 24, 2020

Part 4: Supporting Routines
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#ifdef _SM2_SIGN_DEBUG
pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41""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.

375
376
377

Error Return

Meaning

TPM_RC_SCHEME

scheme is not supported

LIB_EXPORT TPM_RC
CryptEccSign(
TPMT_SIGNATURE

Family “2.0”Level 00 Revision 01.64*signature,// OUT: signature

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 737
December 24, 2020

Part 4: Supporting Routines
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
439
440
441

OBJECT
const TPM2B_DIGEST
TPMT_ECC_SCHEMERAND_STATE)

Trusted Platform Module Library*signKey,*digest,*scheme,*rand// IN: ECC key to sign the hash// IN: digest to sign// 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 TPM_ALG_ECDSA:
retVal = BnSignEcdsa(bnR, bnS, E, bnD, digest, rand);break;#if ALG_ECDAA
case TPM_ALG_ECDAA:
retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, bnS, E,
bnD, digest, scheme, signKey, rand);bnR = NULL;
break;#endif#if ALG_ECSCHNORR
case TPM_ALG_ECSCHNORR:
retVal = BnSignEcSchnorr(bnR, bnS, E, bnD, digest,
signature->signature.ecschnorr.hash,rand);
break;#endif#if ALG_SM2
case TPM_ALG_SM2:
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_ECDSAFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 738
December 24, 2020

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

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

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 739
December 24, 2020

Part 4: Supporting Routines

10.2.12.3.9

Trusted Platform Module Library

BnValidateSignatureEcSm2()This function is used to validate an SM2 signature.

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
549
550
551
552

Error Return

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 740
December 24, 2020

Part 4: Supporting Routines
553
554
555
556
557

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.

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
601
602
603
604
605

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 741
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.

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

Error Return

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 TPM_ALG_ECDSA:#if ALG_ECSCHNORR
case TPM_ALG_ECSCHNORR:#endif#if ALG_SM2
case TPM_ALG_SM2:#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 TPM_ALG_ECDSA:
retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest);
break;#if ALG_ECSCHNORR
case TPM_ALG_ECSCHNORR:
retVal = BnValidateSignatureEcSchnorr(bnR, bnS,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 742
December 24, 2020

Part 4: Supporting Routines
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

Trusted Platform Module Librarysignature->signature.any.hashAlg,
E, ecQ, digest);

break;#endif#if ALG_SM2
case TPM_ALG_SM2:
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.

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

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 743
December 24, 2020

Part 4: Supporting Routines
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{
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 744
December 24, 2020

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

#define _CRYPT_HASH_C_#include "Tpm.h"#include "CryptHash_fp.h"#include "CryptHash.h"#include "OIDs.h"

Instance each of the hash descriptors based on the implemented algorithms
6

FOR_EACH_HASH(HASH_DEF_TEMPLATE)

Instance a null def.
7

HASH_DEF NULL_Def = {{0}};Create a table of pointers to the defined hash definitions
8
9
10
11
12
13
14

#define HASH_DEF_ENTRY(HASH, Hash)&Hash##_Def,
PHASH_DEF
HashDefArray[] = {// for each implemented HASH, expands to: &HASH_Def,
FOR_EACH_HASH(HASH_DEF_ENTRY)&NULL_Def};#undef HASH_DEF_ENTRY

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.
15
16
17
18
19
20
21
22

BOOL
CryptHashInit(
void){
LibHashInit();return TRUE;}

10.2.13.3.2

CryptHashStartup()This function is called by TPM2_Startup(). It checks that the size of the HashDefArray() is consistent with
the HASH_COUNT.
23
24
25
26
27

BOOL
CryptHashStartup(
void
)
{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 745
December 24, 2020

Part 4: Supporting Routines
28
29
30

Trusted Platform Module Libraryint
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.
31
32
33
34
35
36
37
38
39
40
41
42
43
44

PHASH_DEF
CryptGetHashDef(
TPM_ALG_ID)

hashAlg{#define GET_DEF(HASH, Hash) case ALG_##HASH##_VALUE: return &Hash##_Def;
switch(hashAlg){
FOR_EACH_HASH(GET_DEF)
default:
return &NULL_Def;}#undef GET_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.
Return Value

45
46
47
48
49
50
51
52
53
54
55

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
BOOL

hashAlg,
flag// IN: the algorithm to check// 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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 746
December 24, 2020

Part 4: Supporting Routines

56
57
58
59
60
61
62
63
64
65
66
67

Trusted Platform Module Library

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.
Return Value

68
69
70
71
72
73
74

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.
Return Value

75
76
77
78
79
80
81

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 747
December 24, 2020

Part 4: Supporting Routines
82
83
84
85
86
87
88

Trusted Platform Module Library

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.
89
90
91
92
93
94
95

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.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

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){
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.
117
118
119
120
121
122
123

void
CryptHashExportState(
PCHASH_STATEinternalFmt,

PEXPORT_HASH_STATE)

externalFmt// IN: the hash state formatted for use by//library// OUT: the exported hash state{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 748
December 24, 2020

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

BYTE

Trusted Platform Module Library*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.
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

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;//#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){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 749
December 24, 2020

Part 4: Supporting Routines
182
183
184
185
186
187

Trusted Platform Module Library

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

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;}

10.2.13.6.2

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).
Return Value

214
215
216

Meaning0

hash is TPM_ALG_NULL>0digest size

LIB_EXPORT UINT16
CryptHashStart(
PHASH_STATE

hashState,

Family “2.0”Level 00 Revision 01.64// OUT: the running hash state

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 750
December 24, 2020

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

TPM_ALG_ID)

Trusted Platform Module Library

hashAlg// 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.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260

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);#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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 751
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

261
262
263
264
265
266
267
268
269
270

Meaning0

no data returned>0

the number of bytes in the digest or dOutSize, whicheveris 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.
Return Value
>= 0
271
272
273
274
275
276
277
278
279
280
281
282
283
284

Meaning
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.
This function can be used for both HMAC and hash functions so the digestState is void so that either
state type can be passed.
285
286
287
288
289
290
291
292
293
294
295

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 752
December 24, 2020

Part 4: Supporting Routines
296
297
298

Trusted Platform Module Library

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
Return Value
>=0
299
300
301
302
303
304
305
306
307

Meaning
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().
308
309
310
311
312
313
314
315
316
317
318
319

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]);}

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.
Return Value
>= 0

320
321
322

Meaning
number of bytes in digest produced by hashAlg (may be
zero)

LIB_EXPORT UINT16
CryptHmacStart(
PHMAC_STATE

state,

Family “2.0”Level 00 Revision 01.64// IN/OUT: the state buffer

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 753
December 24, 2020

Part 4: Supporting Routines
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

TPM_ALG_ID
UINT16const BYTE)

Trusted Platform Module Library

hashAlg,
keySize,*key// 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
state->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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 754
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

Meaning

>= 0
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

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.
Return Value

411
412
413
414
415
416
417
418
419
420

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);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 755
December 24, 2020

Part 4: Supporting Routines

10.2.13.7.4

Trusted Platform Module Library

CryptHmacEnd2B()

This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is themost common use.
Return Value

Meaning

>=0
421
422
423
424
425
426
427
428

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

CryptMGF_KDF()

This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are T(n) = T(n-1)|| H(seed || counter) with the difference being that, with KDF1, counter starts at 0 but with KDF2, counter
starts at 1. The caller determines which version by setting the initial value of counter to either 0 or 1.
NOTE

Any value that is not 0 is considered to be 1.

This function returns the length of the mask produced which could be zero if the digest algorithm is notsupported
Return Value

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

Meaning0

hash algorithm was TPM_ALG_NULL>0should be the same as mSize

LIB_EXPORT UINT16
CryptMGF_KDF(
UINT32BYTE
TPM_ALG_ID
UINT32BYTE
UINT32)

mSize,*mask,
hashAlg,
seedSize,*seed,
counter// 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// IN: counter initial value{
HASH_STATEPHASH_DEF
UINT32
UINT32

hashState;hDef = CryptGetHashDef(hashAlg);
hLen;
bytes;//// If there is no digest to compute returnif((hDef->digestSize == 0) || (mSize == 0))
return 0;if(counter != 0)
counter = 1;
hLen = hDef->digestSize;for(bytes = 0; bytes < mSize; bytes += hLen){// Start the hash and include the seed and counter

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 756
December 24, 2020

Part 4: Supporting Routines
453
454
455
456
457
458
459
460
461
462

Trusted Platform Module Library

CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate(&hashState, seedSize, seed);
CryptDigestUpdateInt(&hashState, 4, counter);// Get as much as will fit.
CryptHashEnd(&hashState, MIN((mSize - bytes), hLen),&mask[bytes]);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.
Return Value

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

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,

UINT16blocks// 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//
avoid large intermediate buffers.
// IN: If non-zero, this is the maximum number//of blocks to be returned, regardless//of sizeInBits){
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 757
December 24, 2020

Part 4: Supporting Routines
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
549

Trusted Platform Module Libraryif(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
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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 758
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.
Return Value

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
595
596
597
598
599
600
601
602
603
604

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://
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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 759
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 760
December 24, 2020

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
11
12
13

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

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.
41
42

BOOL
IsPrimeInt(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 761
December 24, 2020

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

uint32_t)

Trusted Platform Module Libraryn{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.
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

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((uint32_t)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);}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 762
December 24, 2020

Part 4: Supporting Routines

10.2.14.2.4

Trusted Platform Module Library

MillerRabinRounds()

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.
96
97
98
99
100
101
102
103
104

UINT32
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.
Return Value

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

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 = (int)(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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 763
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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)|| (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.
188
189
190
191
192
193
194

TPM_RC
RsaCheckPrime(
bigNumUINT32
RAND_STATE)

prime,
exponent,*rand{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 764
December 24, 2020

Part 4: Supporting Routines
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

#if !RSA_KEY_SIEVE
TPM_RCUINT32Trusted Platform Module Library

retVal = TPM_RC_SUCCESS;
modE = BnModWord(prime, exponent);

NOT_REFERENCED(rand);if(modE == 0)// 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

RsaAdjustPrimeCandiate()

For this math, we assume that the RSA numbers are fixed-point numbers with the decimal point to the leftof the most significant bit. This approach helps make it clear what is happening with the MSb of thevalues. The two RSA primes have to be large enough so that their product will be a number with thenecessary number of significant bits. For example, we want to be able to multiply two 1024-bit numbers to
produce a number with 2028 significant bits. If we accept any 1024-bit prime that has its MSb set, then it
is possible to produce a product that does not have the MSb SET. For example, if we use tiny keys of 16
bits and have two 8-bit primes of 0x80, then the public key would be 0x4000 which is only 15-bits. So,
what we need to do is made sure that each of the primes is large enough so that the product of theprimes is twice as large as each prime. A little arithmetic will show that the only way to do this is to makesure that each of the primes is no less than root(2)/2. That''s what this functions does. This function
adjusts the candidate prime so that it is odd and >= root(2)/2. This allows the product of these two
numbers to be .5, which, in fixed point notation means that the most significant bit is 1. For this routine,
the root(2)/2 (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.
This function can be replaced with a function that just sets the two most significant bits of each prime
candidate without introducing any computational issues.
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

LIB_EXPORT void
RsaAdjustPrimeCandidate(
bigNum)prime

UINT32
UINT32msw;
adjusted;{// If the radix is 32, the compiler should turn this into a simple assignment
msw = prime->d[prime->size - 1] >> ((RADIX_BITS == 64) ? 32 : 0);// Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0
adjusted = (msw >> 16) * 0x4AFB;
adjusted += ((msw & 0xFFFF) * 0x4AFB) >> 16;
adjusted += 0xB5050000UL;#if RADIX_BITS == 64

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 765
December 24, 2020

Part 4: Supporting Routines
234
235
236
237
238
239
240
241
242
243

Trusted Platform Module Library// Save the low-order 32 bits
prime->d[prime->size - 1] &= 0xFFFFFFFFUL;// replace the upper 32-bits
prime->d[prime->size -1] |= ((crypt_uword_t)adjusted << 32);
#else
prime->d[prime->size - 1] = (crypt_uword_t)adjusted;#endif// 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.
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

TPM_RC
BnGeneratePrimeForRSA(
bigNumprime,// IN/OUT: points to the BN that will get the// random value// IN: number of bits to get// IN: the exponent// IN: the random state

UINT32
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){// The change below is to make sure that all keys that are generated from the same// seed value will be the same regardless of the endianess or word size of the CPU.
//DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old//if(g_inFailureMode)// oldif(!BnGetRandomBits(prime, bits, rand))// new
return TPM_RC_FAILURE;
RsaAdjustPrimeCandidate(prime);
found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS;}
return TPM_RC_SUCCESS;}#endif // ALG_RSA

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 766
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.15 CryptPrimeSieve.c
10.2.15.1 Includes and defines
1
2
3
4
5

#include "Tpm.h"#if RSA_KEY_SIEVE#include "CryptPrimeSieve_fp.h"

This determines the number of bits in the largest sieve field.
6
7
8
9
10
11

#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.
12
13
14
15

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.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 767
December 24, 2020

Part 4: Supporting Routines
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

Trusted Platform Module Library

LIB_EXPORT uint32_t
RsaNextPrime(
uint32_t)

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

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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 768
December 24, 2020

Part 4: Supporting Routines
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

Trusted Platform Module Library

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,
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.
108
109
110
111
112
113
114
115
116
117
118

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
Return Value

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

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 769
December 24, 2020

Part 4: Supporting Routines
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

Trusted Platform Module Librarysel = a[i];// Subtract the bits in the last byte added.
sum -= BitsInByte(sel);// Now process the byte, one bit at a time.
for(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1)
sum += (sel & 1) != 0;
return (sum == n) ? retValue : -1;}
typedef struct{
UINT16
UINT16} SIEVE_MARKS;

prime;
count;

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

LIB_EXPORT UINT32
PrimeSieve(
bigNumUINT32
BYTE)

bnN,// IN/OUT: number to sieve
fieldSize, // IN: size of the field area in bytes*field// IN: field

UINT32
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 = (UINT32)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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 770
December 24, 2020

Part 4: Supporting Routines
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
252

//

Trusted Platform Module LibrarypAssert(BnModWord(bnN, 105) == 0);
pField = field;for(i = fieldSize; i >= sizeof(seedValues);
pField += sizeof(seedValues), i -= sizeof(seedValues)){
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 = (UINT32)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 we have picked a field-sized// range that is aligned to a 105 count boundary. The problem is, this field// only contains odd numbers. If we take our prime guess and walk through all// the numbers using that prime as the 'stride', then every other 'stride' is// going to be an even number. So, we are actually counting by 2 * the stride// We want the count to start on an odd number at the start of our field. That// is, we want to assume that we have counted up to the edge of the field by// the 'stride' and now we are going to start flipping bits in the field as we// continue to count up by 'stride'. If we take the base of our field and// divide by the stride, we find out how much we find out how short the last// count was from reaching the edge of the bit field. Say we get a quotient of// 3 and remainder of 1. This means that after 3 strides, we are 1 short of// the start of the field and the next stride will either land within the// field or step completely over it. The confounding factor is that our field// only contains odd numbers and our stride is actually 2 * stride. If the// quoitent is even, then that means that when we add 2 * stride, we are going// to hit another even number. So, we have to know if we need to back off// by 1 stride before we start couting by 2 * stride.
// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 771
December 24, 2020

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

Trusted Platform Module Library// even stride, we need 0.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);
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.
278
279
280
281
282
283
284
285
286
287
288
289

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.

290
291
292

Error Return

Meaning

TPM_RC_FAILURE

TPM in failure mode, probably due to entropy source

TPM_RC_NO_RESULT

candidate is not prime and couldn't find and alternative in thefield

LIB_EXPORT TPM_RC
PrimeSelectWithSieve(
bigNumcandidate,

Family “2.0”Level 00 Revision 01.64// IN/OUT: The candidate to filter

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 772
December 24, 2020

Part 4: Supporting Routines
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
357
358

UINT32
RAND_STATE
)

e,
*rand

Trusted Platform Module Library// 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// 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 = (UINT32)(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 = (UINT32)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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 773
December 24, 2020

Part 4: Supporting Routines
359
360
361
362
363

INSTRUMENT_INC(noPrimeFields[PrimeIndex]);return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT);}#if RSA_INSTRUMENT
static char

10.2.15.2.8
364
365
366
367
368
369
370
371
372

a[256];

PrintTuple()char *
PrintTuple(
UINT32)*i{sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]);return a;}#define CLEAR_VALUE(x)10.2.15.2.9
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

Trusted Platform Module Librarymemset(x, 0, sizeof(x))

RsaSimulationEnd()

void
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);}

10.2.15.2.10 GetSieveStats()
405
406
407
408
409
410
411

LIB_EXPORT void
GetSieveStats(uint32_t
uint32_t
uint32_t)*trials,*emptyFields,*averageBits{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 774
December 24, 2020

Part 4: Supporting Routines
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

Trusted Platform Module Libraryuint32_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

10.2.15.2.11 RsaSimulationEnd()
Stub for call when not doing instrumentation.
436
437
438
439
440
441
442
443

void
RsaSimulationEnd(
void){
return;}#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 775
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
9
10

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 776
December 24, 2020

Part 4: Supporting Routines

10.2.16.2.2
11
12
13
14
15
16
17
18
19
20
21
22
23

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.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

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.
47
48
49
50
51
52
53
54
55
56
57
58

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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 777
December 24, 2020

Part 4: Supporting Routines
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

Trusted Platform Module Library

0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
#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().
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

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.
104
105
106
107

static DRBG_SEED *DfEnd(PDF_STATE)

dfStateFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 778
December 24, 2020

Part 4: Supporting Routines
108
109
110
111
112
113
114
115
116
117
118

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();
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

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.
Return Value

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

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()){

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 779
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#endif// 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().
182
183
184
185
186
187
188
189

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.
190
191
192
193
194
195
196
197
198
199
200
201
202

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 780
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library//
UINT32
int
BYTE

temp[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 then
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 781
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module LibraryprovidedData is XORed into drbgState→seed to complete the encryption of providedData. This works
because the IV is the last thing that gets encrypted.
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

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

the provided entropy must be the required size.

Return Value

298
299
300
301
302
303

Meaning

TRUE(1)reseed succeeded

FALSE(0)reseed failed, probably due to the entropy generation

BOOL
DRBG_Reseed(
DRBG_STATEDRBG_SEEDDRBG_SEED)

Family “2.0”Level 00 Revision 01.64*drbgState,*providedEntropy,*additionalData// IN: the state to update// IN: entropy// IN:TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 782
December 24, 2020

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
326
327
328

Trusted Platform Module Library{
DRBG_SEED

seed;

pAssert((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.

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,Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 783
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library"Key after 1st Generate");dbgDumpMemBlock(pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,"Value after 1st Generate");#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.
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.

393
394
395
396
397
398
399
400
401

Error Return

Meaning

TPM_RC_NO_RESULT

failure of the entropy generator

LIB_EXPORT TPM_RC
CryptRandomStir(UINT16
BYTE){#if !USE_DEBUG_RNG
DRBG_SEEDDRBG_SEED

additionalDataSize,*additionalData

tmpBuf;dfResult;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 784
December 24, 2020

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
431
432
433

Trusted Platform Module Library//// All reseed with outside data starts with a buffer full of entropy
if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE *)&tmpBuf))
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.
434
435
436
437
438
439
440
441

LIB_EXPORT UINT16
CryptRandomGenerate(
UINT16
BYTE)

randomSize,*buffer{
return DRBG_Generate((RAND_STATE *)&drbgDefault, buffer, randomSize);}

10.2.16.3.4

DRBG_InstantiateSeededKdf()

This function is used to instantiate a KDF-based RNG. This is used for derivations. This function always
returns TRUE.
442
443
444
445
446
447
448
449
450
451
452
453

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 785
December 24, 2020

Part 4: Supporting Routines
454
455
456
457
458
459
460
461
462
463
464

Trusted Platform Module Librarystate->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;}

10.2.16.3.5

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.
465
466
467
468
469
470
471
472
473
474
475
476
477

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);}}

10.2.16.3.6

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.

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

Error Return

Meaning

TPM_RC_FAILURE

DRBG self-test failure

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 786
December 24, 2020

Part 4: Supporting Routines
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523

Trusted Platform Module Library

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;}

10.2.16.3.7

CryptRandStartup()This function is called when TPM_Startup is executed. This function always returns TRUE.
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
return 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)
return DRBG_Reseed(&go.drbgState, NULL, NULL);
else
return DRBG_Instantiate(&go.drbgState, 0, NULL);#endif}10.2.16.3.8

CryptRandInit()

This function is called when _TPM_Init is being processed.

541
542
543
544
545
546

Return Value

Meaning

TRUE(1)success

FALSE(0)failureLIB_EXPORT BOOL
CryptRandInit(void){#if !USE_DEBUG_RNG

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 787
December 24, 2020

Part 4: Supporting Routines
547
548
549
550

Trusted Platform Module Library_plat__GetEntropy(NULL, 0);#endifreturn DRBG_SelfTest();}10.2.16.3.9

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 zero without generating any bits or updating the reseed counter. This function returns thenumber of bytes produced which could be less than the number requested if the request is too large (toolarge is implementation dependent.)
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
595
596
597
598
599
600
601

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(random == NULL)
return 0;// 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 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;
//
// 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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 788
December 24, 2020

Part 4: Supporting Routines
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
662
663
664
665
666
667

Trusted Platform Module Library

}
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{// 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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 789
December 24, 2020

Part 4: Supporting Routines
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684

Trusted Platform Module Library}// 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.10 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.
Return Value

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

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// 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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 790
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.16.3.11 DRBG_Uninstantiate()
This is Uninstantiate_function() from [SP 800-90A 9.4].

716
717
718
719
720
721
722
723
724
725

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 791
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
12
3
4#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().
5
6
7
8
9
10
11

BOOL
CryptRsaInit(
void){
return TRUE;}

10.2.17.3.2

CryptRsaStartup()

Function called at TPM2_Startup()
12
13
14
15
16
17
18

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.
19
20
21
22
23
24
25

static privateExponent *RsaInitializeExponent(
privateExponent)*Z{
bigNumint

Family “2.0”Level 00 Revision 01.64*bn = (bigNum *)&Z->P;i;

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 792
December 24, 2020

Part 4: Supporting Routines
26
27
28
29
30
31
32
33

Trusted Platform Module Library//for(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.
34
35
36
37
38
39
40
41
42
43
44
45

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.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 793
December 24, 2020

Part 4: Supporting Routines

10.2.17.4.4

Trusted Platform Module Library

UnpackExponent()

This function unpacks the private exponent from its TPM2B form into its bignum form.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

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.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 794
December 24, 2020

Part 4: Supporting Routines
108
109
110
111
112
113
114
115

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.

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

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

144
145
146
147

Error Return

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.64// 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-2021

Page 795
December 24, 2020

Part 4: Supporting Routines
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

OBJECT)

Trusted Platform Module Library//
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.

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

Error Return

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 796
December 24, 2020

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

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

Error Return

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
UINT16
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 797
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

DRBG_Generate(rand, mySeed, (UINT16)hLen);if(g_inFailureMode)
ERROR_RETURN(TPM_RC_FAILURE);// mask = MGF1 (seed, nSize hLen 1)
CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0);// 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(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) !=(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 is available, the size is not changed and the return code is TPM_RC_VALUE.

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

Error Return

Meaning

TPM_RC_VALUE

the value to decode was larger than the modulus, or the padding
is wrong 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 798
December 24, 2020

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

Trusted Platform Module Library

CryptMGF_KDF(hLen, seedMask, hashAlg, padded->size - hLen - 1,
&padded->buffer[hLen + 1], 0);// 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
CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0);// 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

350
351
352
353

Error Return

Meaning

TPM_RC_VALUE

message size is too large

static TPM_RC
RSAES_PKCS1v1_5Encode(
TPM2B
TPM2B

*padded,*message,

Family “2.0”Level 00 Revision 01.64// OUT: the pad data// IN: the message being padded

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 799
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

RAND_STATE
)

*rand

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

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

Error Return

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 800
December 24, 2020

Part 4: Supporting Routines
409
410
411
412
413
414
415

Trusted Platform Module Library

fail = ((pSize - 2) <= 8) | fail;if((message->size < (UINT16)(coded->size - pSize)) || fail)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.
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

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.
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 801
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library//using eOut for scratch space// 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(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != 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.

498
499
500
501
502
503
504

Error Return

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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 802December 24, 2020

Part 4: Supporting Routines
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
566
567
568
569
570

UINT32
BYTE
BYTE
BYTE
BYTE
UINT32
UINT32BYTE
TPM_RC
HASH_STATE

Trusted Platform Module Library

hLen = CryptHashGetDigestSize(hashAlg);mask[MAX_RSA_KEY_BYTES];*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;
CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0);// 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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 803
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// hash and the seed to recreate the hash in the lower portion of eIn.
CryptHashStart(&hashState, hashAlg);// 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

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

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 804
December 24, 2020

Part 4: Supporting Routines
624
625
626
627
628
629
630
631
632
633
634
635

Trusted Platform Module Library

MemoryCopy(buffer, info->OID, oidSize);buffer += oidSize;*buffer++ = 0x05;// Add a NULL
*buffer++ = 0x00;*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.

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

Error Return

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 805
December 24, 2020

Part 4: Supporting Routines
676
677
678
679

*eOut++ = *der++;Exit:
return retVal;}

Trusted Platform Module Library// copy the hash10.2.17.4.18 RSASSA_Decode()This function performs the RSASSA decoding of a signature.

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
728

Error Return

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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 806
December 24, 2020

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

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.

769
770

Error Return

Meaning

TPM_RC_BINDING

public and private parts of rsaKey are not matched

TPM_RCCryptRsaLoadPrivateExponent(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 807
December 24, 2020

Part 4: Supporting Routines
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

TPMT_PUBLIC
TPMT_SENSITIVE)

Trusted Platform Module Library*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(TPM_ALG_NULL);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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 808
December 24, 2020

Part 4: Supporting Routines

NOTE

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
867

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 Return

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 TPM_ALG_NULL: // '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 TPM_ALG_RSAES:
retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand);break;
case TPM_ALG_OAEP:
retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn,rand);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 809
December 24, 2020

Part 4: Supporting Routines
868
869
870
871
872
873
874
875
876
877
878
879
880

Trusted Platform Module Library

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.

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 Return

Meaning

TPM_RC_SIZE

cInSize is not the same as the size of the public modulus of key;or numeric value of the encrypted data is greater than themodulus

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 TPM_ALG_NULL:
if(dOut->size < cIn->size)
return TPM_RC_VALUE;
MemoryCopy2B(dOut, cIn, dOut->size);break;
case TPM_ALG_RSAES:
retVal = RSAES_Decode(dOut, cIn);
break;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 810
December 24, 2020

Part 4: Supporting Routines
917
918
919
920
921
922
923
924
925
926
927

Trusted Platform Module Librarycase TPM_ALG_OAEP:
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.

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 Return

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 TPM_ALG_NULL:
sigOut->signature.rsapss.sig.t.size = 0;
return TPM_RC_SUCCESS;
case TPM_ALG_RSAPSS:
retVal = PssEncode(&sigOut->signature.rsapss.sig.b,
sigOut->signature.rsapss.hash, &hIn->b, rand);break;
case TPM_ALG_RSASSA:
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 811
December 24, 2020

Part 4: Supporting Routines
970
971
972

Trusted Platform Module Library}
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.

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 Return

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 TPM_ALG_RSAPSS:
case TPM_ALG_RSASSA:
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 TPM_ALG_RSAPSS:
retVal = PssDecode(sig->signature.any.hashAlg, &digest->b,&sig->signature.rsassa.sig.b);break;
case TPM_ALG_RSASSA:
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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 812
December 24, 2020

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 Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 813
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

return TPM_RC_SUCCESS;#endif// Make sure that key generation has been tested
TEST(TPM_ALG_NULL);// 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
PackExponent(&sensitive->sensitive.rsa, Z);// Make sure everything came out right. The MSb of the values must be one

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 814
December 24, 2020

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

Trusted Platform Module Libraryif(((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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 815
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
4#define _CRYPT_HASH_C_#include "Tpm.h"#if SMAC_IMPLEMENTED

10.2.18.2.1

CryptSmacStart()

Function to start an SMAC.
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

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 TPM_ALG_CMAC:
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.
34
35
36
37
38

UINT16
CryptMacStart(
HMAC_STATETPMU_PUBLIC_PARMS
TPM_ALG_ID

Family “2.0”Level 00 Revision 01.64*state,*keyParameters,
macAlg,// IN: the type of MAC

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 816
December 24, 2020

Part 4: Supporting Routines
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Trusted Platform Module Library

TPM2B

*key

)
{
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.
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

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.
70
71
72
73
74
75
76
77
78

UINT16
CryptMacEnd2B (HMAC_STATE
TPM2B*state,*data){
return CryptMacEnd(state, data->size, data->buffer);}#endif // SMAC_IMPLEMENTED

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 817
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

#include "Tpm.h"#include "CryptSym.h"#defineKEY_BLOCK_SIZES(ALG, alg)
static const INT16
alg##KeyBlockSizes[] = {ALG##_KEY_SIZES_BITS, -1, ALG##_BLOCK_SIZES };\\FOR_EACH_SYM(KEY_BLOCK_SIZES)

10.2.19.3 Initialization and Data Access Functions
10.2.19.3.1

CryptSymInit()

This function is called to do _TPM_Init processing
10
11
12
13
14
15
16

BOOL
CryptSymInit(
void){
return TRUE;}

10.2.19.3.2

CryptSymStartup()This function is called to do TPM2_Startup() processing
17
18
19
20
21
22
23

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 818
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

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

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 TPM_ALG_##SYM: sizes = sym##KeyBlockSizes; breakswitch(symmetricAlg){#define GET_KEY_BLOCK_POINTER(SYM, sym)
case TPM_ALG_##SYM:
sizes = sym##KeyBlockSizes;
break;// Get the pointer to the block size array
FOR_EACH_SYM(GET_KEY_BLOCK_POINTER);\\\

default:
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.

61
62
63
64
65
66
67
68
69

Error Return

Meaning

TPM_RC_SIZE

dSize is not a multiple of the block size for an algorithm that
requires it

TPM_RC_FAILURE

Fatal error

LIB_EXPORT TPM_RC
CryptSymmetricEncrypt(
BYTE
TPM_ALG_ID
UINT16const BYTE
TPM2B_IV
TPM_ALG_ID

Family “2.0”Level 00 Revision 01.64*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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 819
December 24, 2020

Part 4: Supporting Routines
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
128
129
130
131
132
133
134
135

Trusted Platform Module Library

INT32

dSize,

const BYTE)

*dIn// IN: data size (may need to be a//multiple of the blockSize)// IN: data buffer

{
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 != TPM_ALG_ECB)){ivInOut->t.size = blockSize;iv = ivInOut->t.buffer;}else
iv = defaultIv;
pIv = iv;// Create encrypt key schedule and set the encryption function pointer.
switch (algorithm){
FOR_EACH_SYM(ENCRYPT_CASE)
default:
return TPM_RC_SYMMETRIC;}
switch(mode){#if ALG_CTR
case TPM_ALG_CTR:
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_OFB
case TPM_ALG_OFB:// This is written so that dIn and dOut may be the same

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 820
December 24, 2020

Part 4: Supporting Routines
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
198
199
200
201

Trusted Platform Module Libraryfor(; 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 TPM_ALG_CBC:// 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 TPM_ALG_CFB:// 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
case TPM_ALG_ECB:// 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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 821
December 24, 2020

Part 4: Supporting Routines
202
203
204
205
206
207

Trusted Platform Module Library#endifdefault:
return TPM_RC_FAILURE;}
return TPM_RC_SUCCESS;}

10.2.19.4.1

CryptSymmetricDecrypt()This function performs symmetric decryption based on the mode.

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

Error Return

Meaning

TPM_RC_FAILURE

A fatal error

TPM_RCS_SIZE

dSize is not a multiple of the block size for an algorithm that
requires it

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);
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 != TPM_ALG_ECB)){ivInOut->t.size = blockSize;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 822
December 24, 2020

Part 4: Supporting Routines
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
319

Trusted Platform Module Libraryiv = 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 TPM_ALG_CBC: // decrypt = decrypt
case TPM_ALG_ECB:// For ECB and CBC, the data size must be an even multiple of the// cipher block sizeif((dSize % blockSize) != 0)
return TPM_RC_SIZE;
switch (algorithm){
FOR_EACH_SYM(DECRYPT_CASE)
default:
return TPM_RC_SYMMETRIC;}
break;#endifdefault:// For the remaining stream ciphers, use encryption to decryptswitch (algorithm){
FOR_EACH_SYM(ENCRYPT_CASE)
default:
return TPM_RC_SYMMETRIC;}}// Now do the mode-dependent decryption
switch(mode){#if ALG_CBC
case TPM_ALG_CBC:// 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 TPM_ALG_CFB:
for(; dSize > 0; dSize -= blockSize){// Encrypt the IV into the temp buffer
ENCRYPT(&keySchedule, iv, tmp);
pT = tmp;
pIv = iv;
for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 823
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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 TPM_ALG_CTR:
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 TPM_ALG_ECB:
for(; dSize > 0; dSize -= blockSize){
DECRYPT(&keySchedule, dIn, dOut);dIn = &dIn[blockSize];
dOut = &dOut[blockSize];}break;#endif#if ALG_OFB
case TPM_ALG_OFB:// 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;}

10.2.19.4.2

CryptSymKeyValidate()

Validate that a provided symmetric key meets the requirements of the TPM
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 824
December 24, 2020

Part 4: Supporting Routines

380
381
382
383
384
385
386
387
388
389
390
391
392
393

Trusted Platform Module Library

Error Return

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 825
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
17

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 826
December 24, 2020

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

0x00, 0x8a, 0x90, 0x44, 0x82, 0x32, 0x65, 0x18, 0x90, 0x00, 0x0a, 0x02,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 827
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

0x29, 0x52, 0x00, 0x41, 0x08, 0x34, 0x60, 0x10, 0x00, 0x28, 0x01, 0x10,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 828
December 24, 2020

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

0x00, 0x03, 0xa2, 0x09, 0xd0, 0x14, 0x00, 0x8a, 0x84, 0x25, 0x4a, 0x00,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 829
December 24, 2020

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 Library

0x6d, 0x11, 0x00, 0x00, 0x40, 0x20, 0x00, 0x03, 0x10, 0x40, 0x88, 0x30,
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,

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 830
December 24, 2020

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
375
376

Trusted Platform Module Library

0x04, 0xd2, 0x10, 0x4c, 0x88, 0x86, 0x00, 0x10, 0x80, 0x0c, 0x02, 0x14,
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 831
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
16
17
18

#include "Tpm.h"#if USE_RSA_KEY_CACHE#include <stdio.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
TPM2B_PRIVATE_KEY_RSA} RSA_KEY_CACHE;

publicModulus;
privateExponent;

Determine the number of RSA key sizes for the cache
19
20
21
22
23
24
25
26
27
28
29
30
31

TPMI_RSA_KEY_BITS#if RSA_1024
1024,#endif#if RSA_2048
2048,#endif#if RSA_3072
3072,#endif#if RSA_4096
4096,#endifFamily “2.0”Level 00 Revision 01.64

SupportedRsaKeySizes[] = {TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 832
December 24, 2020

Part 4: Supporting Routines
32
33
34
35

Trusted Platform Module Library0};#define RSA_KEY_CACHE_ENTRIES (RSA_1024 + RSA_2048 + RSA_3072 + RSA_4096)

The key cache holds one entry for each of the supported key sizes
36

RSA_KEY_CACHE

s_rsaKeyCache[RSA_KEY_CACHE_ENTRIES];

Indicates if the key cache is loaded. It can be loaded and enabled or disabled.
37

BOOL

s_keyCacheLoaded = 0;

Indicates if the key cache is enabled38

int

s_rsaKeyCacheEnabled = FALSE;

10.2.21.2.1

RsaKeyCacheControl()

Used to enable and disable the RSA key cache.
39
40
41
42
43
44
45

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.

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)success

FALSE(0)failurestatic BOOL
InitializeKeyCache(
TPMT_PUBLIC
TPMT_SENSITIVERAND_STATE*publicArea,*sensitive,*rand// IN: if not NULL, the deterministic//
RNG state){int
TPM_KEY_BITS
BOOL

index;
keySave = publicArea->parameters.rsaDetail.keyBits;
OK = TRUE;//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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 833
December 24, 2020

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

Trusted Platform Module Library}}
publicArea->parameters.rsaDetail.keyBits = keySave;s_keyCacheLoaded = OK;#if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE
if(OK){
FILE*cacheFile;const char
*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.
Return Value

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

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)#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 834
December 24, 2020

Part 4: Supporting Routines
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

{
fseek(cacheFile, 0L, SEEK_END);
if(ftell(cacheFile) == sizeof(s_rsaKeyCache)){fseek(cacheFile, 0L, SEEK_SET);
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

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 835
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.22 Ticket.c
10.2.22.1 Introduction
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
Return Value

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

Meaning

TRUE(1)

safe to produce ticket

FALSE(0)not safe to produce ticket

BOOL
TicketIsSafe(
TPM2B)*buffer{
TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE;
BYTE
bufferToCompare[sizeof(valueToCompare)];BYTE*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_CONSTANTS32_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
32
33

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{//// Fill in ticket fields

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 836
December 24, 2020

Part 4: Supporting Routines
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Trusted Platform Module Libraryticket->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
91
92

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
CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE),
g_timeEpoch);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 837
December 24, 2020

Part 4: Supporting Routines
93
94
95
96
97
98
99
100
101
102

Trusted Platform Module Library// 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
144
145

void
TicketComputeCreation(
TPMI_RH_HIERARCHYTPM2B_NAME
TPM2B_DIGEST
TPMT_TK_CREATION)

hierarchy,*name,*creation,*ticketTPM2B_PROOF
HMAC_STATE*proof;hmacState;// IN: hierarchy for ticket// IN: object name// IN: creation hash// OUT: created ticket{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 838
December 24, 2020

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

Trusted Platform Module Library// 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 839
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.
Return Value

23
24
25
26
27
28
29
30
31
32

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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 840
December 24, 2020

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.
Return Value

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 841
December 24, 2020

Part 4: Supporting Routines
84

Trusted Platform Module Library}

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. The bit string is left
justified so that the MSb of the input is the MSb of the returned value. If there is a general parsing 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
127
128
129
130
131
132

Return Value

Meaning

TRUE(1)success

FALSE(0)failureBOOL
ASN1GetBitStringValue(
ASN1UnmarshalContext
UINT32

*ctx,
*val

)
{
int
INT16
UINT32int

shift;
length;value = 0;
inputBits;//
length = ASN1NextTag(ctx);
VERIFY(length >= 1);
VERIFY(ctx->tag == ASN1_BITSTRING);// Get the shift value for the bit field (how many bits to lop off of the end)
shift = NEXT_OCTET(ctx);
length--;// Get the number of bits in the input
inputBits = (8 * length) - shift;// the shift count has to make sense
VERIFY((shift < 8) && ((length > 0) || (shift == 0)));// if there are any bytes leftfor(; length > 1; length--){// 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);}
if(length == 1){// 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);}// 'Left justify' the result
if(inputBits > 0)
value <<= (32 - inputBits);*val = value;
return TRUE;
Error:
ctx->size = -1;
return FALSE;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 842
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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 forthe 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.
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 843
December 24, 2020

Part 4: Supporting Routines
148
149
150
151
152
153
154
155
156
157

Trusted Platform Module Libraryvoid
ASN1StartMarshalContext(
ASN1MarshalContext

*ctx

)
{
pAssert((ctx->depth + 1) < MAX_DEPTH);
ctx->depth++;ctx->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.
Return Value

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

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.
Return Value

173
174
175
176
177
178
179
180
181
182
183
184

Meaning>0

number of octets in the encapsulation== 0

failureUINT16ASN1EndEncapsulation(
ASN1MarshalContext
BYTE

*ctx,
tag

)
{
// 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);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 844
December 24, 2020

Part 4: Supporting Routines

10.2.23.3.6
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

Trusted Platform Module Library

ASN1PushByte()

BOOL
ASN1PushByte(
ASN1MarshalContext
BYTE

*ctx,
b

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

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

Meaning>0

count bytes== 0

failure unless count was zero

INT16
ASN1PushBytes(
ASN1MarshalContext
INT16
const BYTE

*ctx,
count,*buffer){// 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

224

Return ValueASN1PushNull()
Return Value

Meaning>0

count bytes== 0

failure unless count was zero

INT16

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 845
December 24, 2020

Part 4: Supporting Routines
225
226
227
228
229
230
231
232

Trusted Platform Module Library

ASN1PushNull(
ASN1MarshalContext

*ctx

)
{
ASN1PushByte(ctx, 0);
ASN1PushByte(ctx, ASN1_NULL);
return (ctx->offset >= 0) ? 2 : 0;}

10.2.23.3.9

ASN1PushLength()

Push a length value. This will only handle length values that fit in an INT16.
Return Value

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

Meaning>0

number of bytes added== 0

failureASN1MarshalContext
INT16

*ctx,
len

INT16
ASN1PushLength(){
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()
Return Value

261
262
263
264
265
266
267

Meaning>0

number of bytes added== 0

failure

INT16
ASN1PushTagAndLength(
ASN1MarshalContext
BYTE
INT16

*ctx,
tag,
length){Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 846
December 24, 2020

Part 4: Supporting Routines
268
269
270
271
272

Trusted Platform Module Library

INT16
bytes;
bytes = ASN1PushLength(ctx, length);bytes += (INT16)ASN1PushByte(ctx, tag);
return (ctx->offset < 0) ? 0 : bytes;}

10.2.23.3.11 ASN1PushTaggedOctetString()
This function will push a random octet string.
Return Value

273
274
275
276
277
278
279
280
281
282
283
284
285
286

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.

287
288
289
290
291
292
293
294
295
296

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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 847
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Meaning>0

the number of bytes marshaled for the integer== 0

failure

INT16
ASN1PushInteger(
ASN1MarshalContext
INT16
BYTE

*ctx,
iLen,
*integer// IN/OUT: buffer context// IN: octets of the 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.
Return Value

317
318
319
320
321
322
323
324
325
326
327
328
329

Meaning>0

the number of bytes marshaled for the integer== 0

failureASN1MarshalContext
const BYTE

*ctx,
*OID

INT16
ASN1PushOID(){
if((*OID == ASN1_OBJECT_IDENTIFIER) && ((OID[1] & 0x80) == 0)){
return ASN1PushBytes(ctx, OID[1] + 2, OID);}
ctx->offset = -1;
return 0;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 848
December 24, 2020

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
7

#include "Tpm.h"#include "X509.h"#include "OIDs.h"#include "TpmASN1_fp.h"#include "X509_ECC_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...
Return Value

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

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.
Return Value

24
25
26
27
28
29
30
31
32

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);){//

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 849
December 24, 2020

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

Trusted Platform Module Library

NOT_REFERENCED(signKey);// If the desired hashAlg definition wasn't found...
if(hashDef->hashAlg != scheme->details.any.hashAlg)
return 0;
switch(scheme->scheme){#if ALG_ECDSA
case TPM_ALG_ECDSA:// 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);#endif // ALG_ECDSA
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.
Return Value

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

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{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 850
December 24, 2020

Part 4: Supporting Routines
85
86
87
88
89
90
91

Trusted Platform Module Library

ASN1PushOID(ctx, curveOid); // curve dependent
ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1)}
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd}
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 851
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.25 X509_RSA.c
10.2.25.1 Includes
1
2
3
4
5
6
7

#include "Tpm.h"#include "X509.h"#include "TpmASN1_fp.h"#include "X509_RSA_fp.h"#include "X509_spt_fp.h"#include "CryptHash_fp.h"#include "CryptRsa_fp.h"

10.2.25.2 Functions
8#if ALG_RSA

10.2.25.2.1

X509AddSigningAlgorithmRSA()This creates the singing algorithm data.
Return Value

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

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 TPM_ALG_RSASSA:{// 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;
return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1);}
case TPM_ALG_RSAPSS:// 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 == TPM_ALG_SHA1){
return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 852
December 24, 2020

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

}
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)){// This adds a NULL, then an OID and a SEQUENCE// wrapper.
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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 853
December 24, 2020

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

Trusted Platform Module Library//
OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST)//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.
Return Value

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

Meaning>0

number of bytes added== 0

failureOBJECT
ASN1MarshalContext*object,
*ctx

INT16
X509AddPublicRSA(){
UINT32

exp = object->publicArea.parameters.rsaDetail.exponent;//// 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;// 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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 854
December 24, 2020

Part 4: Supporting Routines
163
164
165
166
167
168
169
170
171
172
173

Trusted Platform Module Library// 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 855
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

X509FindExtensionByOID()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
44

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;// if the provided search context is different from the context of the extension,// then copy the search context to the search context.
else if(ctx != ctxIn)*ctx = *ctxIn;// Now, search in the extension context
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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 856
December 24, 2020

Part 4: Supporting Routines
45
46
47

Trusted Platform Module Libraryif (MemoryEqual(OID, &(ctx->buffer[ctx->offset]), OID_SIZE(OID))){// Return with ' ctx' set to point to the start of the OID with the
size

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

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

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 857
December 24, 2020

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
132
133
134
135
136
137
138
139
140

Trusted Platform Module Library

Error Return

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(
OBJECT*object,stringRef*extension// IN: The object with the attributes to//check// IN: The start and length of the extensions){
ASN1UnmarshalContext
ASN1UnmarshalContext
INT16
UINT32
TPMA_OBJECT

ctx;
extensionCtx;
length;value;
attributes = object->publicArea.objectAttributes;//
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.
// NOTE: MemoryEqual() is used rather than a simple UINT32 compare to avoid// type-punned pointer warning/error.
if(!MemoryEqual(&value, &attributes, 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_EXTENSION) &&X509GetExtensionBits(&extensionCtx, &value)){
x509KeyUsageUnion
keyUsage;
BOOL
badSign;
BOOL
badDecrypt;
BOOL
badFixedTPM;
BOOL
badRestricted;//
keyUsage.integer = value;// For KeyUsage:// 1) 'sign' is SET if Key Usage includes signing
badSign = ((KEY_USAGE_SIGN.integer & keyUsage.integer) != 0)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign);// 2) 'decrypt' is SET if Key Usage includes decryption uses
badDecrypt = ((KEY_USAGE_DECRYPT.integer & keyUsage.integer) != 0)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt);// 3) 'fixedTPM' is SET if Key Usage is non-repudiation
badFixedTPM = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE,
nonrepudiation)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 858
December 24, 2020

Part 4: Supporting Routines
141
142
143
144
145
146
147
148
149
150
151
152
153

Trusted Platform Module Library&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM);// 4)'restricted' is SET if Key Usage is for key agreement.
badRestricted = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement)&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted);if(badSign || badDecrypt || badFixedTPM || badRestricted)
return TPM_RCS_VALUE;}
else// The KeyUsage extension is required
return TPM_RCS_VALUE;
return TPM_RC_SUCCESS;}

10.2.26.3 Marshaling Functions
10.2.26.3.1

X509AddSigningAlgorithm()

This creates the singing algorithm data.
Return Value

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

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 TPM_ALG_RSA:
return X509AddSigningAlgorithmRSA(signKey, scheme, ctx);#endif // ALG_RSA#if ALG_ECC
case TPM_ALG_ECC:
return X509AddSigningAlgorithmECC(signKey, scheme, ctx);#endif // ALG_ECC#if ALG_SM2
case TPM_ALG_SM2:
break; // no signing algorithm for SM2 yet//
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.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 859
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

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

Meaning>0

number of octets added== 0

failure

INT16
X509AddPublicKey(
ASN1MarshalContext
OBJECT*ctx,*object){
switch(object->publicArea.type){#if ALG_RSA
case TPM_ALG_RSA:
return X509AddPublicRSA(object, ctx);#endif#if ALG_ECC
case TPM_ALG_ECC:
return X509AddPublicECC(object, ctx);#endif#if ALG_SM2
case TPM_ALG_SM2:
break;#endifdefault:
break;}
return FALSE;}

10.2.26.3.3

X509PushAlgorithmIdentifierSequence()

The function adds the algorithm identifier sequence.
Return Value

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

Meaning>0

number of bytes added== 0

failure

INT16
X509PushAlgorithmIdentifierSequence(
ASN1MarshalContext
const BYTE
)

*ctx,
*OID

{
// An algorithm ID sequence is:// SEQUENCE
//
OID
//
NULL
ASN1StartMarshalContext(ctx);// hash algorithm
ASN1PushNull(ctx);
ASN1PushOID(ctx, OID);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 860
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

10.2.27 AC_spt.c
10.2.27.1 Includes and Structures
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#include "Tpm.h"#include "AC_spt_fp.h"#if 1// This is the simulated AC data. This should be present in an actual// implementation.

typedef struct {TPMI_RH_AC
TPML_AC_CAPABILITIESac;*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.2 Functions
10.2.27.2.1

AcToCapabilities()

This function returns a pointer to a list of AC capabilities.
21
22
23
24
25
26
27
28
29
30
31
32
33
34

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

AcIsAccessible()

Function to determine if an AC handle references an actual AC
35
36
37
38
39
40
41
42
43

BOOL
AcIsAccessible(
TPM_HANDLE)

acHandle{// In this implementation, the AC exists if there are some capabilities to go// with the handle
return AcToCapabilities(acHandle) != NULL;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 861
December 24, 2020

Part 4: Supporting Routines

10.2.27.2.3

Trusted Platform Module Library

AcCapabilitiesGet()

This function returns a list of capabilities associated with an AC
Return Value

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

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

AcSendObject()Stub to handle sending of an AC object
81
82
83
84
85
86
87
88
89
90
91
92

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;

Family “2.0”Level 00 Revision 01.64// indicate that the response contains an// error code// but there is no error.

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 862
December 24, 2020

Part 4: Supporting Routines
93
94
95

Trusted Platform Module Library

return TPM_RC_SUCCESS;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 863
December 24, 2020

Part 4: Supporting Routines

10.2.28

Trusted Platform Module Library

CryptEccCrypt.c

10.2.28.1 Includes and Defines
1
2
3#include "Tpm.h"#if CC_ECC_Encrypt || CC_ECC_Encrypt

10.2.28.2 Functions
10.2.28.2.1

CryptEccSelectScheme()

This function is used by TPM2_ECC_Decrypt and TPM2_ECC_Encrypt. It sets scheme either the input
scheme or the key scheme. If they key scheme is not TPM_ALG_NULL then the input scheme must be
TPM_ALG_NULL or the same as the key scheme. If not, then the function returns FALSE.
Return Value

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

Meaning

TRUE

scheme is set

FALSE

scheme is not valid (it may have been changed).

BOOL
CryptEccSelectScheme(
OBJECT
TPMT_KDF_SCHEME*key,*scheme//IN: key containing default scheme// IN: a decrypt scheme

TPMT_KDF_SCHEME*keyScheme = &key->publicArea.parameters.eccDetail.kdf;){// Get sign object pointerif(scheme->scheme == TPM_ALG_NULL)*scheme = *keyScheme;
if(keyScheme->scheme == TPM_ALG_NULL)
keyScheme = scheme;
return (scheme->scheme != TPM_ALG_NULL &&(keyScheme->scheme == scheme->scheme&& keyScheme->details.anyKdf.hashAlg == scheme->details.anyKdf.hashAlg));}

10.2.28.2.2

CryptEccEncrypt()This function performs ECC-based data obfuscation. The only scheme that is currently supported is
MGF1 based. See Part 1, Annex D for details.

21
22
23
24
25

Error Return

Meaning

TPM_RC_CURVE

unsupported curve

TPM_RC_HASHhash not allowed

TPM_RC_SCHEME

scheme is not supported

TPM_RC_NO_RESULT

internal error in big number processing

LIB_EXPORT TPM_RC
CryptEccEncrypt(
OBJECT
TPMT_KDF_SCHEME
TPM2B_MAX_BUFFER

Family “2.0”Level 00 Revision 01.64*key,*scheme,*plainText,// IN: public key of recipient// IN: scheme to use.
// IN: the text to obfuscate

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 864
December 24, 2020

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

TPMS_ECC_POINT
TPM2B_MAX_BUFFER
TPM2B_DIGEST

Trusted Platform Module Library
*c1,
*c2,
*c3

// OUT: public ephemeral key// OUT: obfuscated text// OUT: digest of ephemeral key//
and plainText){
CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
POINT_INITIALIZED(PB, &key->publicArea.unique.ecc);
POINT_VAR(Px, MAX_ECC_KEY_BITS);TPMS_ECC_POINTp2;
ECC_NUM(D);TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2);
TPM2B_2ECC
z;
int
i;
HASH_STATE
hashState;
TPM_RC
retVal = TPM_RC_SUCCESS;//#if defined DEBUG_ECC_ENCRYPT && DEBUG_ECC_ENCRYPT == YES
RND_DEBUG
dbg;// This value is one less than the value from the reference so that it// will become the correct value after having one added
TPM2B_ECC_PARAMETER k = {24, {0x38, 0x4F, 0x30, 0x35, 0x30, 0x73, 0xAE, 0xEC,
0xE7, 0xA1, 0x65, 0x43, 0x30, 0xA9, 0x62, 0x04,
0xD3, 0x79, 0x82, 0xA3, 0xE1, 0x5B, 0x2C, 0xB4}};RND_DEBUG_Instantiate(&dbg, &k.b);#define RANDOM(RAND_STATE *)&dbg#else#
define RANDOM
NULL#endifif (E == NULL)ERROR_RETURN(TPM_RC_CURVE);
if (TPM_ALG_KDF2 != scheme->scheme)
ERROR_RETURN(TPM_RC_SCHEME);// generate an ephemeral key from a random k
if (!BnEccGenerateKeyPair(D, Px, E, RANDOM)// C1 is the public part of the ephemeral key|| !BnPointTo2B(c1, Px, E)// Compute P2|| (BnPointMult(Px, PB, D, NULL, NULL, E) != TPM_RC_SUCCESS)|| !BnPointTo2B(&p2, Px, E))
ERROR_RETURN(TPM_RC_NO_RESULT);//Compute the C3 value hash(x2 || M || y2)
if (0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg))
ERROR_RETURN(TPM_RC_HASH);
CryptDigestUpdate2B(&hashState, &p2.x.b);
CryptDigestUpdate2B(&hashState, &plainText->b);
CryptDigestUpdate2B(&hashState, &p2.y.b);c3->t.size = CryptHashEnd(&hashState, sizeof(c3->t.buffer), c3->t.buffer);
MemoryCopy2B(&z.b, &p2.x.b, sizeof(z.t.buffer));
MemoryConcat2B(&z.b, &p2.y.b, sizeof(z.t.buffer));// Generate the mask value from MGF1 and put it in the return bufferc2->t.size = CryptMGF_KDF(plainText->t.size, c2->t.buffer,scheme->details.mgf1.hashAlg, z.t.size, z.t.buffer, 1);// XOR the plainText into the generated mask to create the obfuscated datafor (i = 0; i < plainText->t.size; i++)c2->t.buffer[i] ^= plainText->t.buffer[i];Exit:
CURVE_FREE(E);return retVal;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 865
December 24, 2020

Part 4: Supporting Routines

10.2.28.2.3

Trusted Platform Module Library

CryptEccDecrypt()This function performs ECC decryption and integrity check of the input data.

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

Error Return

Meaning

TPM_RC_CURVE

unsupported curve

TPM_RC_HASHhash not allowed

TPM_RC_SCHEME

scheme is not supported

TPM_RC_NO_RESULT

internal error in big number processing

TPM_RC_VALUE

C3 did not match hash of recovered data

LIB_EXPORT TPM_RC
CryptEccDecrypt(
OBJECT
TPMT_KDF_SCHEME
TPM2B_MAX_BUFFER
TPMS_ECC_POINT
TPM2B_MAX_BUFFER
TPM2B_DIGEST*key,*scheme,*plainText,
*c1,
*c2,
*c3

// IN: key used for data recovery// IN: scheme to use.
// OUT: the recovered text// IN: public ephemeral key// IN: obfuscated text// IN: digest of ephemeral key//
and plainText){
CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
ECC_INITIALIZED(D, &key->sensitive.sensitive.ecc.b);
POINT_INITIALIZED(C1, c1);
TPMS_ECC_POINTp2;
TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2);
TPM2B_DIGEST
check;TPM2B_2ECC
z;
int
i;
HASH_STATE
hashState;
TPM_RC
retVal = TPM_RC_SUCCESS;//
if (E == NULL)ERROR_RETURN(TPM_RC_CURVE);
if (TPM_ALG_KDF2 != scheme->scheme)
ERROR_RETURN(TPM_RC_SCHEME);// Generate the Z value
BnPointMult(C1, C1, D, NULL, NULL, E);
BnPointTo2B(&p2, C1, E);// Start the hash to check the algorithm
if (0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg))
ERROR_RETURN(TPM_RC_HASH);
CryptDigestUpdate2B(&hashState, &p2.x.b);
MemoryCopy2B(&z.b, &p2.x.b, sizeof(z.t.buffer));
MemoryConcat2B(&z.b, &p2.y.b, sizeof(z.t.buffer));// Generate the mask
plainText->t.size = CryptMGF_KDF(c2->t.size, plainText->t.buffer,scheme->details.mgf1.hashAlg, z.t.size,
z.t.buffer, 1);// XOR the obfuscated data into the generated mask to create the plainText datafor (i = 0; i < plainText->t.size; i++)plainText->t.buffer[i] ^= c2->t.buffer[i];// Complete the hash and verify the data
CryptDigestUpdate2B(&hashState, &plainText->b);
CryptDigestUpdate2B(&hashState, &p2.y.b);check.t.size = CryptHashEnd(&hashState, sizeof(check.t.buffer), check.t.buffer);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 866
December 24, 2020

Part 4: Supporting Routines
140
141
142
143
144
145
146

Trusted Platform Module Library

if (!MemoryEqual2B(&check.b, &c3->b))
ERROR_RETURN(TPM_RC_VALUE);
Exit:
CURVE_FREE(E);return retVal;}#endif // CC_ECC_Encrypt || CC_ECC_Encrypt

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 867
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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 Registry,
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 command line.
Additionally, TpmBuildSwitches.h allows an additional file to be specified in the compiler command line
and preset any of these values.
A.2
1
2

TpmProfile.h#ifndef _TPM_PROFILE_H_#define _TPM_PROFILE_H_

TPM 2.0 Part 2: Table 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

Vendor -Specific: Table 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

Vendor -Specific: Table 4 - Defines for Implemented Curves
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 868
December 24, 2020

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
YES

Vendor -Specific: Table 6 - Defines for Implemented ACT
54
55
56
57
58
59
60
61
62

#ifndef RH_ACT_0#define RH_ACT_0#endif#ifndef RH_ACT_1#define RH_ACT_1#endif#ifndef RH_ACT_A#define RH_ACT_A#endifYES
NO
YES

Vendor -Specific: Table 7 - Defines for Implementation 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

#ifndef FIELD_UPGRADE_IMPLEMENTED#define FIELD_UPGRADE_IMPLEMENTED#endif#ifndef HASH_LIB#define HASH_LIB#endif#ifndef SYM_LIB#define SYM_LIB#endif#ifndef MATH_LIB#define MATH_LIB#endif#ifndef IMPLEMENTATION_PCR#define IMPLEMENTATION_PCR#endif#ifndef PLATFORM_PCR#define PLATFORM_PCR#endif#ifndef DRTM_PCR#define DRTM_PCR#endif#ifndef HCRTM_PCR#define HCRTM_PCR#endif#ifndef NUM_LOCALITIES#define NUM_LOCALITIESFamily “2.0”Level 00 Revision 01.64

NO
Ossl
Ossl
Ossl
24
24
17
0
5

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 869
December 24, 2020

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

Trusted Platform Module Library#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 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_SIZE#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

Family “2.0”Level 00 Revision 01.64

364
UINT16
3
3
3
2
1
1
1344
1024
2048
1024
1024
16384
8
16
64
32
AES
12
1

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 870
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#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 SIZE_OF_X509_SERIAL_NUMBER#define SIZE_OF_X509_SERIAL_NUMBER#endif#ifndef PRIVATE_VENDOR_SPECIFIC_BYTES#define PRIVATE_VENDOR_SPECIFIC_BYTES#endif

4096
4096
8
128
64
512
0x00010001
YES
YES
0
1024
20
RSA_PRIVATE_SIZE

Vendor -Specific: Table 2 - Defines for Implemented Algorithms
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

#ifndef ALG_AES#define ALG_AES#endif#ifndef ALG_CAMELLIA#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

Family “2.0”Level 00 Revision 01.64

ALG_YESALG_YESALG_YESALG_YESALG_YESALG_YESALG_YESTCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 871
December 24, 2020

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

#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#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

Family “2.0”Level 00 Revision 01.64

Trusted Platform Module Library
ALG_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_YESALG_YESALG_YES(ALG_YES && ALG_RSA)
ALG_YESALG_YES(ALG_YES && ALG_RSA)(ALG_YES && ALG_RSA)(ALG_YES && ALG_RSA)
ALG_NOALG_YESALG_YESALG_YESTCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 872
December 24, 2020

Part 4: Supporting Routines
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

#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_NOALG_NOALG_NOALG_NO(ALG_YES && ALG_ECC)
ALG_YESALG_YESALG_YESALG_NOALG_YESTCG Algorithm Registry: Table 3 - Defines for RSA Asymmetric Cipher Algorithm Constants
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

#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#ifndef RSA_16384#define RSA_16384#endif(ALG_RSA && YES)
(ALG_RSA && YES)
(ALG_RSA && NO)(ALG_RSA && NO)(ALG_RSA && NO)

TCG Algorithm Registry: Table 21 - Defines for AES Symmetric Cipher Algorithm Constants
327
328
329
330
331
332
333
334
335

#ifndef AES_128#define AES_128#endif#ifndef AES_192#define AES_192#endif#ifndef AES_256#define AES_256#endif(ALG_AES && YES)
(ALG_AES && NO)(ALG_AES && YES)TCG Algorithm Registry: Table 22 - Defines for SM4 Symmetric Cipher Algorithm Constants
336
337#ifndef SM4_128#define SM4_128

Family “2.0”Level 00 Revision 01.64(ALG_SM4 && YES)TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 873
December 24, 2020

Part 4: Supporting Routines
338

Trusted Platform Module Library#endif

TCG Algorithm Registry: Table 23 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants
339
340
341
342
343
344
345
346
347

#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 && YES)TCG Algorithm Registry: Table 24 - Defines for TDES Symmetric Cipher Algorithm Constants
348
349
350
351
352
353

#ifndef TDES_128#define TDES_128#endif#ifndef TDES_192#define TDES_192#endif(ALG_TDES && YES)
(ALG_TDES && YES)

Vendor -Specific: Table 5 - Defines for Implemented Commands
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

#ifndef CC_ACT_SetTimeout#define CC_ACT_SetTimeout#endif#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#define CC_Clear#endif#ifndef CC_ClearControl#define CC_ClearControl#endif#ifndef CC_ClockRateAdjust#define CC_ClockRateAdjust#endif#ifndef CC_ClockSet#define CC_ClockSet#endifFamily “2.0”Level 00 Revision 01.64

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-2021

Page 874
December 24, 2020

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
454
455
456
457
458

Trusted Platform Module Library#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_Decrypt#define CC_ECC_Decrypt#endif#ifndef CC_ECC_Encrypt#define CC_ECC_Encrypt#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#define CC_FieldUpgradeStart#endif#ifndef CC_FirmwareRead#define CC_FirmwareRead#endifFamily “2.0”Level 00 Revision 01.64(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 && ALG_ECC)(CC_YES && ALG_ECC)
CC_YES
CC_YES
CC_YES
CC_YES
CC_NO
CC_NO
CC_NO

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 875
December 24, 2020

Part 4: Supporting Routines
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
515
516
517
518
519
520
521
522
523
524

Trusted Platform Module Library#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#define CC_NV_Certify#endif#ifndef CC_NV_ChangeAuth#define CC_NV_ChangeAuth#endifFamily “2.0”Level 00 Revision 01.64

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
CC_YES
CC_YES

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 876
December 24, 2020

Part 4: Supporting Routines
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
581
582
583
584
585
586
587
588
589
590

Trusted Platform Module Library#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#define CC_PP_Commands#endif#ifndef CC_PolicyAuthValue#define CC_PolicyAuthValue#endifFamily “2.0”Level 00 Revision 01.64

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-2021

Page 877
December 24, 2020

Part 4: Supporting Routines
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
650
651
652
653
654
655
656

Trusted Platform Module Library#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_SendSelect#define CC_Policy_AC_SendSelect#endif#ifndef CC_Quote#define CC_Quote#endifFamily “2.0”Level 00 Revision 01.64

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-2021

Page 878
December 24, 2020

Part 4: Supporting Routines
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
717
718
719
720
721

Trusted Platform Module Library#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#define CC_ZGen_2Phase#endif(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(CC_YES && ALG_ECC)#endif // _TPM_PROFILE_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 879
December 24, 2020

Part 4: Supporting Routines

A.3

TpmSizeChecks.c

A.3.1.
1
2
3
4
5
6
7
8
9
10
11

Trusted Platform Module Library

Includes, Defines, and Types#include#include#include"Tpm.h"<stdio.h><assert.h>#if RUNTIME_SIZE_CHECKS#if TABLE_DRIVEN_MARSHAL
extern uint32_t
MarshalDataSize;#endifstaticA.3.2.

int once = 0;

TpmSizeChecks()

This function is used during the development process to make sure that the vendor-specific values resultin a consistent implementation. When possible, the code contains #if to do compile-time checks.
However, in some cases, the values require the use of sizeof() and that can't be used in an #if.
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

BOOL
TpmSizeChecks(
void
)
{
BOOL
PASS = TRUE;#if DEBUG//
if(once++ != 0)
return 1;{
UINT32
maxAsymSecurityStrength = MAX_ASYM_SECURITY_STRENGTH;UINT32
maxHashSecurityStrength = MAX_HASH_SECURITY_STRENGTH;UINT32
maxSymSecurityStrength = MAX_SYM_SECURITY_STRENGTH;UINT32
maxSecurityStrengthBits = MAX_SECURITY_STRENGTH_BITS;
UINT32
proofSize = PROOF_SIZE;UINT32compliantProofSize = COMPLIANT_PROOF_SIZE;UINT32compliantPrimarySeedSize = COMPLIANT_PRIMARY_SEED_SIZE;UINT32
primarySeedSize = PRIMARY_SEED_SIZE;UINT32
UINT32
UINT32

cmacState = sizeof(tpmCmacState_t);
hashState = sizeof(HASH_STATE);
keyScheduleSize = sizeof(tpmCryptKeySchedule_t);//
NOT_REFERENCED(cmacState);
NOT_REFERENCED(hashState);
NOT_REFERENCED(keyScheduleSize);
NOT_REFERENCED(maxAsymSecurityStrength);
NOT_REFERENCED(maxHashSecurityStrength);
NOT_REFERENCED(maxSymSecurityStrength);
NOT_REFERENCED(maxSecurityStrengthBits);
NOT_REFERENCED(proofSize);
NOT_REFERENCED(compliantProofSize);
NOT_REFERENCED(compliantPrimarySeedSize);
NOT_REFERENCED(primarySeedSize);{
TPMT_SENSITIVE*p;// This assignment keeps compiler from complaining about a conditional// comparison being between two constants
UINT16
max_rsa_key_bytes = MAX_RSA_KEY_BYTES;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 880
December 24, 2020

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

Trusted Platform Module Libraryif((max_rsa_key_bytes / 2) != (sizeof(p->sensitive.rsa.t.buffer) / 5)){
printf("Sensitive part of TPMT_SENSITIVE is undersized. May be caused"" by use of wrong version of Part 2.\n");PASS = FALSE;}}#if TABLE_DRIVEN_MARSHAL
printf("sizeof(MarshalData) = %zu\n", sizeof(MarshalData_st));#endifprintf("Size of OBJECT = %zu\n", sizeof(OBJECT));
printf("Size of components in TPMT_SENSITIVE = %zu\n",sizeof(TPMT_SENSITIVE));
printf("
TPMI_ALG_PUBLIC%zu\n", sizeof(TPMI_ALG_PUBLIC));
printf("TPM2B_AUTH%zu\n", sizeof(TPM2B_AUTH));
printf("TPM2B_DIGEST%zu\n", sizeof(TPM2B_DIGEST));
printf("
TPMU_SENSITIVE_COMPOSITE%zu\n",
sizeof(TPMU_SENSITIVE_COMPOSITE));}// Make sure that the size of the context blob is large enough for the largest// context// TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is// implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to// determine the amount of data in the encrypted data. That part is not// independently sized. This makes the actual size 2 bytes smaller than// calculated using Part 2. Since this is opaque to the caller, it is not// necessary to fix. The actual size is returned by TPM2_GetCapabilties().
// Initialize output handle. At the end of command action, the output// handle of an object will be replaced, while the output handle// for a session will be the same as input// Get the size of fingerprint in context blob. The sequence value in// TPMS_CONTEXT structure is used as the fingerprint{
UINT32 fingerprintSize = sizeof(UINT64);
UINT32 integritySize = sizeof(UINT16)+ CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);UINT32 biggestObject = MAX(MAX(sizeof(HASH_OBJECT), sizeof(OBJECT)),sizeof(SESSION));UINT32 biggestContext = fingerprintSize + integritySize + biggestObject;// round required size up to nearest 8 byte boundary.
biggestContext = 8 * ((biggestContext + 7) / 8);if(MAX_CONTEXT_SIZE < biggestContext){
printf("MAX_CONTEXT_SIZE needs to be increased to at least %d (%d)\n",biggestContext, MAX_CONTEXT_SIZE);PASS = FALSE;}
else if (MAX_CONTEXT_SIZE > biggestContext){
printf("MAX_CONTEXT_SIZE can be reduced to %d (%d)\n",biggestContext, MAX_CONTEXT_SIZE);}}{
union u{
TPMA_OBJECT
attributes;
UINT32
uint32Value;} u;// these are defined so that compiler doesn't complain about conditional// expressions comparing two constants.

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 881
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

int
aSize = sizeof(u.attributes);
intuSize = sizeof(u.uint32Value);u.uint32Value = 0;
SET_ATTRIBUTE(u.attributes, TPMA_OBJECT, fixedTPM);
if(u.uint32Value != 2){
printf("The bit allocation in a TPMA_OBJECT is not as expected");PASS = FALSE;}
if(aSize != uSize) // comparison of two sizeof() values annoys compiler{
printf("A TPMA_OBJECT is not the expected size.");PASS = FALSE;}}// Check that the platorm implementes each of the ACT that the TPM thinks are// present{
uint32_t
act;
for(act = 0; act < 16; act++){
switch(act){
FOR_EACH_ACT(CASE_ACT_NUMBER)
if(!_plat__ACT_GetImplemented(act)){
printf("TPM_RH_ACT_%1X is not implemented by platform\n",act);
PASS = FALSE;}
default:
break;}}}#endif // DEBUG
return (PASS);}#endif // RUNTIME_SIZE_CHECKSFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 882
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 883
December 24, 2020

Part 4: Supporting Routines

B.2

Trusted Platform Module Library

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

#ifndef HASH_LIB_DEFINED#define HASH_LIB_DEFINED#define HASH_LIB_OSSL#include <openssl/evp.h>#include <openssl/sha.h>#if ALG_SM3_256#
if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L#
undef ALG_SM3_256#
define ALG_SM3_256 ALG_NO#
elif OPENSSL_VERSION_NUMBER >= 0x10200000L#
include <openssl/sm3.h>#else// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory,// and they do not get installed as part of the libssl package#
define SM3_LBLOCK(64/4)
typedef struct SM3state_st {unsigned int A, B, C, D, E, F, G, H;
unsigned int Nl, Nh;unsigned int data[SM3_LBLOCK];
unsigned int num;
} SM3_CTX;
int sm3_init(SM3_CTX *c);
int sm3_update(SM3_CTX *c, const void *data, size_t len);int sm3_final(unsigned char *md, SM3_CTX *c);#endif // OpenSSL < 1.2#endif // ALG_SM3_256#include <openssl/ossl_typ.h>#define HASH_ALIGNMENT

B.2.2.1.2.

RADIX_BYTES

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.
36
37#define tpmHashStateSHA1_t#define tpmHashStateSHA256_t

SHA_CTX
SHA256_CTX

Family “2.0”

TCG PUBLIC REVIEW

Level 00 Revision 01.64

Copyright © TCG 2006-2021

Page 884
December 24, 2020

Part 4: Supporting Routines
38
39
40

#define tpmHashStateSHA384_t#define tpmHashStateSHA512_t#define tpmHashStateSM3_256_t

Trusted Platform Module Library
SHA512_CTX
SHA512_CTX
SM3_CTX

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.
41
42
43
44

#ifdef _CRYPT_HASH_C_
typedef BYTE
typedef const BYTE*PBYTE;*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
45
46
47

#define HASH_START_METHOD_DEF
void (HASH_START_METHOD)(PANY_HASH_STATE state)#define HASH_START(hashState)\((hashState)->def->method.start)(&(hashState)->state);

Add data to the hash
48
49
50
51
52
53

#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
54
55
56
57

#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

58
59
60
61
62
63
64
65

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 blob66

#define

HASH_STATE_EXPORT_METHOD_DEF

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 885
December 24, 2020

Part 4: Supporting Routines
67
68
69
70
71
72
73
74

#defineTrusted Platform Module Libraryvoid (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
75
76
77
78
79
80
81
82
83

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

#define tpmHashStart_SHA1

SHA1_Init// external name of the// initialization method#define tpmHashData_SHA1#define tpmHashEnd_SHA1#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_SHA_512#define tpmHashStart_SM3_256#define tpmHashData_SM3_256#define tpmHashEnd_SM3_256#define tpmHashStateCopy_SM3_256#define tpmHashStateExport_SM3_256#define tpmHashStateImport_SM3_256

SHA1_Update
SHA1_Final
memcpymemcpymemcpySHA256_Init
SHA256_Update
SHA256_Final
memcpymemcpymemcpySHA384_Init
SHA384_Update
SHA384_Final
memcpymemcpymemcpySHA512_Init
SHA512_Update
SHA512_Final
memcpymemcpymemcpysm3_init
sm3_update
sm3_final
memcpymemcpymemcpy#endif // _CRYPT_HASH_C_#define LibHashInit()

This definition would change if there were something to report119120#define HashLibSimulationEnd()

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 886
December 24, 2020

Part 4: Supporting Routines
121

Trusted Platform Module Library#endif // HASH_LIB_DEFINED

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 887
December 24, 2020

Part 4: Supporting Routines

B.2.2.2.

TpmToOsslMath.h

B.2.2.2.1.

Introduction

Trusted Platform Module LibraryThis file contains the structure definitions used for ECC in the OpenSSL 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
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#ifndef MATH_LIB_DEFINED#define MATH_LIB_DEFINED#define MATH_LIB_OSSL#include <openssl/evp.h>#include <openssl/ec.h>#define SYMMETRIC_ALIGNMENT RADIX_BYTES#if OPENSSL_VERSION_NUMBER >= 0x10200000L// Check the bignum_st definition in crypto/bn/bn_lcl.h and either update the// version check or provide the new definition for this version.
#
error Untested OpenSSL version#elif OPENSSL_VERSION_NUMBER >= 0x10100000L// from crypto/bn/bn_lcl.h
struct bignum_st {BN_ULONG *d;
int top;int dmax;
int neg;
int flags;
};
#else
#
define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp#
define EC_POINT_set_affine_coordinates EC_POINT_set_affine_coordinates_GFp#endif // OPENSSL_VERSION_NUMBER#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
31
32
33
34
35

#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.
36
37
38
39
40
41

#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
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 888
December 24, 2020

Part 4: Supporting Routines
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

Trusted Platform Module Library#define BIG_INITIALIZED(name, initializer)\
BIGNUM_##name;\BIGNUM*name = BigInitialized(&_##name, initializer)
typedef struct{const ECC_CURVE_DATA
EC_GROUP
BN_CTX

*C;
*G;
*CTX;

// the TPM curve values// group parameters// 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
59
60#define OSSL_ENTER()#define OSSL_LEAVE()

BN_CTX*CTX = OsslContextEnter()
OsslContextLeave(CTX)

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.
61
62
63
64

#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
65
66
67
68

#define ECC_ENTER()#define ECC_LEAVE()

BN_CTX*CTX = OsslPushContext(E->CTX)
OsslPopContext(CTX)#define BN_NEW()

BnNewVariable(CTX)

This definition would change if there were something to report
69
70
71

#define MathLibSimulationEnd()#endif // MATH_LIB_DEFINED

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 889
December 24, 2020

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.
All of the library-dependent headers should have the same guard to that only the first one gets defined.
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

#ifndef SYM_LIB_DEFINED#define SYM_LIB_DEFINED#define SYM_LIB_OSSL#include <openssl/aes.h>#if ALG_TDES#include <openssl/des.h>#endif#if ALG_SM4#
if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L#
undef ALG_SM4#
define ALG_SM4 ALG_NO#
elif OPENSSL_VERSION_NUMBER >= 0x10200000L#
include <openssl/sm4.h>#else// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory,// and they do not get installed as part of the libssl package#

define SM4_KEY_SCHEDULE

32

typedef struct SM4_KEY_st {uint32_t rk[SM4_KEY_SCHEDULE];} SM4_KEY;
int SM4_set_key(const uint8_t *key, SM4_KEY *ks);void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);#
endif // OpenSSL < 1.2#endif // ALG_SM4#if ALG_CAMELLIA#include <openssl/camellia.h>#endif#include <openssl/bn.h>#include <openssl/ossl_typ.h>

B.2.2.3.2.

Links to the OpenSSL symmetric algorithms.

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.
40#define SWIZZLE(keySchedule, in, out)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\

Page 890
December 24, 2020

Part 4: Supporting Routines
41

Trusted Platform Module Library(const BYTE *)(in), (BYTE *)(out), (void *)(keySchedule)

Define the order of parameters to the library functions that do block encryption and decryption.
42
43
44
45
46
47
48

typedef void(*TpmCryptSetSymKeyCall_t)(
const BYTE *in,
BYTE
*out,
void *keySchedule);#define SYM_ALIGNMENT

B.2.2.3.3.

RADIX_BYTES

Links to the OpenSSL AES code

Macros to set up the encryption/decryption key schedules
AES:
49
50
51
52

#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))\\

Macros to alias encryption calls to specific algorithms. This should be used sparingly. Currently, only usedby CryptSym.c and CryptRand.c
When using these calls, to call the AES block encryption code, the caller should use:
TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out));
53
54
55

#define TpmCryptEncryptAES#define TpmCryptDecryptAES#define tpmKeyScheduleAES

B.2.2.3.4.
56
57
58
59
60
61
62
63

AES_encrypt
AES_decrypt
AES_KEY

Links to the OpenSSL DES code

#if ALG_TDES#include "TpmToOsslDesSupport_fp.h"#endif#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))\\

Macros to alias encryption calls to specific algorithms. This should be used sparingly. Currently, only usedby CryptRand.c
64
65
66

#define TpmCryptEncryptTDES#define TpmCryptDecryptTDES#define tpmKeyScheduleTDES

B.2.2.3.5.

TDES_encrypt
TDES_decrypt
DES_key_schedule

Links to the OpenSSL SM4 code

Macros to set up the encryption/decryption key schedules
67
68
69
70

#define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule)
SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule))#define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule)
SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule))

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021\\

Page 891
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Macros to alias encryption calls to specific algorithms. This should be used sparingly.
71
72
73

#define TpmCryptEncryptSM4#define TpmCryptDecryptSM4#define tpmKeyScheduleSM4

B.2.2.3.6.

SM4_encrypt
SM4_decrypt
SM4_KEY

Links to the OpenSSL CAMELLIA code

Macros to set up the encryption/decryption key schedules
74
75
76
77

#define TpmCryptSetEncryptKeyCAMELLIA(key, keySizeInBits, schedule)
Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule))#define TpmCryptSetDecryptKeyCAMELLIA(key, keySizeInBits, schedule)
Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule))\\

Macros to alias encryption calls to specific algorithms. This should be used sparingly.
78
79
80

#define TpmCryptEncryptCAMELLIA#define TpmCryptDecryptCAMELLIA#define tpmKeyScheduleCAMELLIA

Camellia_encrypt
Camellia_decrypt
CAMELLIA_KEY

Forward reference81

typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t;

This definition would change if there were something to report
82
83
84

#define SymLibSimulationEnd()#endif // SYM_LIB_DEFINED

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 892
December 24, 2020

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
3

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.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

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.
21
22
23
24
25
26
27
28
29
30

void TDES_encrypt(
const BYTE
BYTE
tpmKeyScheduleTDES
)

*in,
*out,
*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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 893
December 24, 2020

Part 4: Supporting Routines

B.2.3.1.3.3.

Trusted Platform Module Library

TDES_decrypt()

As with TDES_encypt() this function bridges between the TPM single schedule model and the OpenSSL
three schedule model.
31
32
33
34
35
36
37
38
39
40
41

void TDES_decrypt(
const BYTE
BYTE
tpmKeyScheduleTDES
)

*in,
*out,
*ks

{
DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out,&ks[0], &ks[1], &ks[2],DES_DECRYPT);}#endif // SYM_LIB_OSSLFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 894
December 24, 2020

Part 4: Supporting Routines

B.2.3.2.

TpmToOsslMath.c

B.2.3.2.1.

Introduction

Trusted Platform Module Library

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 function 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.2.
1
2
3
4

Includes and Defines#include "Tpm.h"#ifdef MATH_LIB_OSSL#include "TpmToOsslMath_fp.h"

B.2.3.2.3.

Functions

B.2.3.2.3.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.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

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);// 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);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 895
December 24, 2020

Part 4: Supporting Routines
22
23
24
25
26

Trusted Platform Module Library}
return TRUE;
Error:
return FALSE;}

B.2.3.2.3.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().
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

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 = (int)initializer->allocated;
toInit->top = (int)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.3.3.
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

*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){
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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 896
December 24, 2020

Part 4: Supporting Routines
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

Trusted Platform Module Library{
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.3.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.
90
91
92
93
94
95
96
97
98
99
100
101
102
103

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

MathLibraryCompatibilityCheck()

BOOL
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
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 1;
Error:

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 897
December 24, 2020

Part 4: Supporting Routines
129
130
131

Trusted Platform Module Library

return 0;}#endifB.2.3.2.3.6.

BnModMult()

This function does a modular multiply. It first does a multiply and then a divide and returns the remainderof the divide.

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

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

BnMult()Multiplies two numbers

158
159
160
161
162
163
164
165
166
167
168

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

LIB_EXPORT BOOL
BnMult(bigNumbigConst
bigConst)

result,multiplicand,multiplier{
OSSL_ENTER();BIGNUM*bnTemp = BN_NEW();
BOOL
OK = TRUE;
BIG_INITIALIZED(bnA, multiplicand);Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 898
December 24, 2020

Part 4: Supporting Routines
169
170
171
172
173
174
175
176
177
178
179

Trusted Platform Module Library

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

BnDiv()

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

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

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;}#if ALG_RSA

B.2.3.2.3.9.

BnGcd()

Get the greatest common divisor of two numbers

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 899
December 24, 2020

Part 4: Supporting Routines

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

Trusted Platform Module Library

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

gcd,
number1,
number2// OUT: the common divisor// IN:// IN:

LIB_EXPORT BOOL
BnGcd(
bigNumbigConst
bigConst){
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.3.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

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

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));
goto Exit;
Error:OK = FALSE;Exit:
OSSL_LEAVE();
return OK;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 900
December 24, 2020

Part 4: Supporting Routines

B.2.3.2.3.11.

Trusted Platform Module Library

BnModInverse()

Modular multiplicative inverse

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

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

PointFromOssl()

Function to copy the point result from an OSSL function to a bigNum

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

Return Value

Meaning

TRUE(1)success

FALSE(0)failure in operation

static BOOL
PointFromOssl(
bigPoint
EC_POINT
bigCurve
)

pOut,
*pIn,
E

// OUT: resulting point// IN: the point to return// IN: the curve{
BIGNUM*x = NULL;BIGNUM*y = NULL;
BOOLOK;
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 901
December 24, 2020

Part 4: Supporting Routines
302
303
304
305
306
307
308
309
310
311
312
313

Trusted Platform Module Library

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

EcPointInitialized()

Allocate and initialize a point.
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

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);if(E == NULL)
FAIL(FATAL_ERROR_ALLOCATION);
P = EC_POINT_new(E->G);if(!EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX))
P = NULL;}
return P;}

B.2.3.2.3.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.
Return Value
NULL
non-NULL
334
335
336
337
338
339
340
341
342
343
344
345

Meaning*
the TPM_ECC_CURVE is not valid or there was a
problem in in initializing the curve data
points to E

LIB_EXPORT bigCurve
BnCurveInitialize(
bigCurve
TPM_ECC_CURVE

E,
curveId// IN: curve structure to initialize// IN: curve identifier){
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

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 902
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// curve (E) is defined.
OSSL_ENTER();
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);// if the allocation fails, the TPM fails//
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.3.15.

BnCurveFree()This function will free the allocated components of the curve and end the frame in which the curve data
exists
386
387
388
389
390
391
392
393
394
395
396

LIB_EXPORT void
BnCurveFree(
bigCurve

E

)
{
if(E)
{
EC_GROUP_free(E->G);
OsslContextLeave(E->CTX);}}

B.2.3.2.3.16.

BnEccModMult()

This function does a point multiply of the form R = [d]SFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 903
December 24, 2020

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

Trusted Platform Module Library

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

BnEccModMult2()

This function does a point multiply of the form R = [d]G + [u]Q

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

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{
const EC_POINT*points[2];const BIGNUM*scalars[2];points[0] = pS;
points[1] = pQ;
scalars[0] = bnD;
scalars[1] = bnU;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 904
December 24, 2020

Part 4: Supporting Routines
444
445
446
447
448
449
450
451

Trusted Platform Module Library

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

BnEccAdd()

This function does addition of two points.

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 905
December 24, 2020

Part 4: Supporting Routines

B.2.3.3.

Trusted Platform Module Library

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
3

Defines and Includes#include "Tpm.h"#if defined(HASH_LIB_OSSL) || defined(MATH_LIB_OSSL) || defined(SYM_LIB_OSSL)

Used to pass the pointers to the correct sub-keys
4

typedef const BYTE *desKeyPointers[3];B.2.3.3.2.1.

SupportLibInit()

This does any initialization required by the support library.
5
6
7
8
9
10
11

LIB_EXPORT int
SupportLibInit(
void){
return 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.
12
13
14
15
16
17
18
19
20

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().
21
22
23
24
25
26
27
28

void
OsslContextLeave(
BN_CTX)*CTX{
OsslPopContext(CTX);
BN_CTX_free(CTX);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 906
December 24, 2020

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()
29
30
31
32
33
34
35
36
37
38

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().
39
40
41
42
43
44
45
46
47
48

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 // HASH_LIB_OSSL || MATH_LIB_OSSL || SYM_LIB_OSSLFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 907
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Annex C
(informative)
Simulation Environment
C.1

Introduction

These files are used to simulate some of the implementation-dependent hardware of a TPM. These files
are provided to allow creation of a simulation environment for the TPM. These files are not expected to 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
Return Value

2
3
4
5
6
7
8
9

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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 908
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 909
December 24, 2020

Part 4: Supporting Routines

C.3

Trusted Platform Module Library

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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 910
December 24, 2020

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

LIB_EXPORT 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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 911
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library

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}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 912
December 24, 2020

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 int_plat__TimerWasReset(
void
)
{
int
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 int_plat__TimerWasStopped(
void
)
{
int
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.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 913
December 24, 2020

Part 4: Supporting Routines
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

Trusted Platform Module Librarycase 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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 914
December 24, 2020

Part 4: Supporting Routines

C.4

Entropy.c

C.4.1.
1
2
3
4
5
6
7
8
9
10
11

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 an RNG produces blocks of n bits (where n > 15), the first n-bit block generated after
power-up, initialization, or reset shall not be used, but shall be saved for comparison with the next nbit block to be generated. Each subsequent generation of an n-bit block shall be compared with thepreviously generated block. The test shall fail if any two compared n-bit blocks are equal."
12

extern uint32_t

C.4.2.

FunctionsC.4.2.1.

rand32()

lastEntropy;

Local function to get a 32-bit random number
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 915
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

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

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;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 916
December 24, 2020

Part 4: Supporting Routines
93

Trusted Platform Module Library}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 917
December 24, 2020

Part 4: Supporting Routines

1

C.5

LocalityPlat.c

C.5.1.

IncludesTrusted Platform Module Library#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;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 918
December 24, 2020

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
9

#include <memory.h>#include <string.h>#include <assert.h>#include "Platform.h"#if FILE_BACKED_NV#
include<stdio.h>static FILE
*s_NvFile = NULL;
static int
s_NeedsManufacture = FALSE;#endifC.6.3.
10

Includes and Local

Functions#if FILE_BACKED_NV

C.6.3.1.

NvFileOpen()

This function opens the file used to hold the NV image.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

Return Value

Meaning>= 0

success-1

error

static int
NvFileOpen(
const char
*mode
)
{
#if defined(NV_FILE_PATH)#
define TO_STRING(s) TO_STRING_IMPL(s)#define TO_STRING_IMPL(s) #s
const char* s_NvFilePath = TO_STRING(NV_FILE_PATH);#
undef TO_STRING#
undef TO_STRING_IMPL#else
const char* s_NvFilePath = "NVChip";#endif###// Try to open an exist NVChip file for read/write
if defined _MSC_VER && 1
if(fopen_s(&s_NvFile, s_NvFilePath, mode) != 0)s_NvFile = NULL;
else
s_NvFile = fopen(s_NvFilePath, mode);
endif
return (s_NvFile == NULL) ? -1 : 0;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 919
December 24, 2020

Part 4: Supporting Routines

C.6.3.2.

Trusted Platform Module Library

NvFileCommit()

Write all of the contents of the NV image to a file.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

Return Value

Meaning

TRUE(1)success

FALSE(0)failurestatic int
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 where desired using the seek method
values. SEEK_SET => beginning; SEEK_CUR => current position and SEEK_END => to the end of the
file.
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

static long
NvFileSize(
int

leaveAt

)
{
long
long

fileSize;
filePos = ftell(s_NvFile);//
assert(NULL != s_NvFile);
int fseek_result = fseek(s_NvFile, 0, SEEK_END);NOT_REFERENCED(fseek_result); // Fix compiler warning for NDEBUG
assert(fseek_result == 0);
fileSize = ftell(s_NvFile);
assert(fileSize >= 0);
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;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 920
December 24, 2020

Part 4: Supporting Routines
81

Trusted Platform Module Library#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
82
83
84
85
86
87
88
89
90

LIB_EXPORT void
_plat__NvErrors(
int
int
)

recoverable,
unrecoverable{
s_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.

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 data
if (NV_MEMORY_SIZE == fileSize){s_NeedsManufacture =Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 921
December 24, 2020

Part 4: Supporting Routines
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

Trusted Platform Module Libraryfread(s_NV, 1, NV_MEMORY_SIZE, s_NvFile) != NV_MEMORY_SIZE;}
else{
NvFileCommit();// for any other size, initialize it
s_NeedsManufacture = TRUE;}}// If NVChip file does not exist, try to create it for read/write.
else if(NvFileOpen("w+b") >= 0){
NvFileCommit();// Initialize the files_NeedsManufacture = TRUE;}
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;}

C.6.3.6.

_plat__NVDisable()

Disable NV memory
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

LIB_EXPORT void
_plat__NVDisable(
int)

delete// IN: If TRUE, delete the NV contents.

{#if

FILE_BACKED_NV
if(NULL != s_NvFile){fclose(s_NvFile);// Close NV file// Alternative to deleting the file is to set its size to 0. This will not// match the NV size so the TPM will need to be remanufactured.
if(delete){// Open for writing at the start. Sets the size to zero.
if(NvFileOpen("w") >= 0){
fflush(s_NvFile);
fclose(s_NvFile);}}}s_NvFile = NULL;// Set file handle to NULL
#endifreturn;}C.6.3.7.

_plat__IsNvAvailable()

Check if NV is available

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 922
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

Return Value

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

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
180
181
182
183
184
185
186
187
188
189
190

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;}C.6.3.9.

_plat__NvIsDifferent()

This function checks to see if the NV is different from the test value. This is so that NV will not be written if
it has not changed.
Return Value

191
192
193
194
195
196
197
198
199

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);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 923
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

200
201
202
203
204
205
206
207
208
209
210
211
212
213

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 int_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.
214
215
216
217
218
219
220
221
222
223

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);}

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
224
225
226
227
228
229
230
231
232
233
234
235

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}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 924
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.
Return Value
0
non-0
236
237
238
239
240
241
242
243
244
245
246

Meaning
NV write success
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 theplatform NV logic
247
248
249
250
251
252
253
254

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
255
256
257
258
259
260
261
262

LIB_EXPORT void
_plat__ClearNvAvail(void){
s_NvIsAvailable = FALSE;
return;}C.6.3.16. _plat__NVNeedsManufacture()
This function is used by the simulator to determine when the TPM''s NV state needs to be manufactured.
263
264
265
266
267

LIB_EXPORT int_plat__NVNeedsManufacture(
void
)
{

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 925
December 24, 2020

Part 4: Supporting Routines
268
269
270
271
272
273

Trusted Platform Module Library#if FILE_BACKED_NV
return s_NeedsManufacture;#else
return FALSE;#endif}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 926
December 24, 2020

Part 4: Supporting Routines

C.7

PowerPlat.c

C.7.1.
1
2

Trusted Platform Module Library

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
Return Value

16
17
18
19
20
21
22
23
24

Meaning

TRUE(1)

power was lost

FALSE(0)power was not lost

LIB_EXPORT int_plat__WasPowerLost(
void
)
{
int
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(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 927
December 24, 2020

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
53
54
55

LIB_EXPORT void
_plat__Signal_PowerOff(
void){// Prepare NV memory for power off_plat__NVDisable(0);// Disable tick ACT tick processing_plat__ACT_EnableTicks(FALSE);
return;}Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 928
December 24, 2020

Part 4: Supporting Routines

C.8

Trusted Platform Module Library

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
3
4
5
6
7
8

#ifndef _PLATFORM_DATA_H_#define _PLATFORM_DATA_H_#ifdef _PLATFORM_DATA_C_#define EXTERN#else#define EXTERN extern#endifFrom Cancel.c Cancel flag. It is initialized as FALSE, which indicate the command is not being canceled
9
10
11
12

EXTERN int

s_isCanceled;#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.
13

EXTERN 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 int

s_timerReset;

This value indicates that the timer was stopped. It causes a clock discontinuity.
19

EXTERN int

s_timerStopped;

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
20

EXTERN uint64_ts_initClock;This variable records the timer adjustment factor.
21

EXTERN unsigned int

s_adjustRate;

For LocalityPlat.c Locality of current command
22

EXTERN unsigned char s_locality;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 929
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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.
23
24
25
26

#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
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#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#endif // SIMULATIONEXTERN unsigned char
EXTERN int
EXTERN int
EXTERN int

YES

s_NV[NV_MEMORY_SIZE];
s_NvIsAvailable;
s_NV_unrecoverable;
s_NV_recoverable;

For PPPlat.c Physical presence. It is initialized to FALSE
41

EXTERN int

s_physicalPresence;

From Power
42

EXTERN int

s_powerLost;

For Entropy.c
43
44
45
46
47
48
49
50

EXTERN uint32_t

lastEntropy;#define DEFINE_ACT(N)
EXTERN ACT_DATA ACT_##N;
FOR_EACH_ACT(DEFINE_ACT)EXTERN int

actTicksAllowed;#endif // _PLATFORM_DATA_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 930
December 24, 2020

Part 4: Supporting Routines

C.9

PlatformData.c

C.9.1.

Description

Trusted Platform Module LibraryThis 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
2

Includes#define _PLATFORM_DATA_C_#include"Platform.h"

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 931
December 24, 2020

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
Return Value

2
3
4
5
6
7
8
9
10

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 932
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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
1
2
3
4
5

#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.
6
7
8
9
10
11
12
13
14
15
16

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.
17
18
19
20
21
22
23

LIB_EXPORT NORETURN void
_plat__Fail(void){
longjmp(&s_jumpBuffer[0], 1);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 933
December 24, 2020

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
1
2
3
4
5

#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

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

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 934
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

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

#include <stdio.h>#include <time.h>#include "Platform.h"#if CERTIFYX509_DEBUG
const char*debugFileName = "DebugFile.txt";

C.13.2.1. fileOpen()
This exists to allow use of the safe version of fopen() with a MS runtime.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

static FILE *fileOpen(
const charconst char

*fn,
*mode

)
{
#
#
#

FILE
*f;
if defined _MSC_VER
if(fopen_s(&f, fn, mode) != 0)
f = NULL;else
f = fopen(fn, mode);
endif
return f;}

C.13.2.2. DebugFileInit()
This function initializes the file containing the debug data with the time of the file creation.

23
24
25
26
27
28
29
30
31
32
33
34
35

Return Value

Meaning0

success

!= 0

error

int
DebugFileInit(
void
)
{
FILE
time_t*f = NULL;t = time(NULL);//##// Get current date and time.
if defined _MSC_VER
chartimeString[100];
ctime_s(timeString, (size_t)sizeof(timeString), &t);
else

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 935
December 24, 2020

Part 4: Supporting Routines
36
37
38
39
40
41
42
43
44
45
46
47
48
49

#

Trusted Platform Module Librarychar*timeString;timeString = ctime(&t);
endif// Try to open the debug filef = fileOpen(debugFileName, "w");if(f){// Initialize the contents with the time.
fprintf(f, "%s\n", timeString);
fclose(f);return 0;}
return -1;}

C.13.2.3. DebugDumpBuffer()
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

void
DebugDumpBuffer(int
unsigned charconst char

size,
*buf,
*identifier

int

i;

)
{
//
FILE *f = fileOpen(debugFileName, "a");if(!f)
return;if(identifier)fprintf(f, "%s\n", identifier);if(buf){for(i = 0; i < size; i++){if(((i % 16) == 0) && (i))
fprintf(f, "\n");fprintf(f, " %02X", buf[i]);}if((size % 16) != 0)
fprintf(f, "\n");}fclose(f);}#endif // CERTIFYX509_DEBUG

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 936
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

C.14 Platform.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#ifndef#define_PLATFORM_H__PLATFORM_H_#include "TpmBuildSwitches.h"#include "BaseTypes.h"#include "TPMB.h"#include "MinMax.h"#include "TpmProfile.h"#include "PlatformACT.h"#include "PlatformClock.h"#include "PlatformData.h"#include "Platform_fp.h"#endif// _PLATFORM_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 937
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

C.15 PlatformACT.hThis file contains the definitions for the ACT macros and data types used in the ACT implementation.
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

#ifndef _PLATFORM_ACT_H_#define _PLATFORM_ACT_H_
typedef struct ACT_DATA{
uint32_tremaining;
uint32_t
newValue;
uint8_tsignaled;
uint8_tpending;
uint8_t
number;} ACT_DATA, *P_ACT_DATA;#if !(defined RH_ACT_0) || (RH_ACT_0 != YES)#
undef
RH_ACT_0#
define RH_ACT_0 NO#
define IF_ACT_0_IMPLEMENTED(op)#else#define IF_ACT_0_IMPLEMENTED(op) op(0)#endif#if !(defined RH_ACT_1) || (RH_ACT_1 != YES)#
undef
RH_ACT_1#
define RH_ACT_1 NO#
define IF_ACT_1_IMPLEMENTED(op)#else#define IF_ACT_1_IMPLEMENTED(op) op(1)#endif#if !(defined RH_ACT_2) || (RH_ACT_2 != YES)#
undef
RH_ACT_2#
define RH_ACT_2 NO#
define IF_ACT_2_IMPLEMENTED(op)#else#define IF_ACT_2_IMPLEMENTED(op) op(2)#endif#if !(defined RH_ACT_3) || (RH_ACT_3 != YES)#
undef
RH_ACT_3#
define RH_ACT_3 NO#
define IF_ACT_3_IMPLEMENTED(op)#else#define IF_ACT_3_IMPLEMENTED(op) op(3)#endif#if !(defined RH_ACT_4) || (RH_ACT_4 != YES)#
undef
RH_ACT_4#
define RH_ACT_4 NO#
define IF_ACT_4_IMPLEMENTED(op)#else#define IF_ACT_4_IMPLEMENTED(op) op(4)#endif#if !(defined RH_ACT_5) || (RH_ACT_5 != YES)#
undef
RH_ACT_5#
define RH_ACT_5 NO#
define IF_ACT_5_IMPLEMENTED(op)#else#define IF_ACT_5_IMPLEMENTED(op) op(5)#endif#if !(defined RH_ACT_6) || (RH_ACT_6 != YES)#
undef
RH_ACT_6#
define RH_ACT_6 NO#
define IF_ACT_6_IMPLEMENTED(op)#else#define IF_ACT_6_IMPLEMENTED(op) op(6)#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 938
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library#if !(defined RH_ACT_7) || (RH_ACT_7 != YES)#
undef
RH_ACT_7#
define RH_ACT_7 NO#
define IF_ACT_7_IMPLEMENTED(op)#else#define IF_ACT_7_IMPLEMENTED(op) op(7)#endif#if !(defined RH_ACT_8) || (RH_ACT_8 != YES)#
undef
RH_ACT_8#
define RH_ACT_8 NO#
define IF_ACT_8_IMPLEMENTED(op)#else#define IF_ACT_8_IMPLEMENTED(op) op(8)#endif#if !(defined RH_ACT_9) || (RH_ACT_9 != YES)#
undef
RH_ACT_9#
define RH_ACT_9 NO#
define IF_ACT_9_IMPLEMENTED(op)#else#define IF_ACT_9_IMPLEMENTED(op) op(9)#endif#if !(defined RH_ACT_A) || (RH_ACT_A != YES)#
undef
RH_ACT_A#
define RH_ACT_A NO#
define IF_ACT_A_IMPLEMENTED(op)#else#define IF_ACT_A_IMPLEMENTED(op) op(A)#endif#if !(defined RH_ACT_B) || (RH_ACT_B != YES)#
undef
RH_ACT_B#
define RH_ACT_B NO#
define IF_ACT_B_IMPLEMENTED(op)#else#define IF_ACT_B_IMPLEMENTED(op) op(B)#endif#if !(defined RH_ACT_C) || (RH_ACT_C != YES)#
undef
RH_ACT_C#
define RH_ACT_C NO#
define IF_ACT_C_IMPLEMENTED(op)#else#define IF_ACT_C_IMPLEMENTED(op) op(C)#endif#if !(defined RH_ACT_D) || (RH_ACT_D != YES)#
undef
RH_ACT_D#
define RH_ACT_D NO#
define IF_ACT_D_IMPLEMENTED(op)#else#define IF_ACT_D_IMPLEMENTED(op) op(D)#endif#if !(defined RH_ACT_E) || (RH_ACT_E != YES)#
undef
RH_ACT_E#
define RH_ACT_E NO#
define IF_ACT_E_IMPLEMENTED(op)#else#define IF_ACT_E_IMPLEMENTED(op) op(E)#endif#if !(defined RH_ACT_F) || (RH_ACT_F != YES)#
undef
RH_ACT_F#
define RH_ACT_F NO#
define IF_ACT_F_IMPLEMENTED(op)#else#define IF_ACT_F_IMPLEMENTED(op) op(F)#endif#define FOR_EACH_ACT(op)
IF_ACT_0_IMPLEMENTED(op)Family “2.0”Level 00 Revision 01.64\\

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 939
December 24, 2020

Part 4: Supporting Routines
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

Trusted Platform Module Library

IF_ACT_1_IMPLEMENTED(op)
IF_ACT_2_IMPLEMENTED(op)
IF_ACT_3_IMPLEMENTED(op)
IF_ACT_4_IMPLEMENTED(op)
IF_ACT_5_IMPLEMENTED(op)
IF_ACT_6_IMPLEMENTED(op)
IF_ACT_7_IMPLEMENTED(op)
IF_ACT_8_IMPLEMENTED(op)
IF_ACT_9_IMPLEMENTED(op)
IF_ACT_A_IMPLEMENTED(op)
IF_ACT_B_IMPLEMENTED(op)
IF_ACT_C_IMPLEMENTED(op)
IF_ACT_D_IMPLEMENTED(op)
IF_ACT_E_IMPLEMENTED(op)
IF_ACT_F_IMPLEMENTED(op)

\
\
\
\
\
\
\
\
\
\
\
\
\
\

#endif // _PLATFORM_ACT_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 940
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

C.16 PlatformACT.c
C.16.1. Includes
1#include "Platform.h"

C.16.2. Functions
C.16.2.1. ActSignal()
Function called when there is an ACT event to signal or unsignal
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

static void
ActSignal(
P_ACT_DATA
int

actData,on){if(actData == NULL)
return;// If this is to turn a signal on, don't do anything if it is already on. If this// is to turn the signal off, do it anyway because this might be for// initialization.
if(on && (actData->signaled == TRUE))
return;actData->signaled = (uint8_t)on;// If there is an action, then replace the "Do something" with the correct action.
// It should test 'on' to see if it is turning the signal on or off.
switch(actData->number){#if RH_ACT_0
case 0: // Do something
return;#endif#if RH_ACT_1
case 1: // Do something
return;#endif#if RH_ACT_2
case 2: // Do something
return;#endif#if RH_ACT_3
case 3: // Do something
return;#endif#if RH_ACT_4
case 4: // Do something
return;#endif#if RH_ACT_5
case 5: // Do something
return;#endif#if RH_ACT_6
case 6: // Do something
return;#endif#if RH_ACT_7
case 7: // Do something
return;Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 941
December 24, 2020

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

Trusted Platform Module Library#endif#if RH_ACT_8
case 8: // Do something
return;#endif#if RH_ACT_9
case 9: // Do something
return;#endif#if RH_ACT_A
case 0xA: // Do something
return;#endif#if RH_ACT_B
case 0xB:// Do something
return;#endif#if RH_ACT_C
case 0xC: // Do something
return;#endif#if RH_ACT_D
case 0xD: // Do something
return;#endif#if RH_ACT_E
case 0xE: // Do something
return;#endif#if RH_ACT_F
case 0xF: // Do something
return;#endifdefault:
return;}}C.16.2.2. ActGetDataPointer()
90
91
92
93
94
95
96
97
98
99
100
101

static P_ACT_DATA
ActGetDataPointer(uint32_t

act){#define RETURN_ACT_POINTER(N)if(0x##N == act) return &ACT_##N;

FOR_EACH_ACT(RETURN_ACT_POINTER)
return (P_ACT_DATA)NULL;}

C.16.2.3. _plat__ACT_GetImplemented()
This function tests to see if an ACT is implemented. It is a belt and suspenders function because the TPM
should not be calling to manipulate an ACT that is not implemented. However, this could help thesimulator code which doesn't necessarily know if an ACT is implemented or not.
102
103
104

LIB_EXPORT int_plat__ACT_GetImplemented(
uint32_t

Family “2.0”Level 00 Revision 01.64

act

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 942
December 24, 2020

Part 4: Supporting Routines
105
106
107
108

Trusted Platform Module Library){
return (ActGetDataPointer(act) != NULL);}

C.16.2.4. _plat__ACT_GetRemaining()
This function returns the remaining time. If an update is pending, newValue is returned. Otherwise, thecurrent counter value is returned. Note that since the timers keep running, the returned value can get
stale immediately. The actual count value will be no greater than the returned value.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

LIB_EXPORT uint32_t_plat__ACT_GetRemaining(
uint32_t

act//IN: the ACT selector){
P_ACT_DATA
uint32_t

actData = ActGetDataPointer(act);
remain;//if(actData == NULL)
return 0;
remain = actData->remaining;if(actData->pending)remain = actData->newValue;
return remain;}

C.16.2.5. _plat__ACT_GetSignaled()
124
125
126
127
128
129
130
131
132
133
134

LIB_EXPORT int_plat__ACT_GetSignaled(uint32_t

act//IN: number of ACT to check){
P_ACT_DATA

actData = ActGetDataPointer(act);//
if(actData == NULL)
return 0;
return (int )actData->signaled;}

C.16.2.6. _plat__ACT_SetSignaled()
135
136
137
138
139
140
141
142

LIB_EXPORT void
_plat__ACT_SetSignaled(uint32_t
int

act,
on

)
{
ActSignal(ActGetDataPointer(act), on);}

C.16.2.7. _plat__ACT_GetPending()
143
144
145
146
147
148

LIB_EXPORT int_plat__ACT_GetPending(uint32_t

act//IN: number of ACT to check){
P_ACT_DATA

Family “2.0”Level 00 Revision 01.64

actData = ActGetDataPointer(act);

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 943
December 24, 2020

Part 4: Supporting Routines
149
150
151
152
153

Trusted Platform Module Library//if(actData == NULL)
return 0;
return (int )actData->pending;}

C.16.2.8. _plat__ACT_UpdateCounter()This function is used to write the newValue for the counter. If an update is pending, then no update
occurs and the function returns FALSE. If setSignaled is TRUE, then the ACT signaled state is SET and if
newValue is 0, nothing is posted.
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

LIB_EXPORT int_plat__ACT_UpdateCounter(uint32_t
uint32_t

act,
newValue// IN: ACT to update// IN: the value to post

P_ACT_DATA

actData = ActGetDataPointer(act);){//
if(actData == NULL)// actData doesn't exist but pretend update is pending rather than indicate// that a retry is necessary.
return TRUE;// if an update is pending then return FALSE so that there will be a retryif(actData->pending != 0)
return FALSE;
actData->newValue = newValue;
actData->pending = TRUE;
return TRUE;}

C.16.2.9. _plat__ACT_EnableTicks()
This enables and disables the processing of the once-per-second ticks. This should be turned off (enable= FALSE) by _TPM_Init and turned on (enable = TRUE) by TPM2_Startup() after all the initializations
have completed.
174
175
176
177
178
179
180

LIB_EXPORT void
_plat__ACT_EnableTicks(
int

enable){actTicksAllowed = enable;}

C.16.2.10. ActDecrement()
If newValue is non-zero it is copied to remaining and then newValue is set to zero. Then remaining isdecremented by one if it is not already zero. If the value is decremented to zero, then the associatedevent is signaled. If setting remaining causes it to be greater than 1, then the signal associated with the
ACT is turned off.
181
182
183
184
185
186

static void
ActDecrement(
P_ACT_DATA

actData){// Check to see if there is an update pending

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 944
December 24, 2020

Part 4: Supporting Routines
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Trusted Platform Module Libraryif(actData->pending){// If this update will cause the count to go from non-zero to zero, set// the newValue to 1 so that it will timeout when decremented below.
if((actData->newValue == 0) && (actData->remaining != 0))
actData->newValue = 1;
actData->remaining = actData->newValue;// Update processed
actData->pending = 0;}// no update so countdown if the count is non-zero but not max
if((actData->remaining != 0) && (actData->remaining != UINT32_MAX)){// If this countdown causes the count to go to zero, then turn the signal for// the ACT on.
if((actData->remaining -= 1) == 0)
ActSignal(actData, TRUE);}// If the current value of the counter is non-zero, then the signal should be// off.
if(actData->signaled && (actData->remaining > 0))
ActSignal(actData, FALSE);}

C.16.2.11. _plat__ACT_Tick()This processes the once-per-second clock tick from the hardware. This is set up for the simulator to use
the control interface to send ticks to the TPM. These ticks do not have to be on a per second basis. They
can be as slow or as fast as desired so that the simulation can be tested.
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

LIB_EXPORT void
_plat__ACT_Tick(void){// Ticks processing is turned off at certain times just to make sure that nothing// strange is happening before pointers and things areif(actTicksAllowed){// Handle the update for each counter.
#define DECREMENT_COUNT(N)
ActDecrement(&ACT_##N);
FOR_EACH_ACT(DECREMENT_COUNT)}}

C.16.2.12. ActZero()This function initializes a single ACT
226
227
228
229
230
231
232
233
234
235
236

static void
ActZero(uint32_t
P_ACT_DATA

act,
actData){
actData->remaining = 0;
actData->newValue = 0;
actData->pending = 0;
actData->number = (uint8_t)act;
ActSignal(actData, FALSE);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 945
December 24, 2020

Part 4: Supporting Routines
237

Trusted Platform Module Library}

C.16.2.13. _plat__ACT_Initialize()This function initializes the ACT hardware and data structures
238
239
240
241
242
243
244
245
246
247
248

LIB_EXPORT int_plat__ACT_Initialize(
void){
actTicksAllowed = 0;
#define ZERO_ACT(N) ActZero(0x##N, &ACT_##N);
FOR_EACH_ACT(ZERO_ACT)
return TRUE;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 946
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

C.17 PlatformClock.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
3
4
5
6
7
8
9
10

#ifndef _PLATFORM_CLOCK_H_#define _PLATFORM_CLOCK_H_#ifdef _MSC_VER#include <sys/types.h>#include <sys/timeb.h>#else#include <sys/time.h>#include <time.h>#endif

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
would 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.
11#define

CLOCK_NOMINAL

30000

A 1% change in rate is 300 counts
12#define

CLOCK_ADJUST_COARSE

300

A 0.1% change in rate is 30 counts
13#define

CLOCK_ADJUST_MEDIUM

30

A minimum change in rate is 1 count14#define

CLOCK_ADJUST_FINE

1

The clock tolerance is +/-15% (4500 counts) Allow some guard band (16.7%)
15
16
17

#define

CLOCK_ADJUST_LIMIT

5000#endif // _PLATFORM_CLOCK_H_

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 947
December 24, 2020

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

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 948
December 24, 2020

Part 4: Supporting Routines

D.2

TpmTcpProtocol.hD.2.1.

Introduction

Trusted Platform Module Library

TPM commands are communicated as uint8_t streams on a TCP connection. The TPM commandprotocol is enveloped with the interface protocol described in this file. The command is indicated by auint32 with one of the values below. Most commands take no parameters return no TPM errors. In thesecases the TPM interface protocol acknowledges that command processing is completed by returning auint32=0. The command TPM_SIGNAL_HASH_DATA takes a uint32-prepended variable length byte
array and the interface protocol acknowledges command completion with a uint32=0. Most TPM
commands are enveloped using the TPM_SEND_COMMAND interface command. The parameters are
as indicated below. The interface layer also appends a UIN32=0 to the TPM response for regularity.
D.2.2.
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
28
29
30
31
32
33
34

#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_DATA6// {uint32_t BufferSize, uint8_t[BufferSize] Buffer}#define TPM_SIGNAL_HASH_END
7#define TPM_SEND_COMMAND
8// {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} >//{uint32_t OutBufferSize, uint8_t[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#define TPM_SET_ALTERNATIVE_RESULT

15
16#define TPM_SIGNAL_RESET#define TPM_SIGNAL_RESTART

17
18#define TPM_SESSION_END#define TPM_STOP

20
21#define TPM_GET_COMMAND_RESPONSE_SIZES#define TPM_ACT_GET_SIGNALED

26#define TPM_TEST_FAILURE_MODE

30

D.2.4.
35

25

Enumerations and Structuresenum TpmEndPointInfo

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 949
December 24, 2020

Part 4: Supporting Routines
36
37
38
39
40
41
42
43
44
45

Trusted Platform Module Library{
tpmPlatformAvailable = 0x01,
tpmUsesTbs = 0x02,
tpmInRawMode = 0x04,
tpmSupportsPP = 0x08};
#ifdef _MSC_VER#
pragma warning(push, 3)#endifExisting RPC interface type definitions retained so that the implementation can be re-used
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

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;#ifdef _MSC_VER#
pragma warning(pop)#endif#ifndef WIN32
typedef unsigned long
typedef void
#endif

DWORD;*LPVOID;#endifFamily “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 950
December 24, 2020

Part 4: Supporting Routines

D.3
D.3.1.

Trusted Platform Module Library

TcpServer.c
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Includes, Locals, Defines and Function Prototypes#include "TpmBuildSwitches.h"#include <stdio.h>#include <stdbool.h>#ifdef _MSC_VER#
pragma warning(push, 3)#
include <windows.h>#
include <winsock.h>#pragma warning(pop)typedef int socklen_t;#elif defined(__unix__)#
include <string.h>#include <unistd.h>#include <errno.h>#include <stdint.h>#include <netinet/in.h>#include <sys/socket.h>#include <pthread.h>#define ZeroMemory(ptr, sz) (memset((ptr), 0, (sz)))#
define closesocket(x) close(x)#define INVALID_SOCKET (-1)#
define SOCKET_ERROR(-1)#
define WSAGetLastError() (errno)#
define INT_PTR intptr_t
typedef int SOCKET;#else#
error "Unsupported platform."#endif#include "TpmTcpProtocol.h"#include "Manufacture_fp.h"#include "TpmProfile.h"#include "Simulator_fp.h"#include "Platform_fp.h"

To access key cache control in TPM
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

void RsaKeyCacheControl(int state);#ifndef __IGNORE_STATE__
static uint32_t ServerVersion = 1;
#define MAX_BUFFER 1048576
char InputBuffer[MAX_BUFFER];
char OutputBuffer[MAX_BUFFER];
struct{uint32_t
uint32_t
uint32_t//The input data buffer for the simulator.
//The output data buffer for the simulator.

largestCommandSize;largestCommand;largestResponseSize;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 951
December 24, 2020

Part 4: Supporting Routines
52
53
54
55

Trusted Platform Module Libraryuint32_t
largestResponse;} CommandResponseSizes = {0};#endif // __IGNORE_STATE___

D.3.3.
D.3.3.1.

Functions
CreateSocket()This function creates a socket listening on PortNumber.
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

static int
CreateSocket(
int
SOCKET)

PortNumber,*listenSocket

structint res;sockaddr_in MyAddress;{//// Initialize Winsock#ifdef _MSC_VER
WSADATA
wsaData;
res = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(res != 0){
printf("WSAStartup failed with error: %d\n", res);return -1;}#endif// 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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 952
December 24, 2020

Part 4: Supporting Routines
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
160
161
162
163
164
165
166
167
168

Trusted Platform Module Librarybool
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;
case 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:Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 953
December 24, 2020

Part 4: Supporting Routines
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

Trusted Platform Module Library

OK = WriteVarBytes(s, (char *)&CommandResponseSizes,
sizeof(CommandResponseSizes));
memset(&CommandResponseSizes, 0, sizeof(CommandResponseSizes));if(!OK)
return true;break;
case TPM_ACT_GET_SIGNALED:{
uint32_t actHandle;
OK = ReadUINT32(s, &actHandle);
WriteUINT32(s, _rpc__ACT_GetSignaled(actHandle));break;}
default:
printf("Unrecognized platform interface command %d\n",(int)Command);WriteUINT32(s, 1);
return true;}
WriteUINT32(s, 0);}}

D.3.3.3.

PlatformSvcRoutine()

This function is called to set up the socket interfaces to listen for commands.
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

DWORD WINAPI
PlatformSvcRoutine(
LPVOID
)

port

{
int
SOCKET
structint
socklen_t
bool

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 (DWORD)-1;}
printf("Client accepted\n");Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 954
December 24, 2020

Part 4: Supporting Routines
228
229
230
231
232
233
234
235

Trusted Platform Module Library// 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.
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

int
PlatformSignalService(
int)

PortNumber{#if defined(_MSC_VER)
HANDLEhPlatformSvc;
int
ThreadId;
int
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;}
return 0;#else
pthread_tthread_id;
int
ret;
int
port = PortNumber;
ret = pthread_create(&thread_id, NULL, (void*)PlatformSvcRoutine,(LPVOID)(INT_PTR)port);
if (ret == -1){
printf("pthread_create failed: %s", strerror(ret));}return ret;#endif // _MSC_VER}

D.3.3.5.

RegularCommandService()This function services regular commands.
270
271
272
273
274
275
276
277
278
279

int
RegularCommandService(
int)

PortNumber{
SOCKET
SOCKET
structint
socklen_t

Family “2.0”Level 00 Revision 01.64

listenSocket;
serverSocket;
sockaddr_in HerAddress;
res;length;TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 955
December 24, 2020

Part 4: Supporting Routines
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

bool

Trusted Platform Module LibrarycontinueServing;//
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 == 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 = TpmServer(serverSocket);closesocket(serverSocket);} while(continueServing);
return 0;}#if RH_ACT_0

D.3.3.6.

SimulatorTimeServiceRoutine()

This function is called to service the time ticks.
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

static unsigned long WINAPI
SimulatorTimeServiceRoutine(
LPVOID

notUsed){// All time is in ms
const int64_ttick = 1000;
uint64_t
prevTime = _plat__RealTime();int64_ttimeout = tick;(void)notUsed;
while (true){
uint64_t

curTime;#if defined(_MSC_VER)
Sleep((DWORD)timeout);#else
struct timespec
req = { timeout / 1000, (timeout % 1000) * 1000 };struct timespec
rem;nanosleep(&req, &rem);#endif // _MSC_VER
curTime = _plat__RealTime();Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 956
December 24, 2020

Part 4: Supporting Routines
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

Trusted Platform Module Library// May need to issue several ticks if the Sleep() took longer than asked,// or no ticks at all, it Sleep() was interrupted prematurely.
while (prevTime < curTime - tick / 2){//printf("%05lld | %05lld\n",//prevTime % 100000, (curTime - tick / 2) % 100000);_plat__ACT_Tick();
prevTime += (uint64_t)tick;}// Adjust the next timeout to keep the average interval of one second
timeout = tick + (prevTime - curTime);//prevTime = curTime;//printf("%04lld | c:%05lld | p:%05llu\n",//timeout, curTime % 100000, prevTime);}
return 0;}

D.3.3.7.

ActTimeService()This function starts a new thread waiting to wait for time ticks.

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

Return Value

Meaning==0

success!=0

failurestatic int
ActTimeService(
void){
static bool
running = false;
int
ret = 0;if(!running){#if defined(_MSC_VER)
HANDLE
hThr;
int
ThreadId;//
printf("Starting ACT thread...\n");// Don't allow ticks to be processed before TPM is manufactured.
_plat__ACT_EnableTicks(false);// Create service thread for ACT internal timer
hThr = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)SimulatorTimeServiceRoutine,(LPVOID)(INT_PTR)NULL, 0, (LPDWORD)&ThreadId);if(hThr != NULL)
CloseHandle(hThr);else
ret = -1;#else
pthread_tthread_id;//
ret = pthread_create(&thread_id, NULL, (void*)SimulatorTimeServiceRoutine,(LPVOID)(INT_PTR)NULL);#endif // _MSC_VER
if(ret != 0)
printf("ACT thread Creation failed\n");else

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 957
December 24, 2020

Part 4: Supporting Routines
392
393
394
395
396

Trusted Platform Module Libraryrunning = true;}
return ret;}#endif // RH_ACT_0

D.3.3.8.

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

int
StartTcpServer(
int)

PortNumber

{
int
res;
//
#ifdef RH_ACT_0// Start the Time Service routine
res = ActTimeService();if(res != 0){
printf("TimeService failed\n");return res;}#endif// 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.9.

ReadBytes()

This function reads the indicated number of bytes (NumBytes) into buffer from the indicated socket.
430
431
432
433
434
435
436
437
438
439
440
441
442
443

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)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 958
December 24, 2020

Part 4: Supporting Routines
444
445
446
447
448
449
450
451
452
453
454
455

Trusted Platform Module Library{
printf("Receive error.
return false;

Error is 0x%x\n", WSAGetLastError());}
if(res == 0){
return false;}
numGot += res;}return true;}

D.3.3.10. WriteBytes()
This function will send the indicated number of bytes (NumBytes) to the indicated socket
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

bool
WriteBytes(
SOCKET
char
int
)

s,
*buffer,
NumBytes

{
int
int

res;
numSent = 0;//
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.11. WriteUINT32()
Send 4 byte integer
485
486
487
488
489
490
491
492
493
494

bool
WriteUINT32(
SOCKET
uint32_t
)

s,
val

{
uint32_t netVal = htonl(val);//
return WriteBytes(s, (char*)&netVal, 4);}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 959
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

D.3.3.12. ReadUINT32()
Function to read 4 byte integer from socket.
495
496
497
498
499
500
501
502
503
504
505
506
507

bool
ReadUINT32(
SOCKET
uint32_t

s,
*val

)
{
uint32_t netVal;//
if (!ReadBytes(s, (char*)&netVal, 4))
return false;*val = ntohl(netVal);
return true;}

D.3.3.13. ReadVarBytes()
Get a uint32-length-prepended binary array. Note that the 4-byte length is in network byte order (bigendian).
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

bool
ReadVarBytes(
SOCKETchar
uint32_t
int)s,*buffer,*BytesReceived,
MaxLen{int
boollength;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;return true;}

D.3.3.14. WriteVarBytes()
Send a uint32-length-prepended binary array. Note that the 4-byte length is in network byte order (bigendian).
533
534
535
536
537
538
539
540

bool
WriteVarBytes(
SOCKET
char
int
)

s,
*buffer,
BytesToSend{
uint32_t

Family “2.0”Level 00 Revision 01.64

netLength = htonl(BytesToSend);

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 960
December 24, 2020

Part 4: Supporting Routines
541
542
543
544
545
546
547
548
549
550

Trusted Platform Module Librarybool res;//
res = WriteBytes(s, (char*)&netLength, 4);if(!res)return res;
res = WriteBytes(s, buffer, BytesToSend);
if(!res)return res;return true;}

D.3.3.15. TpmServer()
Processing incoming TPM command requests using the protocol / interface defined above.
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
595
596
597
598
599

bool
TpmServer(
SOCKET)s{uint32_t
uint32_t
uint8_t
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:
OK = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
if(!OK) return true;
InBuffer.Buffer = (uint8_t*)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 = (uint8_t*)InputBuffer;
InBuffer.BufferSize = length;
OutBuffer.BufferSize = MAX_BUFFER;
OutBuffer.Buffer = (_OUTPUT_BUFFER)OutputBuffer;

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 961
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library// 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_t));}_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_t));}
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;
default:
printf("Unrecognized TPM interface command %d\n", (int)Command);return true;}
OK = WriteUINT32(s, 0);if(!OK)
return true;}}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 962
December 24, 2020

Part 4: Supporting Routines

D.4

Trusted Platform Module Library

TPMCmdp.c

D.4.1.

Description

This file contains the functions that process the commands received on the control port or the command
port of the simulator. The control port is used to allow simulation of hardware events (such as,_TPM_Hash_Start) to test the simulated TPM''s reaction to those events. This improves code coverage ofthe testing.
D.4.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

Includes and Data Definitions#include <stdbool.h>#include "TpmBuildSwitches.h"#ifdef _MSC_VER#
pragma warning(push, 3)#
include <windows.h>#
include <winsock.h>#pragma warning(pop)#elif defined(__unix__)#
include "BaseTypes.h"// on behalf of TpmFail_fp.h
typedef int SOCKET;#else#
error "Unsupported platform."#endif#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

D.4.3.

s_isPowerOn = false;

FunctionsD.4.3.1.

Signal_PowerOn()

This function processes a power-on indication. Among other things, it calls the _TPM_Init() handler.
29
30
31
32
33
34
35
36
37
38
39
40
41
42

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();

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 963
December 24, 2020

Part 4: Supporting Routines
43
44
45
46
47
48

Trusted Platform Module Library// Power on and reset both lead to _TPM_Init()_plat__Signal_Reset();// Set state as power on
s_isPowerOn = true;}

D.4.3.2.

Signal_Restart()

This function processes the clock restart indication. All it does is call the platform function.
49
50
51
52
53
54
55

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

void
_rpc__Signal_PowerOff(void){
if(s_isPowerOn)// Pass power off signal to platform_plat__Signal_PowerOff();// This could be redundant, but...
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.
69
70
71
72
73
74
75
76

void
_rpc__ForceFailureMode(void){
SetForceFailureMode();return;}D.4.3.5.

_rpc__Signal_PhysicalPresenceOn()

This function is called to simulate activation of the physical presence pin.
77
78
79

void
_rpc__Signal_PhysicalPresenceOn(
void

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 964
December 24, 2020

Part 4: Supporting Routines
80
81
82
83
84
85
86
87

Trusted Platform Module Library){// If TPM power is on...
if(s_isPowerOn)// ... pass physical presence on to platform_plat__Signal_PhysicalPresenceOn();
return;}D.4.3.6.

_rpc__Signal_PhysicalPresenceOff()

This function is called to simulate deactivation of the physical presence pin.
88
89
90
91
92
93
94
95
96
97
98

void
_rpc__Signal_PhysicalPresenceOff(
void){// If TPM is power on...
if(s_isPowerOn)// ... 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
99
100
101
102
103
104
105
106
107
108
109

void
_rpc__Signal_Hash_Start(void){// If TPM power is on...
if(s_isPowerOn)// ... 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.
110
111
112
113
114
115
116
117
118
119
120

void
_rpc__Signal_Hash_Data(_IN_BUFFER
)

input

{
// If TPM power is on...
if(s_isPowerOn)// ... 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.
Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 965
December 24, 2020

Part 4: Supporting Routines
121
122
123
124
125
126
127
128
129
130
131

Trusted Platform Module Libraryvoid_rpc__Signal_HashEnd(
void){// If TPM power is on...
if(s_isPowerOn)// ... 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.
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

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.
152
153
154
155
156
157
158
159
160
161
162

void
_rpc__Signal_CancelOn(
void){// If TPM power is on...
if(s_isPowerOn)// ... 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.
163
164

void
_rpc__Signal_CancelOff(

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 966
December 24, 2020

Part 4: Supporting Routines
165
166
167
168
169
170
171
172
173

Trusted Platform Module Library

void
)
{
// If TPM power is on...
if(s_isPowerOn)// ... 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.
174
175
176
177
178
179
180
181
182
183
184

void
_rpc__Signal_NvOn(
void){// If TPM power is on...
if(s_isPowerOn)// ... make the NV available_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.
185
186
187
188
189
190
191
192
193
194
195
196

void
_rpc__Signal_NvOff(
void){// If TPM power is on...
if(s_isPowerOn)// ... make NV not available_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.
197
198
199
200
201
202
203
204
205
206
207
208
209

void
_rpc__RsaKeyCacheControl(
int
)

state

{
#if USE_RSA_KEY_CACHE
RsaKeyCacheControl(state);#else
NOT_REFERENCED(state);#endifreturn;}#define TPM_RH_ACT_00x40000110

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 967
December 24, 2020

Part 4: Supporting Routines

Trusted Platform Module Library

D.4.3.16. _rpc__ACT_GetSignaled()
This function is used to count the ACT second tick.
210
211
212
213
214
215
216
217
218
219
220

bool
_rpc__ACT_GetSignaled(uint32_t actHandle){// If TPM power is on...
if (s_isPowerOn)// ... query the platform
return _plat__ACT_GetSignaled(actHandle - TPM_RH_ACT_0);
return false;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 968
December 24, 2020

Part 4: Supporting Routines

D.5

Trusted Platform Module Library

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
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Includes, Defines, Data Definitions, and Function Prototypes#include "TpmBuildSwitches.h"#include <stdlib.h>#include <stdio.h>#include <stdint.h>#include <stdbool.h>#include <ctype.h>#include <string.h>#ifdef _MSC_VER#
pragma warning(push, 3)#
include <windows.h>#
include <winsock.h>#pragma warning(pop)#elif defined(__unix__)#
define _strcmpi strcasecmp
typedef int SOCKET;#else#
error "Unsupported platform."#endif#include "TpmTcpProtocol.h"#include "Manufacture_fp.h"#include "Platform_fp.h"#include "Simulator_fp.h"#define PURPOSE \"TPM 2.0 Reference Simulator.\n" \"Copyright (c) Microsoft Corporation. All rights reserved."#define DEFAULT_TPM_PORT 2321

Information about command line arguments (does not include program name)
32
33
34

static uint32_t
s_ArgsMask = 0;
static int
s_Argc = 0;
static const char **s_Argv = NULL;

D.5.3.
35// Bit mask of unmatched command line args

Functions#if DEBUG

D.5.3.1.

Assert()This function implements a run-time assertion. Computation of its parameters must not result in any side
effects, as these computations will be stripped from the release builds.
36
37
38
39
40

static void Assert (bool cond, const char* msg){
if (cond)
return;fputs(msg, stderr);

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 969
December 24, 2020

Part 4: Supporting Routines
41
42
43
44
45

Trusted Platform Module Libraryexit(2);}#else#define Assert(cond, msg)
#endifD.5.3.2.

Usage()

This function prints the proper calling sequence for the simulator.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

static void
Usage(
const char*programName){
fprintf(stderr, "%s\n\n", PURPOSE);
fprintf(stderr, "Usage: %s [PortNum] [opts]\n\n""Starts the TPM server listening on TCP port PortNum (by default %d).\n\n""An option can be in the short form (one letter preceded with '-' or '/')\n""or in the full form (preceded with '--' or no option marker at all).\n""Possible options are:\n""-h (--help) or ? - print this message\n""-m (--manufacture) - forces NV state of the TPM simulator to be ""(re)manufactured\n",programName, DEFAULT_TPM_PORT);
exit(1);}

D.5.3.3.

CmdLineParser_Init()

This function initializes command line option parser.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

static bool
CmdLineParser_Init(
int argc,
char *argv[],
int maxOpts){
if (argc == 1)
return false;
if (maxOpts && (argc - 1) > maxOpts){
fprintf(stderr, "No more than %d options can be specified\n\n", maxOpts);
Usage(argv[0]);}s_Argc = argc - 1;
s_Argv = (const char**)(argv + 1);
s_ArgsMask = (1 << s_Argc) - 1;
return true;}

D.5.3.4.

CmdLineParser_More()

Returns true if there are unparsed options still.
83
84
85
86

static bool
CmdLineParser_More(void)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 970
December 24, 2020

Part 4: Supporting Routines
87
88
89

Trusted Platform Module Library{
return s_ArgsMask != 0;}

D.5.3.5.

CmdLineParser_IsOpt()

This function determines if the given command line parameter represents a valid option.
90
91
92
93
94
95
96
97
98
99
100
101

static bool
CmdLineParser_IsOpt(
const char* opt,
const char* optFull,const char* optShort,bool dashed)// Command line parameter to check// Expected full name// Expected short (single letter) name// The parameter is preceded by a single dash{
return 0 == strcmp(opt, optFull)|| (optShort && opt[0] == optShort[0] && opt[1] == 0)|| (dashed && opt[0] == '-' && 0 == strcmp(opt + 1, optFull));}

D.5.3.6.

CmdLineParser_IsOptPresent()

This function determines if the given command line parameter represents a valid option.
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

static bool
CmdLineParser_IsOptPresent(
const char* optFull,const char* optShort
)
{
int
i;
int
curArgBit;
Assert(s_Argv != NULL,"InitCmdLineOptParser(argc, argv) has not been invoked\n");Assert(optFull && optFull[0],"Full form of a command line option must be present.\n""If only a short (single letter) form is supported, it must be""specified as the full one.\n");Assert(!optShort || (optShort[0] && !optShort[1]),"If a short form of an option is specified, it must consist ""of a single letter only.\n");if (!CmdLineParser_More())
return false;for (i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1){
const char* opt = s_Argv[i];if ((s_ArgsMask & curArgBit) && opt&& (0 == strcmp(opt, optFull)|| ((opt[0] == '/' || opt[0] == '-')&& CmdLineParser_IsOpt(opt + 1, optFull, optShort,
opt[0] == '-')))){
s_ArgsMask ^= curArgBit;
return true;}}
return false;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 971
December 24, 2020

Part 4: Supporting Routines

D.5.3.7.

Trusted Platform Module Library

CmdLineParser_Done()

This function notifies the parser that no more options are needed.
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

static void
CmdLineParser_Done(
const char*programName){
char delim = ':';
int
i;
int
curArgBit;
if (!CmdLineParser_More())
return;fprintf(stderr, "Command line contains unknown option%s",
s_ArgsMask & (s_ArgsMask - 1) ? "s" : "");for (i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1){
if (s_ArgsMask & curArgBit){
fprintf(stderr, "%c %s", delim, s_Argv[i]);delim = ',';}}
fprintf(stderr, "\n\n");Usage(programName);}

D.5.3.8.

main()

This is the main entry point for the simulator. It registers the interface and starts listening for clients
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

int
main(
int
char
)

argc,
*argv[]

{
bool
int

manufacture = false;
PortNum = DEFAULT_TPM_PORT;// Parse command line options
if (CmdLineParser_Init(argc, argv, 2)){if (CmdLineParser_IsOptPresent("?", "?")|| CmdLineParser_IsOptPresent("help", "h")){Usage(argv[0]);}if (CmdLineParser_IsOptPresent("manufacture", "m")){manufacture = true;}
if (CmdLineParser_More()){
inti;for (i = 0; i < s_Argc; ++i){
char *nptr = NULL;
int portNum = (int)strtol(s_Argv[i], &nptr, 0);
if (s_Argv[i] != nptr)

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 972
December 24, 2020

Part 4: Supporting Routines
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

Trusted Platform Module Library{// A numeric option is foundif(!*nptr && portNum > 0 && portNum < 65535){
PortNum = portNum;s_ArgsMask ^= 1 << i;break;}
fprintf(stderr, "Invalid numeric option %s\n\n", s_Argv[i]);Usage(argv[0]);}}}CmdLineParser_Done(argv[0]);}printf("LIBRARY_COMPATIBILITY_CHECK is %s\n",(LIBRARY_COMPATIBILITY_CHECK ? "ON" : "OFF"));// Enable NV memory_plat__NVEnable(NULL);
if (manufacture || _plat__NVNeedsManufacture()){
printf("Manufacturing NV state...\n");if(TPM_Manufacture(1) != 0){// if the manufacture didn't work, then make sure that the NV file doesn't// survive. This prevents manufacturing failures from being ignored the// next time the code is run.
_plat__NVDisable(1);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(0);StartTcpServer(PortNum);
return EXIT_SUCCESS;}

Family “2.0”Level 00 Revision 01.64

TCG PUBLIC REVIEW
Copyright © TCG 2006-2021

Page 973
December 24, 2020