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 //** Introduction
36*5c591343SA. Cody Schuffelen // This file contains the functions relating to the TPM's time functions including
37*5c591343SA. Cody Schuffelen // the interface to the implementation-specific time functions.
38*5c591343SA. Cody Schuffelen //
39*5c591343SA. Cody Schuffelen //** Includes
40*5c591343SA. Cody Schuffelen #include "Tpm.h"
41*5c591343SA. Cody Schuffelen #include "PlatformClock.h"
42*5c591343SA. Cody Schuffelen
43*5c591343SA. Cody Schuffelen //** Functions
44*5c591343SA. Cody Schuffelen
45*5c591343SA. Cody Schuffelen //*** TimePowerOn()
46*5c591343SA. Cody Schuffelen // This function initialize time info at _TPM_Init().
47*5c591343SA. Cody Schuffelen //
48*5c591343SA. Cody Schuffelen // This function is called at _TPM_Init() so that the TPM time can start counting
49*5c591343SA. Cody Schuffelen // as soon as the TPM comes out of reset and doesn't have to wait until
50*5c591343SA. Cody Schuffelen // TPM2_Startup() in order to begin the new time epoch. This could be significant
51*5c591343SA. Cody Schuffelen // for systems that could get powered up but not run any TPM commands for some
52*5c591343SA. Cody Schuffelen // period of time.
53*5c591343SA. Cody Schuffelen //
54*5c591343SA. Cody Schuffelen void
TimePowerOn(void)55*5c591343SA. Cody Schuffelen TimePowerOn(
56*5c591343SA. Cody Schuffelen void
57*5c591343SA. Cody Schuffelen )
58*5c591343SA. Cody Schuffelen {
59*5c591343SA. Cody Schuffelen g_time = _plat__TimerRead();
60*5c591343SA. Cody Schuffelen }
61*5c591343SA. Cody Schuffelen
62*5c591343SA. Cody Schuffelen //*** TimeNewEpoch()
63*5c591343SA. Cody Schuffelen // This function does the processing to generate a new time epoch nonce and
64*5c591343SA. Cody Schuffelen // set NV for update. This function is only called when NV is known to be available
65*5c591343SA. Cody Schuffelen // and the clock is running. The epoch is updated to persistent data.
66*5c591343SA. Cody Schuffelen static void
TimeNewEpoch(void)67*5c591343SA. Cody Schuffelen TimeNewEpoch(
68*5c591343SA. Cody Schuffelen void
69*5c591343SA. Cody Schuffelen )
70*5c591343SA. Cody Schuffelen {
71*5c591343SA. Cody Schuffelen #if CLOCK_STOPS
72*5c591343SA. Cody Schuffelen CryptRandomGenerate(sizeof(CLOCK_NONCE), (BYTE *)&g_timeEpoch);
73*5c591343SA. Cody Schuffelen #else
74*5c591343SA. Cody Schuffelen // if the epoch is kept in NV, update it.
75*5c591343SA. Cody Schuffelen gp.timeEpoch++;
76*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(timeEpoch);
77*5c591343SA. Cody Schuffelen #endif
78*5c591343SA. Cody Schuffelen // Clean out any lingering state
79*5c591343SA. Cody Schuffelen _plat__TimerWasStopped();
80*5c591343SA. Cody Schuffelen }
81*5c591343SA. Cody Schuffelen
82*5c591343SA. Cody Schuffelen //*** TimeStartup()
83*5c591343SA. Cody Schuffelen // This function updates the resetCount and restartCount components of
84*5c591343SA. Cody Schuffelen // TPMS_CLOCK_INFO structure at TPM2_Startup().
85*5c591343SA. Cody Schuffelen //
86*5c591343SA. Cody Schuffelen // This function will deal with the deferred creation of a new epoch.
87*5c591343SA. Cody Schuffelen // TimeUpdateToCurrent() will not start a new epoch even if one is due when
88*5c591343SA. Cody Schuffelen // TPM_Startup() has not been run. This is because the state of NV is not known
89*5c591343SA. Cody Schuffelen // until startup completes. When Startup is done, then it will create the epoch
90*5c591343SA. Cody Schuffelen // nonce to complete the initializations by calling this function.
91*5c591343SA. Cody Schuffelen BOOL
TimeStartup(STARTUP_TYPE type)92*5c591343SA. Cody Schuffelen TimeStartup(
93*5c591343SA. Cody Schuffelen STARTUP_TYPE type // IN: start up type
94*5c591343SA. Cody Schuffelen )
95*5c591343SA. Cody Schuffelen {
96*5c591343SA. Cody Schuffelen NOT_REFERENCED(type);
97*5c591343SA. Cody Schuffelen // If the previous cycle is orderly shut down, the value of the safe bit
98*5c591343SA. Cody Schuffelen // the same as previously saved. Otherwise, it is not safe.
99*5c591343SA. Cody Schuffelen if(!NV_IS_ORDERLY)
100*5c591343SA. Cody Schuffelen go.clockSafe = NO;
101*5c591343SA. Cody Schuffelen return TRUE;
102*5c591343SA. Cody Schuffelen }
103*5c591343SA. Cody Schuffelen
104*5c591343SA. Cody Schuffelen //*** TimeClockUpdate()
105*5c591343SA. Cody Schuffelen // This function updates go.clock. If 'newTime' requires an update of NV, then
106*5c591343SA. Cody Schuffelen // NV is checked for availability. If it is not available or is rate limiting, then
107*5c591343SA. Cody Schuffelen // go.clock is not updated and the function returns an error. If 'newTime' would
108*5c591343SA. Cody Schuffelen // not cause an NV write, then go.clock is updated. If an NV write occurs, then
109*5c591343SA. Cody Schuffelen // go.safe is SET.
110*5c591343SA. Cody Schuffelen void
TimeClockUpdate(UINT64 newTime)111*5c591343SA. Cody Schuffelen TimeClockUpdate(
112*5c591343SA. Cody Schuffelen UINT64 newTime // IN: New time value in mS.
113*5c591343SA. Cody Schuffelen )
114*5c591343SA. Cody Schuffelen {
115*5c591343SA. Cody Schuffelen #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
116*5c591343SA. Cody Schuffelen
117*5c591343SA. Cody Schuffelen // Check to see if the update will cause a need for an nvClock update
118*5c591343SA. Cody Schuffelen if((newTime | CLOCK_UPDATE_MASK) > (go.clock | CLOCK_UPDATE_MASK))
119*5c591343SA. Cody Schuffelen {
120*5c591343SA. Cody Schuffelen pAssert(g_NvStatus == TPM_RC_SUCCESS);
121*5c591343SA. Cody Schuffelen
122*5c591343SA. Cody Schuffelen // Going to update the NV time state so SET the safe flag
123*5c591343SA. Cody Schuffelen go.clockSafe = YES;
124*5c591343SA. Cody Schuffelen
125*5c591343SA. Cody Schuffelen // update the time
126*5c591343SA. Cody Schuffelen go.clock = newTime;
127*5c591343SA. Cody Schuffelen
128*5c591343SA. Cody Schuffelen NvWrite(NV_ORDERLY_DATA, sizeof(go), &go);
129*5c591343SA. Cody Schuffelen }
130*5c591343SA. Cody Schuffelen else
131*5c591343SA. Cody Schuffelen // No NV update needed so just update
132*5c591343SA. Cody Schuffelen go.clock = newTime;
133*5c591343SA. Cody Schuffelen
134*5c591343SA. Cody Schuffelen }
135*5c591343SA. Cody Schuffelen
136*5c591343SA. Cody Schuffelen //*** TimeUpdate()
137*5c591343SA. Cody Schuffelen // This function is used to update the time and clock values. If the TPM
138*5c591343SA. Cody Schuffelen // has run TPM2_Startup(), this function is called at the start of each command.
139*5c591343SA. Cody Schuffelen // If the TPM has not run TPM2_Startup(), this is called from TPM2_Startup() to
140*5c591343SA. Cody Schuffelen // get the clock values initialized. It is not called on command entry because, in
141*5c591343SA. Cody Schuffelen // this implementation, the go structure is not read from NV until TPM2_Startup().
142*5c591343SA. Cody Schuffelen // The reason for this is that the initialization code (_TPM_Init()) may run before
143*5c591343SA. Cody Schuffelen // NV is accessible.
144*5c591343SA. Cody Schuffelen void
TimeUpdate(void)145*5c591343SA. Cody Schuffelen TimeUpdate(
146*5c591343SA. Cody Schuffelen void
147*5c591343SA. Cody Schuffelen )
148*5c591343SA. Cody Schuffelen {
149*5c591343SA. Cody Schuffelen UINT64 elapsed;
150*5c591343SA. Cody Schuffelen //
151*5c591343SA. Cody Schuffelen // Make sure that we consume the current _plat__TimerWasStopped() state.
152*5c591343SA. Cody Schuffelen if(_plat__TimerWasStopped())
153*5c591343SA. Cody Schuffelen {
154*5c591343SA. Cody Schuffelen TimeNewEpoch();
155*5c591343SA. Cody Schuffelen }
156*5c591343SA. Cody Schuffelen // Get the difference between this call and the last time we updated the tick
157*5c591343SA. Cody Schuffelen // timer.
158*5c591343SA. Cody Schuffelen elapsed = _plat__TimerRead() - g_time;
159*5c591343SA. Cody Schuffelen // Don't read +
160*5c591343SA. Cody Schuffelen g_time += elapsed;
161*5c591343SA. Cody Schuffelen
162*5c591343SA. Cody Schuffelen // Don't need to check the result because it has to be success because have
163*5c591343SA. Cody Schuffelen // already checked that NV is available.
164*5c591343SA. Cody Schuffelen TimeClockUpdate(go.clock + elapsed);
165*5c591343SA. Cody Schuffelen
166*5c591343SA. Cody Schuffelen // Call self healing logic for dictionary attack parameters
167*5c591343SA. Cody Schuffelen DASelfHeal();
168*5c591343SA. Cody Schuffelen }
169*5c591343SA. Cody Schuffelen
170*5c591343SA. Cody Schuffelen //*** TimeUpdateToCurrent()
171*5c591343SA. Cody Schuffelen // This function updates the 'Time' and 'Clock' in the global
172*5c591343SA. Cody Schuffelen // TPMS_TIME_INFO structure.
173*5c591343SA. Cody Schuffelen //
174*5c591343SA. Cody Schuffelen // In this implementation, 'Time' and 'Clock' are updated at the beginning
175*5c591343SA. Cody Schuffelen // of each command and the values are unchanged for the duration of the
176*5c591343SA. Cody Schuffelen // command.
177*5c591343SA. Cody Schuffelen //
178*5c591343SA. Cody Schuffelen // Because 'Clock' updates may require a write to NV memory, 'Time' and 'Clock'
179*5c591343SA. Cody Schuffelen // are not allowed to advance if NV is not available. When clock is not advancing,
180*5c591343SA. Cody Schuffelen // any function that uses 'Clock' will fail and return TPM_RC_NV_UNAVAILABLE or
181*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE.
182*5c591343SA. Cody Schuffelen //
183*5c591343SA. Cody Schuffelen // This implementation does not do rate limiting. If the implementation does do
184*5c591343SA. Cody Schuffelen // rate limiting, then the 'Clock' update should not be inhibited even when doing
185*5c591343SA. Cody Schuffelen // rate limiting.
186*5c591343SA. Cody Schuffelen void
TimeUpdateToCurrent(void)187*5c591343SA. Cody Schuffelen TimeUpdateToCurrent(
188*5c591343SA. Cody Schuffelen void
189*5c591343SA. Cody Schuffelen )
190*5c591343SA. Cody Schuffelen {
191*5c591343SA. Cody Schuffelen // Can't update time during the dark interval or when rate limiting so don't
192*5c591343SA. Cody Schuffelen // make any modifications to the internal clock value. Also, defer any clock
193*5c591343SA. Cody Schuffelen // processing until TPM has run TPM2_Startup()
194*5c591343SA. Cody Schuffelen if(!NV_IS_AVAILABLE || !TPMIsStarted())
195*5c591343SA. Cody Schuffelen return;
196*5c591343SA. Cody Schuffelen
197*5c591343SA. Cody Schuffelen TimeUpdate();
198*5c591343SA. Cody Schuffelen }
199*5c591343SA. Cody Schuffelen
200*5c591343SA. Cody Schuffelen
201*5c591343SA. Cody Schuffelen //*** TimeSetAdjustRate()
202*5c591343SA. Cody Schuffelen // This function is used to perform rate adjustment on 'Time' and 'Clock'.
203*5c591343SA. Cody Schuffelen void
TimeSetAdjustRate(TPM_CLOCK_ADJUST adjust)204*5c591343SA. Cody Schuffelen TimeSetAdjustRate(
205*5c591343SA. Cody Schuffelen TPM_CLOCK_ADJUST adjust // IN: adjust constant
206*5c591343SA. Cody Schuffelen )
207*5c591343SA. Cody Schuffelen {
208*5c591343SA. Cody Schuffelen switch(adjust)
209*5c591343SA. Cody Schuffelen {
210*5c591343SA. Cody Schuffelen case TPM_CLOCK_COARSE_SLOWER:
211*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
212*5c591343SA. Cody Schuffelen break;
213*5c591343SA. Cody Schuffelen case TPM_CLOCK_COARSE_FASTER:
214*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
215*5c591343SA. Cody Schuffelen break;
216*5c591343SA. Cody Schuffelen case TPM_CLOCK_MEDIUM_SLOWER:
217*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
218*5c591343SA. Cody Schuffelen break;
219*5c591343SA. Cody Schuffelen case TPM_CLOCK_MEDIUM_FASTER:
220*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
221*5c591343SA. Cody Schuffelen break;
222*5c591343SA. Cody Schuffelen case TPM_CLOCK_FINE_SLOWER:
223*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
224*5c591343SA. Cody Schuffelen break;
225*5c591343SA. Cody Schuffelen case TPM_CLOCK_FINE_FASTER:
226*5c591343SA. Cody Schuffelen _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
227*5c591343SA. Cody Schuffelen break;
228*5c591343SA. Cody Schuffelen case TPM_CLOCK_NO_CHANGE:
229*5c591343SA. Cody Schuffelen break;
230*5c591343SA. Cody Schuffelen default:
231*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
232*5c591343SA. Cody Schuffelen break;
233*5c591343SA. Cody Schuffelen }
234*5c591343SA. Cody Schuffelen
235*5c591343SA. Cody Schuffelen return;
236*5c591343SA. Cody Schuffelen }
237*5c591343SA. Cody Schuffelen
238*5c591343SA. Cody Schuffelen //*** TimeGetMarshaled()
239*5c591343SA. Cody Schuffelen // This function is used to access TPMS_TIME_INFO in canonical form.
240*5c591343SA. Cody Schuffelen // The function collects the time information and marshals it into 'dataBuffer'
241*5c591343SA. Cody Schuffelen // and returns the marshaled size
242*5c591343SA. Cody Schuffelen UINT16
TimeGetMarshaled(TIME_INFO * dataBuffer)243*5c591343SA. Cody Schuffelen TimeGetMarshaled(
244*5c591343SA. Cody Schuffelen TIME_INFO *dataBuffer // OUT: result buffer
245*5c591343SA. Cody Schuffelen )
246*5c591343SA. Cody Schuffelen {
247*5c591343SA. Cody Schuffelen TPMS_TIME_INFO timeInfo;
248*5c591343SA. Cody Schuffelen
249*5c591343SA. Cody Schuffelen // Fill TPMS_TIME_INFO structure
250*5c591343SA. Cody Schuffelen timeInfo.time = g_time;
251*5c591343SA. Cody Schuffelen TimeFillInfo(&timeInfo.clockInfo);
252*5c591343SA. Cody Schuffelen
253*5c591343SA. Cody Schuffelen // Marshal TPMS_TIME_INFO to canonical form
254*5c591343SA. Cody Schuffelen return TPMS_TIME_INFO_Marshal(&timeInfo, (BYTE **)&dataBuffer, NULL);
255*5c591343SA. Cody Schuffelen }
256*5c591343SA. Cody Schuffelen
257*5c591343SA. Cody Schuffelen //*** TimeFillInfo
258*5c591343SA. Cody Schuffelen // This function gathers information to fill in a TPMS_CLOCK_INFO structure.
259*5c591343SA. Cody Schuffelen void
TimeFillInfo(TPMS_CLOCK_INFO * clockInfo)260*5c591343SA. Cody Schuffelen TimeFillInfo(
261*5c591343SA. Cody Schuffelen TPMS_CLOCK_INFO *clockInfo
262*5c591343SA. Cody Schuffelen )
263*5c591343SA. Cody Schuffelen {
264*5c591343SA. Cody Schuffelen clockInfo->clock = go.clock;
265*5c591343SA. Cody Schuffelen clockInfo->resetCount = gp.resetCount;
266*5c591343SA. Cody Schuffelen clockInfo->restartCount = gr.restartCount;
267*5c591343SA. Cody Schuffelen
268*5c591343SA. Cody Schuffelen // If NV is not available, clock stopped advancing and the value reported is
269*5c591343SA. Cody Schuffelen // not "safe".
270*5c591343SA. Cody Schuffelen if(NV_IS_AVAILABLE)
271*5c591343SA. Cody Schuffelen clockInfo->safe = go.clockSafe;
272*5c591343SA. Cody Schuffelen else
273*5c591343SA. Cody Schuffelen clockInfo->safe = NO;
274*5c591343SA. Cody Schuffelen
275*5c591343SA. Cody Schuffelen return;
276*5c591343SA. Cody Schuffelen }