• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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