Coverage Report

Created: 2025-07-11 06:15

/src/tpm2/Time.c
Line
Count
Source (jump to first uncovered line)
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
#include "InternalRoutines.h"
9
#include "Platform.h"
10
//          Functions
11
//
12
//           TimePowerOn()
13
//
14
//     This function initialize time info at _TPM_Init().
15
//
16
void
17
TimePowerOn(
18
    void
19
    )
20
231
{
21
231
    TPM_SU               orderlyShutDown;
22
    // Read orderly data info from NV memory
23
231
    NvReadReserved(NV_ORDERLY_DATA, &go);
24
    // Read orderly shut down state flag
25
231
    NvReadReserved(NV_ORDERLY, &orderlyShutDown);
26
    // If the previous cycle is orderly shut down, the value of the safe bit
27
    // the same as previously saved. Otherwise, it is not safe.
28
231
    if(orderlyShutDown == SHUTDOWN_NONE)
29
0
        go.clockSafe= NO;
30
231
    else
31
231
        go.clockSafe = YES;
32
    // Set the initial state of the DRBG
33
231
    CryptDrbgGetPutState(PUT_STATE);
34
    // Clear time since TPM power on
35
231
    g_time = 0;
36
231
    return;
37
231
}
38
//
39
//
40
//           TimeStartup()
41
//
42
//     This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at
43
//     TPM2_Startup().
44
//
45
void
46
TimeStartup(
47
    STARTUP_TYPE          type                // IN: start up type
48
    )
49
231
{
50
231
    if(type == SU_RESUME)
51
0
    {
52
        // Resume sequence
53
0
        gr.restartCount++;
54
0
    }
55
231
    else
56
231
    {
57
231
        if(type == SU_RESTART)
58
0
        {
59
             // Hibernate sequence
60
0
             gr.clearCount++;
61
0
             gr.restartCount++;
62
0
        }
63
231
        else
64
231
        {
65
             // Reset sequence
66
             // Increase resetCount
67
231
             gp.resetCount++;
68
              // Write resetCount to NV
69
231
              NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
70
231
              gp.totalResetCount++;
71
              // We do not expect the total reset counter overflow during the life
72
              // time of TPM. if it ever happens, TPM will be put to failure mode
73
              // and there is no way to recover it.
74
              // The reason that there is no recovery is that we don't increment
75
              // the NV totalResetCount when incrementing would make it 0. When the
76
              // TPM starts up again, the old value of totalResetCount will be read
77
              // and we will get right back to here with the increment failing.
78
231
              if(gp.totalResetCount == 0)
79
0
                  FAIL(FATAL_ERROR_INTERNAL);
80
              // Write total reset counter to NV
81
231
              NvWriteReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
82
              // Reset restartCount
83
231
              gr.restartCount = 0;
84
231
         }
85
231
   }
86
231
   return;
87
231
}
88
//
89
//
90
//             TimeUpdateToCurrent()
91
//
92
//      This function updates the Time and Clock in the global TPMS_TIME_INFO structure.
93
//      In this implementation, Time and Clock are updated at the beginning of each command and the values
94
//      are unchanged for the duration of the command.
95
//      Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance if
96
//      NV is not available. When clock is not advancing, any function that uses Clock will fail and return
97
//      TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE.
98
//      This implementations does not do rate limiting. If the implementation does do rate limiting, then the Clock
99
//      update should not be inhibited even when doing rather limiting.
100
//
101
void
102
TimeUpdateToCurrent(
103
   void
104
   )
105
462
{
106
462
   UINT64          oldClock;
107
462
   UINT64          elapsed;
108
924
#define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
109
   // Can't update time during the dark interval or when rate limiting.
110
462
   if(NvIsAvailable() != TPM_RC_SUCCESS)
111
0
       return;
112
   // Save the old clock value
113
462
   oldClock = go.clock;
114
   // Update the time info to current
115
462
   elapsed = _plat__ClockTimeElapsed();
116
462
   go.clock += elapsed;
117
462
   g_time += elapsed;
118
   // Check to see if the update has caused a need for an nvClock update
119
   // CLOCK_UPDATE_MASK is measured by second, while the value in go.clock is
120
   // recorded by millisecond. Align the clock value to second before the bit
121
//
122
   // operations
123
462
   if( ((go.clock/1000) | CLOCK_UPDATE_MASK)
124
462
           > ((oldClock/1000) | CLOCK_UPDATE_MASK))
125
0
   {
126
       // Going to update the time state so the safe flag
127
       // should be set
128
0
       go.clockSafe = YES;
129
         // Get the DRBG state before updating orderly data
130
0
         CryptDrbgGetPutState(GET_STATE);
131
0
         NvWriteReserved(NV_ORDERLY_DATA, &go);
132
0
   }
133
   // Call self healing logic for dictionary attack parameters
134
462
   DASelfHeal();
135
462
   return;
136
462
}
137
//
138
//
139
//           TimeSetAdjustRate()
140
//
141
//      This function is used to perform rate adjustment on Time and Clock.
142
//
143
void
144
TimeSetAdjustRate(
145
   TPM_CLOCK_ADJUST          adjust            // IN: adjust constant
146
   )
147
0
{
148
0
   switch(adjust)
149
0
   {
150
0
       case TPM_CLOCK_COARSE_SLOWER:
151
0
           _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
152
0
           break;
153
0
       case TPM_CLOCK_COARSE_FASTER:
154
0
           _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
155
0
           break;
156
0
       case TPM_CLOCK_MEDIUM_SLOWER:
157
0
           _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
158
0
           break;
159
0
       case TPM_CLOCK_MEDIUM_FASTER:
160
0
           _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
161
0
           break;
162
0
       case TPM_CLOCK_FINE_SLOWER:
163
0
           _plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
164
0
           break;
165
0
       case TPM_CLOCK_FINE_FASTER:
166
0
           _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
167
0
           break;
168
0
       case TPM_CLOCK_NO_CHANGE:
169
0
           break;
170
0
       default:
171
0
           pAssert(FALSE);
172
0
           break;
173
0
   }
174
0
   return;
175
0
}
176
//
177
//
178
//           TimeGetRange()
179
//
180
//      This function is used to access TPMS_TIME_INFO. The TPMS_TIME_INFO structure is treaded as an
181
//      array of bytes, and a byte offset and length determine what bytes are returned.
182
//
183
//      Error Returns                   Meaning
184
//
185
//      TPM_RC_RANGE                    invalid data range
186
//
187
TPM_RC
188
TimeGetRange(
189
   UINT16              offset,             // IN: offset in TPMS_TIME_INFO
190
   UINT16              size,               // IN: size of data
191
   TIME_INFO          *dataBuffer          // OUT: result buffer
192
   )
193
0
{
194
0
   TPMS_TIME_INFO            timeInfo;
195
0
   UINT16                    infoSize;
196
0
   BYTE                      infoData[sizeof(TPMS_TIME_INFO)];
197
0
   BYTE                      *buffer;
198
0
   INT32                     bufferSize;
199
   // Fill TPMS_TIME_INFO structure
200
0
   timeInfo.time = g_time;
201
0
   TimeFillInfo(&timeInfo.clockInfo);
202
   // Marshal TPMS_TIME_INFO to canonical form
203
0
   buffer = infoData;
204
0
   bufferSize = sizeof(TPMS_TIME_INFO);
205
0
   infoSize = TPMS_TIME_INFO_Marshal(&timeInfo, &buffer, &bufferSize);
206
   // Check if the input range is valid
207
0
   if(offset + size > infoSize) return TPM_RC_RANGE;
208
   // Copy info data to output buffer
209
0
   MemoryCopy(dataBuffer, infoData + offset, size, sizeof(TIME_INFO));
210
0
   return TPM_RC_SUCCESS;
211
0
}
212
//
213
//
214
//          TimeFillInfo
215
//
216
//      This function gathers information to fill in a TPMS_CLOCK_INFO structure.
217
//
218
void
219
TimeFillInfo(
220
   TPMS_CLOCK_INFO           *clockInfo
221
   )
222
0
{
223
0
   clockInfo->clock = go.clock;
224
0
   clockInfo->resetCount = gp.resetCount;
225
0
   clockInfo->restartCount = gr.restartCount;
226
   // If NV is not available, clock stopped advancing and the value reported is
227
   // not "safe".
228
0
   if(NvIsAvailable() == TPM_RC_SUCCESS)
229
0
       clockInfo->safe = go.clockSafe;
230
0
   else
231
0
       clockInfo->safe = NO;
232
0
   return;
233
0
}