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//
21void
22DAPreInstall_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//
48void
49DAStartup(
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//
86void
87DARegisterFailure(
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//
107void
108DASelfHeal(
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