diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 21:41:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 21:41:43 +0000 |
commit | 92cccad89d1c12b39165d5f0ed7ccd2d44965a1a (patch) | |
tree | f59a2764cd8c50959050a428bd8fc935138df750 /src/tpm2/Global.h | |
parent | Initial commit. (diff) | |
download | libtpms-upstream.tar.xz libtpms-upstream.zip |
Adding upstream version 0.9.2.upstream/0.9.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tpm2/Global.h')
-rw-r--r-- | src/tpm2/Global.h | 1350 |
1 files changed, 1350 insertions, 0 deletions
diff --git a/src/tpm2/Global.h b/src/tpm2/Global.h new file mode 100644 index 0000000..84a0d13 --- /dev/null +++ b/src/tpm2/Global.h @@ -0,0 +1,1350 @@ +/********************************************************************************/ +/* */ +/* Internal Global Type Definitions */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Global.h 1658 2021-01-22 23:14:01Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2021 */ +/* */ +/********************************************************************************/ + +/* 5.9 Global.h */ +/* 5.9.2 Includes */ + +#if !defined _TPM_H_ +#error "Should only be instanced in TPM.h" +#endif + +#ifndef GLOBAL_H +#define GLOBAL_H +_REDUCE_WARNING_LEVEL_(2) +#include <string.h> +#include <stddef.h> +_NORMAL_WARNING_LEVEL_ +#include "BackwardsCompatibility.h" // libtpms added + +#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" +#include "Utils.h" // libtpms added + +//** Defines and Types + +//*** Size Types +// These types are used to differentiate the two different size values used. +// +// NUMBYTES is used when a size is a number of bytes (usually a TPM2B) +typedef UINT16 NUMBYTES; + +//*** Other Types +// An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA) +typedef BYTE AUTH_VALUE[sizeof(TPMU_HA)]; + +/* A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO */ +typedef BYTE TIME_INFO[sizeof(TPMS_TIME_INFO)]; + +/* A NAME is a BYTE array that can contain a TPMU_NAME */ +typedef BYTE NAME[sizeof(TPMU_NAME)]; + +/* Definition for a PROOF value */ +TPM2B_TYPE(PROOF, PROOF_SIZE); + +/* Definition for a Primary Seed value */ +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. */ +#if CLOCK_STOPS +typedef UINT64 CLOCK_NONCE; +#else +typedef UINT32 CLOCK_NONCE; +#endif + +// 5.9.3 Loaded Object Structures +// 5.9.3.1 Description +// The structures in this section define the object layout as it exists in TPM memory. +// Two types of objects are defined: an ordinary object such as a key, and a sequence object that +// may be a hash, HMAC, or event. + +/* 5.9.3.2 OBJECT_ATTRIBUTES */ +/* An OBJECT_ATTRIBUTES structure contains the variable attributes of an object. These properties + are not part of the public properties but are used by the TPM in managing the object. An + OBJECT_ATTRIBUTES is used in the definition of the OBJECT data type. */ +typedef struct +{ +#if LITTLE_ENDIAN_TPM == YES /* libtpms added */ + unsigned publicOnly : 1; //0) SET if only the public portion of + // an object is loaded + unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS + // Hierarchy + unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS + // Hierarchy + unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS + // Hierarchy + unsigned evict : 1; //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. + // This bit is also used to mark a + // completed sequence object so it + // will be flush when the + // SequenceComplete command succeeds. + unsigned primary : 1; //5) SET for a primary object + unsigned temporary : 1; //6) SET for a temporary object + unsigned stClear : 1; //7) SET for an stClear object + unsigned hmacSeq : 1; //8) SET for an HMAC or MAC sequence object + unsigned hashSeq : 1; //9) SET for a hash sequence object + unsigned eventSeq : 1; //10) SET for an event sequence object + unsigned ticketSafe : 1; //11) SET if a ticket is safe to create + // for hash sequence object + unsigned firstBlock : 1; //12) SET if the first block of hash + // data has been received. It + // works with ticketSafe bit + unsigned isParent : 1; //13) SET if the key has the proper + // attributes to be a parent key + unsigned privateExp : 1; //14) SET when the private exponent + // of an RSA key has been validated. + unsigned occupied : 1; //15) SET when the slot is occupied. + unsigned derivation : 1; //16) SET when the key is a derivation + // parent + unsigned external : 1; //17) SET when the object is loaded with + // TPM2_LoadExternal(); + unsigned reserved : 14; //18-31) /* libtpms added */ +#endif /* libtpms added */ +#if BIG_ENDIAN_TPM == YES /* libtpms added begin */ + unsigned reserved : 14; //18-31) + unsigned external : 1; //17) SET when the object is loaded with + unsigned derivation : 1; //16) SET when the key is a derivation + unsigned occupied : 1; //15) SET when the slot is occupied. + unsigned privateExp : 1; //14) SET when the private exponent + unsigned isParent : 1; //13) SET if the key has the proper + unsigned firstBlock : 1; //12) SET if the first block of hash + unsigned ticketSafe : 1; //11) SET if a ticket is safe to create + unsigned eventSeq : 1; //10) SET for an event sequence object + unsigned hashSeq : 1; //9) SET for a hash sequence object + unsigned hmacSeq : 1; //8) SET for an HMAC sequence object + unsigned stClear : 1; //7) SET for an stClear object + unsigned temporary : 1; //6) SET for a temporary object + unsigned primary : 1; //5) SET for a primary object + + unsigned evict : 1; //4) SET if the object is a platform or + unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS + unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS + unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS + unsigned publicOnly : 1; //0) SET if only the public portion of +#endif /* libtpms added end */ +} 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. */ +#define RSA_prime_flag 0x8000 +#endif + +/* 5.9.3.3 OBJECT Structure */ +/* An OBJECT structure holds the object public, sensitive, and meta-data associated. This structure + is implementation dependent. For this implementation, the structure is not optimized for space + but rather for clarity of the reference implementation. Other implementations may choose to + overlap portions of the structure that are not used simultaneously. These changes would + necessitate changes to the source code but those changes would be compatible with the reference + implementation. */ +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 +#if ALG_RSA + privateExponent_t privateExponent; // Additional field for the private +#endif + 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. + + // libtpms added: SEED_COMPAT_LEVEL to use for deriving child keys + SEED_COMPAT_LEVEL seedCompatLevel; + // libtpms added: OBJECT lies in NVRAM; to avoid that it needs different number + // of bytes on 32 bit and 64 bit architectures, we need to make sure it's the + // same size; simple padding at the end works here + UINT8 _pad[3]; +} OBJECT; + +/* 5.9.3.4 HASH_OBJECT Structure */ +/* This structure holds a hash sequence object or an event sequence object. */ +/* The first four components of this structure are manually set to be the same as the first four + components of the object structure. This prevents the object from being inadvertently misused as + sequence objects occupy the same memory as a regular object. A debug check is present to make + sure that the offsets are what they are supposed to be. */ +/* NOTE: In a future version, this will probably be renamed as SEQUENCE_OBJECT */ +typedef struct HASH_OBJECT +{ + OBJECT_ATTRIBUTES attributes; // The attributes of the HASH object + TPMI_ALG_PUBLIC type; // algorithm + TPMI_ALG_HASH nameAlg; // name algorithm + TPMA_OBJECT objectAttributes; // object attributes + // The data below is unique to a sequence object + TPM2B_AUTH auth; // authorization for use of sequence + union + { + HASH_STATE hashState[HASH_COUNT]; + HMAC_STATE hmacState; + } state; +} HASH_OBJECT; +typedef BYTE HASH_OBJECT_BUFFER[sizeof(HASH_OBJECT)]; + +/* 5.9.3.5 ANY_OBJECT */ +/* This is the union for holding either a sequence object or a regular object. for ContextSave() and + ContextLoad() */ +typedef union ANY_OBJECT +{ + OBJECT entity; + HASH_OBJECT hash; +} ANY_OBJECT; +typedef BYTE ANY_OBJECT_BUFFER[sizeof(ANY_OBJECT)]; + +/* 5.9.4 AUTH_DUP Types */ +/* These values are used in the authorization processing. */ +typedef UINT32 AUTH_ROLE; +#define AUTH_NONE ((AUTH_ROLE)(0)) +#define AUTH_USER ((AUTH_ROLE)(1)) +#define AUTH_ADMIN ((AUTH_ROLE)(2)) +#define AUTH_DUP ((AUTH_ROLE)(3)) + +/* 5.9.5 Active Session Context */ +/* 5.9.5.1 Description */ +/* The structures in this section define the internal structure of a session context. */ +/* 5.9.5.2 SESSION_ATTRIBUTES */ +/* The attributes in the SESSION_ATTRIBUTES structure track the various properties of the + session. It maintains most of the tracking state information for the policy session. It is used + within the SESSION structure. */ +typedef struct SESSION_ATTRIBUTES +{ +#if LITTLE_ENDIAN_TPM == YES /* libtpms added */ + unsigned isPolicy : 1; //1) SET if the session may only be used + // for policy + unsigned isAudit : 1; //2) SET if the session is used for audit + unsigned isBound : 1; //3) SET if the session is bound to with an + // entity. This attribute will be CLEAR + // if either isPolicy or isAudit is SET. + unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined + // This attribute is not SET unless + // 'isPolicy' is SET. + unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for + // computing the session HMAC. This + // attribute is not SET unless 'isPolicy' + // is SET. + unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required + // for authorization This attribute is not + // SET unless 'isPolicy' is SET. + unsigned isPPRequired : 1; //7) SET if physical presence is required to + // be asserted when the authorization is + // checked. This attribute is not SET + // unless 'isPolicy' is SET. + unsigned isTrialPolicy : 1; //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. + unsigned isDaBound : 1; //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. + unsigned isLockoutBound : 1; //10) SET if the session is bound to + // lockoutAuth. + unsigned includeAuth : 1; //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') + unsigned checkNvWritten : 1; //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. + unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to + // be SET. Used when 'checkNvWritten' is + // SET + unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be + // checked for Create, CreatePrimary, or + // CreateLoaded. + unsigned _reserved : 18; //15-32 /* libtpms added */ +#endif /* libtpms added */ +#if BIG_ENDIAN_TPM == YES /* libtpms added begin */ + unsigned _reserved : 18; //15-32 + unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be + unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to + unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN attribute + unsigned includeAuth : 1; //11) This attribute is SET when the + unsigned isLockoutBound : 1; //10) SET if the session is bound to + unsigned isDaBound : 1; //9) SET if the bind entity had noDA CLEAR. + unsigned isTrialPolicy : 1; //8) SET if the policy session is created + unsigned isPPRequired : 1; //7) SET if physical presence is required to + unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required + unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for + unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined + unsigned isBound : 1; //3) SET if the session is bound to with an + unsigned isAudit : 1; //2) SET if the session is used for audit + unsigned isPolicy : 1; //1) SET if the session may only be used +#endif /* libtpms added end */ +} SESSION_ATTRIBUTES; + +/* 5.9.5.3 SESSION Structure */ +/* The SESSION structure contains all the context of a session except for the associated + contextID. */ +/* NOTE: The contextID of a session is only relevant when the session context is stored off the + TPM. */ +typedef struct SESSION +{ + SESSION_ATTRIBUTES attributes; // session attributes + UINT32 pcrCounter; // PCR counter value when PCR is + // included (policy session) + // If no PCR is included, this + // value is 0. + UINT64 startTime; // The value in g_time + // when the session was started (policy session) + UINT64 timeout; // The timeout relative to g_time + // There is no timeout if this value + // is 0. + CLOCK_NONCE epoch; // 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. + TPM_CC commandCode; // command code (policy session) + TPM_ALG_ID authHashAlg; // session hash algorithm + TPMA_LOCALITY commandLocality; // command locality (policy session) + TPMT_SYM_DEF symmetric; // session symmetric algorithm (if any) + TPM2B_AUTH sessionKey; // session secret value used for + // this session + TPM2B_NONCE nonceTPM; // 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 + TPM2B_DIGEST nameHash; // the required nameHash + TPM2B_DIGEST templateHash; // the required template for creation + } u1; + union + { + TPM2B_DIGEST auditDigest; // audit session digest + TPM2B_DIGEST policyDigest; // policyHash + } u2; // audit log and policyHash may + // share space to save memory +} SESSION; +#define EXPIRES_ON_RESET INT32_MIN +#define TIMEOUT_ON_RESET UINT64_MAX +#define EXPIRES_ON_RESTART (INT32_MIN + 1) +#define TIMEOUT_ON_RESTART (UINT64_MAX - 1) +typedef BYTE SESSION_BUF[sizeof(SESSION)]; + +/* 5.9.7 PCR */ +/* 5.9.7.1 PCR_SAVE Structure */ +/* The PCR_SAVE structure type contains the PCR data that are saved across power cycles. Only the + static PCR are required to be saved across power cycles. The DRTM and resettable PCR are not + saved. The number of static and resettable PCR is determined by the platform-specific + specification to which the TPM is built. */ + +#define PCR_SAVE_SPACE(HASH, Hash) BYTE Hash[NUM_STATIC_PCR][HASH##_DIGEST_SIZE]; + +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.6.2 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. */ +typedef struct PCR_POLICY +{ + TPMI_ALG_HASH hashAlg[NUM_POLICY_PCR_GROUP]; + TPM2B_DIGEST a_unused; /* libtpms: renamed field since not used and not initialized */ + TPM2B_DIGEST policy[NUM_POLICY_PCR_GROUP]; +} PCR_POLICY; +#endif + +/* 5.9.6.3 PCR_AUTHVALUE */ +/* This structure holds the PCR policies, one for each group of PCR controlled by policy. */ +typedef struct PCR_AUTH_VALUE +{ + TPM2B_DIGEST auth[NUM_AUTHVALUE_PCR_GROUP]; +} PCR_AUTHVALUE; + +/* 5.9.7 STARTUP_TYPE */ +/* This enumeration is the possible startup types. The type is determined by the combination of + TPM2_ShutDown() and TPM2_Startup(). */ +typedef enum + { + SU_RESET, + SU_RESTART, + SU_RESUME + } STARTUP_TYPE; + +/* 5.9.8 NV */ +/* 5.9.8.1 NV_INDEX */ +/* The NV_INDEX structure defines the internal format for an NV index. The indexData size varies + according to the type of the index. In this implementation, all of the index is manipulated as a + unit. */ +typedef struct NV_INDEX +{ + TPMS_NV_PUBLIC publicArea; + TPM2B_AUTH authValue; +} NV_INDEX; + +/* 5.9.8.2 NV_REF */ +/* An 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 that is kept in RAM. */ +typedef UINT32 NV_REF; +typedef BYTE *NV_RAM_REF; + +/* 5.9.8.3 NV_PIN */ +/* This structure deals with the possible endianness differences between the canonical form of the + TPMS_NV_PIN_COUNTER_PARAMETERS structure and the internal value. The structures allow the data 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 a normal index with the octets in canonical order. */ +#if BIG_ENDIAN_TPM +typedef struct +{ + UINT32 pinCount; + UINT32 pinLimit; +} PIN_DATA; +#else +typedef struct +{ + UINT32 pinLimit; + UINT32 pinCount; +} PIN_DATA; +#endif +typedef union +{ + UINT64 intVal; + PIN_DATA pin; +} NV_PIN; + +/* 5.9.9 COMMIT_INDEX_MASK */ +/* This is the define for the mask value that is used when manipulating the bits in the commit bit + array. The commit counter is a 64-bit value and the low order bits are used to index the + commitArray. This mask value is applied to the commit counter to extract the bit number in the + array. */ +#if ALG_ECC +#define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1)) +#endif + +/* 5.9.10 RAM Global Values */ +/* 5.9.10.1 Description */ +/* The values in this section are only extant in RAM or ROM as constant values. */ +/* 5.9.10.2 Crypto Self-Test Values */ +EXTERN ALGORITHM_VECTOR g_implementedAlgorithms; +EXTERN ALGORITHM_VECTOR g_toTest; + +/* 5.9.10.3 g_rcIndex[] */ +/* This array is used to contain the array of values that are added to a return code when it is a + parameter-, handle-, or session-related error. This is an implementation choice and the same + result can be achieved by using a macro. */ +#define g_rcIndexInitializer { 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 } +EXTERN const UINT16 g_rcIndex[15] INITIALIZER(g_rcIndexInitializer); + +/* 5.9.10.4 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. */ +EXTERN TPM_HANDLE g_exclusiveAuditSession; + +/* 5.9.10.5 g_time */ +/* This is the value in which we keep the current command time. This is initialized at the start of + each command. 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. */ +EXTERN UINT64 g_time; + +/* 5.9.10.6 g_timeEpoch */ +/* This value contains the current clock Epoch. It changes when there is a clock discontinuity. It + may be necessary to place this in NV should the timer be able to run across a power down of the + TPM but not in all cases (e.g. dead battery). If the nonce is placed in NV, it should go in gp + because it should be changing slowly. */ +#if CLOCK_STOPS +EXTERN CLOCK_NONCE g_timeEpoch; +#else +#define g_timeEpoch gp.timeEpoch +#endif + +/* 5.9.10.7 g_phEnable */ +/* This is the platform hierarchy control and determines if the platform hierarchy is + available. This value is SET on each TPM2_Startup(). The default value is SET. */ +EXTERN BOOL g_phEnable; + +/* 5.9.10.8 g_pcrReConfig */ +/* This value is SET if a TPM2_PCR_Allocate() command successfully executed since the last + TPM2_Startup(). If so, then the next shutdown is required to be Shutdown(CLEAR). */ +EXTERN BOOL g_pcrReConfig; + +/* 5.9.10.9 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(). */ +EXTERN TPMI_DH_OBJECT g_DRTMHandle; + +/* 5.9.10.10 g_DrtmPreStartup */ +/* This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The + 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. */ +EXTERN BOOL g_DrtmPreStartup; + +/* 5.9.10.11 g_StartupLocality3 */ +/* This value indicates that a TPM2_Startup() occurred at locality 3. Otherwise, it at locality + 0. The define for STARTUP_LOCALITY_3 is to indicate that the startup was not at locality 0. This + hack is to avoid adding another NV variable. */ +EXTERN BOOL g_StartupLocality3; + +/* 5.9.10.12 TPM_SU_NONE */ +/* Part 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() and + TPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was + received. */ +/* NOTE: This is a reserved value. */ +#define SU_NONE_VALUE (0xFFFF) +#define TPM_SU_NONE (TPM_SU)(SU_NONE_VALUE) + +/* 5.9.10.13 TPM_SU_DA_USED */ +/* As with TPM_SU_NONE, this value is added to allow indication that the shutdown was not orderly + and that a DA=protected object was reference during the previous cycle. */ +#define SU_DA_USED_VALUE (SU_NONE_VALUE - 1) +#define TPM_SU_DA_USED (TPM_SU)(SU_DA_USED_VALUE) + +/* 5.9.10.14 Startup Flags */ +/* These flags are included in gp.orderlyState. These are hacks and are being used to avoid having + to change the layout of gp. The PRE_STARTUP_FLAG indicates that a + _TPM_Hash_Start()/_Data()/_End() sequence was received after _TPM_Init() but before + TPM2_StartUp(). STARTUP_LOCALITY_3 indicates that the last TPM2_Startup() was received at + locality 3. These flags are only relevant if after a TPM2_Shutdown(STATE). */ +#define PRE_STARTUP_FLAG 0x8000 +#define STARTUP_LOCALITY_3 0x4000 +#define TPM_SU_STATE_MASK ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3) // libtpms added +#if USE_DA_USED + +/* 5.9.10.15 g_daUsed */ +/* This location indicates if a DA-protected value is accessed during a boot cycle. If none has, + then there is no 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 */ + +/* This global is set to FALSE on startup (after a decision has been made on whether to increment + the failedTries or not). On a first attempt to access a DA protected object: this global is set + to 1, the orderlyState is set to SU_DA_USED, committed to NV and the command execution returns + with RC_RETRY (without exposing any information on the DA attempt). */ +EXTERN BOOL g_daUsed; +#endif + +/* 5.9.10.16 g_updateNV */ +/* This flag indicates if NV should be updated at the end of a command. This flag is set to UT_NONE + at the beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand() + after the detailed 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. */ +typedef BYTE UPDATE_TYPE; +#define UT_NONE (UPDATE_TYPE)0 +#define UT_NV (UPDATE_TYPE)1 +#define UT_ORDERLY (UPDATE_TYPE)(UT_NV + 2) +EXTERN UPDATE_TYPE g_updateNV; +/* 5.9.10.17 g_powerWasLost */ +/* This flag is used to indicate if the power was lost. It is SET in _TPM__Init(). This flag is + cleared by TPM2_Startup() after all power-lost activities are completed. */ +/* NOTE: When power is applied, this value can come up as anything. However, _plat__WasPowerLost() + will provide the proper indication in that case. So, when power is actually lost, we get the + correct answer. When power was not lost, but the power-lost processing has not been completed + before the next _TPM_Init(), then the TPM still does the correct thing. */ +EXTERN BOOL g_powerWasLost; + +/* 5.9.10.18 g_clearOrderly */ +/* This flag indicates if the execution of a command should cause the orderly state to be cleared. + This flag is set to FALSE at the beginning of each command in ExecuteCommand() and is checked in + ExecuteCommand() after the detailed actions of a command complete but before the check of + g_updateNV. If this flag is TRUE, and the orderly state is not SU_NONE_VALUE, then the orderly + state in NV memory will be changed to SU_NONE_VALUE or SU_DA_USED_VALUE. */ +EXTERN BOOL g_clearOrderly; + +/* 5.9.10.19 g_prevOrderlyState */ +/* This location indicates how the TPM was shut down before the most recent TPM2_Startup(). This + value, along with the startup type, determines if the TPM should do a TPM Reset, TPM Restart, or + TPM Resume. */ +EXTERN TPM_SU g_prevOrderlyState; + +/* 5.9.10.20 g_nvOk */ +/* This value indicates if the NV integrity check was successful or not. If not and the failure was + severe, then the TPM would have been put into failure mode after it had been re-manufactured. If + the NV failure was in the area where the state-save data is kept, then this variable will have a + value of FALSE indicating that a TPM2_Startup(CLEAR) is required. */ +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 */ +EXTERN TPM_RC g_NvStatus; + +/* 5.9.10.21 g_platformUnique */ +/* This location contains the unique value(s) used to identify the TPM. It is loaded on every + _TPM2_Startup() The first value is used to seed the RNG. The second value is used as a vendor + authValue. The value used by the RNG would be the value derived from the chip unique value (such + as fused) with a dependency on the authorities of the code in the TPM boot path. The second would + be derived from the chip unique value with a dependency on the details of the code in the boot + path. That is, the first value depends on the various signers of the code and the second depends + on what was signed. The TPM vendor should not be able to know the first value but they are + expected to know the second. */ +EXTERN TPM2B_AUTH g_platformUniqueAuthorities; // Reserved for RNG +EXTERN TPM2B_AUTH g_platformUniqueDetails; // 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 the values determines the structure in which the value +// is placed. + +/* 5.9.11.2 PERSISTENT_DATA */ +/* This structure holds the persistent values that only change as a consequence of a specific + Protected Capability and are not affected by TPM power events (TPM2_Startup() or + TPM2_Shutdown(). */ +typedef struct +{ + //********************************************************************************* + // Hierarchy + //********************************************************************************* + // The values in this section are related to the hierarchies. + BOOL disableClear; // TRUE if TPM2_Clear() using + // 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_SEED EPSeed; + TPM2B_SEED SPSeed; + TPM2B_SEED PPSeed; + // SEED_COMPAT_LEVELs related to creation time of seeds + SEED_COMPAT_LEVEL EPSeedCompatLevel; // libtpms added begin + SEED_COMPAT_LEVEL SPSeedCompatLevel; + SEED_COMPAT_LEVEL PPSeedCompatLevel; // libtpms added end + // Note there is a nullSeed in the state_reset memory. + // Hierarchy proofs + TPM2B_PROOF phProof; + TPM2B_PROOF shProof; + TPM2B_PROOF ehProof; + // Note there is a nullProof in the state_reset memory. + //********************************************************************************* + // Reset Events + //********************************************************************************* + // A count that increments at each TPM reset and never get reset during the life + // time of TPM. The value of this counter is initialized to 1 during TPM + // manufacture process. It is used to invalidate all saved contexts after a TPM + // Reset. + UINT64 totalResetCount; + // This counter increments on each TPM Reset. The counter is reset by + // TPM2_Clear(). + UINT32 resetCount; + //********************************************************************************* + // PCR + //********************************************************************************* + // This structure hold the policies for those PCR that have an update policy. + // This implementation only supports a single group of PCR controlled by + // policy. If more are required, then this structure would be changed to + // an array. +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + PCR_POLICY pcrPolicies; +#endif + // This structure indicates the allocation of PCR. The structure contains a + // list of PCR allocations for each implemented algorithm. If no PCR are + // allocated for an algorithm, a list entry still exists but the bit map + // will contain no SET bits. + TPML_PCR_SELECTION pcrAllocated; + //********************************************************************************* + // Physical Presence + //********************************************************************************* + // The PP_LIST type contains a bit map of the commands that require physical + // to be asserted when the authorization is evaluated. Physical presence will be + // checked if the corresponding bit in the array is SET and if the authorization + // handle is TPM_RH_PLATFORM. + // + // These bits may be changed with TPM2_PP_Commands(). + BYTE ppList[(COMMAND_COUNT + 7) / 8]; + //********************************************************************************* + // Dictionary attack values + //********************************************************************************* + // These values are used for dictionary attack tracking and control. + UINT32 failedTries; // 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_SU orderlyState; + //***************************************************************************** + // Command audit values. + //***************************************************************************** + BYTE auditCommands[((COMMAND_COUNT + 1) + 7) / 8]; + TPMI_ALG_HASH auditHashAlg; + UINT64 auditCounter; + //***************************************************************************** + // 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. + UINT32 algorithmSet; + //***************************************************************************** + // 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 YYYYMMDD + UINT32 firmwareV1; + // g_firmwareV1 contains the less significant 32-bits of the vendor version number. + // In the reference implementation, if this value is printed as a hex + // value, it will have the format of 00 HH MM SS + UINT32 firmwareV2; + //***************************************************************************** + // Timer Epoch + //***************************************************************************** + // timeEpoch contains a nonce that has a vendor=specific size (should not be + // 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_STOPS + CLOCK_NONCE timeEpoch; +#endif +} PERSISTENT_DATA; +EXTERN PERSISTENT_DATA gp; + +/* 5.9.11.3 ORDERLY_DATA */ +/* The data in this structure is saved to NV on each TPM2_Shutdown(). */ +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 clock; // The orderly version of clock + TPMI_YES_NO clockSafe; // 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_TIMER + UINT64 selfHealTimer; // current value of s_selfHealTimer + UINT64 lockoutTimer; // current value of s_lockoutTimer + UINT64 time; // current value of g_time at shutdown +#endif // ACCUMULATE_SELF_HEAL_TIMER + +#ifndef __ACT_DISABLED // libtpms added +#error ACT not supported in ORDERLY_DATA! + // 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. + UINT16 signaledACT; + UINT16 preservedSignaled; +#endif // libtpms added +} ORDERLY_DATA; +#if ACCUMULATE_SELF_HEAL_TIMER +#define s_selfHealTimer go.selfHealTimer +#define s_lockoutTimer go.lockoutTimer +#endif // ACCUMULATE_SELF_HEAL_TIMER +# define drbgDefault go.drbgState +EXTERN ORDERLY_DATA go; + +/* 5.9.11.4 STATE_CLEAR_DATA */ +/* This structure contains the data that is saved on Shutdown(STATE). and restored on + Startup(STATE). The values are set to their default settings on any Startup(Clear). In other + words the data is only persistent across TPM Resume. */ +/* If the comments associated with a parameter indicate a default reset value, the value is applied + on each Startup(CLEAR). */ +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; + +#ifndef __ACT_DISABLED // libtpms added + //***************************************************************************** + // ACT + //***************************************************************************** +#define DefineActPolicySpace(N) TPMT_HA act_##N; + FOR_EACH_ACT(DefineActPolicySpace) + +#endif // libtpms added +} STATE_CLEAR_DATA; +EXTERN STATE_CLEAR_DATA gc; + +/* 5.9.11.5 State Reset Data */ +/* This structure contains data is that is saved on Shutdown(STATE) and restored on the subsequent + Startup(ANY). That is, the data is preserved across TPM Resume and TPM Restart. */ +/* If a default value is specified in the comments this value is applied on TPM Reset. */ +typedef struct state_reset_data +{ + //***************************************************************************** + // Hierarchy Control + //***************************************************************************** + TPM2B_PROOF nullProof; // The proof value associated with + // the TPM_RH_NULL hierarchy. The + // default reset value is from the RNG. + TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL + SEED_COMPAT_LEVEL nullSeedCompatLevel; // libtpms added + // 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 objectContextID; // This is the context ID for a saved + // object context. The default reset + // value is 0. + CONTEXT_SLOT contextArray[MAX_ACTIVE_SESSIONS]; // This array contains + // contains the values used to track + // the version numbers of saved + // contexts (see + // Session.c in for details). The + // default reset value is {0}. + CONTEXT_COUNTER contextCounter; // This is the value from which the + // 'contextID' is derived. The + // default reset value is {0}. + //***************************************************************************** + // Command Audit + //***************************************************************************** + // When an audited command completes, ExecuteCommand() checks the return + // value. If it is TPM_RC_SUCCESS, and the command is an audited command, the + // TPM will extend the cpHash and rpHash for the command to this value. If this + // digest was the Zero Digest before the cpHash was extended, the audit counter + // is incremented. + TPM2B_DIGEST commandAuditDigest; // This value is set to an Empty Digest + // by TPM2_GetCommandAuditDigest() or a + // TPM Reset. + //***************************************************************************** + // Boot counter + //***************************************************************************** + UINT32 restartCount; // This counter counts TPM Restarts. + // The default reset value is 0. + //********************************************************************************* + // PCR + //********************************************************************************* + // This counter increments whenever the PCR are updated. This counter is preserved + // across TPM Resume even though the PCR are not preserved. This is because + // sessions remain active across TPM Restart and the count value in the session + // is compared to this counter so this counter must have values that are unique + // as long as the sessions are active. + // NOTE: A platform-specific specification may designate that certain PCR changes + // do not increment this counter to increment. + UINT32 pcrCounter; // The default reset value is 0. +#if ALG_ECC + //***************************************************************************** + // ECDAA + //***************************************************************************** + UINT64 commitCounter; // This counter increments each time + // TPM2_Commit() returns + // TPM_RC_SUCCESS. The default reset + // value is 0. + TPM2B_NONCE commitNonce; // This random value is used to compute + // the commit values. The default reset + // value is from the RNG. + // This implementation relies on the number of bits in g_commitArray being a + // power of 2 (8, 16, 32, 64, etc.) and no greater than 64K. + BYTE commitArray[16]; // The default reset value is {0}. +#endif // ALG_ECC +} STATE_RESET_DATA; +EXTERN STATE_RESET_DATA gr; + + // libtpms added begin +/* The s_ContextSlotMask masks CONTEXT_SLOT values; this variable can have + * only two valid values, 0xff or 0xffff. The former is used to simulate + * a CONTEXT_SLOT defined as UINT8, the latter is used for the CONTEXT_SLOT + * when it is a UINT16. The original TPM 2 code uses a cast to CONTEXT_SLOT + * to truncate larger values and has been modified to use CONTEXT_SLOT_MASKED + * to achieve the same effect with the above two values. + * + * Using CONTEXT_SLOT_MASKED we make sure that when we write values into + * gr.contextArray that these values are properly masked/truncated so that + * when we read values from gr.contextArray that we don't have to mask + * them again. + * + * s_ContextSlotMask may only be initialized to 0xff when resuming an older + * state from the time when CONTEXT_SLOT was UINT8, otherwise it must be set + * to 0xffff. We set it to 0xffff in SessionStartup(SU_CLEAR) and to be + * able to save the TPM state really early (and restore it) also in + * TPM_Manufacture(). + */ +EXTERN CONTEXT_SLOT s_ContextSlotMask; +#define CONTEXT_SLOT_MASKED(val) ((CONTEXT_SLOT)(val) & s_ContextSlotMask) // libtpms added end + +/* 5.9.12 NV Layout */ +/* The NV data organization is */ +/* a) a PERSISTENT_DATA structure */ +/* b) a STATE_RESET_DATA structure */ +/* c) a STATE_CLEAR_DATA structure */ +/* d) an ORDERLY_DATA structure */ +/* e) the user defined NV index space */ + +/* libtpms added: to put certain data structure at fixed offsets + * to give the ones below some room to expand + */ +#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 TPM2_ROUNDUP(NV_ORDERLY_DATA + sizeof(ORDERLY_DATA),\ + 1024) /* libtpms added */ +#define NV_USER_DYNAMIC (NV_INDEX_RAM_DATA + sizeof(s_indexOrderlyRam)) +#define NV_USER_DYNAMIC_END NV_MEMORY_SIZE + +/* 5.9.13 Global Macro Definitions */ +/* The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members of the + PERSISTENT_DATA structure in NV. */ +#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 to access 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(). */ +typedef UINT16 COMMAND_INDEX; +#define UNIMPLEMENTED_COMMAND_INDEX ((COMMAND_INDEX)(~0)) +#if 0 /* libtpms added */ +typedef struct _COMMAND_FLAGS_ +{ +#if LITTLE_ENDIAN_TPM == YES /* libtpms added */ + unsigned trialPolicy : 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. + unsigned reserved : 31; //2-31) /* libtpms added begin */ +#endif +#if BIG_ENDIAN_TPM == YES + unsigned reserved : 31; //2-31) + unsigned trialPolicy : 1; //1) If SET, one of the handles references a +#endif /* libtpms added end */ +} COMMAND_FLAGS; +#endif /* libtpms added */ + +/* This structure is used to avoid having to manage a large number of parameters being passed + through various levels of the command input processing. + + The following macros are used to define the space for the CP and RP hashes. Space is provided + for each implemented hash algorithm because it is not known what the caller may use. +*/ + +#define CP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##CpHash; +#define RP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##RpHash; + +typedef struct _COMMAND_ +{ + TPM_ST tag; // the parsed command tag + TPM_CC code; // the parsed command code + COMMAND_INDEX index; // the computed command index + UINT32 handleNum; // 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 +// across functions to make sure that they are all using consistent string values. +#define STRING_INITIALIZER(value) {{sizeof(value), {value}}} +#define TPM2B_STRING(name, value) \ + typedef union name##_ { \ + struct { \ + UINT16 size; \ + BYTE buffer[sizeof(value)]; \ + } t; \ + TPM2B b; \ + } TPM2B_##name##_; \ + EXTERN const TPM2B_##name##_ name##_ INITIALIZER(STRING_INITIALIZER(value)); \ + EXTERN const TPM2B *name INITIALIZER(&name##_.b) +TPM2B_STRING(PRIMARY_OBJECT_CREATION, "Primary Object Creation"); +TPM2B_STRING(CFB_KEY, "CFB"); +TPM2B_STRING(CONTEXT_KEY, "CONTEXT"); +TPM2B_STRING(INTEGRITY_KEY, "INTEGRITY"); +TPM2B_STRING(SECRET_KEY, "SECRET"); +TPM2B_STRING(SESSION_KEY, "ATH"); +TPM2B_STRING(STORAGE_KEY, "STORAGE"); +TPM2B_STRING(XOR_KEY, "XOR"); +TPM2B_STRING(COMMIT_STRING, "ECDAA Commit"); +TPM2B_STRING(DUPLICATE_STRING, "DUPLICATE"); +TPM2B_STRING(IDENTITY_STRING, "IDENTITY"); +TPM2B_STRING(OBFUSCATE_STRING, "OBFUSCATE"); +#if SELF_TEST +TPM2B_STRING(OAEP_TEST_STRING, "OAEP Test Value"); +#endif // SELF_TEST + +// 5.9.14 From CryptTest.c +// This structure contains the self-test state values for the cryptographic modules. +EXTERN CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState; + +/* 5.9.15 From Manufacture.c */ +EXTERN BOOL g_manufactured; +/* 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. */ +EXTERN BOOL g_initialized; + +/* 5.9.16 Private data */ +#if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C +/* From SessionProcess.c */ +/* The following arrays are used to save command sessions information so that the command + handle/session buffer does not have to be preserved for the duration of the command. These arrays + are indexed by the session index in accordance with the order of sessions in the session area of + the command. */ + +/* Array of the authorization session handles */ +EXTERN TPM_HANDLE s_sessionHandles[MAX_SESSION_NUM]; + +/* Array of authorization session attributes */ +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 */ + +EXTERN TPM_HANDLE s_associatedHandles[MAX_SESSION_NUM]; + +/* Array of nonces provided by the caller for the corresponding sessions */ +EXTERN TPM2B_NONCE s_nonceCaller[MAX_SESSION_NUM]; + +/* Array of authorization values (HMAC's or passwords) for the corresponding sessions */ +EXTERN TPM2B_AUTH s_inputAuthValues[MAX_SESSION_NUM]; + +/* Array of pointers to the SESSION structures for the sessions in a command */ +EXTERN SESSION *s_usedSessions[MAX_SESSION_NUM]; + +/* Special value to indicate an undefined session index */ +#define UNDEFINED_INDEX (0xFFFF) +/* Index of the session used for encryption of a response parameter */ +EXTERN UINT32 s_encryptSessionIndex; + +/* Index of the session used for decryption of a command parameter */ +EXTERN UINT32 s_decryptSessionIndex; + +/* Index of a session used for audit */ +EXTERN UINT32 s_auditSessionIndex; + +/* The cpHash for command audit */ +#if CC_GetCommandAuditDigest +EXTERN TPM2B_DIGEST s_cpHashForCommandAudit; +#endif + +/* Flag indicating if NV update is pending for the lockOutAuthEnabled or failedTries DA parameter */ +EXTERN BOOL s_DAPendingOnNV; + +#endif // SESSION_PROCESS_C + +/* 5.9.16.2 From DA.c */ +#if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C + +/* From DA.c */ +/* This variable holds the accumulated time since the last time that failedTries was + decremented. This value is in millisecond. */ + +#if !ACCUMULATE_SELF_HEAL_TIMER +EXTERN UINT64 s_selfHealTimer; + +/* This variable holds the accumulated time that the lockoutAuth has been blocked. */ +EXTERN UINT64 s_lockoutTimer; + +#endif // ACCUMULATE_SELF_HEAL_TIMER +#endif // DA_C + +/* 5.9.16.3 From NV.c */ + +#if defined NV_C || defined GLOBAL_C + +/* From NV.c */ +/* This marks the end of the NV area. This is a run-time variable as it might not be compile-time + constant. */ +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. */ +EXTERN BYTE s_indexOrderlyRam[RAM_INDEX_SPACE]; // The orderly NV Index data + +/* This value contains the current max counter value. It is written to the end of allocatable NV + space each time 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. */ +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 were verified. */ +/* NOTE: 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 will verify that only one NV Index is referenced by the handles of the + command. */ + +EXTERN NV_INDEX s_cachedNvIndex; +EXTERN NV_REF s_cachedNvRef; +EXTERN BYTE *s_cachedNvRamRef; + +/* Initial NV Index/evict object iterator value */ +#define NV_REF_INIT (NV_REF)0xFFFFFFFF +#endif + +/* 5.9.16.4 From Object.c */ +#if defined OBJECT_C || defined GLOBAL_C + +/* This type is the container for an object. */ + +EXTERN OBJECT s_objects[MAX_LOADED_OBJECTS]; +#endif // OBJECT_C + +/* 5.9.17.5 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. */ + +#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; // if the PCR value should be + // saved in state save + unsigned int resetLocality : 5; // The locality that the PCR + // can be reset + unsigned int extendLocality : 5; // The locality that the PCR + // can be extend +} PCR_Attributes; +EXTERN PCR s_pcrs[IMPLEMENTATION_PCR]; +#endif // PCR_C + +/* 5.9.16.6 From Session.c */ + +#if defined SESSION_C || defined GLOBAL_C + +/* Container for HMAC or policy session tracking information */ +typedef struct +{ + BOOL occupied; + SESSION session; // session structure +} SESSION_SLOT; +EXTERN SESSION_SLOT s_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. */ + +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) */ +EXTERN int s_freeSessionSlots; + +#endif // SESSION_C + +/* 5.9.16.7 From IoBuffers.c */ + +#if defined IO_BUFFER_C || defined GLOBAL_C + +/* The value of s_actionIoAllocation is the number of UINT64 values allocated. It is used to set the + pointer for the response structure. */ +EXTERN UINT64 s_actionIoBuffer[768]; // action I/O buffer +EXTERN UINT32 s_actionIoAllocation; // number of UIN64 allocated for the action input + // structure +#endif // MEMORY_LIB_C + +/* 5.9.16.8 From TPMFail.c */ + +/* This value holds the address of the string containing the name of the function in which the + failure occurred. This address value isn't useful for anything other than helping the vendor to + know in which file the failure occurred. */ +EXTERN BOOL g_inFailureMode; // Indicates that the TPM is in failure mode +#if SIMULATION +EXTERN BOOL g_forceFailureMode; // flag to force failure mode during test +#endif +typedef void(FailFunction)(const char *function, int line, int code); +#if defined TPM_FAIL_C || defined GLOBAL_C || 1 +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 + +//***************************************************************************** +//*** From ACT_spt.c +//***************************************************************************** +// This value is used to indicate if an ACT has been updated since the last +// TPM2_Startup() (one bit for each ACT). 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 +EXTERN UINT16 s_ActUpdated; + +/* 5.9.16.9 From CommandCodeAttributes.c */ + +extern const TPMA_CC s_ccAttr[]; +extern const COMMAND_ATTRIBUTES s_commandAttributes[]; + +#endif // GLOBAL_H |