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
DAPreInstall_Init(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
DAStartup(STARTUP_TYPE type)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
DARegisterFailure(TPM_HANDLE handle)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
DASelfHeal(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