Coverage Report

Created: 2025-08-03 07:04

/src/ibmswtpm2/src/DA.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*         Dictionary Attack Logic.         */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: DA.c 1259 2018-07-10 19:11:09Z kgoldman $      */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2016 - 2018       */
59
/*                    */
60
/********************************************************************************/
61
62
/* 8.2 DA.c */
63
/* 8.2.1 Introduction */
64
/* This file contains the functions and data definitions relating to the dictionary attack logic. */
65
/* 8.2.2 Includes and Data Definitions */
66
#define DA_C
67
#include "Tpm.h"
68
/* 8.2.3 Functions */
69
/* 8.2.3.1 DAPreInstall_Init() */
70
/* This function initializes the DA parameters to their manufacturer-default values. The default
71
   values are determined by a platform-specific specification. */
72
/* This function should not be called outside of a manufacturing or simulation environment. */
73
/* The DA parameters will be restored to these initial values by TPM2_Clear(). */
74
void
75
DAPreInstall_Init(
76
      void
77
      )
78
644
{
79
644
    gp.failedTries = 0;
80
644
    gp.maxTries = 3;
81
644
    gp.recoveryTime = 1000;         // in seconds (~16.67 minutes)
82
644
    gp.lockoutRecovery = 1000;      // in seconds
83
644
    gp.lockOutAuthEnabled = TRUE;   // Use of lockoutAuth is enabled
84
    // Record persistent DA parameter changes to NV
85
644
    NV_SYNC_PERSISTENT(failedTries);
86
644
    NV_SYNC_PERSISTENT(maxTries);
87
644
    NV_SYNC_PERSISTENT(recoveryTime);
88
644
    NV_SYNC_PERSISTENT(lockoutRecovery);
89
644
    NV_SYNC_PERSISTENT(lockOutAuthEnabled);
90
644
    return;
91
644
}
92
/* 8.2.3.2 DAStartup() */
93
/* This function is called by TPM2_Startup() to initialize the DA parameters. In the case of
94
   Startup(CLEAR), use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise,
95
   lockoutAuth will not be enabled until the TPM has been continuously powered for the
96
   lockoutRecovery time. */
97
/* This function requires that NV be available and not rate limiting. */
98
void
99
DAStartup(
100
    STARTUP_TYPE     type           // IN: startup type
101
    )
102
0
{
103
0
    NOT_REFERENCED(type);
104
#if !ACCUMULATE_SELF_HEAL_TIMER
105
    _plat__TimerWasReset();
106
    s_selfHealTimer = 0;
107
    s_lockoutTimer = 0;
108
#else
109
0
    if(_plat__TimerWasReset())
110
0
  {
111
0
      if(!NV_IS_ORDERLY)
112
0
    {
113
        // If shutdown was not orderly, then don't really know if go.time has
114
        // any useful value so reset the timer to 0. This is what the tick
115
        // was reset to
116
0
        s_selfHealTimer = 0;
117
0
        s_lockoutTimer = 0;
118
0
    }
119
0
      else
120
0
    {
121
        // If we know how much time was accumulated at the last orderly shutdown
122
        // subtract that from the saved timer values so that they effectively
123
        // have the accumulated values
124
0
        s_selfHealTimer -= go.time;
125
0
        s_lockoutTimer -= go.time;
126
0
    }
127
0
  }
128
0
#endif
129
    // For any Startup(), if lockoutRecovery is 0, enable use of lockoutAuth.
130
0
    if(gp.lockoutRecovery == 0)
131
0
  {
132
0
      gp.lockOutAuthEnabled = TRUE;
133
      // Record the changes to NV
134
0
      NV_SYNC_PERSISTENT(lockOutAuthEnabled);
135
0
  }
136
    // If DA has not been disabled and the previous shutdown is not orderly
137
    // failedTries is not already at its maximum then increment 'failedTries'
138
0
    if(gp.recoveryTime != 0
139
0
       && gp.failedTries < gp.maxTries
140
0
       && !IS_ORDERLY(g_prevOrderlyState))
141
0
  {
142
0
#if USE_DA_USED
143
0
      gp.failedTries += g_daUsed;
144
0
      g_daUsed = FALSE;
145
#else
146
      gp.failedTries++;
147
#endif
148
      // Record the change to NV
149
0
      NV_SYNC_PERSISTENT(failedTries);
150
0
  }
151
    // Before Startup, the TPM will not do clock updates. At startup, need to
152
    // do a time update which will do the DA update.
153
0
    TimeUpdate();
154
0
    return;
155
0
}
156
/* 8.2.3.3 DARegisterFailure() */
157
/* This function is called when a authorization failure occurs on an entity that is subject to
158
   dictionary-attack protection. When a DA failure is triggered, register the failure by resetting
159
   the relevant self-healing timer to the current time. */
160
void
161
DARegisterFailure(
162
      TPM_HANDLE       handle         // IN: handle for failure
163
      )
164
0
{
165
    // Reset the timer associated with lockout if the handle is the lockoutAuth.
166
0
    if(handle == TPM_RH_LOCKOUT)
167
0
  s_lockoutTimer = g_time;
168
0
    else
169
0
  s_selfHealTimer = g_time;
170
0
    return;
171
0
}
172
/* 8.2.3.4 DASelfHeal() */
173
/* This function is called to check if sufficient time has passed to allow decrement of failedTries
174
   or to re-enable use of lockoutAuth. */
175
/* This function should be called when the time interval is updated. */
176
void
177
DASelfHeal(
178
     void
179
     )
180
0
{
181
    // Regular authorization self healing logic
182
    // If no failed authorization tries, do nothing.  Otherwise, try to
183
    // decrease failedTries
184
0
    if(gp.failedTries != 0)
185
0
  {
186
      // if recovery time is 0, DA logic has been disabled.  Clear failed tries
187
      // immediately
188
0
      if(gp.recoveryTime == 0)
189
0
    {
190
0
        gp.failedTries = 0;
191
        // Update NV record
192
0
        NV_SYNC_PERSISTENT(failedTries);
193
0
    }
194
0
      else
195
0
    {
196
0
        UINT64          decreaseCount;
197
#if 0 // Errata eliminates this code
198
        // In the unlikely event that failedTries should become larger than
199
        // maxTries
200
        if(gp.failedTries > gp.maxTries)
201
      gp.failedTries = gp.maxTries;
202
#endif
203
        // How much can failedTries be decreased
204
        // Cast s_selfHealTimer to an int in case it became negative at
205
        // startup
206
0
        decreaseCount = ((g_time - (INT64)s_selfHealTimer) / 1000)
207
0
            / gp.recoveryTime;
208
0
        if(gp.failedTries <= (UINT32)decreaseCount)
209
      // should not set failedTries below zero
210
0
      gp.failedTries = 0;
211
0
        else
212
0
      gp.failedTries -= (UINT32)decreaseCount;
213
        // the cast prevents overflow of the product
214
0
        s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000;
215
0
        if(decreaseCount != 0)
216
      // If there was a change to the failedTries, record the changes
217
      // to NV
218
0
      NV_SYNC_PERSISTENT(failedTries);
219
0
    }
220
0
  }
221
    // LockoutAuth self healing logic
222
    // If lockoutAuth is enabled, do nothing.  Otherwise, try to see if we
223
    // may enable it
224
0
    if(!gp.lockOutAuthEnabled)
225
0
  {
226
      // if lockout authorization recovery time is 0, a reboot is required to
227
      // re-enable use of lockout authorization.  Self-healing would not
228
      // apply in this case.
229
0
      if(gp.lockoutRecovery != 0)
230
0
    {
231
0
        if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery)
232
0
      {
233
0
          gp.lockOutAuthEnabled = TRUE;
234
          // Record the changes to NV
235
0
          NV_SYNC_PERSISTENT(lockOutAuthEnabled);
236
0
      }
237
0
    }
238
0
  }
239
0
    return;
240
0
}