summaryrefslogtreecommitdiffstats
path: root/src/tpm2/PropertyCap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tpm2/PropertyCap.c')
-rw-r--r--src/tpm2/PropertyCap.c610
1 files changed, 610 insertions, 0 deletions
diff --git a/src/tpm2/PropertyCap.c b/src/tpm2/PropertyCap.c
new file mode 100644
index 0000000..db7d679
--- /dev/null
+++ b/src/tpm2/PropertyCap.c
@@ -0,0 +1,610 @@
+/********************************************************************************/
+/* */
+/* For accessing the TPM_CAP_TPM_PROPERTY values */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: PropertyCap.c 1519 2019-11-15 20:43:51Z 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 - 2019 */
+/* */
+/********************************************************************************/
+
+/* 9.14 PropertyCap.c */
+/* 9.14.1 Description */
+/* This file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values. */
+/* 9.14.2 Includes */
+#include "Tpm.h"
+
+#define TPM_HAVE_TPM2_DECLARATIONS
+#include "tpm_library_intern.h" // libtpms added
+/* 9.14.3 Functions */
+/* 9.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 Values Meaning */
+/* TRUE referenced property exists and value set */
+/* FALSE referenced property does not exist */
+static BOOL
+TPMPropertyIsDefined(
+ TPM_PT property, // IN: property
+ UINT32 *value // 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);
+ 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;
+#endif
+ break;
+ 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;
+#endif
+ break;
+ 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;
+#endif
+ break;
+ 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;
+ case 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
+#if 0
+ *value = ((UINT32)1 << (sizeof(CONTEXT_SLOT) * 8)) - 1;
+#endif
+ *value = s_ContextSlotMask; // libtpms added; the mask is either 0xff (old state) or 0xffff
+ 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;
+ UINT32 u32;
+ } 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
+ // NO) so the bits are manipulated 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:
+ // 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);
+#endif
+ break;
+ 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);
+#endif
+ break;
+ case TPM_PT_PS_FAMILY_INDICATOR:
+ // platform specific values for the TPM_PT_PS parameters from
+ // the relevant platform-specific specification
+ // 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;
+#endif
+ break;
+ 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 commands
+ for(commandIndex = GetClosestCommandIndex(0);
+ commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
+ commandIndex = GetNextCommandIndex(commandIndex))
+ {
+ (*value)++; // count of all implemented
+ }
+#endif
+ break;
+ }
+ 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 commands
+ for(commandIndex = GetClosestCommandIndex(0);
+ commandIndex < LIBRARY_COMMAND_ARRAY_SIZE;
+ commandIndex = GetNextCommandIndex(commandIndex))
+ {
+ (*value)++;
+ }
+#endif
+ 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;
+#endif
+ break;
+ 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;
+ UINT32 u32;
+ } 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;
+ UINT32 u32;
+ } 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)
+ 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;
+#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
+ and continue until propertyList has as many values as will fit, or the last property has been
+ reported, or the list has as many values as requested in count. */
+/* Return Values Meaning */
+/* YES more properties are available */
+/* NO no more properties to be reported */
+TPMI_YES_NO
+TPMCapGetProperties(
+ TPM_PT property, // IN: the starting TPM property
+ UINT32 count, // IN: maximum number of returned
+ // properties
+ TPML_TAGGED_TPM_PROPERTY *propertyList // OUT: property list
+ )
+{
+ TPMI_YES_NO more = NO;
+ UINT32 i;
+ UINT32 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
+ // last
+ if(property >= (PT_VAR + PT_GROUP))
+ return more;
+ // Don't read past the end of the selected group
+ nextGroup = ((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;
+}