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
TimePowerOn(void)17 TimePowerOn(
18 void
19 )
20 {
21 TPM_SU orderlyShutDown;
22 // Read orderly data info from NV memory
23 NvReadReserved(NV_ORDERLY_DATA, &go);
24 // Read orderly shut down state flag
25 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 if(orderlyShutDown == SHUTDOWN_NONE)
29 go.clockSafe= NO;
30 else
31 go.clockSafe = YES;
32 // Set the initial state of the DRBG
33 CryptDrbgGetPutState(PUT_STATE);
34 // Clear time since TPM power on
35 g_time = 0;
36 return;
37 }
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
TimeStartup(STARTUP_TYPE type)46 TimeStartup(
47 STARTUP_TYPE type // IN: start up type
48 )
49 {
50 if(type == SU_RESUME)
51 {
52 // Resume sequence
53 gr.restartCount++;
54 }
55 else
56 {
57 if(type == SU_RESTART)
58 {
59 // Hibernate sequence
60 gr.clearCount++;
61 gr.restartCount++;
62 }
63 else
64 {
65 // Reset sequence
66 // Increase resetCount
67 gp.resetCount++;
68 // Write resetCount to NV
69 NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
70 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 if(gp.totalResetCount == 0)
79 FAIL(FATAL_ERROR_INTERNAL);
80 // Write total reset counter to NV
81 NvWriteReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
82 // Reset restartCount
83 gr.restartCount = 0;
84 }
85 }
86 return;
87 }
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
TimeUpdateToCurrent(void)102 TimeUpdateToCurrent(
103 void
104 )
105 {
106 UINT64 oldClock;
107 UINT64 elapsed;
108 #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
109 // Can't update time during the dark interval or when rate limiting.
110 if(NvIsAvailable() != TPM_RC_SUCCESS)
111 return;
112 // Save the old clock value
113 oldClock = go.clock;
114 // Update the time info to current
115 elapsed = _plat__ClockTimeElapsed();
116 go.clock += elapsed;
117 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 if( ((go.clock/1000) | CLOCK_UPDATE_MASK)
124 > ((oldClock/1000) | CLOCK_UPDATE_MASK))
125 {
126 // Going to update the time state so the safe flag
127 // should be set
128 go.clockSafe = YES;
129 // Get the DRBG state before updating orderly data
130 CryptDrbgGetPutState(GET_STATE);
131 NvWriteReserved(NV_ORDERLY_DATA, &go);
132 }
133 // Call self healing logic for dictionary attack parameters
134 DASelfHeal();
135 return;
136 }
137 //
138 //
139 // TimeSetAdjustRate()
140 //
141 // This function is used to perform rate adjustment on Time and Clock.
142 //
143 void
TimeSetAdjustRate(TPM_CLOCK_ADJUST adjust)144 TimeSetAdjustRate(
145 TPM_CLOCK_ADJUST adjust // IN: adjust constant
146 )
147 {
148 switch(adjust)
149 {
150 case TPM_CLOCK_COARSE_SLOWER:
151 _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
152 break;
153 case TPM_CLOCK_COARSE_FASTER:
154 _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
155 break;
156 case TPM_CLOCK_MEDIUM_SLOWER:
157 _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
158 break;
159 case TPM_CLOCK_MEDIUM_FASTER:
160 _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
161 break;
162 case TPM_CLOCK_FINE_SLOWER:
163 _plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
164 break;
165 case TPM_CLOCK_FINE_FASTER:
166 _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
167 break;
168 case TPM_CLOCK_NO_CHANGE:
169 break;
170 default:
171 pAssert(FALSE);
172 break;
173 }
174 return;
175 }
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
TimeGetRange(UINT16 offset,UINT16 size,TIME_INFO * dataBuffer)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 {
194 TPMS_TIME_INFO timeInfo;
195 UINT16 infoSize;
196 BYTE infoData[sizeof(TPMS_TIME_INFO)];
197 BYTE *buffer;
198 INT32 bufferSize;
199 // Fill TPMS_TIME_INFO structure
200 timeInfo.time = g_time;
201 TimeFillInfo(&timeInfo.clockInfo);
202 // Marshal TPMS_TIME_INFO to canonical form
203 buffer = infoData;
204 bufferSize = sizeof(TPMS_TIME_INFO);
205 infoSize = TPMS_TIME_INFO_Marshal(&timeInfo, &buffer, &bufferSize);
206 // Check if the input range is valid
207 if(offset + size > infoSize) return TPM_RC_RANGE;
208 // Copy info data to output buffer
209 MemoryCopy(dataBuffer, infoData + offset, size, sizeof(TIME_INFO));
210 return TPM_RC_SUCCESS;
211 }
212 //
213 //
214 // TimeFillInfo
215 //
216 // This function gathers information to fill in a TPMS_CLOCK_INFO structure.
217 //
218 void
TimeFillInfo(TPMS_CLOCK_INFO * clockInfo)219 TimeFillInfo(
220 TPMS_CLOCK_INFO *clockInfo
221 )
222 {
223 clockInfo->clock = go.clock;
224 clockInfo->resetCount = gp.resetCount;
225 clockInfo->restartCount = gr.restartCount;
226 // If NV is not available, clock stopped advancing and the value reported is
227 // not "safe".
228 if(NvIsAvailable() == TPM_RC_SUCCESS)
229 clockInfo->safe = go.clockSafe;
230 else
231 clockInfo->safe = NO;
232 return;
233 }
234