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 | } |