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
22 * other 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 //** Introduction
36 // This code implements the ACT update code. It does not use a mutex. This code uses
37 // a platform service (_plat__ACT_UpdateCounter()) that returns 'false' if the update
38 // is not accepted. If this occurs, then TPM_RC_RETRY should be sent to the caller so
39 // that they can retry the operation later. The implementation of this is platform
40 // dependent but the reference uses a simple flag to indicate that an update is
41 // pending and the only process that can clear that flag is the process that does the
42 // actual update.
43
44 //** Includes
45 #include "Tpm.h"
46 #include "ACT_spt_fp.h"
47 #include "Platform_fp.h"
48
49 //** Functions
50
51 //*** _ActResume()
52 // This function does the resume processing for an ACT. It updates the saved count
53 // and turns signaling back on if necessary.
54 static void
_ActResume(UINT32 act,ACT_STATE * actData)55 _ActResume(
56 UINT32 act, //IN: the act number
57 ACT_STATE *actData //IN: pointer to the saved ACT data
58 )
59 {
60 // If the act was non-zero, then restore the counter value.
61 if(actData->remaining > 0)
62 _plat__ACT_UpdateCounter(act, actData->remaining);
63 // if the counter was zero and the ACT signaling, enable the signaling.
64 else if(go.signaledACT & (1 << act))
65 _plat__ACT_SetSignaled(act, TRUE);
66 }
67
68 //*** ActStartup()
69 // This function is called by TPM2_Startup() to initialize the ACT counter values.
70 BOOL
ActStartup(STARTUP_TYPE type)71 ActStartup(
72 STARTUP_TYPE type
73 )
74 {
75 // Reset all the ACT hardware
76 _plat__ACT_Initialize();
77
78 // If this not a cold start, copy all the current 'signaled' settings to
79 // 'preservedSignaled'.
80 if (g_powerWasLost)
81 go.preservedSignaled = 0;
82 else
83 go.preservedSignaled |= go.signaledACT;
84
85 // For TPM_RESET or TPM_RESTART, the ACTs will all be disabled and the output
86 // de-asserted.
87 if(type != SU_RESUME)
88 {
89 go.signaledACT = 0;
90 #define CLEAR_ACT_POLICY(N) \
91 go.ACT_##N.hashAlg = TPM_ALG_NULL; \
92 go.ACT_##N.authPolicy.b.size = 0;
93 FOR_EACH_ACT(CLEAR_ACT_POLICY)
94 }
95 else
96 {
97 // Resume each of the implemented ACT
98 #define RESUME_ACT(N) _ActResume(0x##N, &go.ACT_##N);
99
100 FOR_EACH_ACT(RESUME_ACT)
101 }
102 // set no ACT updated since last startup. This is to enable the halving of the
103 // timeout value
104 s_ActUpdated = 0;
105 _plat__ACT_EnableTicks(TRUE);
106 return TRUE;
107 }
108
109 //*** _ActSaveState()
110 // Get the counter state and the signaled state for an ACT. If the ACT has not been
111 // updated since the last time it was saved, then divide the count by 2.
112 static void
_ActSaveState(UINT32 act,P_ACT_STATE actData)113 _ActSaveState(
114 UINT32 act,
115 P_ACT_STATE actData
116 )
117 {
118 actData->remaining = _plat__ACT_GetRemaining(act);
119 // If the ACT hasn't been updated since the last startup, then it should be
120 // be halved.
121 if((s_ActUpdated & (1 << act)) == 0)
122 {
123 // Don't halve if the count is set to max or if halving would make it zero
124 if((actData->remaining != UINT32_MAX) && (actData->remaining > 1))
125 actData->remaining /= 2;
126 }
127 if(_plat__ACT_GetSignaled(act))
128 go.signaledACT |= (1 << act);
129 }
130
131 //*** ActGetSignaled()
132 // This function returns the state of the signaled flag associated with an ACT.
133 BOOL
ActGetSignaled(TPM_RH actHandle)134 ActGetSignaled(
135 TPM_RH actHandle
136 )
137 {
138 UINT32 act = actHandle - TPM_RH_ACT_0;
139 //
140 return _plat__ACT_GetSignaled(act);
141 }
142
143 //***ActShutdown()
144 // This function saves the current state of the counters
145 BOOL
ActShutdown(TPM_SU state)146 ActShutdown(
147 TPM_SU state //IN: the type of the shutdown.
148 )
149 {
150 // if this is not shutdown state, then the only type of startup is TPM_RESTART
151 // so the timer values will be cleared. If this is shutdown state, get the current
152 // countdown and signaled values. Plus, if the counter has not been updated
153 // since the last restart, divide the time by 2 so that there is no attack on the
154 // countdown by saving the countdown state early and then not using the TPM.
155 if(state == TPM_SU_STATE)
156 {
157 // This will be populated as each of the ACT is queried
158 go.signaledACT = 0;
159 // Get the current count and the signaled state
160 #define SAVE_ACT_STATE(N) _ActSaveState(0x##N, &go.ACT_##N);
161
162 FOR_EACH_ACT(SAVE_ACT_STATE);
163 }
164 return TRUE;
165 }
166
167
168 //*** ActIsImplemented()
169 // This function determines if an ACT is implemented in both the TPM and the platform
170 // code.
171 BOOL
ActIsImplemented(UINT32 act)172 ActIsImplemented(
173 UINT32 act
174 )
175 {
176 // This switch accounts for the TPM implemented values.
177 switch(act)
178 {
179 FOR_EACH_ACT(CASE_ACT_NUMBER)
180 // This ensures that the platform implements the values implemented by
181 // the TPM
182 return _plat__ACT_GetImplemented(act);
183 default:
184 break;
185 }
186 return FALSE;
187 }
188
189 //***ActCounterUpdate()
190 // This function updates the ACT counter. If the counter already has a pending update,
191 // it returns TPM_RC_RETRY so that the update can be tried again later.
192 TPM_RC
ActCounterUpdate(TPM_RH handle,UINT32 newValue)193 ActCounterUpdate(
194 TPM_RH handle, //IN: the handle of the act
195 UINT32 newValue //IN: the value to set in the ACT
196 )
197 {
198 UINT32 act;
199 TPM_RC result;
200 //
201 act = handle - TPM_RH_ACT_0;
202 // This should never fail, but...
203 if(!_plat__ACT_GetImplemented(act))
204 result = TPM_RC_VALUE;
205 else
206 {
207 // Will need to clear orderly so fail if we are orderly and NV is
208 // not available
209 if(NV_IS_ORDERLY)
210 RETURN_IF_NV_IS_NOT_AVAILABLE;
211 // if the attempt to update the counter fails, it means that there is an
212 // update pending so wait until it has occurred and then do an update.
213 if(!_plat__ACT_UpdateCounter(act, newValue))
214 result = TPM_RC_RETRY;
215 else
216 {
217 // Indicate that the ACT has been updated since last TPM2_Startup().
218 s_ActUpdated |= (UINT16)(1 << act);
219
220 // Clear the preservedSignaled attribute.
221 go.preservedSignaled &= ~((UINT16)(1 << act));
222
223 // Need to clear the orderly flag
224 g_clearOrderly = TRUE;
225
226 result = TPM_RC_SUCCESS;
227 }
228 }
229 return result;
230 }
231
232
233 //*** ActGetCapabilityData()
234 // This function returns the list of ACT data
235 // Return Type: TPMI_YES_NO
236 // YES if more ACT data is available
237 // NO if no more ACT data to
238 TPMI_YES_NO
ActGetCapabilityData(TPM_HANDLE actHandle,UINT32 maxCount,TPML_ACT_DATA * actList)239 ActGetCapabilityData(
240 TPM_HANDLE actHandle, // IN: the handle for the starting ACT
241 UINT32 maxCount, // IN: maximum allowed return values
242 TPML_ACT_DATA *actList // OUT: ACT data list
243 )
244 {
245 // Initialize output property list
246 actList->count = 0;
247
248 // Make sure that the starting handle value is in range (again)
249 if((actHandle < TPM_RH_ACT_0) || (actHandle > TPM_RH_ACT_F))
250 return FALSE;
251 // The maximum count of curves we may return is MAX_ECC_CURVES
252 if(maxCount > MAX_ACT_DATA)
253 maxCount = MAX_ACT_DATA;
254 // Scan the ACT data from the starting ACT
255 for(; actHandle <= TPM_RH_ACT_F; actHandle++)
256 {
257 UINT32 act = actHandle - TPM_RH_ACT_0;
258 if(actList->count < maxCount)
259 {
260 if(ActIsImplemented(act))
261 {
262 TPMS_ACT_DATA *actData = &actList->actData[actList->count];
263 //
264 memset(&actData->attributes, 0, sizeof(actData->attributes));
265 actData->handle = actHandle;
266 actData->timeout = _plat__ACT_GetRemaining(act);
267 if(_plat__ACT_GetSignaled(act))
268 SET_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled);
269 else
270 CLEAR_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled);
271 if (go.preservedSignaled & (1 << act))
272 SET_ATTRIBUTE(actData->attributes, TPMA_ACT, preserveSignaled);
273 actList->count++;
274 }
275 }
276 else
277 {
278 if(_plat__ACT_GetImplemented(act))
279 return YES;
280 }
281 }
282 // If we get here, either all of the ACT values were put in the list, or the list
283 // was filled and there are no more ACT values to return
284 return NO;
285 }
286
287
288
289