xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen  *
3*5c591343SA. Cody Schuffelen  *  The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen  *  included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen  *  contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen  *  under this license.
7*5c591343SA. Cody Schuffelen  *
8*5c591343SA. Cody Schuffelen  *  Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen  *
10*5c591343SA. Cody Schuffelen  *  All rights reserved.
11*5c591343SA. Cody Schuffelen  *
12*5c591343SA. Cody Schuffelen  *  BSD License
13*5c591343SA. Cody Schuffelen  *
14*5c591343SA. Cody Schuffelen  *  Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen  *  are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen  *
17*5c591343SA. Cody Schuffelen  *  Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen  *  of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen  *
20*5c591343SA. Cody Schuffelen  *  Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen  *  list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen  *  other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen  *
24*5c591343SA. Cody Schuffelen  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen  */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen // This file contains the functions and data definitions relating to the
37*5c591343SA. Cody Schuffelen // dictionary attack logic.
38*5c591343SA. Cody Schuffelen 
39*5c591343SA. Cody Schuffelen //** Includes and Data Definitions
40*5c591343SA. Cody Schuffelen #define DA_C
41*5c591343SA. Cody Schuffelen #include "Tpm.h"
42*5c591343SA. Cody Schuffelen 
43*5c591343SA. Cody Schuffelen //** Functions
44*5c591343SA. Cody Schuffelen 
45*5c591343SA. Cody Schuffelen //*** DAPreInstall_Init()
46*5c591343SA. Cody Schuffelen // This function initializes the DA parameters to their manufacturer-default
47*5c591343SA. Cody Schuffelen // values. The default values are determined by a platform-specific specification.
48*5c591343SA. Cody Schuffelen //
49*5c591343SA. Cody Schuffelen // This function should not be called outside of a manufacturing or simulation
50*5c591343SA. Cody Schuffelen // environment.
51*5c591343SA. Cody Schuffelen //
52*5c591343SA. Cody Schuffelen // The DA parameters will be restored to these initial values by TPM2_Clear().
53*5c591343SA. Cody Schuffelen void
DAPreInstall_Init(void)54*5c591343SA. Cody Schuffelen DAPreInstall_Init(
55*5c591343SA. Cody Schuffelen     void
56*5c591343SA. Cody Schuffelen     )
57*5c591343SA. Cody Schuffelen {
58*5c591343SA. Cody Schuffelen     gp.failedTries = 0;
59*5c591343SA. Cody Schuffelen     gp.maxTries = 3;
60*5c591343SA. Cody Schuffelen     gp.recoveryTime = 1000;         // in seconds (~16.67 minutes)
61*5c591343SA. Cody Schuffelen     gp.lockoutRecovery = 1000;      // in seconds
62*5c591343SA. Cody Schuffelen     gp.lockOutAuthEnabled = TRUE;   // Use of lockoutAuth is enabled
63*5c591343SA. Cody Schuffelen 
64*5c591343SA. Cody Schuffelen     // Record persistent DA parameter changes to NV
65*5c591343SA. Cody Schuffelen     NV_SYNC_PERSISTENT(failedTries);
66*5c591343SA. Cody Schuffelen     NV_SYNC_PERSISTENT(maxTries);
67*5c591343SA. Cody Schuffelen     NV_SYNC_PERSISTENT(recoveryTime);
68*5c591343SA. Cody Schuffelen     NV_SYNC_PERSISTENT(lockoutRecovery);
69*5c591343SA. Cody Schuffelen     NV_SYNC_PERSISTENT(lockOutAuthEnabled);
70*5c591343SA. Cody Schuffelen 
71*5c591343SA. Cody Schuffelen     return;
72*5c591343SA. Cody Schuffelen }
73*5c591343SA. Cody Schuffelen 
74*5c591343SA. Cody Schuffelen 
75*5c591343SA. Cody Schuffelen //*** DAStartup()
76*5c591343SA. Cody Schuffelen // This function is called  by TPM2_Startup() to initialize the DA parameters.
77*5c591343SA. Cody Schuffelen // In the case of Startup(CLEAR), use of lockoutAuth will be enabled if the
78*5c591343SA. Cody Schuffelen // lockout recovery time is 0. Otherwise, lockoutAuth will not be enabled until
79*5c591343SA. Cody Schuffelen // the TPM has been continuously powered for the lockoutRecovery time.
80*5c591343SA. Cody Schuffelen //
81*5c591343SA. Cody Schuffelen // This function requires that NV be available and not rate limiting.
82*5c591343SA. Cody Schuffelen BOOL
DAStartup(STARTUP_TYPE type)83*5c591343SA. Cody Schuffelen DAStartup(
84*5c591343SA. Cody Schuffelen     STARTUP_TYPE     type           // IN: startup type
85*5c591343SA. Cody Schuffelen     )
86*5c591343SA. Cody Schuffelen {
87*5c591343SA. Cody Schuffelen     NOT_REFERENCED(type);
88*5c591343SA. Cody Schuffelen #if !ACCUMULATE_SELF_HEAL_TIMER
89*5c591343SA. Cody Schuffelen     _plat__TimerWasReset();
90*5c591343SA. Cody Schuffelen     s_selfHealTimer = 0;
91*5c591343SA. Cody Schuffelen     s_lockoutTimer = 0;
92*5c591343SA. Cody Schuffelen #else
93*5c591343SA. Cody Schuffelen     if(_plat__TimerWasReset())
94*5c591343SA. Cody Schuffelen     {
95*5c591343SA. Cody Schuffelen         if(!NV_IS_ORDERLY)
96*5c591343SA. Cody Schuffelen         {
97*5c591343SA. Cody Schuffelen             // If shutdown was not orderly, then don't really know if go.time has
98*5c591343SA. Cody Schuffelen             // any useful value so reset the timer to 0. This is what the tick
99*5c591343SA. Cody Schuffelen             // was reset to
100*5c591343SA. Cody Schuffelen             s_selfHealTimer = 0;
101*5c591343SA. Cody Schuffelen             s_lockoutTimer = 0;
102*5c591343SA. Cody Schuffelen         }
103*5c591343SA. Cody Schuffelen         else
104*5c591343SA. Cody Schuffelen         {
105*5c591343SA. Cody Schuffelen             // If we know how much time was accumulated at the last orderly shutdown
106*5c591343SA. Cody Schuffelen             // subtract that from the saved timer values so that they effectively
107*5c591343SA. Cody Schuffelen             // have the accumulated values
108*5c591343SA. Cody Schuffelen             s_selfHealTimer -= go.time;
109*5c591343SA. Cody Schuffelen             s_lockoutTimer -= go.time;
110*5c591343SA. Cody Schuffelen         }
111*5c591343SA. Cody Schuffelen     }
112*5c591343SA. Cody Schuffelen #endif
113*5c591343SA. Cody Schuffelen 
114*5c591343SA. Cody Schuffelen     // For any Startup(), if lockoutRecovery is 0, enable use of lockoutAuth.
115*5c591343SA. Cody Schuffelen     if(gp.lockoutRecovery == 0)
116*5c591343SA. Cody Schuffelen     {
117*5c591343SA. Cody Schuffelen         gp.lockOutAuthEnabled = TRUE;
118*5c591343SA. Cody Schuffelen         // Record the changes to NV
119*5c591343SA. Cody Schuffelen         NV_SYNC_PERSISTENT(lockOutAuthEnabled);
120*5c591343SA. Cody Schuffelen     }
121*5c591343SA. Cody Schuffelen 
122*5c591343SA. Cody Schuffelen     // If DA has not been disabled and the previous shutdown is not orderly
123*5c591343SA. Cody Schuffelen     // failedTries is not already at its maximum then increment 'failedTries'
124*5c591343SA. Cody Schuffelen     if(gp.recoveryTime != 0
125*5c591343SA. Cody Schuffelen        && gp.failedTries < gp.maxTries
126*5c591343SA. Cody Schuffelen        && !IS_ORDERLY(g_prevOrderlyState))
127*5c591343SA. Cody Schuffelen     {
128*5c591343SA. Cody Schuffelen #if USE_DA_USED
129*5c591343SA. Cody Schuffelen         gp.failedTries += g_daUsed;
130*5c591343SA. Cody Schuffelen         g_daUsed = FALSE;
131*5c591343SA. Cody Schuffelen #else
132*5c591343SA. Cody Schuffelen         gp.failedTries++;
133*5c591343SA. Cody Schuffelen #endif
134*5c591343SA. Cody Schuffelen         // Record the change to NV
135*5c591343SA. Cody Schuffelen         NV_SYNC_PERSISTENT(failedTries);
136*5c591343SA. Cody Schuffelen     }
137*5c591343SA. Cody Schuffelen     // Before Startup, the TPM will not do clock updates. At startup, need to
138*5c591343SA. Cody Schuffelen     // do a time update which will do the DA update.
139*5c591343SA. Cody Schuffelen     TimeUpdate();
140*5c591343SA. Cody Schuffelen 
141*5c591343SA. Cody Schuffelen     return TRUE;
142*5c591343SA. Cody Schuffelen }
143*5c591343SA. Cody Schuffelen 
144*5c591343SA. Cody Schuffelen //*** DARegisterFailure()
145*5c591343SA. Cody Schuffelen // This function is called when an authorization failure occurs on an entity
146*5c591343SA. Cody Schuffelen // that is subject to dictionary-attack protection. When a DA failure is
147*5c591343SA. Cody Schuffelen // triggered, register the failure by resetting the relevant self-healing
148*5c591343SA. Cody Schuffelen // timer to the current time.
149*5c591343SA. Cody Schuffelen void
DARegisterFailure(TPM_HANDLE handle)150*5c591343SA. Cody Schuffelen DARegisterFailure(
151*5c591343SA. Cody Schuffelen     TPM_HANDLE       handle         // IN: handle for failure
152*5c591343SA. Cody Schuffelen     )
153*5c591343SA. Cody Schuffelen {
154*5c591343SA. Cody Schuffelen     // Reset the timer associated with lockout if the handle is the lockoutAuth.
155*5c591343SA. Cody Schuffelen     if(handle == TPM_RH_LOCKOUT)
156*5c591343SA. Cody Schuffelen         s_lockoutTimer = g_time;
157*5c591343SA. Cody Schuffelen     else
158*5c591343SA. Cody Schuffelen         s_selfHealTimer = g_time;
159*5c591343SA. Cody Schuffelen     return;
160*5c591343SA. Cody Schuffelen }
161*5c591343SA. Cody Schuffelen 
162*5c591343SA. Cody Schuffelen //*** DASelfHeal()
163*5c591343SA. Cody Schuffelen // This function is called to check if sufficient time has passed to allow
164*5c591343SA. Cody Schuffelen // decrement of failedTries or to re-enable use of lockoutAuth.
165*5c591343SA. Cody Schuffelen //
166*5c591343SA. Cody Schuffelen // This function should be called when the time interval is updated.
167*5c591343SA. Cody Schuffelen void
DASelfHeal(void)168*5c591343SA. Cody Schuffelen DASelfHeal(
169*5c591343SA. Cody Schuffelen     void
170*5c591343SA. Cody Schuffelen     )
171*5c591343SA. Cody Schuffelen {
172*5c591343SA. Cody Schuffelen     // Regular authorization self healing logic
173*5c591343SA. Cody Schuffelen     // If no failed authorization tries, do nothing.  Otherwise, try to
174*5c591343SA. Cody Schuffelen     // decrease failedTries
175*5c591343SA. Cody Schuffelen     if(gp.failedTries != 0)
176*5c591343SA. Cody Schuffelen     {
177*5c591343SA. Cody Schuffelen         // if recovery time is 0, DA logic has been disabled.  Clear failed tries
178*5c591343SA. Cody Schuffelen         // immediately
179*5c591343SA. Cody Schuffelen         if(gp.recoveryTime == 0)
180*5c591343SA. Cody Schuffelen         {
181*5c591343SA. Cody Schuffelen             gp.failedTries = 0;
182*5c591343SA. Cody Schuffelen             // Update NV record
183*5c591343SA. Cody Schuffelen             NV_SYNC_PERSISTENT(failedTries);
184*5c591343SA. Cody Schuffelen         }
185*5c591343SA. Cody Schuffelen         else
186*5c591343SA. Cody Schuffelen         {
187*5c591343SA. Cody Schuffelen             UINT64          decreaseCount;
188*5c591343SA. Cody Schuffelen #if 0 // Errata eliminates this code
189*5c591343SA. Cody Schuffelen             // In the unlikely event that failedTries should become larger than
190*5c591343SA. Cody Schuffelen             // maxTries
191*5c591343SA. Cody Schuffelen             if(gp.failedTries > gp.maxTries)
192*5c591343SA. Cody Schuffelen                 gp.failedTries = gp.maxTries;
193*5c591343SA. Cody Schuffelen #endif
194*5c591343SA. Cody Schuffelen             // How much can failedTries be decreased
195*5c591343SA. Cody Schuffelen 
196*5c591343SA. Cody Schuffelen             // Cast s_selfHealTimer to an int in case it became negative at
197*5c591343SA. Cody Schuffelen             // startup
198*5c591343SA. Cody Schuffelen             decreaseCount = ((g_time - (INT64)s_selfHealTimer) / 1000)
199*5c591343SA. Cody Schuffelen                 / gp.recoveryTime;
200*5c591343SA. Cody Schuffelen 
201*5c591343SA. Cody Schuffelen             if(gp.failedTries <= (UINT32)decreaseCount)
202*5c591343SA. Cody Schuffelen                 // should not set failedTries below zero
203*5c591343SA. Cody Schuffelen                 gp.failedTries = 0;
204*5c591343SA. Cody Schuffelen             else
205*5c591343SA. Cody Schuffelen                 gp.failedTries -= (UINT32)decreaseCount;
206*5c591343SA. Cody Schuffelen 
207*5c591343SA. Cody Schuffelen             // the cast prevents overflow of the product
208*5c591343SA. Cody Schuffelen             s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000;
209*5c591343SA. Cody Schuffelen             if(decreaseCount != 0)
210*5c591343SA. Cody Schuffelen                 // If there was a change to the failedTries, record the changes
211*5c591343SA. Cody Schuffelen                 // to NV
212*5c591343SA. Cody Schuffelen                 NV_SYNC_PERSISTENT(failedTries);
213*5c591343SA. Cody Schuffelen         }
214*5c591343SA. Cody Schuffelen     }
215*5c591343SA. Cody Schuffelen 
216*5c591343SA. Cody Schuffelen     // LockoutAuth self healing logic
217*5c591343SA. Cody Schuffelen     // If lockoutAuth is enabled, do nothing.  Otherwise, try to see if we
218*5c591343SA. Cody Schuffelen     // may enable it
219*5c591343SA. Cody Schuffelen     if(!gp.lockOutAuthEnabled)
220*5c591343SA. Cody Schuffelen     {
221*5c591343SA. Cody Schuffelen         // if lockout authorization recovery time is 0, a reboot is required to
222*5c591343SA. Cody Schuffelen         // re-enable use of lockout authorization.  Self-healing would not
223*5c591343SA. Cody Schuffelen         // apply in this case.
224*5c591343SA. Cody Schuffelen         if(gp.lockoutRecovery != 0)
225*5c591343SA. Cody Schuffelen         {
226*5c591343SA. Cody Schuffelen             if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery)
227*5c591343SA. Cody Schuffelen             {
228*5c591343SA. Cody Schuffelen                 gp.lockOutAuthEnabled = TRUE;
229*5c591343SA. Cody Schuffelen                 // Record the changes to NV
230*5c591343SA. Cody Schuffelen                 NV_SYNC_PERSISTENT(lockOutAuthEnabled);
231*5c591343SA. Cody Schuffelen             }
232*5c591343SA. Cody Schuffelen         }
233*5c591343SA. Cody Schuffelen     }
234*5c591343SA. Cody Schuffelen     return;
235*5c591343SA. Cody Schuffelen }