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