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