xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen  *
3*5c591343SA. Cody Schuffelen  *  The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen  *  included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen  *  contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen  *  under this license.
7*5c591343SA. Cody Schuffelen  *
8*5c591343SA. Cody Schuffelen  *  Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen  *
10*5c591343SA. Cody Schuffelen  *  All rights reserved.
11*5c591343SA. Cody Schuffelen  *
12*5c591343SA. Cody Schuffelen  *  BSD License
13*5c591343SA. Cody Schuffelen  *
14*5c591343SA. Cody Schuffelen  *  Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen  *  are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen  *
17*5c591343SA. Cody Schuffelen  *  Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen  *  of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen  *
20*5c591343SA. Cody Schuffelen  *  Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen  *  list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen  *  other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen  *
24*5c591343SA. Cody Schuffelen  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen  */
35*5c591343SA. Cody Schuffelen //** Description
36*5c591343SA. Cody Schuffelen //
37*5c591343SA. Cody Schuffelen // This file contains the routines that are used by the simulator to mimic
38*5c591343SA. Cody Schuffelen // a hardware clock on a TPM.
39*5c591343SA. Cody Schuffelen //
40*5c591343SA. Cody Schuffelen // In this implementation, all the time values are measured in millisecond.
41*5c591343SA. Cody Schuffelen // However, the precision of the clock functions may be implementation dependent.
42*5c591343SA. Cody Schuffelen 
43*5c591343SA. Cody Schuffelen //** Includes and Data Definitions
44*5c591343SA. Cody Schuffelen #include <assert.h>
45*5c591343SA. Cody Schuffelen #include "Platform.h"
46*5c591343SA. Cody Schuffelen #include "TpmFail_fp.h"
47*5c591343SA. Cody Schuffelen 
48*5c591343SA. Cody Schuffelen 
49*5c591343SA. Cody Schuffelen //** Simulator Functions
50*5c591343SA. Cody Schuffelen //*** Introduction
51*5c591343SA. Cody Schuffelen // This set of functions is intended to be called by the simulator environment in
52*5c591343SA. Cody Schuffelen // order to simulate hardware events.
53*5c591343SA. Cody Schuffelen 
54*5c591343SA. Cody Schuffelen //***_plat__TimerReset()
55*5c591343SA. Cody Schuffelen // This function sets current system clock time as t0 for counting TPM time.
56*5c591343SA. Cody Schuffelen // This function is called at a power on event to reset the clock. When the clock
57*5c591343SA. Cody Schuffelen // is reset, the indication that the clock was stopped is also set.
58*5c591343SA. Cody Schuffelen LIB_EXPORT void
_plat__TimerReset(void)59*5c591343SA. Cody Schuffelen _plat__TimerReset(
60*5c591343SA. Cody Schuffelen     void
61*5c591343SA. Cody Schuffelen     )
62*5c591343SA. Cody Schuffelen {
63*5c591343SA. Cody Schuffelen     s_lastSystemTime = 0;
64*5c591343SA. Cody Schuffelen     s_tpmTime = 0;
65*5c591343SA. Cody Schuffelen     s_adjustRate = CLOCK_NOMINAL;
66*5c591343SA. Cody Schuffelen     s_timerReset = TRUE;
67*5c591343SA. Cody Schuffelen     s_timerStopped = TRUE;
68*5c591343SA. Cody Schuffelen     return;
69*5c591343SA. Cody Schuffelen }
70*5c591343SA. Cody Schuffelen 
71*5c591343SA. Cody Schuffelen //*** _plat__TimerRestart()
72*5c591343SA. Cody Schuffelen // This function should be called in order to simulate the restart of the timer
73*5c591343SA. Cody Schuffelen // should it be stopped while power is still applied.
74*5c591343SA. Cody Schuffelen LIB_EXPORT void
_plat__TimerRestart(void)75*5c591343SA. Cody Schuffelen _plat__TimerRestart(
76*5c591343SA. Cody Schuffelen     void
77*5c591343SA. Cody Schuffelen     )
78*5c591343SA. Cody Schuffelen {
79*5c591343SA. Cody Schuffelen     s_timerStopped = TRUE;
80*5c591343SA. Cody Schuffelen     return;
81*5c591343SA. Cody Schuffelen }
82*5c591343SA. Cody Schuffelen 
83*5c591343SA. Cody Schuffelen //** Functions Used by TPM
84*5c591343SA. Cody Schuffelen //*** Introduction
85*5c591343SA. Cody Schuffelen // These functions are called by the TPM code. They should be replaced by
86*5c591343SA. Cody Schuffelen // appropriated hardware functions.
87*5c591343SA. Cody Schuffelen 
88*5c591343SA. Cody Schuffelen #include <time.h>
89*5c591343SA. Cody Schuffelen clock_t     debugTime;
90*5c591343SA. Cody Schuffelen 
91*5c591343SA. Cody Schuffelen //*** _plat__RealTime()
92*5c591343SA. Cody Schuffelen // This is another, probably futile, attempt to define a portable function
93*5c591343SA. Cody Schuffelen // that will return a 64-bit clock value that has mSec resolution.
94*5c591343SA. Cody Schuffelen LIB_EXPORT uint64_t
_plat__RealTime(void)95*5c591343SA. Cody Schuffelen _plat__RealTime(
96*5c591343SA. Cody Schuffelen     void
97*5c591343SA. Cody Schuffelen )
98*5c591343SA. Cody Schuffelen {
99*5c591343SA. Cody Schuffelen     clock64_t           time;
100*5c591343SA. Cody Schuffelen #ifdef _MSC_VER
101*5c591343SA. Cody Schuffelen     struct _timeb       sysTime;
102*5c591343SA. Cody Schuffelen //
103*5c591343SA. Cody Schuffelen     _ftime_s(&sysTime);
104*5c591343SA. Cody Schuffelen     time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm;
105*5c591343SA. Cody Schuffelen     // set the time back by one hour if daylight savings
106*5c591343SA. Cody Schuffelen     if(sysTime.dstflag)
107*5c591343SA. Cody Schuffelen         time -= 1000 * 60 * 60;  // mSec/sec * sec/min * min/hour = ms/hour
108*5c591343SA. Cody Schuffelen #else
109*5c591343SA. Cody Schuffelen     // hopefully, this will work with most UNIX systems
110*5c591343SA. Cody Schuffelen     struct timespec     systime;
111*5c591343SA. Cody Schuffelen //
112*5c591343SA. Cody Schuffelen     clock_gettime(CLOCK_MONOTONIC, &systime);
113*5c591343SA. Cody Schuffelen     time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000);
114*5c591343SA. Cody Schuffelen #endif
115*5c591343SA. Cody Schuffelen     return time;
116*5c591343SA. Cody Schuffelen }
117*5c591343SA. Cody Schuffelen 
118*5c591343SA. Cody Schuffelen //***_plat__TimerRead()
119*5c591343SA. Cody Schuffelen // This function provides access to the tick timer of the platform. The TPM code
120*5c591343SA. Cody Schuffelen // uses this value to drive the TPM Clock.
121*5c591343SA. Cody Schuffelen //
122*5c591343SA. Cody Schuffelen // The tick timer is supposed to run when power is applied to the device. This timer
123*5c591343SA. Cody Schuffelen // should not be reset by time events including _TPM_Init. It should only be reset
124*5c591343SA. Cody Schuffelen // when TPM power is re-applied.
125*5c591343SA. Cody Schuffelen //
126*5c591343SA. Cody Schuffelen // If the TPM is run in a protected environment, that environment may provide the
127*5c591343SA. Cody Schuffelen // tick time to the TPM as long as the time provided by the environment is not
128*5c591343SA. Cody Schuffelen // allowed to go backwards. If the time provided by the system can go backwards
129*5c591343SA. Cody Schuffelen // during a power discontinuity, then the _plat__Signal_PowerOn should call
130*5c591343SA. Cody Schuffelen // _plat__TimerReset().
131*5c591343SA. Cody Schuffelen LIB_EXPORT uint64_t
_plat__TimerRead(void)132*5c591343SA. Cody Schuffelen _plat__TimerRead(
133*5c591343SA. Cody Schuffelen     void
134*5c591343SA. Cody Schuffelen     )
135*5c591343SA. Cody Schuffelen {
136*5c591343SA. Cody Schuffelen #ifdef HARDWARE_CLOCK
137*5c591343SA. Cody Schuffelen #error      "need a defintion for reading the hardware clock"
138*5c591343SA. Cody Schuffelen     return HARDWARE_CLOCK
139*5c591343SA. Cody Schuffelen #else
140*5c591343SA. Cody Schuffelen     clock64_t         timeDiff;
141*5c591343SA. Cody Schuffelen     clock64_t         adjustedTimeDiff;
142*5c591343SA. Cody Schuffelen     clock64_t         timeNow;
143*5c591343SA. Cody Schuffelen     clock64_t         readjustedTimeDiff;
144*5c591343SA. Cody Schuffelen 
145*5c591343SA. Cody Schuffelen     // This produces a timeNow that is basically locked to the system clock.
146*5c591343SA. Cody Schuffelen     timeNow = _plat__RealTime();
147*5c591343SA. Cody Schuffelen 
148*5c591343SA. Cody Schuffelen     // if this hasn't been initialized, initialize it
149*5c591343SA. Cody Schuffelen     if(s_lastSystemTime == 0)
150*5c591343SA. Cody Schuffelen     {
151*5c591343SA. Cody Schuffelen         s_lastSystemTime = timeNow;
152*5c591343SA. Cody Schuffelen         debugTime = clock();
153*5c591343SA. Cody Schuffelen         s_lastReportedTime = 0;
154*5c591343SA. Cody Schuffelen         s_realTimePrevious = 0;
155*5c591343SA. Cody Schuffelen     }
156*5c591343SA. Cody Schuffelen     // The system time can bounce around and that's OK as long as we don't allow
157*5c591343SA. Cody Schuffelen     // time to go backwards. When the time does appear to go backwards, set
158*5c591343SA. Cody Schuffelen     // lastSystemTime to be the new value and then update the reported time.
159*5c591343SA. Cody Schuffelen     if(timeNow < s_lastReportedTime)
160*5c591343SA. Cody Schuffelen         s_lastSystemTime = timeNow;
161*5c591343SA. Cody Schuffelen     s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime;
162*5c591343SA. Cody Schuffelen     s_lastSystemTime = timeNow;
163*5c591343SA. Cody Schuffelen     timeNow = s_lastReportedTime;
164*5c591343SA. Cody Schuffelen 
165*5c591343SA. Cody Schuffelen     // The code above produces a timeNow that is similar to the value returned
166*5c591343SA. Cody Schuffelen     // by Clock(). The difference is that timeNow does not max out, and it is
167*5c591343SA. Cody Schuffelen     // at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below
168*5c591343SA. Cody Schuffelen     // uses that value and does the rate adjustment on the time value.
169*5c591343SA. Cody Schuffelen     // If there is no difference in time, then skip all the computations
170*5c591343SA. Cody Schuffelen     if(s_realTimePrevious >= timeNow)
171*5c591343SA. Cody Schuffelen         return s_tpmTime;
172*5c591343SA. Cody Schuffelen     // Compute the amount of time since the last update of the system clock
173*5c591343SA. Cody Schuffelen     timeDiff = timeNow - s_realTimePrevious;
174*5c591343SA. Cody Schuffelen 
175*5c591343SA. Cody Schuffelen     // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec
176*5c591343SA. Cody Schuffelen     adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate);
177*5c591343SA. Cody Schuffelen 
178*5c591343SA. Cody Schuffelen     // update the TPM time with the adjusted timeDiff
179*5c591343SA. Cody Schuffelen     s_tpmTime += (clock64_t)adjustedTimeDiff;
180*5c591343SA. Cody Schuffelen 
181*5c591343SA. Cody Schuffelen     // Might have some rounding error that would loose CLOCKS. See what is not
182*5c591343SA. Cody Schuffelen     // being used. As mentioned above, this could result in putting back more than
183*5c591343SA. Cody Schuffelen     // is taken out. Here, we are trying to recreate timeDiff.
184*5c591343SA. Cody Schuffelen     readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate )
185*5c591343SA. Cody Schuffelen                                 / CLOCK_NOMINAL;
186*5c591343SA. Cody Schuffelen 
187*5c591343SA. Cody Schuffelen     // adjusted is now converted back to being the amount we should advance the
188*5c591343SA. Cody Schuffelen     // previous sampled time. It should always be less than or equal to timeDiff.
189*5c591343SA. Cody Schuffelen     // That is, we could not have use more time than we started with.
190*5c591343SA. Cody Schuffelen     s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff;
191*5c591343SA. Cody Schuffelen 
192*5c591343SA. Cody Schuffelen #ifdef  DEBUGGING_TIME
193*5c591343SA. Cody Schuffelen     // Put this in so that TPM time will pass much faster than real time when
194*5c591343SA. Cody Schuffelen     // doing debug.
195*5c591343SA. Cody Schuffelen     // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second
196*5c591343SA. Cody Schuffelen     // A good value might be 100
197*5c591343SA. Cody Schuffelen     return (s_tpmTime * DEBUG_TIME_MULTIPLIER);
198*5c591343SA. Cody Schuffelen #endif
199*5c591343SA. Cody Schuffelen     return s_tpmTime;
200*5c591343SA. Cody Schuffelen #endif
201*5c591343SA. Cody Schuffelen }
202*5c591343SA. Cody Schuffelen 
203*5c591343SA. Cody Schuffelen 
204*5c591343SA. Cody Schuffelen 
205*5c591343SA. Cody Schuffelen //*** _plat__TimerWasReset()
206*5c591343SA. Cody Schuffelen // This function is used to interrogate the flag indicating if the tick timer has
207*5c591343SA. Cody Schuffelen // been reset.
208*5c591343SA. Cody Schuffelen //
209*5c591343SA. Cody Schuffelen // If the resetFlag parameter is SET, then the flag will be CLEAR before the
210*5c591343SA. Cody Schuffelen // function returns.
211*5c591343SA. Cody Schuffelen LIB_EXPORT int
212*5c591343SA. Cody Schuffelen _plat__TimerWasReset(
213*5c591343SA. Cody Schuffelen    void
214*5c591343SA. Cody Schuffelen     )
215*5c591343SA. Cody Schuffelen {
216*5c591343SA. Cody Schuffelen     int          retVal = s_timerReset;
217*5c591343SA. Cody Schuffelen     s_timerReset = FALSE;
218*5c591343SA. Cody Schuffelen     return retVal;
219*5c591343SA. Cody Schuffelen }
220*5c591343SA. Cody Schuffelen 
221*5c591343SA. Cody Schuffelen //*** _plat__TimerWasStopped()
222*5c591343SA. Cody Schuffelen // This function is used to interrogate the flag indicating if the tick timer has
223*5c591343SA. Cody Schuffelen // been stopped. If so, this is typically a reason to roll the nonce.
224*5c591343SA. Cody Schuffelen //
225*5c591343SA. Cody Schuffelen // This function will CLEAR the s_timerStopped flag before returning. This provides
226*5c591343SA. Cody Schuffelen // functionality that is similar to status register that is cleared when read. This
227*5c591343SA. Cody Schuffelen // is the model used here because it is the one that has the most impact on the TPM
228*5c591343SA. Cody Schuffelen // code as the flag can only be accessed by one entity in the TPM. Any other
229*5c591343SA. Cody Schuffelen // implementation of the hardware can be made to look like a read-once register.
230*5c591343SA. Cody Schuffelen LIB_EXPORT int
231*5c591343SA. Cody Schuffelen _plat__TimerWasStopped(
232*5c591343SA. Cody Schuffelen     void
233*5c591343SA. Cody Schuffelen     )
234*5c591343SA. Cody Schuffelen {
235*5c591343SA. Cody Schuffelen     int          retVal = s_timerStopped;
236*5c591343SA. Cody Schuffelen     s_timerStopped = FALSE;
237*5c591343SA. Cody Schuffelen     return retVal;
238*5c591343SA. Cody Schuffelen }
239*5c591343SA. Cody Schuffelen 
240*5c591343SA. Cody Schuffelen //***_plat__ClockAdjustRate()
241*5c591343SA. Cody Schuffelen // Adjust the clock rate
242*5c591343SA. Cody Schuffelen LIB_EXPORT void
243*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(
244*5c591343SA. Cody Schuffelen     int              adjust         // IN: the adjust number.  It could be positive
245*5c591343SA. Cody Schuffelen                                     //     or negative
246*5c591343SA. Cody Schuffelen     )
247*5c591343SA. Cody Schuffelen {
248*5c591343SA. Cody Schuffelen     // We expect the caller should only use a fixed set of constant values to
249*5c591343SA. Cody Schuffelen     // adjust the rate
250*5c591343SA. Cody Schuffelen     switch(adjust)
251*5c591343SA. Cody Schuffelen     {
252*5c591343SA. Cody Schuffelen         case CLOCK_ADJUST_COARSE:
253*5c591343SA. Cody Schuffelen             s_adjustRate += CLOCK_ADJUST_COARSE;
254*5c591343SA. Cody Schuffelen             break;
255*5c591343SA. Cody Schuffelen         case -CLOCK_ADJUST_COARSE:
256*5c591343SA. Cody Schuffelen             s_adjustRate -= CLOCK_ADJUST_COARSE;
257*5c591343SA. Cody Schuffelen             break;
258*5c591343SA. Cody Schuffelen         case CLOCK_ADJUST_MEDIUM:
259*5c591343SA. Cody Schuffelen             s_adjustRate += CLOCK_ADJUST_MEDIUM;
260*5c591343SA. Cody Schuffelen             break;
261*5c591343SA. Cody Schuffelen         case -CLOCK_ADJUST_MEDIUM:
262*5c591343SA. Cody Schuffelen             s_adjustRate -= CLOCK_ADJUST_MEDIUM;
263*5c591343SA. Cody Schuffelen             break;
264*5c591343SA. Cody Schuffelen         case CLOCK_ADJUST_FINE:
265*5c591343SA. Cody Schuffelen             s_adjustRate += CLOCK_ADJUST_FINE;
266*5c591343SA. Cody Schuffelen             break;
267*5c591343SA. Cody Schuffelen         case -CLOCK_ADJUST_FINE:
268*5c591343SA. Cody Schuffelen             s_adjustRate -= CLOCK_ADJUST_FINE;
269*5c591343SA. Cody Schuffelen             break;
270*5c591343SA. Cody Schuffelen         default:
271*5c591343SA. Cody Schuffelen             // ignore any other values;
272*5c591343SA. Cody Schuffelen             break;
273*5c591343SA. Cody Schuffelen     }
274*5c591343SA. Cody Schuffelen 
275*5c591343SA. Cody Schuffelen     if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT))
276*5c591343SA. Cody Schuffelen         s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT;
277*5c591343SA. Cody Schuffelen     if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT))
278*5c591343SA. Cody Schuffelen         s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT;
279*5c591343SA. Cody Schuffelen 
280*5c591343SA. Cody Schuffelen     return;
281*5c591343SA. Cody Schuffelen }
282*5c591343SA. Cody Schuffelen 
283