diff --git a/TPMCmd/Platform/include/PlatformData.h b/TPMCmd/Platform/include/PlatformData.h index 490da8cb..b600e51f 100644 --- a/TPMCmd/Platform/include/PlatformData.h +++ b/TPMCmd/Platform/include/PlatformData.h @@ -67,11 +67,18 @@ extern BOOL s_timerReset; // This value indicates that the timer was stopped. It causes a clock discontinuity. extern BOOL s_timerStopped; -// Assume that the nominal divisor is 30000 +// 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 the conversion of the hardware ticks to +// internal hardware clock value. In practice, we would expect that there woudl be +// a hardware register will accumulated mS. It would be incremented by the output +// of a pre-scaler. The pre-scaler would divide the ticks from the clock by some +// value that would compensate for the difference between clock time and real time. +// The code in Clock does the emulation of this function. #define CLOCK_NOMINAL 30000 // A 1% change in rate is 300 counts #define CLOCK_ADJUST_COARSE 300 -// A .1 change in rate is 30 counts +// A 0.1% change in rate is 30 counts #define CLOCK_ADJUST_MEDIUM 30 // A minimum change in rate is 1 count #define CLOCK_ADJUST_FINE 1 diff --git a/TPMCmd/Platform/src/Clock.c b/TPMCmd/Platform/src/Clock.c index d0657829..0a198596 100644 --- a/TPMCmd/Platform/src/Clock.c +++ b/TPMCmd/Platform/src/Clock.c @@ -53,7 +53,8 @@ //***_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. +// 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 is also set. LIB_EXPORT void _plat__TimerReset( void @@ -115,9 +116,6 @@ _plat__TimerRead( clock_t timeDiff; uint64_t adjusted; -# define TOP (THOUSAND * CLOCK_NOMINAL) -# define BOTTOM ((uint64_t)s_adjustRate * CLOCKS_PER_SEC) - // Save the value previously read from the system clock timeDiff = s_realTimePrevious; // update with the current value of the system clock @@ -137,14 +135,16 @@ _plat__TimerRead( timeDiff = s_realTimePrevious - timeDiff; // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec - adjusted = (((uint64_t)timeDiff * TOP) / BOTTOM); + adjusted = (((uint64_t)timeDiff * (THOUSAND * CLOCK_NOMINAL)) + / ((uint64_t)s_adjustRate * CLOCKS_PER_SEC)); s_tpmTime += (clock_t)adjusted; // 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 - adjusted = (adjusted * BOTTOM) / TOP; + adjusted = (adjusted * ((uint64_t)s_adjustRate * CLOCKS_PER_SEC)) + / (THOUSAND * CLOCK_NOMINAL); // If adjusted is not the same as timeDiff, then there is some rounding // error that needs to be pushed back into the previous sample. diff --git a/TPMCmd/Platform/src/RunCommand.c b/TPMCmd/Platform/src/RunCommand.c index 5846b9d9..4461ada6 100644 --- a/TPMCmd/Platform/src/RunCommand.c +++ b/TPMCmd/Platform/src/RunCommand.c @@ -51,7 +51,7 @@ #include "PlatformData.h" #include "Platform_fp.h" #include -#include +#include "ExecCommand_fp.h" jmp_buf s_jumpBuffer; diff --git a/TPMCmd/tpm/include/Global.h b/TPMCmd/tpm/include/Global.h index c47f0a17..8ac80889 100644 --- a/TPMCmd/tpm/include/Global.h +++ b/TPMCmd/tpm/include/Global.h @@ -532,12 +532,7 @@ extern CLOCK_NONCE g_timeEpoch; #else #define g_timeEpoch gp.timeEpoch #endif - -//*** g_timeNewEpochNeeded -// This flag is SET at startup if a new timer nonce is needed. This flag will cause -// a new g_timeEpoch to be generated if it is needed by any of the ticket functions. -extern BOOL g_timeNewEpochNeeded; - + //*** g_phEnable // This is the platform hierarchy control and determines if the platform hierarchy @@ -872,8 +867,21 @@ typedef struct orderly_data // accumulate. DRBG_STATE drbgState; +// These values allow the accumulation of self-healing time across orderly shutdown +// of the TPM. +#ifdef 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 + } ORDERLY_DATA; +#ifdef 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; @@ -1212,11 +1220,13 @@ extern BOOL s_DAPendingOnNV; //***************************************************************************** // This variable holds the accumulated time since the last time // that 'failedTries' was decremented. This value is in millisecond. +#ifndef 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 diff --git a/TPMCmd/tpm/include/GpMacros.h b/TPMCmd/tpm/include/GpMacros.h index 47f43220..c755864f 100644 --- a/TPMCmd/tpm/include/GpMacros.h +++ b/TPMCmd/tpm/include/GpMacros.h @@ -46,10 +46,10 @@ #include "swap.h" #include "VendorString.h" -#ifdef SELF_TEST //** For Self-test // These macros are used in CryptUtil to invoke the incremental self test. +#ifdef SELF_TEST # define TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL) // Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting @@ -71,7 +71,7 @@ #endif #ifdef NO_FAIL_TRACE -# define FAIL(errorCode) (TmpFAIL(errorCode)) +# define FAIL(errorCode) (TpmFail(errorCode)) #else # define FAIL(errorCode) (TpmFail(FUNCTION_NAME, __LINE__, errorCode)) #endif @@ -90,14 +90,14 @@ #endif // 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. +// 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. #define REQUIRE(condition, errorCode, returnCode) \ { \ if(!!(condition)) \ { \ - FAIL(FATAL_ERROR_errorCode); \ + FAIL(FATAL_ERROR_errorCode); \ FAIL_RETURN(returnCode); \ } \ } @@ -105,12 +105,10 @@ #define PARAMETER_CHECK(condition, returnCode) \ REQUIRE((condition), PARAMETER, returnCode) -#if defined(EMPTY_ASSERT) +#if defined EMPTY_ASSERT # define pAssert(a) ((void)0) #else -// The additional parameter following FAIL(FATAL_ERROR_) is so that the expression within -// parenthesis has an lvalue. FAIL has no value so the expression is not complete. -# define pAssert(a) (!!(a) ? 1 : (FAIL(FATAL_ERROR_PARAMETER), 0)) +# define pAssert(a) {if(!(a)) FAIL(FATAL_ERROR_PARAMETER);} #endif //** Derived from Vendor-specific values @@ -123,7 +121,7 @@ //** 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 crypto +// on things that change based on various selections like the chosen cryptographic // libraries. It is possible that these selections will result in incompatible // settings. These are often detectable by the compiler but it isn't always // possible to do the check in the preprocessor code. For example, when the @@ -223,18 +221,19 @@ #define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8) #endif -#ifndef MAX_ECC_KEY_BYTES -#define MAX_ECC_KEY_BYTES 0 -#endif - -// Handle case when no ecc is defined -#ifndef MAX_ECC_KEY_BYTES -# define MAX_ECC_KEY_BYTES MAX_DIGEST_SIZE +#if ALG_ECC +# define LABEL_MAX_BUFFER MAX_ECC_KEY_BYTES +#else +# define LABEL_MAX_BUFFER MAX_DIGEST_SIZE #endif -#define LABEL_MAX_BUFFER MIN(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) -#if LABEL_MAX_BUFFER < 32 -#error "The size allowed for the label is not large enough for interoperability." -#endif +// This bit is used to indicate that an authorization ticket expires on TPM Reset +// and TPM Restart.It is added to the timeout value returned by TPM2_PoliySigned() +// and TPM2_PolicySecret() and used by TPM2_PolicyTicket(). The timeout value is +// relative to Time (g_time). Time is reset whenever the TPM loses power and cannot +// be moved forward by the user (as can Clock). g_time is a 64-bit value expressing +// time in ms. Sealing the MSb for a flag means that the TPM needs to be reset +// at least once every 292,471,208 years rather than once every 584,942,417 years. +#define EXPIRATION_BIT ((UINT64)1 << 63) #endif // GP_MACROS_H \ No newline at end of file diff --git a/TPMCmd/tpm/include/TpmBuildSwitches.h b/TPMCmd/tpm/include/TpmBuildSwitches.h index 599b5090..86e5bc3f 100644 --- a/TPMCmd/tpm/include/TpmBuildSwitches.h +++ b/TPMCmd/tpm/include/TpmBuildSwitches.h @@ -149,7 +149,7 @@ #ifndef NDEBUG // In some cases, the relationship between two values may be dependent -// on things that change based on various selections like the chosen crypto +// on things that change based on various selections like the chosen cryptographic // libraries. It is possible that these selections will result in incompatible // settings. These are often detectable by the compiler but it isn't always // possible to do the check in the preprocessor code. For example, when the @@ -176,6 +176,18 @@ //# define DRBG_DEBUG_PRINT #endif +// If an assertion event it not going to produce any trace information (function and +// line number) then define NO_FAIL_TRACE +#ifndef NO_FAIL_TRACE +//# define NO_FAIL_TRACE +#endif + #endif // NDEBUG +// If the implementation is going to give lockout time credit for time up to the +// last orderly shutdown, then uncomment this variable +#ifndef ACCUMULATE_SELF_HEAL_TIMER +#define ACCUMULATE_SELF_HEAL_TIMER +#endif // ACCUMULATE_SELF_HEAL_TIMER + #endif // _TPM_BUILD_SWITCHES_H_ \ No newline at end of file diff --git a/TPMCmd/tpm/include/TpmTypes.h b/TPMCmd/tpm/include/TpmTypes.h index 464c2a91..5ae3d4e6 100644 --- a/TPMCmd/tpm/include/TpmTypes.h +++ b/TPMCmd/tpm/include/TpmTypes.h @@ -58,9 +58,9 @@ typedef UINT32 TPM_SPEC; #define TPM_SPEC_LEVEL (TPM_SPEC)(SPEC_LEVEL) #define SPEC_VERSION 138 #define TPM_SPEC_VERSION (TPM_SPEC)(SPEC_VERSION) -#define SPEC_YEAR 2016 +#define SPEC_YEAR 2017 #define TPM_SPEC_YEAR (TPM_SPEC)(SPEC_YEAR) -#define SPEC_DAY_OF_YEAR 273 +#define SPEC_DAY_OF_YEAR 61 #define TPM_SPEC_DAY_OF_YEAR (TPM_SPEC)(SPEC_DAY_OF_YEAR) // Table 2:7 - Definition of TPM_GENERATED Constants (EnumTable) diff --git a/TPMCmd/tpm/include/VendorString.h b/TPMCmd/tpm/include/VendorString.h index a2a06474..cfc4e59c 100644 --- a/TPMCmd/tpm/include/VendorString.h +++ b/TPMCmd/tpm/include/VendorString.h @@ -75,7 +75,7 @@ string. // A vendor-specific FIRMWARE_V1 is required here. It is // the more significant 32-bits of a vendor-specific value // indicating the version of the firmware -//#define FIRMWARE_V1 (0x20160929) +//#define FIRMWARE_V1 (0x20170302) // A vendor-specific FIRMWARE_V2 may be provided here. If present, it is the less // significant 32-bits of the version of the firmware. diff --git a/TPMCmd/tpm/include/prototypes/BnConvert_fp.h b/TPMCmd/tpm/include/prototypes/BnConvert_fp.h index 9675b3d9..dc4d293e 100644 --- a/TPMCmd/tpm/include/prototypes/BnConvert_fp.h +++ b/TPMCmd/tpm/include/prototypes/BnConvert_fp.h @@ -34,7 +34,7 @@ */ /*(Auto) Automatically Generated by TpmPrototypes version 2.2 February 10, 2016 - Date: Sep 22, 2016 Time: 05:27:05 PM + Date: Dec 12, 2016 Time: 03:42:13 PM */ #ifndef _BNCONVERT_FP_H_ @@ -76,6 +76,11 @@ BnFromHex( // 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 be reversed. For a big-endian machine, rather than process +// unpack each word individually, the bigNum is converted to little-endian words, +// copied, and then converted back to big-endian. LIB_EXPORT BOOL BnToBytes( bigConst bn, diff --git a/TPMCmd/tpm/include/prototypes/Entity_fp.h b/TPMCmd/tpm/include/prototypes/Entity_fp.h index 6e3ca833..b832992f 100644 --- a/TPMCmd/tpm/include/prototypes/Entity_fp.h +++ b/TPMCmd/tpm/include/prototypes/Entity_fp.h @@ -34,7 +34,7 @@ */ /*(Auto) Automatically Generated by TpmPrototypes version 2.2 February 10, 2016 - Date: Sep 22, 2016 Time: 05:27:05 PM + Date: Dec 12, 2016 Time: 03:42:13 PM */ #ifndef _ENTITY_FP_H_ @@ -101,8 +101,6 @@ EntityGetName( // 2. An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, // is SET, otherwise it belongs to TPM_RH_OWNER // 3. An object handle belongs to its hierarchy. -// All other handles belong to the platform hierarchy. -// or an NV Index. TPMI_RH_HIERARCHY EntityGetHierarchy( TPMI_DH_ENTITY handle // IN :handle of entity diff --git a/TPMCmd/tpm/include/prototypes/Marshal_fp.h b/TPMCmd/tpm/include/prototypes/Marshal_fp.h index 14a29a4b..5765276f 100644 --- a/TPMCmd/tpm/include/prototypes/Marshal_fp.h +++ b/TPMCmd/tpm/include/prototypes/Marshal_fp.h @@ -34,10 +34,10 @@ */ /*(Auto) * Created by TpmMarshal.pl version 2.1 September 17, 2015 - * This file created on Sep 27, 2016, 04:02:56 PM + * This file created on Dec 12, 2016, 03:42:12 PM Processed by TpmReferencesAndReturns Version 1.2, July 27, 2015 - Date: Sep 27, 2016 Time: 04:02:57 PM + Date: Dec 12, 2016 Time: 03:42:12 PM */ @@ -1094,20 +1094,11 @@ TPMS_SENSITIVE_CREATE_Marshal(TPMS_SENSITIVE_CREATE *source, BYTE **buffer, INT3 // Table 2:140 - Definition of TPM2B_SENSITIVE_CREATE Structure (StructureTable) -#ifdef UT_BYTE_TPM2B_SENSITIVE_CREATE TPM_RC TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size); UINT16 TPM2B_SENSITIVE_CREATE_Marshal(TPM2B_SENSITIVE_CREATE *source, BYTE **buffer, INT32 *size); -#else -TPM_RC -TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size); -UINT16 -TPM2B_SENSITIVE_CREATE_Marshal(TPM2B_SENSITIVE_CREATE *source, BYTE **buffer, INT32 *size); - -#endif - // Table 2:141 - Definition of TPMS_SCHEME_HASH Structure (StructureTable) #define TPMS_SCHEME_HASH_Unmarshal(target, buffer, size) \ @@ -1415,19 +1406,11 @@ TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT *source, BYTE **buffer, INT32 *size); // Table 2:169 - Definition of TPM2B_ECC_POINT Structure (StructureTable) #if ALG_ECC -#ifdef UT_BYTE_TPM2B_ECC_POINT TPM_RC TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size); UINT16 TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT *source, BYTE **buffer, INT32 *size); -#else -TPM_RC -TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size); -UINT16 -TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT *source, BYTE **buffer, INT32 *size); - -#endif #endif // ALG_ECC @@ -1642,20 +1625,11 @@ TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size); // Table 2:191 - Definition of TPM2B_PUBLIC Structure (StructureTable) -#ifdef UT_BYTE_TPM2B_PUBLIC -TPM_RC -TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size); -UINT16 -TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC *source, BYTE **buffer, INT32 *size); - -#else TPM_RC TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL flag); UINT16 TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC *source, BYTE **buffer, INT32 *size); -#endif - // Table 2:192 - Definition of TPM2B_TEMPLATE Structure (StructureTable) TPM_RC @@ -1686,20 +1660,11 @@ TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size); // Table 2:196 - Definition of TPM2B_SENSITIVE Structure (StructureTable) -#ifdef UT_BYTE_TPM2B_SENSITIVE TPM_RC TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size); UINT16 TPM2B_SENSITIVE_Marshal(TPM2B_SENSITIVE *source, BYTE **buffer, INT32 *size); -#else -TPM_RC -TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size); -UINT16 -TPM2B_SENSITIVE_Marshal(TPM2B_SENSITIVE *source, BYTE **buffer, INT32 *size); - -#endif - // Table 2:197 - Definition of _PRIVATE Structure (StructureTable) TPM_RC @@ -1759,20 +1724,11 @@ TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC *source, BYTE **buffer, INT32 *size); // Table 2:206 - Definition of TPM2B_NV_PUBLIC Structure (StructureTable) -#ifdef UT_BYTE_TPM2B_NV_PUBLIC -TPM_RC -TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size); -UINT16 -TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC *source, BYTE **buffer, INT32 *size); - -#else TPM_RC TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size); UINT16 TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC *source, BYTE **buffer, INT32 *size); -#endif - // Table 2:207 - Definition of TPM2B_CONTEXT_SENSITIVE Structure (StructureTable) TPM_RC @@ -1810,19 +1766,11 @@ TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA *source, BYTE **buffer, INT32 *siz // Table 2:213 - Definition of TPM2B_CREATION_DATA Structure (StructureTable) -#ifdef UT_BYTE_TPM2B_CREATION_DATA -TPM_RC -TPM2B_CREATION_DATA_Unmarshal(TPM2B_CREATION_DATA *target, BYTE **buffer, INT32 *size); -UINT16 -TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size); - -#else TPM_RC TPM2B_CREATION_DATA_Unmarshal(TPM2B_CREATION_DATA *target, BYTE **buffer, INT32 *size); UINT16 TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size); -#endif // Array Marshal/Unmarshal for BYTE TPM_RC BYTE_Array_Unmarshal(BYTE *target, BYTE **buffer, INT32 *size, INT32 count); diff --git a/TPMCmd/tpm/include/prototypes/Object_spt_fp.h b/TPMCmd/tpm/include/prototypes/Object_spt_fp.h index 1d882e3c..51c2986a 100644 --- a/TPMCmd/tpm/include/prototypes/Object_spt_fp.h +++ b/TPMCmd/tpm/include/prototypes/Object_spt_fp.h @@ -34,7 +34,7 @@ */ /*(Auto) Automatically Generated by TpmPrototypes version 2.2 February 10, 2016 - Date: Sep 22, 2016 Time: 05:27:05 PM + Date: Dec 12, 2016 Time: 03:42:13 PM */ #ifndef _OBJECT_SPT_FP_H_ @@ -71,7 +71,8 @@ ObjectIsParent( TPM_RC CreateChecks( OBJECT *parentObject, - TPMT_PUBLIC *publicArea + TPMT_PUBLIC *publicArea, + UINT16 sensitiveDataSize ); //*** SchemeChecks @@ -365,6 +366,7 @@ MemoryRemoveTrailingZeros( // that 'label' or 'context' can end up being an Empty Buffer. TPM_RC SetLabelAndContext( + TPMS_DERIVE *labelContext, // OUT: the recovered label and context TPMT_PUBLIC *publicArea, // IN/OUT: the public area containing // the unmarshaled template TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data diff --git a/TPMCmd/tpm/include/prototypes/Time_fp.h b/TPMCmd/tpm/include/prototypes/Time_fp.h index ee7bfa86..59986544 100644 --- a/TPMCmd/tpm/include/prototypes/Time_fp.h +++ b/TPMCmd/tpm/include/prototypes/Time_fp.h @@ -34,7 +34,7 @@ */ /*(Auto) Automatically Generated by TpmPrototypes version 2.2 February 10, 2016 - Date: Sep 22, 2016 Time: 05:27:05 PM + Date: Sep 9, 2016 Time: 03:28:04 PM */ #ifndef _TIME_FP_H_ @@ -74,10 +74,7 @@ TimeStartup( // 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. -// return type: TPM_RC -// TPM_RC_NV_RATE NV cannot be written because it is rate limiting -// TPM_RC_NV_UNAVAILABLE NV cannot be accessed -TPM_RC +void TimeClockUpdate( UINT64 newTime ); diff --git a/TPMCmd/tpm/include/prototypes/TpmFail_fp.h b/TPMCmd/tpm/include/prototypes/TpmFail_fp.h index e6ab1993..a36cd76c 100644 --- a/TPMCmd/tpm/include/prototypes/TpmFail_fp.h +++ b/TPMCmd/tpm/include/prototypes/TpmFail_fp.h @@ -34,7 +34,7 @@ */ /*(Auto) Automatically Generated by TpmPrototypes version 2.2 February 10, 2016 - Date: Sep 22, 2016 Time: 05:27:05 PM + Date: Dec 12, 2016 Time: 03:42:13 PM */ #ifndef _TPMFAIL_FP_H_ @@ -54,8 +54,11 @@ SetForceFailureMode( // failure values to be returned on TPM2_GetTestResult(). NORETURN void TpmFail( + +#ifndef NO_FAIL_TRACE const char *function, int line, +#endif int code ); diff --git a/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c b/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c index 09e73786..75b71a8d 100644 --- a/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c +++ b/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c @@ -52,7 +52,6 @@ TPM2_ClockSet( #define CLOCK_UPDATE_MASK ~((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1) // Input Validation - // new time can not be bigger than 0xFFFF000000000000 or smaller than // current clock if(in->newTime > 0xFFFF000000000000ULL @@ -60,8 +59,11 @@ TPM2_ClockSet( return TPM_RCS_VALUE + RC_ClockSet_newTime; // Internal Data Update + // Can't modify the clock if NV is not available. + RETURN_IF_NV_IS_NOT_AVAILABLE; - return TimeClockUpdate(in->newTime); + TimeClockUpdate(in->newTime); + return TPM_RC_SUCCESS; } #endif // CC_ClockSet \ No newline at end of file diff --git a/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c b/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c index 0b888ccb..e9a60e92 100644 --- a/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c +++ b/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c @@ -56,8 +56,14 @@ TPM2_DictionaryAttackParameters( gp.recoveryTime = in->newRecoveryTime; gp.lockoutRecovery = in->lockoutRecovery; +#if 0 // Errata eliminates this code + // This functionality has been disabled. The preferred implementation is now + // to leave failedTries unchanged when the parameters are changed. This could + // have the effect of putting the TPM into DA lockout if in->newMaxTries is + // not greater than the current value of gp.failedTries. // Set failed tries to 0 gp.failedTries = 0; +#endif // Record the changes to NV NV_SYNC_PERSISTENT(failedTries); diff --git a/TPMCmd/tpm/src/command/EA/PolicySecret.c b/TPMCmd/tpm/src/command/EA/PolicySecret.c index 2c7710fa..88327dff 100644 --- a/TPMCmd/tpm/src/command/EA/PolicySecret.c +++ b/TPMCmd/tpm/src/command/EA/PolicySecret.c @@ -95,19 +95,23 @@ TPM2_PolicySecret( && !NvIsPinPassIndex(in->authHandle)) { BOOL expiresOnReset = (in->nonceTPM.t.size == 0); - // Generate timeout buffer. The format of output timeout buffer is - // TPM-specific. - // In this implementation, the timeout parameter is the timeout relative - // to g_time with a one byte flag to indicate if the ticket will expire on - // TPM Reset - out->timeout.t.size = sizeof(authTimeout) + 1; - UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); - out->timeout.t.buffer[sizeof(authTimeout)] = (BYTE)expiresOnReset; - // Compute policy ticket + authTimeout &= ~EXPIRATION_BIT; TicketComputeAuth(TPM_ST_AUTH_SECRET, EntityGetHierarchy(in->authHandle), authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, &entityName, &out->policyTicket); + // Generate timeout buffer. The format of output timeout buffer is + // TPM-specific. + // Note: In this implementation, the timeout buffer value is computed after + // the ticket is produced so, when the ticket is checked, the expiration + // flag needs to be extracted before the ticket is checked. + out->timeout.t.size = sizeof(authTimeout); + // In the Windows compatible version, the least-significant bit of the + // timeout value is used as a flag to indicate if the authorization expires + // on reset. The flag is the MSb. + if(expiresOnReset) + authTimeout |= EXPIRATION_BIT; + UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); } else { diff --git a/TPMCmd/tpm/src/command/EA/PolicySigned.c b/TPMCmd/tpm/src/command/EA/PolicySigned.c index d8329d75..394fa883 100644 --- a/TPMCmd/tpm/src/command/EA/PolicySigned.c +++ b/TPMCmd/tpm/src/command/EA/PolicySigned.c @@ -145,19 +145,24 @@ TPM2_PolicySigned( && session->attributes.isTrialPolicy == CLEAR) { BOOL expiresOnReset = (in->nonceTPM.t.size == 0); - // Generate timeout buffer. The format of output timeout buffer is - // TPM-specific. - // In this implementation, the timeout parameter is the timeout relative - // to g_time with a one byte flag to indicate if the ticket will expire on - // TPM Reset - out->timeout.t.size = sizeof(authTimeout) + 1; - UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); - out->timeout.t.buffer[sizeof(authTimeout)] = (BYTE)expiresOnReset; - // Compute policy ticket + authTimeout &= ~EXPIRATION_BIT; + TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject), authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, &entityName, &out->policyTicket); + // Generate timeout buffer. The format of output timeout buffer is + // TPM-specific. + // Note: In this implementation, the timeout buffer value is computed after + // the ticket is produced so, when the ticket is checked, the expiration + // flag needs to be extracted before the ticket is checked. + // In the Windows compatible version, the least-significant bit of the + // timeout value is used as a flag to indicate if the authorization expires + // on reset. The flag is the MSb. + out->timeout.t.size = sizeof(authTimeout); + if(expiresOnReset) + authTimeout |= EXPIRATION_BIT; + UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); } else { diff --git a/TPMCmd/tpm/src/command/EA/PolicyTicket.c b/TPMCmd/tpm/src/command/EA/PolicyTicket.c index c79b2444..e4fa63dd 100644 --- a/TPMCmd/tpm/src/command/EA/PolicyTicket.c +++ b/TPMCmd/tpm/src/command/EA/PolicyTicket.c @@ -75,14 +75,18 @@ TPM2_PolicyTicket( // would be a substitute. if(session->attributes.isTrialPolicy) return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession; - // Restore timeout data. The format of timeout buffer is TPM-specific. - // In this implementation, we simply copy the value of timeout to the - // buffer. - if(in->timeout.t.size != sizeof(UINT64) + 1) + // In this implementation, the most significant bit of the timeout value is + // used as the flag to indicate that the ticket expires on TPM Reset or + // TPM Restart. The flag has to be removed before the parameters and ticket + // are checked. + if(in->timeout.t.size != sizeof(UINT64)) return TPM_RCS_SIZE + RC_PolicyTicket_timeout; authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer); - expiresOnReset = in->timeout.t.buffer[sizeof(authTimeout)]; + + // extract the flag + expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0; + authTimeout &= ~EXPIRATION_BIT; // Do the normal checks on the cpHashA and timeout values result = PolicyParameterChecks(session, authTimeout, @@ -93,14 +97,11 @@ TPM2_PolicyTicket( RC_PolicyTicket_timeout); if(result != TPM_RC_SUCCESS) return result; - // Validate Ticket // Re-generate policy ticket by input parameters TicketComputeAuth(in->ticket.tag, in->ticket.hierarchy, authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, &in->authName, &ticketToCompare); - - // Compare generated digest with input ticket digest if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b)) return TPM_RCS_TICKET + RC_PolicyTicket_ticket; diff --git a/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c b/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c index 3dcbae0a..7c884751 100644 --- a/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c +++ b/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c @@ -42,10 +42,7 @@ // Creates a primary or temporary object from a primary seed. */ // return type: TPM_RC -// TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data' is -// an Empty Buffer, or is SET when 'sensitive.data' is not -// empty; -// 'fixedTPM', 'fixedParent', or 'encryptedDuplication' +// TPM_RC_ATTRIBUTES 'fixedTPM', 'fixedParent', or 'encryptedDuplication' // attributes are inconsistent between themselves or with // those of the parent object; // inconsistent 'restricted', 'decrypt' and 'sign' @@ -94,15 +91,14 @@ TPM2_CreatePrimary( // Check attributes in input public area. CreateChecks() checks the things that // are unique to creation and then validates the attributes and values that are // common to create and load. - result = CreateChecks(NULL, publicArea); + result = CreateChecks(NULL, publicArea, + in->inSensitive.sensitive.data.t.size); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_CreatePrimary_inPublic); - // Validate the sensitive area values if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) return TPM_RCS_SIZE + RC_CreatePrimary_inSensitive; - // Command output // Compute the name using out->name as a scratch area (this is not the value // that ultimately will be returned, then instantiate the state that will be diff --git a/TPMCmd/tpm/src/command/Object/Create.c b/TPMCmd/tpm/src/command/Object/Create.c index 9074adfb..b42eb0ea 100644 --- a/TPMCmd/tpm/src/command/Object/Create.c +++ b/TPMCmd/tpm/src/command/Object/Create.c @@ -119,21 +119,13 @@ TPM2_Create( // Copy the input structure to the allocated structure *publicArea = in->inPublic.publicArea; - - // The sensitiveDataOrigin attribute must be consistent with the setting of - // the size of the data object in inSensitive. - if((publicArea->objectAttributes.sensitiveDataOrigin == SET) - != (in->inSensitive.sensitive.data.t.size == 0)) - // Mismatch between the object attributes and the parameter. - return TPM_RCS_ATTRIBUTES + RC_Create_inSensitive; - // Check attributes in input public area. CreateChecks() checks the things that // are unique to creation and then validates the attributes and values that are // common to create and load. - result = CreateChecks(parentObject, publicArea); + result = CreateChecks(parentObject, publicArea, + in->inSensitive.sensitive.data.t.size); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_Create_inPublic); - // Clean up the authValue if necessary if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) return TPM_RCS_SIZE + RC_Create_inSensitive; diff --git a/TPMCmd/tpm/src/command/Object/CreateLoaded.c b/TPMCmd/tpm/src/command/Object/CreateLoaded.c index e93e264c..00c4f5de 100644 --- a/TPMCmd/tpm/src/command/Object/CreateLoaded.c +++ b/TPMCmd/tpm/src/command/Object/CreateLoaded.c @@ -40,15 +40,14 @@ /*(See part 3 of specification) * Create and load any type of key, including a temporary key. - * The input template is an marshaled public area rather than an unmarshaled one as + * The input template is an marshaled public area rather than an unmarshaled one as * used in Create and CreatePrimary. This is so that the label and context that * could be in the template can be processed without changing the formats for the * calls to Create and CreatePrimary. */ // return type: TPM_RC // TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data' is -// an Empty Buffer, or is SET when 'sensitive.data' is not -// empty; +// an Empty Buffer; // 'fixedTPM', 'fixedParent', or 'encryptedDuplication' // attributes are inconsistent between themselves or with // those of the parent object; @@ -87,6 +86,7 @@ TPM2_CreateLoaded( TPMT_PUBLIC *publicArea; RAND_STATE randState; RAND_STATE *rand = &randState; + TPMS_DERIVE labelContext; // Input Validation @@ -146,16 +146,17 @@ TPM2_CreateLoaded( return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); // Process the template and sensitive areas to get the actual 'label' and // 'context' values to be used for this derivation. - result = SetLabelAndContext(publicArea, &in->inSensitive.sensitive.data); + result = SetLabelAndContext(&labelContext, publicArea, + &in->inSensitive.sensitive.data); if(result != TPM_RC_SUCCESS) return result; // Set up the KDF for object generation DRBG_InstantiateSeededKdf((KDF_STATE *)rand, scheme->details.xor.hashAlg, scheme->details.xor.kdf, - &parent->sensitive.seedValue.b, - &publicArea->unique.derive.label.b, - &publicArea->unique.derive.context.b); + &parent->sensitive.sensitive.bits.b, + &labelContext.label.b, + &labelContext.context.b); // Clear the sensitive size so that the creation functions will not try // to use this value. in->inSensitive.sensitive.data.t.size = 0; @@ -165,7 +166,8 @@ TPM2_CreateLoaded( // Check attributes in input public area. CreateChecks() checks the things // that are unique to creation and then validates the attributes and values // that are common to create and load. - result = CreateChecks(parent, publicArea); + result = CreateChecks(parent, publicArea, + in->inSensitive.sensitive.data.t.size); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); // Creating a primary object @@ -183,11 +185,12 @@ TPM2_CreateLoaded( (TPM2B *)PublicMarshalAndComputeName(publicArea, &name), &in->inSensitive.sensitive.data.b); - } else - // This is an ordinary object so use the normal random number generator + { + // This is an ordinary object so use the normal random number generator rand = NULL; + } } // Internal data update // Create the object diff --git a/TPMCmd/tpm/src/command/Object/Object_spt.c b/TPMCmd/tpm/src/command/Object/Object_spt.c index 18e728cf..7dcafc92 100644 --- a/TPMCmd/tpm/src/command/Object/Object_spt.c +++ b/TPMCmd/tpm/src/command/Object/Object_spt.c @@ -127,15 +127,12 @@ ComputeProtectionKeyParms( *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; } @@ -191,14 +188,12 @@ ComputeOuterIntegrity( // 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, 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); @@ -226,7 +221,7 @@ ComputeInnerIntegrity( ) { HASH_STATE hashState; - +// // Start hash and get the size of the digest which will become the integrity integrity->t.size = CryptHashStart(&hashState, hashAlg); @@ -262,11 +257,10 @@ ProduceInnerIntegrity( ) { BYTE *sensitiveData; // pointer to the sensitive data - TPM2B_DIGEST integrity; UINT16 integritySize; BYTE *buffer; // Auxiliary buffer pointer - +// // sensitiveData points to the beginning of sensitive data in innerBuffer integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); sensitiveData = innerBuffer + integritySize; @@ -296,12 +290,11 @@ CheckInnerIntegrity( ) { TPM_RC result; - TPM2B_DIGEST integrity; TPM2B_DIGEST integrityToCompare; BYTE *buffer; // Auxiliary buffer pointer INT32 size; - +// // Unmarshal integrity buffer = innerBuffer; size = (INT32)dataSize; @@ -311,7 +304,6 @@ CheckInnerIntegrity( // Compute integrity to compare ComputeInnerIntegrity(hashAlg, name, (UINT16)size, buffer, &integrityToCompare); - // Compare outer blob integrity if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) result = TPM_RC_INTEGRITY; @@ -332,9 +324,9 @@ AdjustAuthSize( ) { 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 - digestSize = (nameAlg == TPM_ALG_NULL) ? sizeof(TPMU_HA) : CryptHashGetDigestSize(nameAlg); if(digestSize < MemoryRemoveTrailingZeros(auth)) @@ -342,6 +334,7 @@ AdjustAuthSize( else if(digestSize > auth->t.size) MemoryPad2B(&auth->b, digestSize); auth->t.size = digestSize; + return TRUE; } @@ -369,29 +362,44 @@ ObjectIsParent( TPM_RC CreateChecks( OBJECT *parentObject, - TPMT_PUBLIC *publicArea + TPMT_PUBLIC *publicArea, + UINT16 sensitiveDataSize ) { TPMA_OBJECT attributes = publicArea->objectAttributes; TPM_RC result = TPM_RC_SUCCESS; - +// + // If the caller indicates that they have provided the data, then make sure that + // they have provided some data. + if((attributes.sensitiveDataOrigin == CLEAR) + && (sensitiveDataSize == 0)) + return TPM_RCS_ATTRIBUTES; + // For an ordinary object, data can only be provided when sensitiveDataOrigin + // is CLEAR + if((parentObject != NULL) + && (attributes.sensitiveDataOrigin == SET) + && (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(!attributes.sign && !attributes.decrypt + && attributes.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 must have sensitiveDataOrigin SET unless it has - // fixedParent and fixedTPM CLEAR. + // A restricted key symmetric key (SYMCIPHER and KEYEDHASH) + // must have sensitiveDataOrigin SET unless it has fixedParent and + // fixedTPM CLEAR. if(attributes.restricted) if(!attributes.sensitiveDataOrigin) if(attributes.fixedParent || attributes.fixedTPM) result = TPM_RCS_ATTRIBUTES; break; - case TPM_ALG_KEYEDHASH: - // if this is a data object (sign == decrypt == CLEAR) then the - // TPM cannot be the data source. - if(!attributes.sign && !attributes.decrypt - && attributes.sensitiveDataOrigin) - result = TPM_RC_ATTRIBUTES; - break; default: // Asymmetric keys cannot have the sensitive portion provided if(!attributes.sensitiveDataOrigin) result = TPM_RCS_ATTRIBUTES; @@ -429,7 +437,7 @@ SchemeChecks( TPM_ALG_ID scheme = TPM_ALG_NULL; TPMA_OBJECT attributes = publicArea->objectAttributes; TPMU_PUBLIC_PARMS *parms = &publicArea->parameters; - +// switch(publicArea->type) { case TPM_ALG_SYMCIPHER: @@ -562,6 +570,13 @@ SchemeChecks( { 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 P2 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 parent if(attributes.fixedParent && (parentObject != NULL)) @@ -603,20 +618,17 @@ PublicAttributesValidation( { TPMA_OBJECT attributes = publicArea->objectAttributes; TPMA_OBJECT parentAttributes = {0}; - +// if(parentObject != NULL) parentAttributes = parentObject->publicArea.objectAttributes; - if(publicArea->nameAlg == TPM_ALG_NULL) return TPM_RCS_HASH; - // If there is an authPolicy, it needs to be the size of the digest produced // by the nameAlg of the object if((publicArea->authPolicy.t.size != 0 && (publicArea->authPolicy.t.size != CryptHashGetDigestSize(publicArea->nameAlg)))) return TPM_RCS_SIZE; - // If the parent is fixedTPM (including a Primary Object) the object must have // the same value for fixedTPM and fixedParent if(parentObject == NULL || parentAttributes.fixedTPM == SET) @@ -682,7 +694,7 @@ FillInCreationData( BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; BYTE *buffer; HASH_STATE hashState; - +// // Fill in TPMS_CREATION_DATA in outCreation // Compute PCR digest @@ -695,7 +707,6 @@ FillInCreationData( // Get locality outCreation->creationData.locality = LocalityGetAttributes(_plat__LocalityGet()); - outCreation->creationData.parentNameAlg = TPM_ALG_NULL; // If the parent is either a primary seed or TPM_ALG_NULL, then the Name @@ -705,7 +716,6 @@ FillInCreationData( 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 @@ -714,7 +724,7 @@ FillInCreationData( else // Regular object { OBJECT *parentObject = HandleToObject(parentHandle); - +// // Set name algorithm outCreation->creationData.parentNameAlg = parentObject->publicArea.nameAlg; @@ -725,7 +735,6 @@ FillInCreationData( outCreation->creationData.parentQualifiedName = parentObject->qualifiedName; } - // Copy outside information outCreation->creationData.outsideInfo = *outsideData; @@ -733,8 +742,7 @@ FillInCreationData( buffer = creationBuffer; outCreation->size = TPMS_CREATION_DATA_Marshal(&outCreation->creationData, &buffer, NULL); - - // Compute hash for creation field in public template + // Compute hash for creation field in public template creationDigest->t.size = CryptHashStart(&hashState, nameHashAlg); CryptDigestUpdate(&hashState, outCreation->size, creationBuffer); CryptHashEnd2B(&hashState, &creationDigest->b); @@ -797,13 +805,11 @@ ProduceOuterWrap( TPM2B_IV ivRNG; // IV from RNG TPM2B_IV *iv = NULL; UINT16 ivSize = 0; // size of iv area, including the size field - BYTE *sensitiveData; // pointer to the sensitive data - TPM2B_DIGEST integrity; UINT16 integritySize; BYTE *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); @@ -829,7 +835,6 @@ ProduceOuterWrap( // Use iv for encryption iv = &ivRNG; } - // Compute symmetric key parameters for outer buffer encryption ComputeProtectionKeyParms(protector, hashAlg, name, seed, &symAlg, &keyBits, &symKey); @@ -837,12 +842,10 @@ ProduceOuterWrap( 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); @@ -887,13 +890,11 @@ UnwrapOuter( UINT16 keyBits = 0; TPM2B_IV ivIn; // input IV retrieved from input buffer TPM2B_IV *iv = NULL; - BYTE *sensitiveData; // pointer to the sensitive data - TPM2B_DIGEST integrityToCompare; TPM2B_DIGEST integrity; INT32 size; - +// // Unmarshal integrity sensitiveData = outerBuffer; size = (INT32)dataSize; @@ -904,15 +905,12 @@ UnwrapOuter( ComputeOuterIntegrity(name, protector, hashAlg, seed, (UINT16)size, sensitiveData, &integrityToCompare); - // Compare outer blob integrity if(!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) { @@ -929,7 +927,7 @@ UnwrapOuter( } } // If no errors, decrypt private in place. Since this function uses CFB, - // CryptSymmetricDecrypt() will not return any errors (it may fail but it will + // 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, @@ -950,17 +948,21 @@ MarshalSensitive( TPMI_ALG_HASH nameAlg // IN: ) { - BYTE *sizeField = buffer; + BYTE *sizeField = buffer; // saved so that size can be + // marshaled after it is known UINT16 retVal; - // Pad the authValue if needed +// + // Pad the authValue if needed MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg)); buffer += 2; + // Marshal the structure retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); + // Marshal the size retVal = (UINT16)(retVal + UINT16_Marshal(&retVal, &sizeField, NULL)); - return retVal; + return retVal; } //*** SensitiveToPrivate() @@ -1143,7 +1145,6 @@ SensitiveToDuplicate( TPM2B_PRIVATE *outPrivate // OUT: output private structure ) { - BYTE *buffer; // Auxiliary buffer pointer BYTE *sensitiveData; // pointer to the sensitive data TPMI_ALG_HASH outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap TPMI_ALG_HASH innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap @@ -1164,8 +1165,10 @@ SensitiveToDuplicate( if(symDef->algorithm != TPM_ALG_NULL) { doInnerWrap = TRUE; + // Use self nameAlg as inner hash algorithm innerHash = nameAlg; + // Adjust sensitive data pointer sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(innerHash); } @@ -1173,22 +1176,14 @@ SensitiveToDuplicate( if(seed->size != 0) { doOuterWrap = TRUE; + // Use parent nameAlg as outer hash algorithm outerHash = ObjectGetNameAlg(parent); + // Adjust sensitive data pointer sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); } - // Marshal sensitive area, leaving the leading 2 bytes for size - buffer = sensitiveData + sizeof(UINT16); - dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); - - // Adding size before the data area - buffer = sensitiveData; - UINT16_Marshal(&dataSize, &buffer, NULL); - - // Adjust the dataSize to include the size field - dataSize += sizeof(UINT16); - + // Marshal sensitive area dataSize = MarshalSensitive(sensitiveData, sensitive, nameAlg); // Apply inner wrap for duplication blob. It includes both integrity and @@ -1203,7 +1198,6 @@ SensitiveToDuplicate( innerBuffer += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, innerBuffer); - // Generate inner encryption key if needed if(innerSymKey->t.size == 0) { @@ -1274,13 +1268,12 @@ DuplicateToSensitive( ) { TPM_RC result; - BYTE *buffer; INT32 size; BYTE *sensitiveData; // pointer to the sensitive data UINT16 dataSize; UINT16 dataSizeInput; - +// // Make sure that name is provided pAssert(name != NULL && name->size != 0); @@ -1301,7 +1294,6 @@ DuplicateToSensitive( 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); @@ -1316,17 +1308,14 @@ DuplicateToSensitive( CryptSymmetricDecrypt(sensitiveData, symDef->algorithm, symDef->keyBits.sym, innerSymKey->buffer, NULL, TPM_ALG_CFB, dataSize, sensitiveData); - // Check inner integrity result = CheckInnerIntegrity(name, nameAlg, dataSize, sensitiveData); if(result != TPM_RC_SUCCESS) return result; - // Adjust sensitive data pointer and size sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); } - // Unmarshal input data size buffer = sensitiveData; size = (INT32)dataSize; @@ -1339,6 +1328,7 @@ DuplicateToSensitive( { // 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; @@ -1367,7 +1357,7 @@ SecretToCredential( BYTE *sensitiveData; // pointer to the sensitive data TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap UINT16 dataSize; // data blob size - +// pAssert(secret != NULL && outIDObject != NULL); // use protector's name algorithm as outer hash @@ -1376,19 +1366,13 @@ SecretToCredential( // Marshal secret area to credential buffer, leave space for integrity sensitiveData = outIDObject->t.credential + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); - // Marshal secret area buffer = sensitiveData; dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL); // Apply outer wrap - outIDObject->t.size = ProduceOuterWrap(protector, - name, - outerHash, - seed, - FALSE, - dataSize, - outIDObject->t.credential); + outIDObject->t.size = ProduceOuterWrap(protector, name, outerHash, seed, FALSE, + dataSize, outIDObject->t.credential); return; } @@ -1421,7 +1405,7 @@ CredentialToSecret( TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap BYTE *sensitiveData; // pointer to the sensitive data UINT16 dataSize; - +// // use protector's name algorithm as outer hash outerHash = ObjectGetNameAlg(protector); @@ -1435,11 +1419,11 @@ CredentialToSecret( + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); dataSize = inIDObject->size - (sizeof(UINT16) + CryptHashGetDigestSize(outerHash)); - - // Unmarshal secret buffer to TPM2B_DIGEST structure + // Unmarshal secret buffer to TPM2B_DIGEST structure buffer = sensitiveData; size = (INT32)dataSize; result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); + // If there were no other unmarshaling errors, make sure that the // expected amount of data was recovered if(result == TPM_RC_SUCCESS && size != 0) @@ -1468,6 +1452,7 @@ MemoryRemoveTrailingZeros( // that 'label' or 'context' can end up being an Empty Buffer. TPM_RC SetLabelAndContext( + TPMS_DERIVE *labelContext, // OUT: the recovered label and context TPMT_PUBLIC *publicArea, // IN/OUT: the public area containing // the unmarshaled template TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data @@ -1476,28 +1461,30 @@ SetLabelAndContext( TPM_RC result; INT32 size; BYTE *buff; - TPM2B_LABEL label; +// + // In case neither the sensitive nor publicArea have a label or a context + labelContext->label.b.size = 0; + labelContext->context.b.size = 0; // Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer - size = sensitive->t.size; // If there is something to unmarshal... - if(size != 0) + if(sensitive->t.size != 0) { + size = sensitive->t.size; buff = sensitive->t.buffer; - result = TPM2B_LABEL_Unmarshal(&label, &buff, &size); + result = TPMS_DERIVE_Unmarshal(labelContext, &buff, &size); if(result != TPM_RC_SUCCESS) return result; - // If there is a label in the publicArea, it overrides - if(publicArea->unique.derive.label.t.size == 0) - MemoryCopy2B(&publicArea->unique.derive.label.b, &label.b, - sizeof(publicArea->unique.derive.label.t.buffer)); - result = TPM2B_LABEL_Unmarshal(&label, &buff, &size); - if(result != TPM_RC_SUCCESS) - return result; - if(publicArea->unique.derive.context.t.size == 0) - MemoryCopy2B(&publicArea->unique.derive.context.b, &label.b, - sizeof(publicArea->unique.derive.context.t.buffer)); } + // If there is a label string in publicArea, it overrides + if(publicArea->unique.derive.label.t.size != 0) + MemoryCopy2B(&labelContext->label.b, &publicArea->unique.derive.label.b, + sizeof(labelContext->label.t.buffer)); + // if there is a context string in publicArea, it overrides + if(publicArea->unique.derive.context.t.size != 0) + MemoryCopy2B(&labelContext->context.b, + &publicArea->unique.derive.context.b, + sizeof(labelContext->label.t.buffer)); return TPM_RC_SUCCESS; } @@ -1522,6 +1509,7 @@ UnmarshalToPublic( // make sure that tOut is zeroed so that there are no remnants from previous // uses MemorySet(tOut, 0, sizeof(TPMT_PUBLIC)); + // Unmarshal a TPMT_PUBLIC but don't allow a nameAlg of TPM_ALG_NULL result = TPMT_PUBLIC_Unmarshal(tOut, &buffer, &size, FALSE); if((result == TPM_RC_SUCCESS) && (derivation == TRUE)) diff --git a/TPMCmd/tpm/src/command/Startup/Shutdown.c b/TPMCmd/tpm/src/command/Startup/Shutdown.c index c953aa80..7678a71a 100644 --- a/TPMCmd/tpm/src/command/Startup/Shutdown.c +++ b/TPMCmd/tpm/src/command/Startup/Shutdown.c @@ -70,6 +70,11 @@ TPM2_Shutdown( // Save RAM backed NV index data NvUpdateIndexOrderlyData(); +#ifdef ACCUMULATE_SELF_HEAL_TIMER + // Save the current time value + go.time = g_time; +#endif + // Save all orderly data NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); diff --git a/TPMCmd/tpm/src/command/Startup/Startup.c b/TPMCmd/tpm/src/command/Startup/Startup.c index 05a40c55..7df79b4d 100644 --- a/TPMCmd/tpm/src/command/Startup/Startup.c +++ b/TPMCmd/tpm/src/command/Startup/Startup.c @@ -144,6 +144,10 @@ TPM2_Startup( // state has been read in from NV. CryptStartup(startup); + // When the cryptographic library has been started, indicate that a TPM2_Startup + // command has been received. + TPMRegisterStartup(); + // Read the platform unique value that is used as VENDOR_PERMANENT // authorization value g_platformUniqueDetails.t.size @@ -227,10 +231,6 @@ TPM2_Startup( NV_SYNC_PERSISTENT(orderlyState); - // Update TPM internal states if command succeeded. - // Record a TPM2_Startup command has been received. - TPMRegisterStartup(); - // This can be reset after the first completion of a TPM2_Startup() after // a power loss. It can probably be reset earlier but this is an OK place. g_powerWasLost = FALSE; diff --git a/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c b/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c index a731b54b..ffb7ae72 100644 --- a/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c +++ b/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c @@ -116,13 +116,13 @@ TPM2_EncryptDecrypt( // If it was not supported the unmarshaling code would have rejected it before // this function were called. This means that, depending on the implementation, // the check could be redundant but it doesn't hurt. - if(((in->mode == ALG_ECB_VALUE) && (in->ivIn.t.size != 0)) - || ((in->mode != ALG_ECB_VALUE) && (in->ivIn.t.size != blockSize))) + if(((mode == ALG_ECB_VALUE) && (in->ivIn.t.size != 0)) + || ((mode != ALG_ECB_VALUE) && (in->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 size - if(((in->mode == ALG_CBC_VALUE) || (in->mode == ALG_ECB_VALUE)) + if(((mode == ALG_CBC_VALUE) || (mode == ALG_ECB_VALUE)) && ((in->inData.t.size % blockSize) != 0)) return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; diff --git a/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c b/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c index 7161a1cc..332ff89d 100644 --- a/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c +++ b/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c @@ -35,6 +35,7 @@ #include "Tpm.h" #include "EncryptDecrypt_fp.h" +#include "EncryptDecrypt_spt_fp.h" #ifdef TPM_CC_EncryptDecrypt2 @@ -112,13 +113,13 @@ EncryptDecryptShared( // If it was not supported the unmarshaling code would have rejected it before // this function were called. This means that, depending on the implementation, // the check could be redundant but it doesn't hurt. - if(((modeIn == ALG_ECB_VALUE) && (ivIn->t.size != 0)) - || ((modeIn != ALG_ECB_VALUE) && (ivIn->t.size != blockSize))) + if(((mode == ALG_ECB_VALUE) && (ivIn->t.size != 0)) + || ((mode != ALG_ECB_VALUE) && (ivIn->t.size != blockSize))) return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; // The input data size of CBC mode or ECB mode must be an even multiple of // the symmetric algorithm's block size - if(((modeIn == ALG_CBC_VALUE) || (modeIn == ALG_ECB_VALUE)) + if(((mode == ALG_CBC_VALUE) || (mode == ALG_ECB_VALUE)) && ((inData->t.size % blockSize) != 0)) return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; diff --git a/TPMCmd/tpm/src/crypt/BnConvert.c b/TPMCmd/tpm/src/crypt/BnConvert.c index ece042b4..a682d5d1 100644 --- a/TPMCmd/tpm/src/crypt/BnConvert.c +++ b/TPMCmd/tpm/src/crypt/BnConvert.c @@ -159,6 +159,11 @@ BnFromHex( // 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 be reversed. For a big-endian machine, rather than process +// unpack each word individually, the bigNum is converted to little-endian words, +// copied, and then converted back to big-endian. LIB_EXPORT BOOL BnToBytes( bigConst bn, @@ -177,27 +182,39 @@ BnToBytes( pAssert(bn != NULL && buffer != NULL && size != NULL); requiredSize = (BnSizeInBits(bn) + 7) / 8; - if(*size == 0) - *size = (NUMBYTES)requiredSize; - pAssert(requiredSize <= *size); + if(requiredSize == 0) + { + // If the input value is 0, return a byte of zero + *size = 1; + *buffer = 0; + } + else + { + if(*size == 0) + *size = (NUMBYTES)requiredSize; + pAssert(requiredSize <= *size); #if BIG_ENDIAN_TPM - for(count = 0; count < bn->size; count++) - bn->d[count] = SWAP_CRYPT_WORD(bn->d[count]); + // byte swap the words to make them little-endian + for(count = 0; count < bn->size; count++) + bn->d[count] = SWAP_CRYPT_WORD(bn->d[count]); #endif - count = *size; - pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1; - pTo = buffer; + // Byte swap the number (not words but the whole value) + count = *size; + pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1; + pTo = buffer; - for(count = *size; count > requiredSize; count--) - *pTo++ = 0; - for(; requiredSize > 0; requiredSize--) - *pTo++ = *pFrom--; + for(count = *size; count > requiredSize; count--) + *pTo++ = 0; + for(; requiredSize > 0; requiredSize--) + *pTo++ = *pFrom--; #if BIG_ENDIAN_TPM - for(count = 0; count < bn->size; count++) - bn->d[count] = SWAP_CRYPT_WORD(bn->d[count]); + // Put the input back into big-endian format + for(count = 0; count < bn->size; count++) + bn->d[count] = SWAP_CRYPT_WORD(bn->d[count]); #endif + } return TRUE; } @@ -257,7 +274,7 @@ BnPointTo2B( ) { UINT16 size = (UINT16)BITS_TO_BYTES( - BnMsb(CurveGetOrder(AccessCurveData(E)))); + BnMsb(CurveGetOrder(AccessCurveData(E)))); pAssert(p && ecP && E); pAssert(BnEqualWord(ecP->z, 1)); BnTo2B(ecP->x, &p->x.b, size); diff --git a/TPMCmd/tpm/src/crypt/BnMath.c b/TPMCmd/tpm/src/crypt/BnMath.c index c5d1979e..e63cea75 100644 --- a/TPMCmd/tpm/src/crypt/BnMath.c +++ b/TPMCmd/tpm/src/crypt/BnMath.c @@ -520,17 +520,27 @@ BnShiftRight( } //*** 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). LIB_EXPORT BOOL BnGetRandomBits( bigNum n, size_t bits, RAND_STATE *rand - ) +) { - n->size = BITS_TO_CRYPT_WORDS(bits); - if(n->size > n->allocated) - n->size = n->allocated; - DRBG_Generate(rand, (BYTE *)n->d, (UINT16)(n->size * RADIX_BYTES)); + TPM2B_TYPE(LARGEST, LARGEST_NUMBER); + TPM2B_LARGEST large; +// + large.b.size = (UINT16)BITS_TO_BYTES(bits); + DRBG_Generate(rand, large.t.buffer, large.t.size); + BnFrom2B(n, &large.b); BnMaskBits(n, bits); return TRUE; } diff --git a/TPMCmd/tpm/src/crypt/CryptEccMain.c b/TPMCmd/tpm/src/crypt/CryptEccMain.c index 40127e66..abe8cd43 100644 --- a/TPMCmd/tpm/src/crypt/CryptEccMain.c +++ b/TPMCmd/tpm/src/crypt/CryptEccMain.c @@ -410,8 +410,10 @@ CryptEccGetParameters( BnTo2B(data->prime, ¶meters->p.b, 0); BnTo2B(data->a, ¶meters->a.b, 0); BnTo2B(data->b, ¶meters->b.b, 0); - BnTo2B(data->base.x, ¶meters->gX.b, parameters->p.t.size); - BnTo2B(data->base.y, ¶meters->gY.b, parameters->p.t.size); + BnTo2B(data->base.x, ¶meters->gX.b, parameters->p.t.size); + BnTo2B(data->base.y, ¶meters->gY.b, parameters->p.t.size); +// BnTo2B(data->base.x, ¶meters->gX.b, 0); +// BnTo2B(data->base.y, ¶meters->gY.b, 0); BnTo2B(data->order, ¶meters->n.b, 0); BnTo2B(data->h, ¶meters->h.b, 0); } @@ -512,7 +514,7 @@ CryptEccIsValidPrivateKey( // return type: TPM_RC // TPM_RC_NO_RESULTS 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 0 < d < n +// TPM_RC_VALUE 'd' or 'u' is not < n TPM_RC BnPointMult( bigPoint R, // OUT: computed point diff --git a/TPMCmd/tpm/src/crypt/CryptSym.c b/TPMCmd/tpm/src/crypt/CryptSym.c index 1bdce798..04775499 100644 --- a/TPMCmd/tpm/src/crypt/CryptSym.c +++ b/TPMCmd/tpm/src/crypt/CryptSym.c @@ -430,6 +430,8 @@ CryptSymmetricDecrypt( 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. diff --git a/TPMCmd/tpm/src/subsystem/DA.c b/TPMCmd/tpm/src/subsystem/DA.c index 1d187895..4cefa57c 100644 --- a/TPMCmd/tpm/src/subsystem/DA.c +++ b/TPMCmd/tpm/src/subsystem/DA.c @@ -74,14 +74,27 @@ DAPreInstall_Init( //*** DAInit() // This function is called during _TPM_INIT in order to make sure that -// the DA timers are reset when g_time is reset. +// the DA timers are reset when g_time is reset. Call this when it has been +// decided that a new time epoch is needed and when g_time is going to be set +// to 0. void DAInit( void ) { - s_selfHealTimer = g_time; - s_lockoutTimer = g_time; +#ifdef ACCUMULATE_SELF_HEAL_TIMER + // Give credit for the accumulated time. s_selfHealTimer is set to g_time when + // a failure occurs. If g_time is going to be reset, then we want + // s_selfHealTimer to be reduced by the last saved value of g_time. This will + // make s_selfHealTime go negative. Remember, this is only called when it has + // been decided to reset g_time. That means that, after returning from this + // function, g_time will be set to zero. + s_selfHealTimer -= g_time; + s_lockoutTimer -= g_time; +#else + s_selfHealTimer = 0; + s_lockoutTimer = 0; +#endif // ACCUMULATE_SELF_HEAL_TIMER } //*** DAStartup() @@ -97,6 +110,32 @@ DAStartup( ) { NOT_REFERENCED(type); +#ifndef ACCUMULATE_SELF_HEAL_TIMER + _plat__TimerWasReset(); + s_selfHealTimer = 0; + s_lockoutTimer = 0; +#else + if(_plat__TimerWasReset()) + { + if(!NV_IS_ORDERLY) + { + // If shutdown was not orderly, then don't really know if go.time has + // any useful value so reset the timer to 0. This is what the tick + // was reset to + s_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) { @@ -120,6 +159,9 @@ DAStartup( // 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; } @@ -168,14 +210,18 @@ DASelfHeal( else { UINT64 decreaseCount; - +#if 0 // Errata eliminates this code // In the unlikely event that failedTries should become larger than // maxTries if(gp.failedTries > gp.maxTries) gp.failedTries = gp.maxTries; - +#endif // How much can failedTries be decreased - decreaseCount = ((g_time - s_selfHealTimer) / 1000) / gp.recoveryTime; + + // 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 zero @@ -202,7 +248,7 @@ DASelfHeal( // apply in this case. if(gp.lockoutRecovery != 0) { - if(((g_time - s_lockoutTimer) / 1000) >= gp.lockoutRecovery) + if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery) { gp.lockOutAuthEnabled = TRUE; // Record the changes to NV @@ -210,6 +256,5 @@ DASelfHeal( } } } - return; } \ No newline at end of file diff --git a/TPMCmd/tpm/src/subsystem/Time.c b/TPMCmd/tpm/src/subsystem/Time.c index aedfade2..d45e5ff5 100644 --- a/TPMCmd/tpm/src/subsystem/Time.c +++ b/TPMCmd/tpm/src/subsystem/Time.c @@ -57,18 +57,7 @@ TimePowerOn( void ) { - // If the timer was reset or stopped, we need a new epoch - if(_plat__TimerWasReset()) - { - g_timeNewEpochNeeded = TRUE; - // If the timer was reset, need to reset the base time of the TPM. By - // resetting to zero here, the TPM can capture the time that passed between - // when the system timer was reset and when the first call is made to - // _plat__TimeRead(). - g_time = 0; - // And reset the DA timers - DAInit(); - } + g_time = _plat__TimerRead(); } //*** TimeNewEpoch() @@ -87,7 +76,6 @@ TimeNewEpoch( gp.timeEpoch++; NV_SYNC_PERSISTENT(timeEpoch); #endif - g_timeNewEpochNeeded = FALSE; // Clean out any lingering state _plat__TimerWasStopped(); } @@ -111,25 +99,18 @@ TimeStartup( // the same as previously saved. Otherwise, it is not safe. if(!NV_IS_ORDERLY) go.clockSafe = NO; - - // Before Startup, the TPM will not do clock updates. At startup, need to - // do a time update. - TimeUpdate(); return; } -//***TimeClockUpdate() +//*** 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. -// return type: TPM_RC -// TPM_RC_NV_RATE NV cannot be written because it is rate limiting -// TPM_RC_NV_UNAVAILABLE NV cannot be accessed -TPM_RC +void TimeClockUpdate( - UINT64 newTime + UINT64 newTime // IN: New time value in mS. ) { #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1) @@ -137,7 +118,7 @@ TimeClockUpdate( // Check to see if the update will cause a need for an nvClock update if((newTime | CLOCK_UPDATE_MASK) > (go.clock | CLOCK_UPDATE_MASK)) { - RETURN_IF_NV_IS_NOT_AVAILABLE; + pAssert(g_NvStatus == TPM_RC_SUCCESS); // Going to update the NV time state so SET the safe flag go.clockSafe = YES; @@ -151,7 +132,6 @@ TimeClockUpdate( // No NV update needed so just update go.clock = newTime; - return TPM_RC_SUCCESS; } //*** TimeUpdate() @@ -167,14 +147,17 @@ TimeUpdate( void ) { - UINT64 elapsed; + UINT64 elapsed; // - if(g_timeNewEpochNeeded) + // 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 @@ -183,8 +166,6 @@ TimeUpdate( // Call self healing logic for dictionary attack parameters DASelfHeal(); - - } //*** TimeUpdateToCurrent() @@ -206,40 +187,18 @@ TimeUpdate( void TimeUpdateToCurrent( void - ) +) { - UINT64 elapsed; -// // Can't update time during the dark interval or when rate limiting so don't - // make any modifications to the internal clock value - if(!NV_IS_AVAILABLE) + // 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; - // Make sure that we consume the current _plat__TimerWasStopped() state. - g_timeNewEpochNeeded |= _plat__TimerWasStopped(); - - // If we need a new epoch but the TPM has not started, don't generate the new - // epoch here because the crypto has not been initialized by TPM2_Startup(). - // Instead, just continue and let TPM2_Startup() processing create the - // new epoch if needed. - if(g_timeNewEpochNeeded && TPMIsStarted()) - { - TimeNewEpoch(); - } - // Get the difference between this call and the last time we updated the tick - // timer. - elapsed = _plat__TimerRead() - g_time; - 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(); - - return; + TimeUpdate(); } + //*** TimeSetAdjustRate() // This function is used to perform rate adjustment on 'Time' and 'Clock'. void diff --git a/TPMCmd/tpm/src/support/Entity.c b/TPMCmd/tpm/src/support/Entity.c index 96850935..074e8e5b 100644 --- a/TPMCmd/tpm/src/support/Entity.c +++ b/TPMCmd/tpm/src/support/Entity.c @@ -400,14 +400,12 @@ EntityGetName( // 2. An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, // is SET, otherwise it belongs to TPM_RH_OWNER // 3. An object handle belongs to its hierarchy. -// All other handles belong to the platform hierarchy. -// or an NV Index. TPMI_RH_HIERARCHY EntityGetHierarchy( TPMI_DH_ENTITY handle // IN :handle of entity ) { - TPMI_RH_HIERARCHY hierarcy = TPM_RH_NULL; + TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL; switch(HandleGetType(handle)) { @@ -418,12 +416,12 @@ EntityGetHierarchy( case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: case TPM_RH_NULL: - hierarcy = handle; + hierarchy = handle; break; // all other permanent handles are associated with the owner // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) default: - hierarcy = TPM_RH_OWNER; + hierarchy = TPM_RH_OWNER; break; } break; @@ -437,9 +435,9 @@ EntityGetHierarchy( // considered to be in the platform hierarchy, otherwise it // is in the owner hierarchy. if(IsNv_TPMA_NV_PLATFORMCREATE(nvIndex->publicArea.attributes)) - hierarcy = TPM_RH_PLATFORM; + hierarchy = TPM_RH_PLATFORM; else - hierarcy = TPM_RH_OWNER; + hierarchy = TPM_RH_OWNER; } break; case TPM_HT_TRANSIENT: @@ -449,20 +447,20 @@ EntityGetHierarchy( object = HandleToObject(handle); if(object->attributes.ppsHierarchy) { - hierarcy = TPM_RH_PLATFORM; + hierarchy = TPM_RH_PLATFORM; } else if(object->attributes.epsHierarchy) { - hierarcy = TPM_RH_ENDORSEMENT; + hierarchy = TPM_RH_ENDORSEMENT; } else if(object->attributes.spsHierarchy) { - hierarcy = TPM_RH_OWNER; + hierarchy = TPM_RH_OWNER; } } break; case TPM_HT_PCR: - hierarcy = TPM_RH_OWNER; + hierarchy = TPM_RH_OWNER; break; default: FAIL(FATAL_ERROR_INTERNAL); @@ -470,5 +468,5 @@ EntityGetHierarchy( } // this is unreachable but it provides a return value for the default // case which makes the complier happy - return hierarcy; + return hierarchy; } \ No newline at end of file diff --git a/TPMCmd/tpm/src/support/Global.c b/TPMCmd/tpm/src/support/Global.c index 07a7b3f2..9ae740e0 100644 --- a/TPMCmd/tpm/src/support/Global.c +++ b/TPMCmd/tpm/src/support/Global.c @@ -60,7 +60,7 @@ UINT64 g_time; #ifdef CLOCK_STOPS CLOCK_NONCE g_timeEpoch; #endif -BOOL g_timeNewEpochNeeded; +//BOOL g_timeNewEpochNeeded; BOOL g_pcrReConfig; @@ -119,8 +119,11 @@ TPM2B_DIGEST s_cpHashForCommandAudit; #endif //*** DA.c +#ifndef ACCUMULATE_SELF_HEAL_TIMER + UINT64 s_selfHealTimer; UINT64 s_lockoutTimer; +#endif // !ACCUMULATE_SELF_HEAL_TIMER //*** NV.c UINT64 s_maxCounter; diff --git a/TPMCmd/tpm/src/support/TpmFail.c b/TPMCmd/tpm/src/support/TpmFail.c index d3fd53d4..b278f5c1 100644 --- a/TPMCmd/tpm/src/support/TpmFail.c +++ b/TPMCmd/tpm/src/support/TpmFail.c @@ -174,16 +174,23 @@ SetForceFailureMode( // failure values to be returned on TPM2_GetTestResult(). NORETURN void TpmFail( +#ifndef NO_FAIL_TRACE const char *function, int line, +#endif int 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. +#ifndef NO_FAIL_TRACE s_failFunction = *(UINT32*)&function; s_failLine = line; +#else + s_failFunction = NULL; + s_failLine = 0; +#endif s_failCode = code; // We are in failure mode