1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 4: Supporting Routines 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #define DA_C 9 #include "InternalRoutines.h" 10 // 11 // 12 // Functions 13 // 14 // DAPreInstall_Init() 15 // 16 // This function initializes the DA parameters to their manufacturer-default values. The default values are 17 // determined by a platform-specific specification. 18 // This function should not be called outside of a manufacturing or simulation environment. 19 // The DA parameters will be restored to these initial values by TPM2_Clear(). 20 // 21 void 22 DAPreInstall_Init( 23 void 24 ) 25 { 26 gp.failedTries = 0; 27 gp.maxTries = 3; 28 gp.recoveryTime = 1000; // in seconds (~16.67 minutes) 29 gp.lockoutRecovery = 1000; // in seconds 30 gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled 31 // Record persistent DA parameter changes to NV 32 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 33 NvWriteReserved(NV_MAX_TRIES, &gp.maxTries); 34 NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime); 35 NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery); 36 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 37 return; 38 } 39 // 40 // 41 // DAStartup() 42 // 43 // This function is called by TPM2_Startup() to initialize the DA parameters. In the case of Startup(CLEAR), 44 // use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, lockoutAuth will not be 45 // enabled until the TPM has been continuously powered for the lockoutRecovery time. 46 // This function requires that NV be available and not rate limiting. 47 // 48 void 49 DAStartup( 50 STARTUP_TYPE type // IN: startup type 51 ) 52 { 53 // For TPM Reset, if lockoutRecovery is 0, enable use of lockoutAuth. 54 if(type == SU_RESET) 55 { 56 if(gp.lockoutRecovery == 0) 57 { 58 gp.lockOutAuthEnabled = TRUE; 59 // Record the changes to NV 60 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 61 } 62 } 63 // If DA has not been disabled and the previous shutdown is not orderly 64 // failedTries is not already at its maximum then increment 'failedTries' 65 if( gp.recoveryTime != 0 66 && g_prevOrderlyState == SHUTDOWN_NONE 67 && gp.failedTries < gp.maxTries) 68 { 69 gp.failedTries++; 70 // Record the change to NV 71 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 72 } 73 // Reset self healing timers 74 s_selfHealTimer = g_time; 75 s_lockoutTimer = g_time; 76 return; 77 } 78 // 79 // 80 // DARegisterFailure() 81 // 82 // This function is called when a authorization failure occurs on an entity that is subject to dictionary-attack 83 // protection. When a DA failure is triggered, register the failure by resetting the relevant self-healing timer 84 // to the current time. 85 // 86 void 87 DARegisterFailure( 88 TPM_HANDLE handle // IN: handle for failure 89 ) 90 { 91 // Reset the timer associated with lockout if the handle is the lockout auth. 92 if(handle == TPM_RH_LOCKOUT) 93 s_lockoutTimer = g_time; 94 else 95 s_selfHealTimer = g_time; 96 // 97 return; 98 } 99 // 100 // 101 // DASelfHeal() 102 // 103 // This function is called to check if sufficient time has passed to allow decrement of failedTries or to re- 104 // enable use of lockoutAuth. 105 // This function should be called when the time interval is updated. 106 // 107 void 108 DASelfHeal( 109 void 110 ) 111 { 112 // Regular auth self healing logic 113 // If no failed authorization tries, do nothing. Otherwise, try to 114 // decrease failedTries 115 if(gp.failedTries != 0) 116 { 117 // if recovery time is 0, DA logic has been disabled. Clear failed tries 118 // immediately 119 if(gp.recoveryTime == 0) 120 { 121 gp.failedTries = 0; 122 // Update NV record 123 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 124 } 125 else 126 { 127 UINT64 decreaseCount; 128 // In the unlikely event that failedTries should become larger than 129 // maxTries 130 if(gp.failedTries > gp.maxTries) 131 gp.failedTries = gp.maxTries; 132 // How much can failedTried be decreased 133 decreaseCount = ((g_time - s_selfHealTimer) / 1000) / gp.recoveryTime; 134 if(gp.failedTries <= (UINT32) decreaseCount) 135 // should not set failedTries below zero 136 gp.failedTries = 0; 137 else 138 gp.failedTries -= (UINT32) decreaseCount; 139 // the cast prevents overflow of the product 140 s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000; 141 if(decreaseCount != 0) 142 // If there was a change to the failedTries, record the changes 143 // to NV 144 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 145 } 146 } 147 // LockoutAuth self healing logic 148 // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we 149 // may enable it 150 if(!gp.lockOutAuthEnabled) 151 { 152 // if lockout authorization recovery time is 0, a reboot is required to 153 // re-enable use of lockout authorization. Self-healing would not 154 // apply in this case. 155 if(gp.lockoutRecovery != 0) 156 // 157 { 158 if(((g_time - s_lockoutTimer)/1000) >= gp.lockoutRecovery) 159 { 160 gp.lockOutAuthEnabled = TRUE; 161 // Record the changes to NV 162 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 163 } 164 } 165 } 166 return; 167 } 168