/src/ibmswtpm2/src/Clock.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Used by the simulator to mimic a hardware clock */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: Clock.c 1311 2018-08-23 21:39:29Z 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 | | /* added for portability because Linux clock is 32 bits */ |
63 | | |
64 | | #include <stdint.h> |
65 | | #include <stdio.h> |
66 | | #include <time.h> |
67 | | |
68 | | /* C.3 Clock.c */ |
69 | | /* C.3.1. Description */ |
70 | | /* This file contains the routines that are used by the simulator to mimic a hardware clock on a |
71 | | TPM. In this implementation, all the time values are measured in millisecond. However, the |
72 | | precision of the clock functions may be implementation dependent. */ |
73 | | /* C.3.2. Includes and Data Definitions */ |
74 | | #include "PlatformData.h" |
75 | | #include "Platform_fp.h" |
76 | | #include "TpmFail_fp.h" |
77 | | #include <assert.h> |
78 | | /* C.3.3. Simulator Functions */ |
79 | | /* C.3.3.1. Introduction */ |
80 | | /* This set of functions is intended to be called by the simulator environment in order to simulate |
81 | | hardware events. */ |
82 | | /* C.3.3.2. _plat__TimerReset() */ |
83 | | /* This function sets current system clock time as t0 for counting TPM time. This function is called |
84 | | at a power on event to reset the clock. When the clock is reset, the indication that the clock |
85 | | was stopped is also set. */ |
86 | | LIB_EXPORT void |
87 | | _plat__TimerReset( |
88 | | void |
89 | | ) |
90 | 1 | { |
91 | 1 | s_lastSystemTime = 0; |
92 | 1 | s_tpmTime = 0; |
93 | 1 | s_adjustRate = CLOCK_NOMINAL; |
94 | 1 | s_timerReset = TRUE; |
95 | 1 | s_timerStopped = TRUE; |
96 | 1 | return; |
97 | 1 | } |
98 | | /* C.3.3.3. _plat__TimerRestart() */ |
99 | | /* This function should be called in order to simulate the restart of the timer should it be stopped |
100 | | while power is still applied. */ |
101 | | LIB_EXPORT void |
102 | | _plat__TimerRestart( |
103 | | void |
104 | | ) |
105 | 0 | { |
106 | 0 | s_timerStopped = TRUE; |
107 | 0 | return; |
108 | 0 | } |
109 | | |
110 | | /* C.3.4. Functions Used by TPM */ |
111 | | /* C.3.4.1. Introduction */ |
112 | | /* These functions are called by the TPM code. They should be replaced by appropriated hardware |
113 | | functions. */ |
114 | | |
115 | | clock_t debugTime; |
116 | | /* C.3.4.2. _plat__Time() */ |
117 | | /* This is another, probably futile, attempt to define a portable function that will return a 64-bit |
118 | | clock value that has mSec resolution. */ |
119 | | uint64_t |
120 | | _plat__RealTime( |
121 | | void |
122 | | ) |
123 | 6.47k | { |
124 | 6.47k | clock64_t time; |
125 | | //#ifdef _MSC_VER kgold |
126 | | #ifdef TPM_WINDOWS |
127 | | #include <SYS/Timeb.h> |
128 | | struct _timeb sysTime; |
129 | | // |
130 | | _ftime(&sysTime); /* kgold, mingw doesn't have _ftime_s */ |
131 | | time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm; |
132 | | // set the time back by one hour if daylight savings |
133 | | if(sysTime.dstflag) |
134 | | time -= 1000 * 60 * 60; // mSec/sec * sec/min * min/hour = ms/hour |
135 | | #else |
136 | | // hopefully, this will work with most UNIX systems |
137 | 6.47k | struct timespec systime; |
138 | | // |
139 | 6.47k | clock_gettime(CLOCK_MONOTONIC, &systime); |
140 | 6.47k | time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000); |
141 | 6.47k | #endif |
142 | 6.47k | return time; |
143 | 6.47k | } |
144 | | |
145 | | |
146 | | |
147 | | /* C.3.4.3. _plat__TimerRead() */ |
148 | | /* This function provides access to the tick timer of the platform. The TPM code uses this value to |
149 | | drive the TPM Clock. */ |
150 | | /* The tick timer is supposed to run when power is applied to the device. This timer should not be |
151 | | reset by time events including _TPM_Init(). It should only be reset when TPM power is |
152 | | re-applied. */ |
153 | | /* If the TPM is run in a protected environment, that environment may provide the tick time to the |
154 | | TPM as long as the time provided by the environment is not allowed to go backwards. If the time |
155 | | provided by the system can go backwards during a power discontinuity, then the |
156 | | _plat__Signal_PowerOn() should call _plat__TimerReset(). */ |
157 | | LIB_EXPORT uint64_t |
158 | | _plat__TimerRead( |
159 | | void |
160 | | ) |
161 | 1 | { |
162 | | #ifdef HARDWARE_CLOCK |
163 | | #error "need a defintion for reading the hardware clock" |
164 | | return HARDWARE_CLOCK |
165 | | #else |
166 | 1 | clock64_t timeDiff; |
167 | 1 | clock64_t adjustedTimeDiff; |
168 | 1 | clock64_t timeNow; |
169 | 1 | clock64_t readjustedTimeDiff; |
170 | | // This produces a timeNow that is basically locked to the system clock. |
171 | 1 | timeNow = _plat__RealTime(); |
172 | | // if this hasn't been initialized, initialize it |
173 | 1 | if(s_lastSystemTime == 0) |
174 | 1 | { |
175 | 1 | s_lastSystemTime = timeNow; |
176 | 1 | debugTime = clock(); |
177 | 1 | s_lastReportedTime = 0; |
178 | 1 | s_realTimePrevious = 0; |
179 | 1 | } |
180 | | // The system time can bounce around and that's OK as long as we don't allow |
181 | | // time to go backwards. When the time does appear to go backwards, set |
182 | | // lastSystemTime to be the new value and then update the reported time. |
183 | 1 | if(timeNow < s_lastReportedTime) |
184 | 0 | s_lastSystemTime = timeNow; |
185 | 1 | s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime; |
186 | 1 | s_lastSystemTime = timeNow; |
187 | 1 | timeNow = s_lastReportedTime; |
188 | | // The code above produces a timeNow that is similar to the value returned |
189 | | // by Clock(). The difference is that timeNow does not max out, and it is |
190 | | // at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below |
191 | | // uses that value and does the rate adjustment on the time value. |
192 | | // If there is no difference in time, then skip all the computations |
193 | 1 | if(s_realTimePrevious >= timeNow) |
194 | 1 | return s_tpmTime; |
195 | | // Compute the amount of time since the last update of the system clock |
196 | 0 | timeDiff = timeNow - s_realTimePrevious; |
197 | | // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec |
198 | 0 | adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate); |
199 | | // update the TPM time with the adjusted timeDiff |
200 | 0 | s_tpmTime += (clock64_t)adjustedTimeDiff; |
201 | | // Might have some rounding error that would loose CLOCKS. See what is not |
202 | | // being used. As mentioned above, this could result in putting back more than |
203 | | // is taken out. Here, we are trying to recreate timeDiff. |
204 | 0 | readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate ) |
205 | 0 | / CLOCK_NOMINAL; |
206 | | // adjusted is now converted back to being the amount we should advance the |
207 | | // previous sampled time. It should always be less than or equal to timeDiff. |
208 | | // That is, we could not have use more time than we started with. |
209 | 0 | s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff; |
210 | | #ifdef DEBUGGING_TIME |
211 | | // Put this in so that TPM time will pass much faster than real time when |
212 | | // doing debug. |
213 | | // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second |
214 | | // A good value might be 100 |
215 | | return (s_tpmTime * DEBUG_TIME_MULTIPLIER); |
216 | | #endif |
217 | 0 | return s_tpmTime; |
218 | 1 | #endif |
219 | 1 | } |
220 | | |
221 | | |
222 | | /* C.3.4.3. _plat__TimerWasReset() */ |
223 | | /* This function is used to interrogate the flag indicating if the tick timer has been reset. */ |
224 | | /* If the resetFlag parameter is SET, then the flag will be CLEAR before the function returns. */ |
225 | | LIB_EXPORT BOOL |
226 | | _plat__TimerWasReset( |
227 | | void |
228 | | ) |
229 | 0 | { |
230 | 0 | BOOL retVal = s_timerReset; |
231 | 0 | s_timerReset = FALSE; |
232 | 0 | return retVal; |
233 | 0 | } |
234 | | /* C.3.4.4. _plat__TimerWasStopped() */ |
235 | | /* This function is used to interrogate the flag indicating if the tick timer has been stopped. If |
236 | | so, this is typically a reason to roll the nonce. */ |
237 | | /* This function will CLEAR the s_timerStopped flag before returning. This provides functionality |
238 | | that is similar to status register that is cleared when read. This is the model used here because |
239 | | it is the one that has the most impact on the TPM code as the flag can only be accessed by one |
240 | | entity in the TPM. Any other implementation of the hardware can be made to look like a read-once |
241 | | register. */ |
242 | | LIB_EXPORT BOOL |
243 | | _plat__TimerWasStopped( |
244 | | void |
245 | | ) |
246 | 0 | { |
247 | 0 | BOOL retVal = s_timerStopped; |
248 | 0 | s_timerStopped = FALSE; |
249 | 0 | return retVal; |
250 | 0 | } |
251 | | /* C.3.4.5. _plat__ClockAdjustRate() */ |
252 | | /* Adjust the clock rate */ |
253 | | LIB_EXPORT void |
254 | | _plat__ClockAdjustRate( |
255 | | int adjust // IN: the adjust number. It could be positive |
256 | | // or negative |
257 | | ) |
258 | 0 | { |
259 | | // We expect the caller should only use a fixed set of constant values to |
260 | | // adjust the rate |
261 | 0 | switch(adjust) |
262 | 0 | { |
263 | 0 | case CLOCK_ADJUST_COARSE: |
264 | 0 | s_adjustRate += CLOCK_ADJUST_COARSE; |
265 | 0 | break; |
266 | 0 | case -CLOCK_ADJUST_COARSE: |
267 | 0 | s_adjustRate -= CLOCK_ADJUST_COARSE; |
268 | 0 | break; |
269 | 0 | case CLOCK_ADJUST_MEDIUM: |
270 | 0 | s_adjustRate += CLOCK_ADJUST_MEDIUM; |
271 | 0 | break; |
272 | 0 | case -CLOCK_ADJUST_MEDIUM: |
273 | 0 | s_adjustRate -= CLOCK_ADJUST_MEDIUM; |
274 | 0 | break; |
275 | 0 | case CLOCK_ADJUST_FINE: |
276 | 0 | s_adjustRate += CLOCK_ADJUST_FINE; |
277 | 0 | break; |
278 | 0 | case -CLOCK_ADJUST_FINE: |
279 | 0 | s_adjustRate -= CLOCK_ADJUST_FINE; |
280 | 0 | break; |
281 | 0 | default: |
282 | | // ignore any other values; |
283 | 0 | break; |
284 | 0 | } |
285 | 0 | if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) |
286 | 0 | s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; |
287 | 0 | if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) |
288 | 0 | s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT; |
289 | 0 | return; |
290 | 0 | } |