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 // TODO(vbendeb): consider finer tuning of this value (crosbug.com/p/55708) 28 gp.maxTries = 200; 29 gp.recoveryTime = 1000; // in seconds (~16.67 minutes) 30 gp.lockoutRecovery = 1000; // in seconds 31 gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled 32 // Record persistent DA parameter changes to NV 33 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 34 NvWriteReserved(NV_MAX_TRIES, &gp.maxTries); 35 NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime); 36 NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery); 37 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 38 return; 39 } 40 // 41 // 42 // DAStartup() 43 // 44 // This function is called by TPM2_Startup() to initialize the DA parameters. In the case of Startup(CLEAR), 45 // use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, lockoutAuth will not be 46 // enabled until the TPM has been continuously powered for the lockoutRecovery time. 47 // This function requires that NV be available and not rate limiting. 48 // 49 void 50 DAStartup( 51 STARTUP_TYPE type // IN: startup type 52 ) 53 { 54 // For TPM Reset, if lockoutRecovery is 0, enable use of lockoutAuth. 55 if(type == SU_RESET) 56 { 57 if(gp.lockoutRecovery == 0) 58 { 59 gp.lockOutAuthEnabled = TRUE; 60 // Record the changes to NV 61 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 62 } 63 } 64 // If DA has not been disabled and the previous shutdown is not orderly 65 // failedTries is not already at its maximum then increment 'failedTries' 66 if( gp.recoveryTime != 0 67 && g_prevOrderlyState == SHUTDOWN_NONE 68 && gp.failedTries < gp.maxTries) 69 { 70 gp.failedTries++; 71 // Record the change to NV 72 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 73 } 74 // Reset self healing timers 75 s_selfHealTimer = g_time; 76 s_lockoutTimer = g_time; 77 return; 78 } 79 // 80 // 81 // DARegisterFailure() 82 // 83 // This function is called when a authorization failure occurs on an entity that is subject to dictionary-attack 84 // protection. When a DA failure is triggered, register the failure by resetting the relevant self-healing timer 85 // to the current time. 86 // 87 void 88 DARegisterFailure( 89 TPM_HANDLE handle // IN: handle for failure 90 ) 91 { 92 // Reset the timer associated with lockout if the handle is the lockout auth. 93 if(handle == TPM_RH_LOCKOUT) 94 s_lockoutTimer = g_time; 95 else 96 s_selfHealTimer = g_time; 97 // 98 return; 99 } 100 // 101 // 102 // DASelfHeal() 103 // 104 // This function is called to check if sufficient time has passed to allow decrement of failedTries or to re- 105 // enable use of lockoutAuth. 106 // This function should be called when the time interval is updated. 107 // 108 void 109 DASelfHeal( 110 void 111 ) 112 { 113 // Regular auth self healing logic 114 // If no failed authorization tries, do nothing. Otherwise, try to 115 // decrease failedTries 116 if(gp.failedTries != 0) 117 { 118 // if recovery time is 0, DA logic has been disabled. Clear failed tries 119 // immediately 120 if(gp.recoveryTime == 0) 121 { 122 gp.failedTries = 0; 123 // Update NV record 124 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 125 } 126 else 127 { 128 UINT64 decreaseCount; 129 // In the unlikely event that failedTries should become larger than 130 // maxTries 131 if(gp.failedTries > gp.maxTries) 132 gp.failedTries = gp.maxTries; 133 // How much can failedTried be decreased 134 decreaseCount = ((g_time - s_selfHealTimer) / 1000) / gp.recoveryTime; 135 if(gp.failedTries <= (UINT32) decreaseCount) 136 // should not set failedTries below zero 137 gp.failedTries = 0; 138 else 139 gp.failedTries -= (UINT32) decreaseCount; 140 // the cast prevents overflow of the product 141 s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000; 142 if(decreaseCount != 0) 143 // If there was a change to the failedTries, record the changes 144 // to NV 145 NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries); 146 } 147 } 148 // LockoutAuth self healing logic 149 // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we 150 // may enable it 151 if(!gp.lockOutAuthEnabled) 152 { 153 // if lockout authorization recovery time is 0, a reboot is required to 154 // re-enable use of lockout authorization. Self-healing would not 155 // apply in this case. 156 if(gp.lockoutRecovery != 0) 157 // 158 { 159 if(((g_time - s_lockoutTimer)/1000) >= gp.lockoutRecovery) 160 { 161 gp.lockOutAuthEnabled = TRUE; 162 // Record the changes to NV 163 NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 164 } 165 } 166 } 167 return; 168 } 169