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 subsystem that process the authorization sessions
37*5c591343SA. Cody Schuffelen // including implementation of the Dictionary Attack logic. ExecCommand() uses
38*5c591343SA. Cody Schuffelen // ParseSessionBuffer() to process the authorization session area of a command and
39*5c591343SA. Cody Schuffelen // BuildResponseSession() to create the authorization session area of a response.
40*5c591343SA. Cody Schuffelen
41*5c591343SA. Cody Schuffelen //** Includes and Data Definitions
42*5c591343SA. Cody Schuffelen
43*5c591343SA. Cody Schuffelen #define SESSION_PROCESS_C
44*5c591343SA. Cody Schuffelen
45*5c591343SA. Cody Schuffelen #include "Tpm.h"
46*5c591343SA. Cody Schuffelen #include "ACT.h"
47*5c591343SA. Cody Schuffelen
48*5c591343SA. Cody Schuffelen //
49*5c591343SA. Cody Schuffelen //** Authorization Support Functions
50*5c591343SA. Cody Schuffelen //
51*5c591343SA. Cody Schuffelen
52*5c591343SA. Cody Schuffelen //*** IsDAExempted()
53*5c591343SA. Cody Schuffelen // This function indicates if a handle is exempted from DA logic.
54*5c591343SA. Cody Schuffelen // A handle is exempted if it is:
55*5c591343SA. Cody Schuffelen // a) a primary seed handle;
56*5c591343SA. Cody Schuffelen // b) an object with noDA bit SET;
57*5c591343SA. Cody Schuffelen // c) an NV Index with TPMA_NV_NO_DA bit SET; or
58*5c591343SA. Cody Schuffelen // d) a PCR handle.
59*5c591343SA. Cody Schuffelen //
60*5c591343SA. Cody Schuffelen // Return Type: BOOL
61*5c591343SA. Cody Schuffelen // TRUE(1) handle is exempted from DA logic
62*5c591343SA. Cody Schuffelen // FALSE(0) handle is not exempted from DA logic
63*5c591343SA. Cody Schuffelen BOOL
IsDAExempted(TPM_HANDLE handle)64*5c591343SA. Cody Schuffelen IsDAExempted(
65*5c591343SA. Cody Schuffelen TPM_HANDLE handle // IN: entity handle
66*5c591343SA. Cody Schuffelen )
67*5c591343SA. Cody Schuffelen {
68*5c591343SA. Cody Schuffelen BOOL result = FALSE;
69*5c591343SA. Cody Schuffelen //
70*5c591343SA. Cody Schuffelen switch(HandleGetType(handle))
71*5c591343SA. Cody Schuffelen {
72*5c591343SA. Cody Schuffelen case TPM_HT_PERMANENT:
73*5c591343SA. Cody Schuffelen // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from
74*5c591343SA. Cody Schuffelen // DA protection.
75*5c591343SA. Cody Schuffelen result = (handle != TPM_RH_LOCKOUT);
76*5c591343SA. Cody Schuffelen break;
77*5c591343SA. Cody Schuffelen // When this function is called, a persistent object will have been loaded
78*5c591343SA. Cody Schuffelen // into an object slot and assigned a transient handle.
79*5c591343SA. Cody Schuffelen case TPM_HT_TRANSIENT:
80*5c591343SA. Cody Schuffelen {
81*5c591343SA. Cody Schuffelen TPMA_OBJECT attributes = ObjectGetPublicAttributes(handle);
82*5c591343SA. Cody Schuffelen result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA);
83*5c591343SA. Cody Schuffelen break;
84*5c591343SA. Cody Schuffelen }
85*5c591343SA. Cody Schuffelen case TPM_HT_NV_INDEX:
86*5c591343SA. Cody Schuffelen {
87*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
88*5c591343SA. Cody Schuffelen result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA);
89*5c591343SA. Cody Schuffelen break;
90*5c591343SA. Cody Schuffelen }
91*5c591343SA. Cody Schuffelen case TPM_HT_PCR:
92*5c591343SA. Cody Schuffelen // PCRs are always exempted from DA.
93*5c591343SA. Cody Schuffelen result = TRUE;
94*5c591343SA. Cody Schuffelen break;
95*5c591343SA. Cody Schuffelen default:
96*5c591343SA. Cody Schuffelen break;
97*5c591343SA. Cody Schuffelen }
98*5c591343SA. Cody Schuffelen return result;
99*5c591343SA. Cody Schuffelen }
100*5c591343SA. Cody Schuffelen
101*5c591343SA. Cody Schuffelen //*** IncrementLockout()
102*5c591343SA. Cody Schuffelen // This function is called after an authorization failure that involves use of
103*5c591343SA. Cody Schuffelen // an authValue. If the entity referenced by the handle is not exempt from DA
104*5c591343SA. Cody Schuffelen // protection, then the failedTries counter will be incremented.
105*5c591343SA. Cody Schuffelen //
106*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
107*5c591343SA. Cody Schuffelen // TPM_RC_AUTH_FAIL authorization failure that caused DA lockout to increment
108*5c591343SA. Cody Schuffelen // TPM_RC_BAD_AUTH authorization failure did not cause DA lockout to
109*5c591343SA. Cody Schuffelen // increment
110*5c591343SA. Cody Schuffelen static TPM_RC
IncrementLockout(UINT32 sessionIndex)111*5c591343SA. Cody Schuffelen IncrementLockout(
112*5c591343SA. Cody Schuffelen UINT32 sessionIndex
113*5c591343SA. Cody Schuffelen )
114*5c591343SA. Cody Schuffelen {
115*5c591343SA. Cody Schuffelen TPM_HANDLE handle = s_associatedHandles[sessionIndex];
116*5c591343SA. Cody Schuffelen TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex];
117*5c591343SA. Cody Schuffelen SESSION *session = NULL;
118*5c591343SA. Cody Schuffelen //
119*5c591343SA. Cody Schuffelen // Don't increment lockout unless the handle associated with the session
120*5c591343SA. Cody Schuffelen // is DA protected or the session is bound to a DA protected entity.
121*5c591343SA. Cody Schuffelen if(sessionHandle == TPM_RS_PW)
122*5c591343SA. Cody Schuffelen {
123*5c591343SA. Cody Schuffelen if(IsDAExempted(handle))
124*5c591343SA. Cody Schuffelen return TPM_RC_BAD_AUTH;
125*5c591343SA. Cody Schuffelen }
126*5c591343SA. Cody Schuffelen else
127*5c591343SA. Cody Schuffelen {
128*5c591343SA. Cody Schuffelen session = SessionGet(sessionHandle);
129*5c591343SA. Cody Schuffelen // If the session is bound to lockout, then use that as the relevant
130*5c591343SA. Cody Schuffelen // handle. This means that an authorization failure with a bound session
131*5c591343SA. Cody Schuffelen // bound to lockoutAuth will take precedence over any other
132*5c591343SA. Cody Schuffelen // lockout check
133*5c591343SA. Cody Schuffelen if(session->attributes.isLockoutBound == SET)
134*5c591343SA. Cody Schuffelen handle = TPM_RH_LOCKOUT;
135*5c591343SA. Cody Schuffelen if(session->attributes.isDaBound == CLEAR
136*5c591343SA. Cody Schuffelen && (IsDAExempted(handle) || session->attributes.includeAuth == CLEAR))
137*5c591343SA. Cody Schuffelen // If the handle was changed to TPM_RH_LOCKOUT, this will not return
138*5c591343SA. Cody Schuffelen // TPM_RC_BAD_AUTH
139*5c591343SA. Cody Schuffelen return TPM_RC_BAD_AUTH;
140*5c591343SA. Cody Schuffelen }
141*5c591343SA. Cody Schuffelen if(handle == TPM_RH_LOCKOUT)
142*5c591343SA. Cody Schuffelen {
143*5c591343SA. Cody Schuffelen pAssert(gp.lockOutAuthEnabled == TRUE);
144*5c591343SA. Cody Schuffelen
145*5c591343SA. Cody Schuffelen // lockout is no longer enabled
146*5c591343SA. Cody Schuffelen gp.lockOutAuthEnabled = FALSE;
147*5c591343SA. Cody Schuffelen
148*5c591343SA. Cody Schuffelen // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since
149*5c591343SA. Cody Schuffelen // the lockout authorization will be reset at startup.
150*5c591343SA. Cody Schuffelen if(gp.lockoutRecovery != 0)
151*5c591343SA. Cody Schuffelen {
152*5c591343SA. Cody Schuffelen if(NV_IS_AVAILABLE)
153*5c591343SA. Cody Schuffelen // Update NV.
154*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(lockOutAuthEnabled);
155*5c591343SA. Cody Schuffelen else
156*5c591343SA. Cody Schuffelen // No NV access for now. Put the TPM in pending mode.
157*5c591343SA. Cody Schuffelen s_DAPendingOnNV = TRUE;
158*5c591343SA. Cody Schuffelen }
159*5c591343SA. Cody Schuffelen }
160*5c591343SA. Cody Schuffelen else
161*5c591343SA. Cody Schuffelen {
162*5c591343SA. Cody Schuffelen if(gp.recoveryTime != 0)
163*5c591343SA. Cody Schuffelen {
164*5c591343SA. Cody Schuffelen gp.failedTries++;
165*5c591343SA. Cody Schuffelen if(NV_IS_AVAILABLE)
166*5c591343SA. Cody Schuffelen // Record changes to NV. NvWrite will SET g_updateNV
167*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(failedTries);
168*5c591343SA. Cody Schuffelen else
169*5c591343SA. Cody Schuffelen // No NV access for now. Put the TPM in pending mode.
170*5c591343SA. Cody Schuffelen s_DAPendingOnNV = TRUE;
171*5c591343SA. Cody Schuffelen }
172*5c591343SA. Cody Schuffelen }
173*5c591343SA. Cody Schuffelen // Register a DA failure and reset the timers.
174*5c591343SA. Cody Schuffelen DARegisterFailure(handle);
175*5c591343SA. Cody Schuffelen
176*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_FAIL;
177*5c591343SA. Cody Schuffelen }
178*5c591343SA. Cody Schuffelen
179*5c591343SA. Cody Schuffelen //*** IsSessionBindEntity()
180*5c591343SA. Cody Schuffelen // This function indicates if the entity associated with the handle is the entity,
181*5c591343SA. Cody Schuffelen // to which this session is bound. The binding would occur by making the "bind"
182*5c591343SA. Cody Schuffelen // parameter in TPM2_StartAuthSession() not equal to TPM_RH_NULL. The binding only
183*5c591343SA. Cody Schuffelen // occurs if the session is an HMAC session. The bind value is a combination of
184*5c591343SA. Cody Schuffelen // the Name and the authValue of the entity.
185*5c591343SA. Cody Schuffelen //
186*5c591343SA. Cody Schuffelen // Return Type: BOOL
187*5c591343SA. Cody Schuffelen // TRUE(1) handle points to the session start entity
188*5c591343SA. Cody Schuffelen // FALSE(0) handle does not point to the session start entity
189*5c591343SA. Cody Schuffelen static BOOL
IsSessionBindEntity(TPM_HANDLE associatedHandle,SESSION * session)190*5c591343SA. Cody Schuffelen IsSessionBindEntity(
191*5c591343SA. Cody Schuffelen TPM_HANDLE associatedHandle, // IN: handle to be authorized
192*5c591343SA. Cody Schuffelen SESSION *session // IN: associated session
193*5c591343SA. Cody Schuffelen )
194*5c591343SA. Cody Schuffelen {
195*5c591343SA. Cody Schuffelen TPM2B_NAME entity; // The bind value for the entity
196*5c591343SA. Cody Schuffelen //
197*5c591343SA. Cody Schuffelen // If the session is not bound, return FALSE.
198*5c591343SA. Cody Schuffelen if(session->attributes.isBound)
199*5c591343SA. Cody Schuffelen {
200*5c591343SA. Cody Schuffelen // Compute the bind value for the entity.
201*5c591343SA. Cody Schuffelen SessionComputeBoundEntity(associatedHandle, &entity);
202*5c591343SA. Cody Schuffelen
203*5c591343SA. Cody Schuffelen // Compare to the bind value in the session.
204*5c591343SA. Cody Schuffelen return MemoryEqual2B(&entity.b, &session->u1.boundEntity.b);
205*5c591343SA. Cody Schuffelen }
206*5c591343SA. Cody Schuffelen return FALSE;
207*5c591343SA. Cody Schuffelen }
208*5c591343SA. Cody Schuffelen
209*5c591343SA. Cody Schuffelen //*** IsPolicySessionRequired()
210*5c591343SA. Cody Schuffelen // Checks if a policy session is required for a command. If a command requires
211*5c591343SA. Cody Schuffelen // DUP or ADMIN role authorization, then the handle that requires that role is the
212*5c591343SA. Cody Schuffelen // first handle in the command. This simplifies this checking. If a new command
213*5c591343SA. Cody Schuffelen // is created that requires multiple ADMIN role authorizations, then it will
214*5c591343SA. Cody Schuffelen // have to be special-cased in this function.
215*5c591343SA. Cody Schuffelen // A policy session is required if:
216*5c591343SA. Cody Schuffelen // a) the command requires the DUP role;
217*5c591343SA. Cody Schuffelen // b) the command requires the ADMIN role and the authorized entity
218*5c591343SA. Cody Schuffelen // is an object and its adminWithPolicy bit is SET;
219*5c591343SA. Cody Schuffelen // c) the command requires the ADMIN role and the authorized entity
220*5c591343SA. Cody Schuffelen // is a permanent handle or an NV Index; or
221*5c591343SA. Cody Schuffelen // d) the authorized entity is a PCR belonging to a policy group, and
222*5c591343SA. Cody Schuffelen // has its policy initialized
223*5c591343SA. Cody Schuffelen // Return Type: BOOL
224*5c591343SA. Cody Schuffelen // TRUE(1) policy session is required
225*5c591343SA. Cody Schuffelen // FALSE(0) policy session is not required
226*5c591343SA. Cody Schuffelen static BOOL
IsPolicySessionRequired(COMMAND_INDEX commandIndex,UINT32 sessionIndex)227*5c591343SA. Cody Schuffelen IsPolicySessionRequired(
228*5c591343SA. Cody Schuffelen COMMAND_INDEX commandIndex, // IN: command index
229*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: session index
230*5c591343SA. Cody Schuffelen )
231*5c591343SA. Cody Schuffelen {
232*5c591343SA. Cody Schuffelen AUTH_ROLE role = CommandAuthRole(commandIndex, sessionIndex);
233*5c591343SA. Cody Schuffelen TPM_HT type = HandleGetType(s_associatedHandles[sessionIndex]);
234*5c591343SA. Cody Schuffelen //
235*5c591343SA. Cody Schuffelen if(role == AUTH_DUP)
236*5c591343SA. Cody Schuffelen return TRUE;
237*5c591343SA. Cody Schuffelen if(role == AUTH_ADMIN)
238*5c591343SA. Cody Schuffelen {
239*5c591343SA. Cody Schuffelen // We allow an exception for ADMIN role in a transient object. If the object
240*5c591343SA. Cody Schuffelen // allows ADMIN role actions with authorization, then policy is not
241*5c591343SA. Cody Schuffelen // required. For all other cases, there is no way to override the command
242*5c591343SA. Cody Schuffelen // requirement that a policy be used
243*5c591343SA. Cody Schuffelen if(type == TPM_HT_TRANSIENT)
244*5c591343SA. Cody Schuffelen {
245*5c591343SA. Cody Schuffelen OBJECT *object = HandleToObject(s_associatedHandles[sessionIndex]);
246*5c591343SA. Cody Schuffelen
247*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
248*5c591343SA. Cody Schuffelen adminWithPolicy))
249*5c591343SA. Cody Schuffelen return FALSE;
250*5c591343SA. Cody Schuffelen }
251*5c591343SA. Cody Schuffelen return TRUE;
252*5c591343SA. Cody Schuffelen }
253*5c591343SA. Cody Schuffelen
254*5c591343SA. Cody Schuffelen if(type == TPM_HT_PCR)
255*5c591343SA. Cody Schuffelen {
256*5c591343SA. Cody Schuffelen if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex]))
257*5c591343SA. Cody Schuffelen {
258*5c591343SA. Cody Schuffelen TPM2B_DIGEST policy;
259*5c591343SA. Cody Schuffelen TPMI_ALG_HASH policyAlg;
260*5c591343SA. Cody Schuffelen policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex],
261*5c591343SA. Cody Schuffelen &policy);
262*5c591343SA. Cody Schuffelen if(policyAlg != TPM_ALG_NULL)
263*5c591343SA. Cody Schuffelen return TRUE;
264*5c591343SA. Cody Schuffelen }
265*5c591343SA. Cody Schuffelen }
266*5c591343SA. Cody Schuffelen return FALSE;
267*5c591343SA. Cody Schuffelen }
268*5c591343SA. Cody Schuffelen
269*5c591343SA. Cody Schuffelen //*** IsAuthValueAvailable()
270*5c591343SA. Cody Schuffelen // This function indicates if authValue is available and allowed for USER role
271*5c591343SA. Cody Schuffelen // authorization of an entity.
272*5c591343SA. Cody Schuffelen //
273*5c591343SA. Cody Schuffelen // This function is similar to IsAuthPolicyAvailable() except that it does not
274*5c591343SA. Cody Schuffelen // check the size of the authValue as IsAuthPolicyAvailable() does (a null
275*5c591343SA. Cody Schuffelen // authValue is a valid authorization, but a null policy is not a valid policy).
276*5c591343SA. Cody Schuffelen //
277*5c591343SA. Cody Schuffelen // This function does not check that the handle reference is valid or if the entity
278*5c591343SA. Cody Schuffelen // is in an enabled hierarchy. Those checks are assumed to have been performed
279*5c591343SA. Cody Schuffelen // during the handle unmarshaling.
280*5c591343SA. Cody Schuffelen //
281*5c591343SA. Cody Schuffelen // Return Type: BOOL
282*5c591343SA. Cody Schuffelen // TRUE(1) authValue is available
283*5c591343SA. Cody Schuffelen // FALSE(0) authValue is not available
284*5c591343SA. Cody Schuffelen static BOOL
IsAuthValueAvailable(TPM_HANDLE handle,COMMAND_INDEX commandIndex,UINT32 sessionIndex)285*5c591343SA. Cody Schuffelen IsAuthValueAvailable(
286*5c591343SA. Cody Schuffelen TPM_HANDLE handle, // IN: handle of entity
287*5c591343SA. Cody Schuffelen COMMAND_INDEX commandIndex, // IN: command index
288*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: session index
289*5c591343SA. Cody Schuffelen )
290*5c591343SA. Cody Schuffelen {
291*5c591343SA. Cody Schuffelen BOOL result = FALSE;
292*5c591343SA. Cody Schuffelen //
293*5c591343SA. Cody Schuffelen switch(HandleGetType(handle))
294*5c591343SA. Cody Schuffelen {
295*5c591343SA. Cody Schuffelen case TPM_HT_PERMANENT:
296*5c591343SA. Cody Schuffelen switch(handle)
297*5c591343SA. Cody Schuffelen {
298*5c591343SA. Cody Schuffelen // At this point hierarchy availability has already been
299*5c591343SA. Cody Schuffelen // checked so primary seed handles are always available here
300*5c591343SA. Cody Schuffelen case TPM_RH_OWNER:
301*5c591343SA. Cody Schuffelen case TPM_RH_ENDORSEMENT:
302*5c591343SA. Cody Schuffelen case TPM_RH_PLATFORM:
303*5c591343SA. Cody Schuffelen #ifdef VENDOR_PERMANENT
304*5c591343SA. Cody Schuffelen // This vendor defined handle associated with the
305*5c591343SA. Cody Schuffelen // manufacturer's shared secret
306*5c591343SA. Cody Schuffelen case VENDOR_PERMANENT:
307*5c591343SA. Cody Schuffelen #endif
308*5c591343SA. Cody Schuffelen // The DA checking has been performed on LockoutAuth but we
309*5c591343SA. Cody Schuffelen // bypass the DA logic if we are using lockout policy. The
310*5c591343SA. Cody Schuffelen // policy would allow execution to continue an lockoutAuth
311*5c591343SA. Cody Schuffelen // could be used, even if direct use of lockoutAuth is disabled
312*5c591343SA. Cody Schuffelen case TPM_RH_LOCKOUT:
313*5c591343SA. Cody Schuffelen // NullAuth is always available.
314*5c591343SA. Cody Schuffelen case TPM_RH_NULL:
315*5c591343SA. Cody Schuffelen result = TRUE;
316*5c591343SA. Cody Schuffelen break;
317*5c591343SA. Cody Schuffelen FOR_EACH_ACT(CASE_ACT_HANDLE)
318*5c591343SA. Cody Schuffelen {
319*5c591343SA. Cody Schuffelen // The ACT auth value is not available if the platform is disabled
320*5c591343SA. Cody Schuffelen result = g_phEnable == SET;
321*5c591343SA. Cody Schuffelen break;
322*5c591343SA. Cody Schuffelen }
323*5c591343SA. Cody Schuffelen default:
324*5c591343SA. Cody Schuffelen // Otherwise authValue is not available.
325*5c591343SA. Cody Schuffelen break;
326*5c591343SA. Cody Schuffelen }
327*5c591343SA. Cody Schuffelen break;
328*5c591343SA. Cody Schuffelen case TPM_HT_TRANSIENT:
329*5c591343SA. Cody Schuffelen // A persistent object has already been loaded and the internal
330*5c591343SA. Cody Schuffelen // handle changed.
331*5c591343SA. Cody Schuffelen {
332*5c591343SA. Cody Schuffelen OBJECT *object;
333*5c591343SA. Cody Schuffelen TPMA_OBJECT attributes;
334*5c591343SA. Cody Schuffelen //
335*5c591343SA. Cody Schuffelen object = HandleToObject(handle);
336*5c591343SA. Cody Schuffelen attributes = object->publicArea.objectAttributes;
337*5c591343SA. Cody Schuffelen
338*5c591343SA. Cody Schuffelen // authValue is always available for a sequence object.
339*5c591343SA. Cody Schuffelen // An alternative for this is to
340*5c591343SA. Cody Schuffelen // SET_ATTRIBUTE(object->publicArea, TPMA_OBJECT, userWithAuth) when the
341*5c591343SA. Cody Schuffelen // sequence is started.
342*5c591343SA. Cody Schuffelen if(ObjectIsSequence(object))
343*5c591343SA. Cody Schuffelen {
344*5c591343SA. Cody Schuffelen result = TRUE;
345*5c591343SA. Cody Schuffelen break;
346*5c591343SA. Cody Schuffelen }
347*5c591343SA. Cody Schuffelen // authValue is available for an object if it has its sensitive
348*5c591343SA. Cody Schuffelen // portion loaded and
349*5c591343SA. Cody Schuffelen // a) userWithAuth bit is SET, or
350*5c591343SA. Cody Schuffelen // b) ADMIN role is required
351*5c591343SA. Cody Schuffelen if(object->attributes.publicOnly == CLEAR
352*5c591343SA. Cody Schuffelen && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth)
353*5c591343SA. Cody Schuffelen || (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN
354*5c591343SA. Cody Schuffelen && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, adminWithPolicy))))
355*5c591343SA. Cody Schuffelen result = TRUE;
356*5c591343SA. Cody Schuffelen }
357*5c591343SA. Cody Schuffelen break;
358*5c591343SA. Cody Schuffelen case TPM_HT_NV_INDEX:
359*5c591343SA. Cody Schuffelen // NV Index.
360*5c591343SA. Cody Schuffelen {
361*5c591343SA. Cody Schuffelen NV_REF locator;
362*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex = NvGetIndexInfo(handle, &locator);
363*5c591343SA. Cody Schuffelen TPMA_NV nvAttributes;
364*5c591343SA. Cody Schuffelen //
365*5c591343SA. Cody Schuffelen pAssert(nvIndex != 0);
366*5c591343SA. Cody Schuffelen
367*5c591343SA. Cody Schuffelen nvAttributes = nvIndex->publicArea.attributes;
368*5c591343SA. Cody Schuffelen
369*5c591343SA. Cody Schuffelen if(IsWriteOperation(commandIndex))
370*5c591343SA. Cody Schuffelen {
371*5c591343SA. Cody Schuffelen // AuthWrite can't be set for a PIN index
372*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE))
373*5c591343SA. Cody Schuffelen result = TRUE;
374*5c591343SA. Cody Schuffelen }
375*5c591343SA. Cody Schuffelen else
376*5c591343SA. Cody Schuffelen {
377*5c591343SA. Cody Schuffelen // A "read" operation
378*5c591343SA. Cody Schuffelen // For a PIN Index, the authValue is available as long as the
379*5c591343SA. Cody Schuffelen // Index has been written and the pinCount is less than pinLimit
380*5c591343SA. Cody Schuffelen if(IsNvPinFailIndex(nvAttributes)
381*5c591343SA. Cody Schuffelen || IsNvPinPassIndex(nvAttributes))
382*5c591343SA. Cody Schuffelen {
383*5c591343SA. Cody Schuffelen NV_PIN pin;
384*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
385*5c591343SA. Cody Schuffelen break; // return false
386*5c591343SA. Cody Schuffelen // get the index values
387*5c591343SA. Cody Schuffelen pin.intVal = NvGetUINT64Data(nvIndex, locator);
388*5c591343SA. Cody Schuffelen if(pin.pin.pinCount < pin.pin.pinLimit)
389*5c591343SA. Cody Schuffelen result = TRUE;
390*5c591343SA. Cody Schuffelen }
391*5c591343SA. Cody Schuffelen // For non-PIN Indexes, need to allow use of the authValue
392*5c591343SA. Cody Schuffelen else if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD))
393*5c591343SA. Cody Schuffelen result = TRUE;
394*5c591343SA. Cody Schuffelen }
395*5c591343SA. Cody Schuffelen }
396*5c591343SA. Cody Schuffelen break;
397*5c591343SA. Cody Schuffelen case TPM_HT_PCR:
398*5c591343SA. Cody Schuffelen // PCR handle.
399*5c591343SA. Cody Schuffelen // authValue is always allowed for PCR
400*5c591343SA. Cody Schuffelen result = TRUE;
401*5c591343SA. Cody Schuffelen break;
402*5c591343SA. Cody Schuffelen default:
403*5c591343SA. Cody Schuffelen // Otherwise, authValue is not available
404*5c591343SA. Cody Schuffelen break;
405*5c591343SA. Cody Schuffelen }
406*5c591343SA. Cody Schuffelen return result;
407*5c591343SA. Cody Schuffelen }
408*5c591343SA. Cody Schuffelen
409*5c591343SA. Cody Schuffelen //*** IsAuthPolicyAvailable()
410*5c591343SA. Cody Schuffelen // This function indicates if an authPolicy is available and allowed.
411*5c591343SA. Cody Schuffelen //
412*5c591343SA. Cody Schuffelen // This function does not check that the handle reference is valid or if the entity
413*5c591343SA. Cody Schuffelen // is in an enabled hierarchy. Those checks are assumed to have been performed
414*5c591343SA. Cody Schuffelen // during the handle unmarshaling.
415*5c591343SA. Cody Schuffelen //
416*5c591343SA. Cody Schuffelen // Return Type: BOOL
417*5c591343SA. Cody Schuffelen // TRUE(1) authPolicy is available
418*5c591343SA. Cody Schuffelen // FALSE(0) authPolicy is not available
419*5c591343SA. Cody Schuffelen static BOOL
IsAuthPolicyAvailable(TPM_HANDLE handle,COMMAND_INDEX commandIndex,UINT32 sessionIndex)420*5c591343SA. Cody Schuffelen IsAuthPolicyAvailable(
421*5c591343SA. Cody Schuffelen TPM_HANDLE handle, // IN: handle of entity
422*5c591343SA. Cody Schuffelen COMMAND_INDEX commandIndex, // IN: command index
423*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: session index
424*5c591343SA. Cody Schuffelen )
425*5c591343SA. Cody Schuffelen {
426*5c591343SA. Cody Schuffelen BOOL result = FALSE;
427*5c591343SA. Cody Schuffelen //
428*5c591343SA. Cody Schuffelen switch(HandleGetType(handle))
429*5c591343SA. Cody Schuffelen {
430*5c591343SA. Cody Schuffelen case TPM_HT_PERMANENT:
431*5c591343SA. Cody Schuffelen switch(handle)
432*5c591343SA. Cody Schuffelen {
433*5c591343SA. Cody Schuffelen // At this point hierarchy availability has already been checked.
434*5c591343SA. Cody Schuffelen case TPM_RH_OWNER:
435*5c591343SA. Cody Schuffelen if(gp.ownerPolicy.t.size != 0)
436*5c591343SA. Cody Schuffelen result = TRUE;
437*5c591343SA. Cody Schuffelen break;
438*5c591343SA. Cody Schuffelen case TPM_RH_ENDORSEMENT:
439*5c591343SA. Cody Schuffelen if(gp.endorsementPolicy.t.size != 0)
440*5c591343SA. Cody Schuffelen result = TRUE;
441*5c591343SA. Cody Schuffelen break;
442*5c591343SA. Cody Schuffelen case TPM_RH_PLATFORM:
443*5c591343SA. Cody Schuffelen if(gc.platformPolicy.t.size != 0)
444*5c591343SA. Cody Schuffelen result = TRUE;
445*5c591343SA. Cody Schuffelen break;
446*5c591343SA. Cody Schuffelen #define ACT_GET_POLICY(N) \
447*5c591343SA. Cody Schuffelen case TPM_RH_ACT_##N: \
448*5c591343SA. Cody Schuffelen if(go.ACT_##N.authPolicy.t.size != 0) \
449*5c591343SA. Cody Schuffelen result = TRUE; \
450*5c591343SA. Cody Schuffelen break;
451*5c591343SA. Cody Schuffelen
452*5c591343SA. Cody Schuffelen FOR_EACH_ACT(ACT_GET_POLICY)
453*5c591343SA. Cody Schuffelen
454*5c591343SA. Cody Schuffelen case TPM_RH_LOCKOUT:
455*5c591343SA. Cody Schuffelen if(gp.lockoutPolicy.t.size != 0)
456*5c591343SA. Cody Schuffelen result = TRUE;
457*5c591343SA. Cody Schuffelen break;
458*5c591343SA. Cody Schuffelen default:
459*5c591343SA. Cody Schuffelen break;
460*5c591343SA. Cody Schuffelen }
461*5c591343SA. Cody Schuffelen break;
462*5c591343SA. Cody Schuffelen case TPM_HT_TRANSIENT:
463*5c591343SA. Cody Schuffelen {
464*5c591343SA. Cody Schuffelen // Object handle.
465*5c591343SA. Cody Schuffelen // An evict object would already have been loaded and given a
466*5c591343SA. Cody Schuffelen // transient object handle by this point.
467*5c591343SA. Cody Schuffelen OBJECT *object = HandleToObject(handle);
468*5c591343SA. Cody Schuffelen // Policy authorization is not available for an object with only
469*5c591343SA. Cody Schuffelen // public portion loaded.
470*5c591343SA. Cody Schuffelen if(object->attributes.publicOnly == CLEAR)
471*5c591343SA. Cody Schuffelen {
472*5c591343SA. Cody Schuffelen // Policy authorization is always available for an object but
473*5c591343SA. Cody Schuffelen // is never available for a sequence.
474*5c591343SA. Cody Schuffelen if(!ObjectIsSequence(object))
475*5c591343SA. Cody Schuffelen result = TRUE;
476*5c591343SA. Cody Schuffelen }
477*5c591343SA. Cody Schuffelen break;
478*5c591343SA. Cody Schuffelen }
479*5c591343SA. Cody Schuffelen case TPM_HT_NV_INDEX:
480*5c591343SA. Cody Schuffelen // An NV Index.
481*5c591343SA. Cody Schuffelen {
482*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
483*5c591343SA. Cody Schuffelen TPMA_NV nvAttributes = nvIndex->publicArea.attributes;
484*5c591343SA. Cody Schuffelen //
485*5c591343SA. Cody Schuffelen // If the policy size is not zero, check if policy can be used.
486*5c591343SA. Cody Schuffelen if(nvIndex->publicArea.authPolicy.t.size != 0)
487*5c591343SA. Cody Schuffelen {
488*5c591343SA. Cody Schuffelen // If policy session is required for this handle, always
489*5c591343SA. Cody Schuffelen // uses policy regardless of the attributes bit setting
490*5c591343SA. Cody Schuffelen if(IsPolicySessionRequired(commandIndex, sessionIndex))
491*5c591343SA. Cody Schuffelen result = TRUE;
492*5c591343SA. Cody Schuffelen // Otherwise, the presence of the policy depends on the NV
493*5c591343SA. Cody Schuffelen // attributes.
494*5c591343SA. Cody Schuffelen else if(IsWriteOperation(commandIndex))
495*5c591343SA. Cody Schuffelen {
496*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE))
497*5c591343SA. Cody Schuffelen result = TRUE;
498*5c591343SA. Cody Schuffelen }
499*5c591343SA. Cody Schuffelen else
500*5c591343SA. Cody Schuffelen {
501*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD))
502*5c591343SA. Cody Schuffelen result = TRUE;
503*5c591343SA. Cody Schuffelen }
504*5c591343SA. Cody Schuffelen }
505*5c591343SA. Cody Schuffelen }
506*5c591343SA. Cody Schuffelen break;
507*5c591343SA. Cody Schuffelen case TPM_HT_PCR:
508*5c591343SA. Cody Schuffelen // PCR handle.
509*5c591343SA. Cody Schuffelen if(PCRPolicyIsAvailable(handle))
510*5c591343SA. Cody Schuffelen result = TRUE;
511*5c591343SA. Cody Schuffelen break;
512*5c591343SA. Cody Schuffelen default:
513*5c591343SA. Cody Schuffelen break;
514*5c591343SA. Cody Schuffelen }
515*5c591343SA. Cody Schuffelen return result;
516*5c591343SA. Cody Schuffelen }
517*5c591343SA. Cody Schuffelen
518*5c591343SA. Cody Schuffelen //** Session Parsing Functions
519*5c591343SA. Cody Schuffelen
520*5c591343SA. Cody Schuffelen //*** ClearCpRpHashes()
521*5c591343SA. Cody Schuffelen void
ClearCpRpHashes(COMMAND * command)522*5c591343SA. Cody Schuffelen ClearCpRpHashes(
523*5c591343SA. Cody Schuffelen COMMAND *command
524*5c591343SA. Cody Schuffelen )
525*5c591343SA. Cody Schuffelen {
526*5c591343SA. Cody Schuffelen // The macros expand according to the implemented hash algorithms. An IDE may
527*5c591343SA. Cody Schuffelen // complain that COMMAND does not contain SHA1CpHash or SHA1RpHash because of the
528*5c591343SA. Cody Schuffelen // complexity of the macro expansion where the data space is defined; but, if SHA1
529*5c591343SA. Cody Schuffelen // is implemented, it actually does and the compiler is happy.
530*5c591343SA. Cody Schuffelen #define CLEAR_CP_HASH(HASH, Hash) command->Hash##CpHash.b.size = 0;
531*5c591343SA. Cody Schuffelen FOR_EACH_HASH(CLEAR_CP_HASH)
532*5c591343SA. Cody Schuffelen #define CLEAR_RP_HASH(HASH, Hash) command->Hash##RpHash.b.size = 0;
533*5c591343SA. Cody Schuffelen FOR_EACH_HASH(CLEAR_RP_HASH)
534*5c591343SA. Cody Schuffelen }
535*5c591343SA. Cody Schuffelen
536*5c591343SA. Cody Schuffelen
537*5c591343SA. Cody Schuffelen //*** GetCpHashPointer()
538*5c591343SA. Cody Schuffelen // Function to get a pointer to the cpHash of the command
539*5c591343SA. Cody Schuffelen static TPM2B_DIGEST *
GetCpHashPointer(COMMAND * command,TPMI_ALG_HASH hashAlg)540*5c591343SA. Cody Schuffelen GetCpHashPointer(
541*5c591343SA. Cody Schuffelen COMMAND *command,
542*5c591343SA. Cody Schuffelen TPMI_ALG_HASH hashAlg
543*5c591343SA. Cody Schuffelen )
544*5c591343SA. Cody Schuffelen {
545*5c591343SA. Cody Schuffelen TPM2B_DIGEST *retVal;
546*5c591343SA. Cody Schuffelen //
547*5c591343SA. Cody Schuffelen // Define the macro that will expand for each implemented algorithm in the switch
548*5c591343SA. Cody Schuffelen // statement below.
549*5c591343SA. Cody Schuffelen #define GET_CP_HASH_POINTER(HASH, Hash) \
550*5c591343SA. Cody Schuffelen case ALG_##HASH##_VALUE: \
551*5c591343SA. Cody Schuffelen retVal = (TPM2B_DIGEST *)&command->Hash##CpHash; \
552*5c591343SA. Cody Schuffelen break;
553*5c591343SA. Cody Schuffelen
554*5c591343SA. Cody Schuffelen switch(hashAlg)
555*5c591343SA. Cody Schuffelen {
556*5c591343SA. Cody Schuffelen // For each implemented hash, this will expand as defined above
557*5c591343SA. Cody Schuffelen // by GET_CP_HASH_POINTER. Your IDE may complain that
558*5c591343SA. Cody Schuffelen // 'struct "COMMAND" has no field "SHA1CpHash"' but the compiler says
559*5c591343SA. Cody Schuffelen // it does, so...
560*5c591343SA. Cody Schuffelen FOR_EACH_HASH(GET_CP_HASH_POINTER)
561*5c591343SA. Cody Schuffelen default:
562*5c591343SA. Cody Schuffelen retVal = NULL;
563*5c591343SA. Cody Schuffelen break;
564*5c591343SA. Cody Schuffelen }
565*5c591343SA. Cody Schuffelen return retVal;
566*5c591343SA. Cody Schuffelen }
567*5c591343SA. Cody Schuffelen
568*5c591343SA. Cody Schuffelen //*** GetRpHashPointer()
569*5c591343SA. Cody Schuffelen // Function to get a pointer to the RpHash of the command
570*5c591343SA. Cody Schuffelen static TPM2B_DIGEST *
GetRpHashPointer(COMMAND * command,TPMI_ALG_HASH hashAlg)571*5c591343SA. Cody Schuffelen GetRpHashPointer(
572*5c591343SA. Cody Schuffelen COMMAND *command,
573*5c591343SA. Cody Schuffelen TPMI_ALG_HASH hashAlg
574*5c591343SA. Cody Schuffelen )
575*5c591343SA. Cody Schuffelen {
576*5c591343SA. Cody Schuffelen TPM2B_DIGEST *retVal;
577*5c591343SA. Cody Schuffelen //
578*5c591343SA. Cody Schuffelen // Define the macro that will expand for each implemented algorithm in the switch
579*5c591343SA. Cody Schuffelen // statement below.
580*5c591343SA. Cody Schuffelen #define GET_RP_HASH_POINTER(HASH, Hash) \
581*5c591343SA. Cody Schuffelen case ALG_##HASH##_VALUE: \
582*5c591343SA. Cody Schuffelen retVal = (TPM2B_DIGEST *)&command->Hash##RpHash; \
583*5c591343SA. Cody Schuffelen break;
584*5c591343SA. Cody Schuffelen
585*5c591343SA. Cody Schuffelen switch(hashAlg)
586*5c591343SA. Cody Schuffelen {
587*5c591343SA. Cody Schuffelen // For each implemented hash, this will expand as defined above
588*5c591343SA. Cody Schuffelen // by GET_RP_HASH_POINTER. Your IDE may complain that
589*5c591343SA. Cody Schuffelen // 'struct "COMMAND" has no field 'SHA1RpHash'" but the compiler says
590*5c591343SA. Cody Schuffelen // it does, so...
591*5c591343SA. Cody Schuffelen FOR_EACH_HASH(GET_RP_HASH_POINTER)
592*5c591343SA. Cody Schuffelen default:
593*5c591343SA. Cody Schuffelen retVal = NULL;
594*5c591343SA. Cody Schuffelen break;
595*5c591343SA. Cody Schuffelen }
596*5c591343SA. Cody Schuffelen return retVal;
597*5c591343SA. Cody Schuffelen }
598*5c591343SA. Cody Schuffelen
599*5c591343SA. Cody Schuffelen
600*5c591343SA. Cody Schuffelen //*** ComputeCpHash()
601*5c591343SA. Cody Schuffelen // This function computes the cpHash as defined in Part 2 and described in Part 1.
602*5c591343SA. Cody Schuffelen static TPM2B_DIGEST *
ComputeCpHash(COMMAND * command,TPMI_ALG_HASH hashAlg)603*5c591343SA. Cody Schuffelen ComputeCpHash(
604*5c591343SA. Cody Schuffelen COMMAND *command, // IN: command parsing structure
605*5c591343SA. Cody Schuffelen TPMI_ALG_HASH hashAlg // IN: hash algorithm
606*5c591343SA. Cody Schuffelen )
607*5c591343SA. Cody Schuffelen {
608*5c591343SA. Cody Schuffelen UINT32 i;
609*5c591343SA. Cody Schuffelen HASH_STATE hashState;
610*5c591343SA. Cody Schuffelen TPM2B_NAME name;
611*5c591343SA. Cody Schuffelen TPM2B_DIGEST *cpHash;
612*5c591343SA. Cody Schuffelen //
613*5c591343SA. Cody Schuffelen // cpHash = hash(commandCode [ || authName1
614*5c591343SA. Cody Schuffelen // [ || authName2
615*5c591343SA. Cody Schuffelen // [ || authName 3 ]]]
616*5c591343SA. Cody Schuffelen // [ || parameters])
617*5c591343SA. Cody Schuffelen // A cpHash can contain just a commandCode only if the lone session is
618*5c591343SA. Cody Schuffelen // an audit session.
619*5c591343SA. Cody Schuffelen // Get pointer to the hash value
620*5c591343SA. Cody Schuffelen cpHash = GetCpHashPointer(command, hashAlg);
621*5c591343SA. Cody Schuffelen if(cpHash->t.size == 0)
622*5c591343SA. Cody Schuffelen {
623*5c591343SA. Cody Schuffelen cpHash->t.size = CryptHashStart(&hashState, hashAlg);
624*5c591343SA. Cody Schuffelen // Add commandCode.
625*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);
626*5c591343SA. Cody Schuffelen // Add authNames for each of the handles.
627*5c591343SA. Cody Schuffelen for(i = 0; i < command->handleNum; i++)
628*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],
629*5c591343SA. Cody Schuffelen &name)->b);
630*5c591343SA. Cody Schuffelen // Add the parameters.
631*5c591343SA. Cody Schuffelen CryptDigestUpdate(&hashState, command->parameterSize,
632*5c591343SA. Cody Schuffelen command->parameterBuffer);
633*5c591343SA. Cody Schuffelen // Complete the hash.
634*5c591343SA. Cody Schuffelen CryptHashEnd2B(&hashState, &cpHash->b);
635*5c591343SA. Cody Schuffelen }
636*5c591343SA. Cody Schuffelen return cpHash;
637*5c591343SA. Cody Schuffelen }
638*5c591343SA. Cody Schuffelen
639*5c591343SA. Cody Schuffelen //*** GetCpHash()
640*5c591343SA. Cody Schuffelen // This function is used to access a precomputed cpHash.
641*5c591343SA. Cody Schuffelen static TPM2B_DIGEST *
GetCpHash(COMMAND * command,TPMI_ALG_HASH hashAlg)642*5c591343SA. Cody Schuffelen GetCpHash(
643*5c591343SA. Cody Schuffelen COMMAND *command,
644*5c591343SA. Cody Schuffelen TPMI_ALG_HASH hashAlg
645*5c591343SA. Cody Schuffelen )
646*5c591343SA. Cody Schuffelen {
647*5c591343SA. Cody Schuffelen TPM2B_DIGEST *cpHash = GetCpHashPointer(command, hashAlg);
648*5c591343SA. Cody Schuffelen //
649*5c591343SA. Cody Schuffelen pAssert(cpHash->t.size != 0);
650*5c591343SA. Cody Schuffelen return cpHash;
651*5c591343SA. Cody Schuffelen }
652*5c591343SA. Cody Schuffelen
653*5c591343SA. Cody Schuffelen //*** CompareTemplateHash()
654*5c591343SA. Cody Schuffelen // This function computes the template hash and compares it to the session
655*5c591343SA. Cody Schuffelen // templateHash. It is the hash of the second parameter
656*5c591343SA. Cody Schuffelen // assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or
657*5c591343SA. Cody Schuffelen // TPM2_CreateLoaded()
658*5c591343SA. Cody Schuffelen // Return Type: BOOL
659*5c591343SA. Cody Schuffelen // TRUE(1) template hash equal to session->templateHash
660*5c591343SA. Cody Schuffelen // FALSE(0) template hash not equal to session->templateHash
661*5c591343SA. Cody Schuffelen static BOOL
CompareTemplateHash(COMMAND * command,SESSION * session)662*5c591343SA. Cody Schuffelen CompareTemplateHash(
663*5c591343SA. Cody Schuffelen COMMAND *command, // IN: parsing structure
664*5c591343SA. Cody Schuffelen SESSION *session // IN: session data
665*5c591343SA. Cody Schuffelen )
666*5c591343SA. Cody Schuffelen {
667*5c591343SA. Cody Schuffelen BYTE *pBuffer = command->parameterBuffer;
668*5c591343SA. Cody Schuffelen INT32 pSize = command->parameterSize;
669*5c591343SA. Cody Schuffelen TPM2B_DIGEST tHash;
670*5c591343SA. Cody Schuffelen UINT16 size;
671*5c591343SA. Cody Schuffelen //
672*5c591343SA. Cody Schuffelen // Only try this for the three commands for which it is intended
673*5c591343SA. Cody Schuffelen if(command->code != TPM_CC_Create
674*5c591343SA. Cody Schuffelen && command->code != TPM_CC_CreatePrimary
675*5c591343SA. Cody Schuffelen #if CC_CreateLoaded
676*5c591343SA. Cody Schuffelen && command->code != TPM_CC_CreateLoaded
677*5c591343SA. Cody Schuffelen #endif
678*5c591343SA. Cody Schuffelen )
679*5c591343SA. Cody Schuffelen return FALSE;
680*5c591343SA. Cody Schuffelen // Assume that the first parameter is a TPM2B and unmarshal the size field
681*5c591343SA. Cody Schuffelen // Note: this will not affect the parameter buffer and size in the calling
682*5c591343SA. Cody Schuffelen // function.
683*5c591343SA. Cody Schuffelen if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
684*5c591343SA. Cody Schuffelen return FALSE;
685*5c591343SA. Cody Schuffelen // reduce the space in the buffer.
686*5c591343SA. Cody Schuffelen // NOTE: this could make pSize go negative if the parameters are not correct but
687*5c591343SA. Cody Schuffelen // the unmarshaling code does not try to unmarshal if the remaining size is
688*5c591343SA. Cody Schuffelen // negative.
689*5c591343SA. Cody Schuffelen pSize -= size;
690*5c591343SA. Cody Schuffelen
691*5c591343SA. Cody Schuffelen // Advance the pointer
692*5c591343SA. Cody Schuffelen pBuffer += size;
693*5c591343SA. Cody Schuffelen
694*5c591343SA. Cody Schuffelen // Get the size of what should be the template
695*5c591343SA. Cody Schuffelen if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
696*5c591343SA. Cody Schuffelen return FALSE;
697*5c591343SA. Cody Schuffelen // See if this is reasonable
698*5c591343SA. Cody Schuffelen if(size > pSize)
699*5c591343SA. Cody Schuffelen return FALSE;
700*5c591343SA. Cody Schuffelen // Hash the template data
701*5c591343SA. Cody Schuffelen tHash.t.size = CryptHashBlock(session->authHashAlg, size, pBuffer,
702*5c591343SA. Cody Schuffelen sizeof(tHash.t.buffer), tHash.t.buffer);
703*5c591343SA. Cody Schuffelen return(MemoryEqual2B(&session->u1.templateHash.b, &tHash.b));
704*5c591343SA. Cody Schuffelen }
705*5c591343SA. Cody Schuffelen
706*5c591343SA. Cody Schuffelen //*** CompareNameHash()
707*5c591343SA. Cody Schuffelen // This function computes the name hash and compares it to the nameHash in the
708*5c591343SA. Cody Schuffelen // session data.
709*5c591343SA. Cody Schuffelen BOOL
CompareNameHash(COMMAND * command,SESSION * session)710*5c591343SA. Cody Schuffelen CompareNameHash(
711*5c591343SA. Cody Schuffelen COMMAND *command, // IN: main parsing structure
712*5c591343SA. Cody Schuffelen SESSION *session // IN: session structure with nameHash
713*5c591343SA. Cody Schuffelen )
714*5c591343SA. Cody Schuffelen {
715*5c591343SA. Cody Schuffelen HASH_STATE hashState;
716*5c591343SA. Cody Schuffelen TPM2B_DIGEST nameHash;
717*5c591343SA. Cody Schuffelen UINT32 i;
718*5c591343SA. Cody Schuffelen TPM2B_NAME name;
719*5c591343SA. Cody Schuffelen //
720*5c591343SA. Cody Schuffelen nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg);
721*5c591343SA. Cody Schuffelen // Add names.
722*5c591343SA. Cody Schuffelen for(i = 0; i < command->handleNum; i++)
723*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],
724*5c591343SA. Cody Schuffelen &name)->b);
725*5c591343SA. Cody Schuffelen // Complete hash.
726*5c591343SA. Cody Schuffelen CryptHashEnd2B(&hashState, &nameHash.b);
727*5c591343SA. Cody Schuffelen // and compare
728*5c591343SA. Cody Schuffelen return MemoryEqual(session->u1.nameHash.t.buffer, nameHash.t.buffer,
729*5c591343SA. Cody Schuffelen nameHash.t.size);
730*5c591343SA. Cody Schuffelen }
731*5c591343SA. Cody Schuffelen
732*5c591343SA. Cody Schuffelen //*** CheckPWAuthSession()
733*5c591343SA. Cody Schuffelen // This function validates the authorization provided in a PWAP session. It
734*5c591343SA. Cody Schuffelen // compares the input value to authValue of the authorized entity. Argument
735*5c591343SA. Cody Schuffelen // sessionIndex is used to get handles handle of the referenced entities from
736*5c591343SA. Cody Schuffelen // s_inputAuthValues[] and s_associatedHandles[].
737*5c591343SA. Cody Schuffelen //
738*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
739*5c591343SA. Cody Schuffelen // TPM_RC_AUTH_FAIL authorization fails and increments DA failure
740*5c591343SA. Cody Schuffelen // count
741*5c591343SA. Cody Schuffelen // TPM_RC_BAD_AUTH authorization fails but DA does not apply
742*5c591343SA. Cody Schuffelen //
743*5c591343SA. Cody Schuffelen static TPM_RC
CheckPWAuthSession(UINT32 sessionIndex)744*5c591343SA. Cody Schuffelen CheckPWAuthSession(
745*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: index of session to be processed
746*5c591343SA. Cody Schuffelen )
747*5c591343SA. Cody Schuffelen {
748*5c591343SA. Cody Schuffelen TPM2B_AUTH authValue;
749*5c591343SA. Cody Schuffelen TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex];
750*5c591343SA. Cody Schuffelen //
751*5c591343SA. Cody Schuffelen // Strip trailing zeros from the password.
752*5c591343SA. Cody Schuffelen MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]);
753*5c591343SA. Cody Schuffelen
754*5c591343SA. Cody Schuffelen // Get the authValue with trailing zeros removed
755*5c591343SA. Cody Schuffelen EntityGetAuthValue(associatedHandle, &authValue);
756*5c591343SA. Cody Schuffelen
757*5c591343SA. Cody Schuffelen // Success if the values are identical.
758*5c591343SA. Cody Schuffelen if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b))
759*5c591343SA. Cody Schuffelen {
760*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
761*5c591343SA. Cody Schuffelen }
762*5c591343SA. Cody Schuffelen else // if the digests are not identical
763*5c591343SA. Cody Schuffelen {
764*5c591343SA. Cody Schuffelen // Invoke DA protection if applicable.
765*5c591343SA. Cody Schuffelen return IncrementLockout(sessionIndex);
766*5c591343SA. Cody Schuffelen }
767*5c591343SA. Cody Schuffelen }
768*5c591343SA. Cody Schuffelen
769*5c591343SA. Cody Schuffelen //*** ComputeCommandHMAC()
770*5c591343SA. Cody Schuffelen // This function computes the HMAC for an authorization session in a command.
771*5c591343SA. Cody Schuffelen /*(See part 1 specification -- this tag keeps this comment from showing up in
772*5c591343SA. Cody Schuffelen // merged document which is probably good because this comment doesn't look right.
773*5c591343SA. Cody Schuffelen // The sessionAuth value
774*5c591343SA. Cody Schuffelen // authHMAC := HMACsHash((sessionKey | authValue),
775*5c591343SA. Cody Schuffelen // (pHash | nonceNewer | nonceOlder | nonceTPMencrypt-only
776*5c591343SA. Cody Schuffelen // | nonceTPMaudit | sessionAttributes))
777*5c591343SA. Cody Schuffelen // Where:
778*5c591343SA. Cody Schuffelen // HMACsHash() The HMAC algorithm using the hash algorithm specified
779*5c591343SA. Cody Schuffelen // when the session was started.
780*5c591343SA. Cody Schuffelen //
781*5c591343SA. Cody Schuffelen // sessionKey A value that is computed in a protocol-dependent way,
782*5c591343SA. Cody Schuffelen // using KDFa. When used in an HMAC or KDF, the size field
783*5c591343SA. Cody Schuffelen // for this value is not included.
784*5c591343SA. Cody Schuffelen //
785*5c591343SA. Cody Schuffelen // authValue A value that is found in the sensitive area of an entity.
786*5c591343SA. Cody Schuffelen // When used in an HMAC or KDF, the size field for this
787*5c591343SA. Cody Schuffelen // value is not included.
788*5c591343SA. Cody Schuffelen //
789*5c591343SA. Cody Schuffelen // pHash Hash of the command (cpHash) using the session hash.
790*5c591343SA. Cody Schuffelen // When using a pHash in an HMAC computation, only the
791*5c591343SA. Cody Schuffelen // digest is used.
792*5c591343SA. Cody Schuffelen //
793*5c591343SA. Cody Schuffelen // nonceNewer A value that is generated by the entity using the
794*5c591343SA. Cody Schuffelen // session. A new nonce is generated on each use of the
795*5c591343SA. Cody Schuffelen // session. For a command, this will be nonceCaller.
796*5c591343SA. Cody Schuffelen // When used in an HMAC or KDF, the size field is not used.
797*5c591343SA. Cody Schuffelen //
798*5c591343SA. Cody Schuffelen // nonceOlder A TPM2B_NONCE that was received the previous time the
799*5c591343SA. Cody Schuffelen // session was used. For a command, this is nonceTPM.
800*5c591343SA. Cody Schuffelen // When used in an HMAC or KDF, the size field is not used.
801*5c591343SA. Cody Schuffelen //
802*5c591343SA. Cody Schuffelen // nonceTPMdecrypt The nonceTPM of the decrypt session is included in
803*5c591343SA. Cody Schuffelen // the HMAC, but only in the command.
804*5c591343SA. Cody Schuffelen //
805*5c591343SA. Cody Schuffelen // nonceTPMencrypt The nonceTPM of the encrypt session is included in
806*5c591343SA. Cody Schuffelen // the HMAC but only in the command.
807*5c591343SA. Cody Schuffelen //
808*5c591343SA. Cody Schuffelen // sessionAttributes A byte indicating the attributes associated with the
809*5c591343SA. Cody Schuffelen // particular use of the session.
810*5c591343SA. Cody Schuffelen */
811*5c591343SA. Cody Schuffelen static TPM2B_DIGEST *
ComputeCommandHMAC(COMMAND * command,UINT32 sessionIndex,TPM2B_DIGEST * hmac)812*5c591343SA. Cody Schuffelen ComputeCommandHMAC(
813*5c591343SA. Cody Schuffelen COMMAND *command, // IN: primary control structure
814*5c591343SA. Cody Schuffelen UINT32 sessionIndex, // IN: index of session to be processed
815*5c591343SA. Cody Schuffelen TPM2B_DIGEST *hmac // OUT: authorization HMAC
816*5c591343SA. Cody Schuffelen )
817*5c591343SA. Cody Schuffelen {
818*5c591343SA. Cody Schuffelen TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));
819*5c591343SA. Cody Schuffelen TPM2B_KEY key;
820*5c591343SA. Cody Schuffelen BYTE marshalBuffer[sizeof(TPMA_SESSION)];
821*5c591343SA. Cody Schuffelen BYTE *buffer;
822*5c591343SA. Cody Schuffelen UINT32 marshalSize;
823*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
824*5c591343SA. Cody Schuffelen TPM2B_NONCE *nonceDecrypt;
825*5c591343SA. Cody Schuffelen TPM2B_NONCE *nonceEncrypt;
826*5c591343SA. Cody Schuffelen SESSION *session;
827*5c591343SA. Cody Schuffelen //
828*5c591343SA. Cody Schuffelen nonceDecrypt = NULL;
829*5c591343SA. Cody Schuffelen nonceEncrypt = NULL;
830*5c591343SA. Cody Schuffelen
831*5c591343SA. Cody Schuffelen // Determine if extra nonceTPM values are going to be required.
832*5c591343SA. Cody Schuffelen // If this is the first session (sessionIndex = 0) and it is an authorization
833*5c591343SA. Cody Schuffelen // session that uses an HMAC, then check if additional session nonces are to be
834*5c591343SA. Cody Schuffelen // included.
835*5c591343SA. Cody Schuffelen if(sessionIndex == 0
836*5c591343SA. Cody Schuffelen && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
837*5c591343SA. Cody Schuffelen {
838*5c591343SA. Cody Schuffelen // If there is a decrypt session and if this is not the decrypt session,
839*5c591343SA. Cody Schuffelen // then an extra nonce may be needed.
840*5c591343SA. Cody Schuffelen if(s_decryptSessionIndex != UNDEFINED_INDEX
841*5c591343SA. Cody Schuffelen && s_decryptSessionIndex != sessionIndex)
842*5c591343SA. Cody Schuffelen {
843*5c591343SA. Cody Schuffelen // Will add the nonce for the decrypt session.
844*5c591343SA. Cody Schuffelen SESSION *decryptSession
845*5c591343SA. Cody Schuffelen = SessionGet(s_sessionHandles[s_decryptSessionIndex]);
846*5c591343SA. Cody Schuffelen nonceDecrypt = &decryptSession->nonceTPM;
847*5c591343SA. Cody Schuffelen }
848*5c591343SA. Cody Schuffelen // Now repeat for the encrypt session.
849*5c591343SA. Cody Schuffelen if(s_encryptSessionIndex != UNDEFINED_INDEX
850*5c591343SA. Cody Schuffelen && s_encryptSessionIndex != sessionIndex
851*5c591343SA. Cody Schuffelen && s_encryptSessionIndex != s_decryptSessionIndex)
852*5c591343SA. Cody Schuffelen {
853*5c591343SA. Cody Schuffelen // Have to have the nonce for the encrypt session.
854*5c591343SA. Cody Schuffelen SESSION *encryptSession
855*5c591343SA. Cody Schuffelen = SessionGet(s_sessionHandles[s_encryptSessionIndex]);
856*5c591343SA. Cody Schuffelen nonceEncrypt = &encryptSession->nonceTPM;
857*5c591343SA. Cody Schuffelen }
858*5c591343SA. Cody Schuffelen }
859*5c591343SA. Cody Schuffelen
860*5c591343SA. Cody Schuffelen // Continue with the HMAC processing.
861*5c591343SA. Cody Schuffelen session = SessionGet(s_sessionHandles[sessionIndex]);
862*5c591343SA. Cody Schuffelen
863*5c591343SA. Cody Schuffelen // Generate HMAC key.
864*5c591343SA. Cody Schuffelen MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
865*5c591343SA. Cody Schuffelen
866*5c591343SA. Cody Schuffelen // Check if the session has an associated handle and if the associated entity
867*5c591343SA. Cody Schuffelen // is the one to which the session is bound. If not, add the authValue of
868*5c591343SA. Cody Schuffelen // this entity to the HMAC key.
869*5c591343SA. Cody Schuffelen // If the session is bound to the object or the session is a policy session
870*5c591343SA. Cody Schuffelen // with no authValue required, do not include the authValue in the HMAC key.
871*5c591343SA. Cody Schuffelen // Note: For a policy session, its isBound attribute is CLEARED.
872*5c591343SA. Cody Schuffelen //
873*5c591343SA. Cody Schuffelen // Include the entity authValue if it is needed
874*5c591343SA. Cody Schuffelen if(session->attributes.includeAuth == SET)
875*5c591343SA. Cody Schuffelen {
876*5c591343SA. Cody Schuffelen TPM2B_AUTH authValue;
877*5c591343SA. Cody Schuffelen // Get the entity authValue with trailing zeros removed
878*5c591343SA. Cody Schuffelen EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);
879*5c591343SA. Cody Schuffelen // add the authValue to the HMAC key
880*5c591343SA. Cody Schuffelen MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));
881*5c591343SA. Cody Schuffelen }
882*5c591343SA. Cody Schuffelen // if the HMAC key size is 0, a NULL string HMAC is allowed
883*5c591343SA. Cody Schuffelen if(key.t.size == 0
884*5c591343SA. Cody Schuffelen && s_inputAuthValues[sessionIndex].t.size == 0)
885*5c591343SA. Cody Schuffelen {
886*5c591343SA. Cody Schuffelen hmac->t.size = 0;
887*5c591343SA. Cody Schuffelen return hmac;
888*5c591343SA. Cody Schuffelen }
889*5c591343SA. Cody Schuffelen // Start HMAC
890*5c591343SA. Cody Schuffelen hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);
891*5c591343SA. Cody Schuffelen
892*5c591343SA. Cody Schuffelen // Add cpHash
893*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState,
894*5c591343SA. Cody Schuffelen &ComputeCpHash(command, session->authHashAlg)->b);
895*5c591343SA. Cody Schuffelen // Add nonces as required
896*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);
897*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);
898*5c591343SA. Cody Schuffelen if(nonceDecrypt != NULL)
899*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b);
900*5c591343SA. Cody Schuffelen if(nonceEncrypt != NULL)
901*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b);
902*5c591343SA. Cody Schuffelen // Add sessionAttributes
903*5c591343SA. Cody Schuffelen buffer = marshalBuffer;
904*5c591343SA. Cody Schuffelen marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]),
905*5c591343SA. Cody Schuffelen &buffer, NULL);
906*5c591343SA. Cody Schuffelen CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);
907*5c591343SA. Cody Schuffelen // Complete the HMAC computation
908*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &hmac->b);
909*5c591343SA. Cody Schuffelen
910*5c591343SA. Cody Schuffelen return hmac;
911*5c591343SA. Cody Schuffelen }
912*5c591343SA. Cody Schuffelen
913*5c591343SA. Cody Schuffelen //*** CheckSessionHMAC()
914*5c591343SA. Cody Schuffelen // This function checks the HMAC of in a session. It uses ComputeCommandHMAC()
915*5c591343SA. Cody Schuffelen // to compute the expected HMAC value and then compares the result with the
916*5c591343SA. Cody Schuffelen // HMAC in the authorization session. The authorization is successful if they
917*5c591343SA. Cody Schuffelen // are the same.
918*5c591343SA. Cody Schuffelen //
919*5c591343SA. Cody Schuffelen // If the authorizations are not the same, IncrementLockout() is called. It will
920*5c591343SA. Cody Schuffelen // return TPM_RC_AUTH_FAIL if the failure caused the failureCount to increment.
921*5c591343SA. Cody Schuffelen // Otherwise, it will return TPM_RC_BAD_AUTH.
922*5c591343SA. Cody Schuffelen //
923*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
924*5c591343SA. Cody Schuffelen // TPM_RC_AUTH_FAIL authorization failure caused failureCount increment
925*5c591343SA. Cody Schuffelen // TPM_RC_BAD_AUTH authorization failure did not cause failureCount
926*5c591343SA. Cody Schuffelen // increment
927*5c591343SA. Cody Schuffelen //
928*5c591343SA. Cody Schuffelen static TPM_RC
CheckSessionHMAC(COMMAND * command,UINT32 sessionIndex)929*5c591343SA. Cody Schuffelen CheckSessionHMAC(
930*5c591343SA. Cody Schuffelen COMMAND *command, // IN: primary control structure
931*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: index of session to be processed
932*5c591343SA. Cody Schuffelen )
933*5c591343SA. Cody Schuffelen {
934*5c591343SA. Cody Schuffelen TPM2B_DIGEST hmac; // authHMAC for comparing
935*5c591343SA. Cody Schuffelen //
936*5c591343SA. Cody Schuffelen // Compute authHMAC
937*5c591343SA. Cody Schuffelen ComputeCommandHMAC(command, sessionIndex, &hmac);
938*5c591343SA. Cody Schuffelen
939*5c591343SA. Cody Schuffelen // Compare the input HMAC with the authHMAC computed above.
940*5c591343SA. Cody Schuffelen if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b))
941*5c591343SA. Cody Schuffelen {
942*5c591343SA. Cody Schuffelen // If an HMAC session has a failure, invoke the anti-hammering
943*5c591343SA. Cody Schuffelen // if it applies to the authorized entity or the session.
944*5c591343SA. Cody Schuffelen // Otherwise, just indicate that the authorization is bad.
945*5c591343SA. Cody Schuffelen return IncrementLockout(sessionIndex);
946*5c591343SA. Cody Schuffelen }
947*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
948*5c591343SA. Cody Schuffelen }
949*5c591343SA. Cody Schuffelen
950*5c591343SA. Cody Schuffelen //*** CheckPolicyAuthSession()
951*5c591343SA. Cody Schuffelen // This function is used to validate the authorization in a policy session.
952*5c591343SA. Cody Schuffelen // This function performs the following comparisons to see if a policy
953*5c591343SA. Cody Schuffelen // authorization is properly provided. The check are:
954*5c591343SA. Cody Schuffelen // a) compare policyDigest in session with authPolicy associated with
955*5c591343SA. Cody Schuffelen // the entity to be authorized;
956*5c591343SA. Cody Schuffelen // b) compare timeout if applicable;
957*5c591343SA. Cody Schuffelen // c) compare commandCode if applicable;
958*5c591343SA. Cody Schuffelen // d) compare cpHash if applicable; and
959*5c591343SA. Cody Schuffelen // e) see if PCR values have changed since computed.
960*5c591343SA. Cody Schuffelen //
961*5c591343SA. Cody Schuffelen // If all the above checks succeed, the handle is authorized.
962*5c591343SA. Cody Schuffelen // The order of these comparisons is not important because any failure will
963*5c591343SA. Cody Schuffelen // result in the same error code.
964*5c591343SA. Cody Schuffelen //
965*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
966*5c591343SA. Cody Schuffelen // TPM_RC_PCR_CHANGED PCR value is not current
967*5c591343SA. Cody Schuffelen // TPM_RC_POLICY_FAIL policy session fails
968*5c591343SA. Cody Schuffelen // TPM_RC_LOCALITY command locality is not allowed
969*5c591343SA. Cody Schuffelen // TPM_RC_POLICY_CC CC doesn't match
970*5c591343SA. Cody Schuffelen // TPM_RC_EXPIRED policy session has expired
971*5c591343SA. Cody Schuffelen // TPM_RC_PP PP is required but not asserted
972*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available for write
973*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting
974*5c591343SA. Cody Schuffelen static TPM_RC
CheckPolicyAuthSession(COMMAND * command,UINT32 sessionIndex)975*5c591343SA. Cody Schuffelen CheckPolicyAuthSession(
976*5c591343SA. Cody Schuffelen COMMAND *command, // IN: primary parsing structure
977*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: index of session to be processed
978*5c591343SA. Cody Schuffelen )
979*5c591343SA. Cody Schuffelen {
980*5c591343SA. Cody Schuffelen SESSION *session;
981*5c591343SA. Cody Schuffelen TPM2B_DIGEST authPolicy;
982*5c591343SA. Cody Schuffelen TPMI_ALG_HASH policyAlg;
983*5c591343SA. Cody Schuffelen UINT8 locality;
984*5c591343SA. Cody Schuffelen //
985*5c591343SA. Cody Schuffelen // Initialize pointer to the authorization session.
986*5c591343SA. Cody Schuffelen session = SessionGet(s_sessionHandles[sessionIndex]);
987*5c591343SA. Cody Schuffelen
988*5c591343SA. Cody Schuffelen // If the command is TPM2_PolicySecret(), make sure that
989*5c591343SA. Cody Schuffelen // either password or authValue is required
990*5c591343SA. Cody Schuffelen if(command->code == TPM_CC_PolicySecret
991*5c591343SA. Cody Schuffelen && session->attributes.isPasswordNeeded == CLEAR
992*5c591343SA. Cody Schuffelen && session->attributes.isAuthValueNeeded == CLEAR)
993*5c591343SA. Cody Schuffelen return TPM_RC_MODE;
994*5c591343SA. Cody Schuffelen // See if the PCR counter for the session is still valid.
995*5c591343SA. Cody Schuffelen if(!SessionPCRValueIsCurrent(session))
996*5c591343SA. Cody Schuffelen return TPM_RC_PCR_CHANGED;
997*5c591343SA. Cody Schuffelen // Get authPolicy.
998*5c591343SA. Cody Schuffelen policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex],
999*5c591343SA. Cody Schuffelen &authPolicy);
1000*5c591343SA. Cody Schuffelen // Compare authPolicy.
1001*5c591343SA. Cody Schuffelen if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b))
1002*5c591343SA. Cody Schuffelen return TPM_RC_POLICY_FAIL;
1003*5c591343SA. Cody Schuffelen // Policy is OK so check if the other factors are correct
1004*5c591343SA. Cody Schuffelen
1005*5c591343SA. Cody Schuffelen // Compare policy hash algorithm.
1006*5c591343SA. Cody Schuffelen if(policyAlg != session->authHashAlg)
1007*5c591343SA. Cody Schuffelen return TPM_RC_POLICY_FAIL;
1008*5c591343SA. Cody Schuffelen
1009*5c591343SA. Cody Schuffelen // Compare timeout.
1010*5c591343SA. Cody Schuffelen if(session->timeout != 0)
1011*5c591343SA. Cody Schuffelen {
1012*5c591343SA. Cody Schuffelen // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE
1013*5c591343SA. Cody Schuffelen // or TPM_RC_NV_RATE error may be returned here. This doesn't mean that
1014*5c591343SA. Cody Schuffelen // a new nonce will be created just that, because TPM time can't advance
1015*5c591343SA. Cody Schuffelen // we can't do time-based operations.
1016*5c591343SA. Cody Schuffelen RETURN_IF_NV_IS_NOT_AVAILABLE;
1017*5c591343SA. Cody Schuffelen
1018*5c591343SA. Cody Schuffelen if((session->timeout < g_time)
1019*5c591343SA. Cody Schuffelen || (session->epoch != g_timeEpoch))
1020*5c591343SA. Cody Schuffelen return TPM_RC_EXPIRED;
1021*5c591343SA. Cody Schuffelen }
1022*5c591343SA. Cody Schuffelen // If command code is provided it must match
1023*5c591343SA. Cody Schuffelen if(session->commandCode != 0)
1024*5c591343SA. Cody Schuffelen {
1025*5c591343SA. Cody Schuffelen if(session->commandCode != command->code)
1026*5c591343SA. Cody Schuffelen return TPM_RC_POLICY_CC;
1027*5c591343SA. Cody Schuffelen }
1028*5c591343SA. Cody Schuffelen else
1029*5c591343SA. Cody Schuffelen {
1030*5c591343SA. Cody Schuffelen // If command requires a DUP or ADMIN authorization, the session must have
1031*5c591343SA. Cody Schuffelen // command code set.
1032*5c591343SA. Cody Schuffelen AUTH_ROLE role = CommandAuthRole(command->index, sessionIndex);
1033*5c591343SA. Cody Schuffelen if(role == AUTH_ADMIN || role == AUTH_DUP)
1034*5c591343SA. Cody Schuffelen return TPM_RC_POLICY_FAIL;
1035*5c591343SA. Cody Schuffelen }
1036*5c591343SA. Cody Schuffelen // Check command locality.
1037*5c591343SA. Cody Schuffelen {
1038*5c591343SA. Cody Schuffelen BYTE sessionLocality[sizeof(TPMA_LOCALITY)];
1039*5c591343SA. Cody Schuffelen BYTE *buffer = sessionLocality;
1040*5c591343SA. Cody Schuffelen
1041*5c591343SA. Cody Schuffelen // Get existing locality setting in canonical form
1042*5c591343SA. Cody Schuffelen sessionLocality[0] = 0;
1043*5c591343SA. Cody Schuffelen TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
1044*5c591343SA. Cody Schuffelen
1045*5c591343SA. Cody Schuffelen // See if the locality has been set
1046*5c591343SA. Cody Schuffelen if(sessionLocality[0] != 0)
1047*5c591343SA. Cody Schuffelen {
1048*5c591343SA. Cody Schuffelen // If so, get the current locality
1049*5c591343SA. Cody Schuffelen locality = _plat__LocalityGet();
1050*5c591343SA. Cody Schuffelen if(locality < 5)
1051*5c591343SA. Cody Schuffelen {
1052*5c591343SA. Cody Schuffelen if(((sessionLocality[0] & (1 << locality)) == 0)
1053*5c591343SA. Cody Schuffelen || sessionLocality[0] > 31)
1054*5c591343SA. Cody Schuffelen return TPM_RC_LOCALITY;
1055*5c591343SA. Cody Schuffelen }
1056*5c591343SA. Cody Schuffelen else if(locality > 31)
1057*5c591343SA. Cody Schuffelen {
1058*5c591343SA. Cody Schuffelen if(sessionLocality[0] != locality)
1059*5c591343SA. Cody Schuffelen return TPM_RC_LOCALITY;
1060*5c591343SA. Cody Schuffelen }
1061*5c591343SA. Cody Schuffelen else
1062*5c591343SA. Cody Schuffelen {
1063*5c591343SA. Cody Schuffelen // Could throw an assert here but a locality error is just
1064*5c591343SA. Cody Schuffelen // as good. It just means that, whatever the locality is, it isn't
1065*5c591343SA. Cody Schuffelen // the locality requested so...
1066*5c591343SA. Cody Schuffelen return TPM_RC_LOCALITY;
1067*5c591343SA. Cody Schuffelen }
1068*5c591343SA. Cody Schuffelen }
1069*5c591343SA. Cody Schuffelen } // end of locality check
1070*5c591343SA. Cody Schuffelen // Check physical presence.
1071*5c591343SA. Cody Schuffelen if(session->attributes.isPPRequired == SET
1072*5c591343SA. Cody Schuffelen && !_plat__PhysicalPresenceAsserted())
1073*5c591343SA. Cody Schuffelen return TPM_RC_PP;
1074*5c591343SA. Cody Schuffelen // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or
1075*5c591343SA. Cody Schuffelen // DUP role for this handle.
1076*5c591343SA. Cody Schuffelen if(session->u1.cpHash.b.size != 0)
1077*5c591343SA. Cody Schuffelen {
1078*5c591343SA. Cody Schuffelen BOOL OK;
1079*5c591343SA. Cody Schuffelen if(session->attributes.isCpHashDefined)
1080*5c591343SA. Cody Schuffelen // Compare cpHash.
1081*5c591343SA. Cody Schuffelen OK = MemoryEqual2B(&session->u1.cpHash.b,
1082*5c591343SA. Cody Schuffelen &ComputeCpHash(command, session->authHashAlg)->b);
1083*5c591343SA. Cody Schuffelen else if(session->attributes.isTemplateSet)
1084*5c591343SA. Cody Schuffelen OK = CompareTemplateHash(command, session);
1085*5c591343SA. Cody Schuffelen else
1086*5c591343SA. Cody Schuffelen OK = CompareNameHash(command, session);
1087*5c591343SA. Cody Schuffelen if(!OK)
1088*5c591343SA. Cody Schuffelen return TPM_RCS_POLICY_FAIL;
1089*5c591343SA. Cody Schuffelen }
1090*5c591343SA. Cody Schuffelen if(session->attributes.checkNvWritten)
1091*5c591343SA. Cody Schuffelen {
1092*5c591343SA. Cody Schuffelen NV_REF locator;
1093*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex;
1094*5c591343SA. Cody Schuffelen //
1095*5c591343SA. Cody Schuffelen // If this is not an NV index, the policy makes no sense so fail it.
1096*5c591343SA. Cody Schuffelen if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX)
1097*5c591343SA. Cody Schuffelen return TPM_RC_POLICY_FAIL;
1098*5c591343SA. Cody Schuffelen // Get the index data
1099*5c591343SA. Cody Schuffelen nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator);
1100*5c591343SA. Cody Schuffelen
1101*5c591343SA. Cody Schuffelen // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state
1102*5c591343SA. Cody Schuffelen if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
1103*5c591343SA. Cody Schuffelen != (session->attributes.nvWrittenState == SET))
1104*5c591343SA. Cody Schuffelen return TPM_RC_POLICY_FAIL;
1105*5c591343SA. Cody Schuffelen }
1106*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1107*5c591343SA. Cody Schuffelen }
1108*5c591343SA. Cody Schuffelen
1109*5c591343SA. Cody Schuffelen //*** RetrieveSessionData()
1110*5c591343SA. Cody Schuffelen // This function will unmarshal the sessions in the session area of a command. The
1111*5c591343SA. Cody Schuffelen // values are placed in the arrays that are defined at the beginning of this file.
1112*5c591343SA. Cody Schuffelen // The normal unmarshaling errors are possible.
1113*5c591343SA. Cody Schuffelen //
1114*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1115*5c591343SA. Cody Schuffelen // TPM_RC_SUCCSS unmarshaled without error
1116*5c591343SA. Cody Schuffelen // TPM_RC_SIZE the number of bytes unmarshaled is not the same
1117*5c591343SA. Cody Schuffelen // as the value for authorizationSize in the command
1118*5c591343SA. Cody Schuffelen //
1119*5c591343SA. Cody Schuffelen static TPM_RC
RetrieveSessionData(COMMAND * command)1120*5c591343SA. Cody Schuffelen RetrieveSessionData(
1121*5c591343SA. Cody Schuffelen COMMAND *command // IN: main parsing structure for command
1122*5c591343SA. Cody Schuffelen )
1123*5c591343SA. Cody Schuffelen {
1124*5c591343SA. Cody Schuffelen int i;
1125*5c591343SA. Cody Schuffelen TPM_RC result;
1126*5c591343SA. Cody Schuffelen SESSION *session;
1127*5c591343SA. Cody Schuffelen TPMA_SESSION sessionAttributes;
1128*5c591343SA. Cody Schuffelen TPM_HT sessionType;
1129*5c591343SA. Cody Schuffelen INT32 sessionIndex;
1130*5c591343SA. Cody Schuffelen TPM_RC errorIndex;
1131*5c591343SA. Cody Schuffelen //
1132*5c591343SA. Cody Schuffelen s_decryptSessionIndex = UNDEFINED_INDEX;
1133*5c591343SA. Cody Schuffelen s_encryptSessionIndex = UNDEFINED_INDEX;
1134*5c591343SA. Cody Schuffelen s_auditSessionIndex = UNDEFINED_INDEX;
1135*5c591343SA. Cody Schuffelen
1136*5c591343SA. Cody Schuffelen for(sessionIndex = 0; command->authSize > 0; sessionIndex++)
1137*5c591343SA. Cody Schuffelen {
1138*5c591343SA. Cody Schuffelen errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];
1139*5c591343SA. Cody Schuffelen
1140*5c591343SA. Cody Schuffelen // If maximum allowed number of sessions has been parsed, return a size
1141*5c591343SA. Cody Schuffelen // error with a session number that is larger than the number of allowed
1142*5c591343SA. Cody Schuffelen // sessions
1143*5c591343SA. Cody Schuffelen if(sessionIndex == MAX_SESSION_NUM)
1144*5c591343SA. Cody Schuffelen return TPM_RCS_SIZE + errorIndex;
1145*5c591343SA. Cody Schuffelen // make sure that the associated handle for each session starts out
1146*5c591343SA. Cody Schuffelen // unassigned
1147*5c591343SA. Cody Schuffelen s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
1148*5c591343SA. Cody Schuffelen
1149*5c591343SA. Cody Schuffelen // First parameter: Session handle.
1150*5c591343SA. Cody Schuffelen result = TPMI_SH_AUTH_SESSION_Unmarshal(
1151*5c591343SA. Cody Schuffelen &s_sessionHandles[sessionIndex],
1152*5c591343SA. Cody Schuffelen &command->parameterBuffer,
1153*5c591343SA. Cody Schuffelen &command->authSize, TRUE);
1154*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1155*5c591343SA. Cody Schuffelen return result + TPM_RC_S + g_rcIndex[sessionIndex];
1156*5c591343SA. Cody Schuffelen // Second parameter: Nonce.
1157*5c591343SA. Cody Schuffelen result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex],
1158*5c591343SA. Cody Schuffelen &command->parameterBuffer,
1159*5c591343SA. Cody Schuffelen &command->authSize);
1160*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1161*5c591343SA. Cody Schuffelen return result + TPM_RC_S + g_rcIndex[sessionIndex];
1162*5c591343SA. Cody Schuffelen // Third parameter: sessionAttributes.
1163*5c591343SA. Cody Schuffelen result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex],
1164*5c591343SA. Cody Schuffelen &command->parameterBuffer,
1165*5c591343SA. Cody Schuffelen &command->authSize);
1166*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1167*5c591343SA. Cody Schuffelen return result + TPM_RC_S + g_rcIndex[sessionIndex];
1168*5c591343SA. Cody Schuffelen // Fourth parameter: authValue (PW or HMAC).
1169*5c591343SA. Cody Schuffelen result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex],
1170*5c591343SA. Cody Schuffelen &command->parameterBuffer,
1171*5c591343SA. Cody Schuffelen &command->authSize);
1172*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1173*5c591343SA. Cody Schuffelen return result + errorIndex;
1174*5c591343SA. Cody Schuffelen
1175*5c591343SA. Cody Schuffelen sessionAttributes = s_attributes[sessionIndex];
1176*5c591343SA. Cody Schuffelen if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
1177*5c591343SA. Cody Schuffelen {
1178*5c591343SA. Cody Schuffelen // A PWAP session needs additional processing.
1179*5c591343SA. Cody Schuffelen // Can't have any attributes set other than continueSession bit
1180*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)
1181*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)
1182*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)
1183*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
1184*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset))
1185*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1186*5c591343SA. Cody Schuffelen // The nonce size must be zero.
1187*5c591343SA. Cody Schuffelen if(s_nonceCaller[sessionIndex].t.size != 0)
1188*5c591343SA. Cody Schuffelen return TPM_RCS_NONCE + errorIndex;
1189*5c591343SA. Cody Schuffelen continue;
1190*5c591343SA. Cody Schuffelen }
1191*5c591343SA. Cody Schuffelen // For not password sessions...
1192*5c591343SA. Cody Schuffelen // Find out if the session is loaded.
1193*5c591343SA. Cody Schuffelen if(!SessionIsLoaded(s_sessionHandles[sessionIndex]))
1194*5c591343SA. Cody Schuffelen return TPM_RC_REFERENCE_S0 + sessionIndex;
1195*5c591343SA. Cody Schuffelen sessionType = HandleGetType(s_sessionHandles[sessionIndex]);
1196*5c591343SA. Cody Schuffelen session = SessionGet(s_sessionHandles[sessionIndex]);
1197*5c591343SA. Cody Schuffelen
1198*5c591343SA. Cody Schuffelen // Check if the session is an HMAC/policy session.
1199*5c591343SA. Cody Schuffelen if((session->attributes.isPolicy == SET
1200*5c591343SA. Cody Schuffelen && sessionType == TPM_HT_HMAC_SESSION)
1201*5c591343SA. Cody Schuffelen || (session->attributes.isPolicy == CLEAR
1202*5c591343SA. Cody Schuffelen && sessionType == TPM_HT_POLICY_SESSION))
1203*5c591343SA. Cody Schuffelen return TPM_RCS_HANDLE + errorIndex;
1204*5c591343SA. Cody Schuffelen // Check that this handle has not previously been used.
1205*5c591343SA. Cody Schuffelen for(i = 0; i < sessionIndex; i++)
1206*5c591343SA. Cody Schuffelen {
1207*5c591343SA. Cody Schuffelen if(s_sessionHandles[i] == s_sessionHandles[sessionIndex])
1208*5c591343SA. Cody Schuffelen return TPM_RCS_HANDLE + errorIndex;
1209*5c591343SA. Cody Schuffelen }
1210*5c591343SA. Cody Schuffelen // If the session is used for parameter encryption or audit as well, set
1211*5c591343SA. Cody Schuffelen // the corresponding Indexes.
1212*5c591343SA. Cody Schuffelen
1213*5c591343SA. Cody Schuffelen // First process decrypt.
1214*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt))
1215*5c591343SA. Cody Schuffelen {
1216*5c591343SA. Cody Schuffelen // Check if the commandCode allows command parameter encryption.
1217*5c591343SA. Cody Schuffelen if(DecryptSize(command->index) == 0)
1218*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1219*5c591343SA. Cody Schuffelen // Encrypt attribute can only appear in one session
1220*5c591343SA. Cody Schuffelen if(s_decryptSessionIndex != UNDEFINED_INDEX)
1221*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1222*5c591343SA. Cody Schuffelen // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL
1223*5c591343SA. Cody Schuffelen if(session->symmetric.algorithm == TPM_ALG_NULL)
1224*5c591343SA. Cody Schuffelen return TPM_RCS_SYMMETRIC + errorIndex;
1225*5c591343SA. Cody Schuffelen // All checks passed, so set the index for the session used to decrypt
1226*5c591343SA. Cody Schuffelen // a command parameter.
1227*5c591343SA. Cody Schuffelen s_decryptSessionIndex = sessionIndex;
1228*5c591343SA. Cody Schuffelen }
1229*5c591343SA. Cody Schuffelen // Now process encrypt.
1230*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt))
1231*5c591343SA. Cody Schuffelen {
1232*5c591343SA. Cody Schuffelen // Check if the commandCode allows response parameter encryption.
1233*5c591343SA. Cody Schuffelen if(EncryptSize(command->index) == 0)
1234*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1235*5c591343SA. Cody Schuffelen // Encrypt attribute can only appear in one session.
1236*5c591343SA. Cody Schuffelen if(s_encryptSessionIndex != UNDEFINED_INDEX)
1237*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1238*5c591343SA. Cody Schuffelen // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL
1239*5c591343SA. Cody Schuffelen if(session->symmetric.algorithm == TPM_ALG_NULL)
1240*5c591343SA. Cody Schuffelen return TPM_RCS_SYMMETRIC + errorIndex;
1241*5c591343SA. Cody Schuffelen // All checks passed, so set the index for the session used to encrypt
1242*5c591343SA. Cody Schuffelen // a response parameter.
1243*5c591343SA. Cody Schuffelen s_encryptSessionIndex = sessionIndex;
1244*5c591343SA. Cody Schuffelen }
1245*5c591343SA. Cody Schuffelen // At last process audit.
1246*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit))
1247*5c591343SA. Cody Schuffelen {
1248*5c591343SA. Cody Schuffelen // Audit attribute can only appear in one session.
1249*5c591343SA. Cody Schuffelen if(s_auditSessionIndex != UNDEFINED_INDEX)
1250*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1251*5c591343SA. Cody Schuffelen // An audit session can not be policy session.
1252*5c591343SA. Cody Schuffelen if(HandleGetType(s_sessionHandles[sessionIndex])
1253*5c591343SA. Cody Schuffelen == TPM_HT_POLICY_SESSION)
1254*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1255*5c591343SA. Cody Schuffelen // If this is a reset of the audit session, or the first use
1256*5c591343SA. Cody Schuffelen // of the session as an audit session, it doesn't matter what
1257*5c591343SA. Cody Schuffelen // the exclusive state is. The session will become exclusive.
1258*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)
1259*5c591343SA. Cody Schuffelen && session->attributes.isAudit == SET)
1260*5c591343SA. Cody Schuffelen {
1261*5c591343SA. Cody Schuffelen // Not first use or reset. If auditExlusive is SET, then this
1262*5c591343SA. Cody Schuffelen // session must be the current exclusive session.
1263*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
1264*5c591343SA. Cody Schuffelen && g_exclusiveAuditSession != s_sessionHandles[sessionIndex])
1265*5c591343SA. Cody Schuffelen return TPM_RC_EXCLUSIVE;
1266*5c591343SA. Cody Schuffelen }
1267*5c591343SA. Cody Schuffelen s_auditSessionIndex = sessionIndex;
1268*5c591343SA. Cody Schuffelen }
1269*5c591343SA. Cody Schuffelen // Initialize associated handle as undefined. This will be changed when
1270*5c591343SA. Cody Schuffelen // the handles are processed.
1271*5c591343SA. Cody Schuffelen s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
1272*5c591343SA. Cody Schuffelen }
1273*5c591343SA. Cody Schuffelen command->sessionNum = sessionIndex;
1274*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1275*5c591343SA. Cody Schuffelen }
1276*5c591343SA. Cody Schuffelen
1277*5c591343SA. Cody Schuffelen //*** CheckLockedOut()
1278*5c591343SA. Cody Schuffelen // This function checks to see if the TPM is in lockout. This function should only
1279*5c591343SA. Cody Schuffelen // be called if the entity being checked is subject to DA protection. The TPM
1280*5c591343SA. Cody Schuffelen // is in lockout if the NV is not available and a DA write is pending. Otherwise
1281*5c591343SA. Cody Schuffelen // the TPM is locked out if checking for lockoutAuth ('lockoutAuthCheck' == TRUE)
1282*5c591343SA. Cody Schuffelen // and use of lockoutAuth is disabled, or 'failedTries' >= 'maxTries'
1283*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1284*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting
1285*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available at this time
1286*5c591343SA. Cody Schuffelen // TPM_RC_LOCKOUT TPM is in lockout
1287*5c591343SA. Cody Schuffelen static TPM_RC
CheckLockedOut(BOOL lockoutAuthCheck)1288*5c591343SA. Cody Schuffelen CheckLockedOut(
1289*5c591343SA. Cody Schuffelen BOOL lockoutAuthCheck // IN: TRUE if checking is for lockoutAuth
1290*5c591343SA. Cody Schuffelen )
1291*5c591343SA. Cody Schuffelen {
1292*5c591343SA. Cody Schuffelen // If NV is unavailable, and current cycle state recorded in NV is not
1293*5c591343SA. Cody Schuffelen // SU_NONE_VALUE, refuse to check any authorization because we would
1294*5c591343SA. Cody Schuffelen // not be able to handle a DA failure.
1295*5c591343SA. Cody Schuffelen if(!NV_IS_AVAILABLE && NV_IS_ORDERLY)
1296*5c591343SA. Cody Schuffelen return g_NvStatus;
1297*5c591343SA. Cody Schuffelen // Check if DA info needs to be updated in NV.
1298*5c591343SA. Cody Schuffelen if(s_DAPendingOnNV)
1299*5c591343SA. Cody Schuffelen {
1300*5c591343SA. Cody Schuffelen // If NV is accessible,
1301*5c591343SA. Cody Schuffelen RETURN_IF_NV_IS_NOT_AVAILABLE;
1302*5c591343SA. Cody Schuffelen
1303*5c591343SA. Cody Schuffelen // ... write the pending DA data and proceed.
1304*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(lockOutAuthEnabled);
1305*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(failedTries);
1306*5c591343SA. Cody Schuffelen s_DAPendingOnNV = FALSE;
1307*5c591343SA. Cody Schuffelen }
1308*5c591343SA. Cody Schuffelen // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth
1309*5c591343SA. Cody Schuffelen // is disabled...
1310*5c591343SA. Cody Schuffelen if(lockoutAuthCheck)
1311*5c591343SA. Cody Schuffelen {
1312*5c591343SA. Cody Schuffelen if(gp.lockOutAuthEnabled == FALSE)
1313*5c591343SA. Cody Schuffelen return TPM_RC_LOCKOUT;
1314*5c591343SA. Cody Schuffelen }
1315*5c591343SA. Cody Schuffelen else
1316*5c591343SA. Cody Schuffelen {
1317*5c591343SA. Cody Schuffelen // ... or if the number of failed tries has been maxed out.
1318*5c591343SA. Cody Schuffelen if(gp.failedTries >= gp.maxTries)
1319*5c591343SA. Cody Schuffelen return TPM_RC_LOCKOUT;
1320*5c591343SA. Cody Schuffelen #if USE_DA_USED
1321*5c591343SA. Cody Schuffelen // If the daUsed flag is not SET, then no DA validation until the
1322*5c591343SA. Cody Schuffelen // daUsed state is written to NV
1323*5c591343SA. Cody Schuffelen if(!g_daUsed)
1324*5c591343SA. Cody Schuffelen {
1325*5c591343SA. Cody Schuffelen RETURN_IF_NV_IS_NOT_AVAILABLE;
1326*5c591343SA. Cody Schuffelen g_daUsed = TRUE;
1327*5c591343SA. Cody Schuffelen gp.orderlyState = SU_DA_USED_VALUE;
1328*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(orderlyState);
1329*5c591343SA. Cody Schuffelen return TPM_RC_RETRY;
1330*5c591343SA. Cody Schuffelen }
1331*5c591343SA. Cody Schuffelen #endif
1332*5c591343SA. Cody Schuffelen }
1333*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1334*5c591343SA. Cody Schuffelen }
1335*5c591343SA. Cody Schuffelen
1336*5c591343SA. Cody Schuffelen //*** CheckAuthSession()
1337*5c591343SA. Cody Schuffelen // This function checks that the authorization session properly authorizes the
1338*5c591343SA. Cody Schuffelen // use of the associated handle.
1339*5c591343SA. Cody Schuffelen //
1340*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1341*5c591343SA. Cody Schuffelen // TPM_RC_LOCKOUT entity is protected by DA and TPM is in
1342*5c591343SA. Cody Schuffelen // lockout, or TPM is locked out on NV update
1343*5c591343SA. Cody Schuffelen // pending on DA parameters
1344*5c591343SA. Cody Schuffelen //
1345*5c591343SA. Cody Schuffelen // TPM_RC_PP Physical Presence is required but not provided
1346*5c591343SA. Cody Schuffelen // TPM_RC_AUTH_FAIL HMAC or PW authorization failed
1347*5c591343SA. Cody Schuffelen // with DA side-effects (can be a policy session)
1348*5c591343SA. Cody Schuffelen //
1349*5c591343SA. Cody Schuffelen // TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA
1350*5c591343SA. Cody Schuffelen // side-effects (can be a policy session)
1351*5c591343SA. Cody Schuffelen //
1352*5c591343SA. Cody Schuffelen // TPM_RC_POLICY_FAIL if policy session fails
1353*5c591343SA. Cody Schuffelen // TPM_RC_POLICY_CC command code of policy was wrong
1354*5c591343SA. Cody Schuffelen // TPM_RC_EXPIRED the policy session has expired
1355*5c591343SA. Cody Schuffelen // TPM_RC_PCR
1356*5c591343SA. Cody Schuffelen // TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable
1357*5c591343SA. Cody Schuffelen static TPM_RC
CheckAuthSession(COMMAND * command,UINT32 sessionIndex)1358*5c591343SA. Cody Schuffelen CheckAuthSession(
1359*5c591343SA. Cody Schuffelen COMMAND *command, // IN: primary parsing structure
1360*5c591343SA. Cody Schuffelen UINT32 sessionIndex // IN: index of session to be processed
1361*5c591343SA. Cody Schuffelen )
1362*5c591343SA. Cody Schuffelen {
1363*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1364*5c591343SA. Cody Schuffelen SESSION *session = NULL;
1365*5c591343SA. Cody Schuffelen TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex];
1366*5c591343SA. Cody Schuffelen TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex];
1367*5c591343SA. Cody Schuffelen TPM_HT sessionHandleType = HandleGetType(sessionHandle);
1368*5c591343SA. Cody Schuffelen BOOL authUsed;
1369*5c591343SA. Cody Schuffelen //
1370*5c591343SA. Cody Schuffelen pAssert(sessionHandle != TPM_RH_UNASSIGNED);
1371*5c591343SA. Cody Schuffelen
1372*5c591343SA. Cody Schuffelen // Take care of physical presence
1373*5c591343SA. Cody Schuffelen if(associatedHandle == TPM_RH_PLATFORM)
1374*5c591343SA. Cody Schuffelen {
1375*5c591343SA. Cody Schuffelen // If the physical presence is required for this command, check for PP
1376*5c591343SA. Cody Schuffelen // assertion. If it isn't asserted, no point going any further.
1377*5c591343SA. Cody Schuffelen if(PhysicalPresenceIsRequired(command->index)
1378*5c591343SA. Cody Schuffelen && !_plat__PhysicalPresenceAsserted())
1379*5c591343SA. Cody Schuffelen return TPM_RC_PP;
1380*5c591343SA. Cody Schuffelen }
1381*5c591343SA. Cody Schuffelen if(sessionHandle != TPM_RS_PW)
1382*5c591343SA. Cody Schuffelen {
1383*5c591343SA. Cody Schuffelen session = SessionGet(sessionHandle);
1384*5c591343SA. Cody Schuffelen
1385*5c591343SA. Cody Schuffelen // Set includeAuth to indicate if DA checking will be required and if the
1386*5c591343SA. Cody Schuffelen // authValue will be included in any HMAC.
1387*5c591343SA. Cody Schuffelen if(sessionHandleType == TPM_HT_POLICY_SESSION)
1388*5c591343SA. Cody Schuffelen {
1389*5c591343SA. Cody Schuffelen // For a policy session, will check the DA status of the entity if either
1390*5c591343SA. Cody Schuffelen // isAuthValueNeeded or isPasswordNeeded is SET.
1391*5c591343SA. Cody Schuffelen session->attributes.includeAuth =
1392*5c591343SA. Cody Schuffelen session->attributes.isAuthValueNeeded
1393*5c591343SA. Cody Schuffelen || session->attributes.isPasswordNeeded;
1394*5c591343SA. Cody Schuffelen }
1395*5c591343SA. Cody Schuffelen else
1396*5c591343SA. Cody Schuffelen {
1397*5c591343SA. Cody Schuffelen // For an HMAC session, need to check unless the session
1398*5c591343SA. Cody Schuffelen // is bound.
1399*5c591343SA. Cody Schuffelen session->attributes.includeAuth =
1400*5c591343SA. Cody Schuffelen !IsSessionBindEntity(s_associatedHandles[sessionIndex], session);
1401*5c591343SA. Cody Schuffelen }
1402*5c591343SA. Cody Schuffelen authUsed = session->attributes.includeAuth;
1403*5c591343SA. Cody Schuffelen }
1404*5c591343SA. Cody Schuffelen else
1405*5c591343SA. Cody Schuffelen // Password session
1406*5c591343SA. Cody Schuffelen authUsed = TRUE;
1407*5c591343SA. Cody Schuffelen // If the authorization session is going to use an authValue, then make sure
1408*5c591343SA. Cody Schuffelen // that access to that authValue isn't locked out.
1409*5c591343SA. Cody Schuffelen if(authUsed)
1410*5c591343SA. Cody Schuffelen {
1411*5c591343SA. Cody Schuffelen // See if entity is subject to lockout.
1412*5c591343SA. Cody Schuffelen if(!IsDAExempted(associatedHandle))
1413*5c591343SA. Cody Schuffelen {
1414*5c591343SA. Cody Schuffelen // See if in lockout
1415*5c591343SA. Cody Schuffelen result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT);
1416*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1417*5c591343SA. Cody Schuffelen return result;
1418*5c591343SA. Cody Schuffelen }
1419*5c591343SA. Cody Schuffelen }
1420*5c591343SA. Cody Schuffelen // Policy or HMAC+PW?
1421*5c591343SA. Cody Schuffelen if(sessionHandleType != TPM_HT_POLICY_SESSION)
1422*5c591343SA. Cody Schuffelen {
1423*5c591343SA. Cody Schuffelen // for non-policy session make sure that a policy session is not required
1424*5c591343SA. Cody Schuffelen if(IsPolicySessionRequired(command->index, sessionIndex))
1425*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_TYPE;
1426*5c591343SA. Cody Schuffelen // The authValue must be available.
1427*5c591343SA. Cody Schuffelen // Note: The authValue is going to be "used" even if it is an EmptyAuth.
1428*5c591343SA. Cody Schuffelen // and the session is bound.
1429*5c591343SA. Cody Schuffelen if(!IsAuthValueAvailable(associatedHandle, command->index, sessionIndex))
1430*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_UNAVAILABLE;
1431*5c591343SA. Cody Schuffelen }
1432*5c591343SA. Cody Schuffelen else
1433*5c591343SA. Cody Schuffelen {
1434*5c591343SA. Cody Schuffelen // ... see if the entity has a policy, ...
1435*5c591343SA. Cody Schuffelen // Note: IsAuthPolicyAvalable will return FALSE if the sensitive area of the
1436*5c591343SA. Cody Schuffelen // object is not loaded
1437*5c591343SA. Cody Schuffelen if(!IsAuthPolicyAvailable(associatedHandle, command->index, sessionIndex))
1438*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_UNAVAILABLE;
1439*5c591343SA. Cody Schuffelen // ... and check the policy session.
1440*5c591343SA. Cody Schuffelen result = CheckPolicyAuthSession(command, sessionIndex);
1441*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1442*5c591343SA. Cody Schuffelen return result;
1443*5c591343SA. Cody Schuffelen }
1444*5c591343SA. Cody Schuffelen // Check authorization according to the type
1445*5c591343SA. Cody Schuffelen if((TPM_RS_PW == sessionHandle) || (session->attributes.isPasswordNeeded == SET))
1446*5c591343SA. Cody Schuffelen result = CheckPWAuthSession(sessionIndex);
1447*5c591343SA. Cody Schuffelen else
1448*5c591343SA. Cody Schuffelen result = CheckSessionHMAC(command, sessionIndex);
1449*5c591343SA. Cody Schuffelen // Do processing for PIN Indexes are only three possibilities for 'result' at
1450*5c591343SA. Cody Schuffelen // this point: TPM_RC_SUCCESS, TPM_RC_AUTH_FAIL, and TPM_RC_BAD_AUTH.
1451*5c591343SA. Cody Schuffelen // For all these cases, we would have to process a PIN index if the
1452*5c591343SA. Cody Schuffelen // authValue of the index was used for authorization.
1453*5c591343SA. Cody Schuffelen if((TPM_HT_NV_INDEX == HandleGetType(associatedHandle)) && authUsed)
1454*5c591343SA. Cody Schuffelen {
1455*5c591343SA. Cody Schuffelen NV_REF locator;
1456*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex = NvGetIndexInfo(associatedHandle, &locator);
1457*5c591343SA. Cody Schuffelen NV_PIN pinData;
1458*5c591343SA. Cody Schuffelen TPMA_NV nvAttributes;
1459*5c591343SA. Cody Schuffelen //
1460*5c591343SA. Cody Schuffelen pAssert(nvIndex != NULL);
1461*5c591343SA. Cody Schuffelen nvAttributes = nvIndex->publicArea.attributes;
1462*5c591343SA. Cody Schuffelen // If this is a PIN FAIL index and the value has been written
1463*5c591343SA. Cody Schuffelen // then we can update the counter (increment or clear)
1464*5c591343SA. Cody Schuffelen if(IsNvPinFailIndex(nvAttributes)
1465*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
1466*5c591343SA. Cody Schuffelen {
1467*5c591343SA. Cody Schuffelen pinData.intVal = NvGetUINT64Data(nvIndex, locator);
1468*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1469*5c591343SA. Cody Schuffelen pinData.pin.pinCount++;
1470*5c591343SA. Cody Schuffelen else
1471*5c591343SA. Cody Schuffelen pinData.pin.pinCount = 0;
1472*5c591343SA. Cody Schuffelen NvWriteUINT64Data(nvIndex, pinData.intVal);
1473*5c591343SA. Cody Schuffelen }
1474*5c591343SA. Cody Schuffelen // If this is a PIN PASS Index, increment if we have used the
1475*5c591343SA. Cody Schuffelen // authorization value.
1476*5c591343SA. Cody Schuffelen // NOTE: If the counter has already hit the limit, then we
1477*5c591343SA. Cody Schuffelen // would not get here because the authorization value would not
1478*5c591343SA. Cody Schuffelen // be available and the TPM would have returned before it gets here
1479*5c591343SA. Cody Schuffelen else if(IsNvPinPassIndex(nvAttributes)
1480*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)
1481*5c591343SA. Cody Schuffelen && result == TPM_RC_SUCCESS)
1482*5c591343SA. Cody Schuffelen {
1483*5c591343SA. Cody Schuffelen // If the access is valid, then increment the use counter
1484*5c591343SA. Cody Schuffelen pinData.intVal = NvGetUINT64Data(nvIndex, locator);
1485*5c591343SA. Cody Schuffelen pinData.pin.pinCount++;
1486*5c591343SA. Cody Schuffelen NvWriteUINT64Data(nvIndex, pinData.intVal);
1487*5c591343SA. Cody Schuffelen }
1488*5c591343SA. Cody Schuffelen }
1489*5c591343SA. Cody Schuffelen return result;
1490*5c591343SA. Cody Schuffelen }
1491*5c591343SA. Cody Schuffelen
1492*5c591343SA. Cody Schuffelen #ifdef TPM_CC_GetCommandAuditDigest
1493*5c591343SA. Cody Schuffelen //*** CheckCommandAudit()
1494*5c591343SA. Cody Schuffelen // This function is called before the command is processed if audit is enabled
1495*5c591343SA. Cody Schuffelen // for the command. It will check to see if the audit can be performed and
1496*5c591343SA. Cody Schuffelen // will ensure that the cpHash is available for the audit.
1497*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1498*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available for write
1499*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting
1500*5c591343SA. Cody Schuffelen static TPM_RC
CheckCommandAudit(COMMAND * command)1501*5c591343SA. Cody Schuffelen CheckCommandAudit(
1502*5c591343SA. Cody Schuffelen COMMAND *command
1503*5c591343SA. Cody Schuffelen )
1504*5c591343SA. Cody Schuffelen {
1505*5c591343SA. Cody Schuffelen // If the audit digest is clear and command audit is required, NV must be
1506*5c591343SA. Cody Schuffelen // available so that TPM2_GetCommandAuditDigest() is able to increment
1507*5c591343SA. Cody Schuffelen // audit counter. If NV is not available, the function bails out to prevent
1508*5c591343SA. Cody Schuffelen // the TPM from attempting an operation that would fail anyway.
1509*5c591343SA. Cody Schuffelen if(gr.commandAuditDigest.t.size == 0
1510*5c591343SA. Cody Schuffelen || GetCommandCode(command->index) == TPM_CC_GetCommandAuditDigest)
1511*5c591343SA. Cody Schuffelen {
1512*5c591343SA. Cody Schuffelen RETURN_IF_NV_IS_NOT_AVAILABLE;
1513*5c591343SA. Cody Schuffelen }
1514*5c591343SA. Cody Schuffelen // Make sure that the cpHash is computed for the algorithm
1515*5c591343SA. Cody Schuffelen ComputeCpHash(command, gp.auditHashAlg);
1516*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1517*5c591343SA. Cody Schuffelen }
1518*5c591343SA. Cody Schuffelen #endif
1519*5c591343SA. Cody Schuffelen
1520*5c591343SA. Cody Schuffelen //*** ParseSessionBuffer()
1521*5c591343SA. Cody Schuffelen // This function is the entry function for command session processing.
1522*5c591343SA. Cody Schuffelen // It iterates sessions in session area and reports if the required authorization
1523*5c591343SA. Cody Schuffelen // has been properly provided. It also processes audit session and passes the
1524*5c591343SA. Cody Schuffelen // information of encryption sessions to parameter encryption module.
1525*5c591343SA. Cody Schuffelen //
1526*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1527*5c591343SA. Cody Schuffelen // various parsing failure or authorization failure
1528*5c591343SA. Cody Schuffelen //
1529*5c591343SA. Cody Schuffelen TPM_RC
ParseSessionBuffer(COMMAND * command)1530*5c591343SA. Cody Schuffelen ParseSessionBuffer(
1531*5c591343SA. Cody Schuffelen COMMAND *command // IN: the structure that contains
1532*5c591343SA. Cody Schuffelen )
1533*5c591343SA. Cody Schuffelen {
1534*5c591343SA. Cody Schuffelen TPM_RC result;
1535*5c591343SA. Cody Schuffelen UINT32 i;
1536*5c591343SA. Cody Schuffelen INT32 size = 0;
1537*5c591343SA. Cody Schuffelen TPM2B_AUTH extraKey;
1538*5c591343SA. Cody Schuffelen UINT32 sessionIndex;
1539*5c591343SA. Cody Schuffelen TPM_RC errorIndex;
1540*5c591343SA. Cody Schuffelen SESSION *session = NULL;
1541*5c591343SA. Cody Schuffelen //
1542*5c591343SA. Cody Schuffelen // Check if a command allows any session in its session area.
1543*5c591343SA. Cody Schuffelen if(!IsSessionAllowed(command->index))
1544*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_CONTEXT;
1545*5c591343SA. Cody Schuffelen // Default-initialization.
1546*5c591343SA. Cody Schuffelen command->sessionNum = 0;
1547*5c591343SA. Cody Schuffelen
1548*5c591343SA. Cody Schuffelen result = RetrieveSessionData(command);
1549*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1550*5c591343SA. Cody Schuffelen return result;
1551*5c591343SA. Cody Schuffelen // There is no command in the TPM spec that has more handles than
1552*5c591343SA. Cody Schuffelen // MAX_SESSION_NUM.
1553*5c591343SA. Cody Schuffelen pAssert(command->handleNum <= MAX_SESSION_NUM);
1554*5c591343SA. Cody Schuffelen
1555*5c591343SA. Cody Schuffelen // Associate the session with an authorization handle.
1556*5c591343SA. Cody Schuffelen for(i = 0; i < command->handleNum; i++)
1557*5c591343SA. Cody Schuffelen {
1558*5c591343SA. Cody Schuffelen if(CommandAuthRole(command->index, i) != AUTH_NONE)
1559*5c591343SA. Cody Schuffelen {
1560*5c591343SA. Cody Schuffelen // If the received session number is less than the number of handles
1561*5c591343SA. Cody Schuffelen // that requires authorization, an error should be returned.
1562*5c591343SA. Cody Schuffelen // Note: for all the TPM 2.0 commands, handles requiring
1563*5c591343SA. Cody Schuffelen // authorization come first in a command input and there are only ever
1564*5c591343SA. Cody Schuffelen // two values requiring authorization
1565*5c591343SA. Cody Schuffelen if(i > (command->sessionNum - 1))
1566*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_MISSING;
1567*5c591343SA. Cody Schuffelen // Record the handle associated with the authorization session
1568*5c591343SA. Cody Schuffelen s_associatedHandles[i] = command->handles[i];
1569*5c591343SA. Cody Schuffelen }
1570*5c591343SA. Cody Schuffelen }
1571*5c591343SA. Cody Schuffelen // Consistency checks are done first to avoid authorization failure when the
1572*5c591343SA. Cody Schuffelen // command will not be executed anyway.
1573*5c591343SA. Cody Schuffelen for(sessionIndex = 0; sessionIndex < command->sessionNum; sessionIndex++)
1574*5c591343SA. Cody Schuffelen {
1575*5c591343SA. Cody Schuffelen errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];
1576*5c591343SA. Cody Schuffelen // PW session must be an authorization session
1577*5c591343SA. Cody Schuffelen if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
1578*5c591343SA. Cody Schuffelen {
1579*5c591343SA. Cody Schuffelen if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED)
1580*5c591343SA. Cody Schuffelen return TPM_RCS_HANDLE + errorIndex;
1581*5c591343SA. Cody Schuffelen // a password session can't be audit, encrypt or decrypt
1582*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)
1583*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)
1584*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
1585*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1586*5c591343SA. Cody Schuffelen session = NULL;
1587*5c591343SA. Cody Schuffelen }
1588*5c591343SA. Cody Schuffelen else
1589*5c591343SA. Cody Schuffelen {
1590*5c591343SA. Cody Schuffelen session = SessionGet(s_sessionHandles[sessionIndex]);
1591*5c591343SA. Cody Schuffelen
1592*5c591343SA. Cody Schuffelen // A trial session can not appear in session area, because it cannot
1593*5c591343SA. Cody Schuffelen // be used for authorization, audit or encrypt/decrypt.
1594*5c591343SA. Cody Schuffelen if(session->attributes.isTrialPolicy == SET)
1595*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1596*5c591343SA. Cody Schuffelen
1597*5c591343SA. Cody Schuffelen // See if the session is bound to a DA protected entity
1598*5c591343SA. Cody Schuffelen // NOTE: Since a policy session is never bound, a policy is still
1599*5c591343SA. Cody Schuffelen // usable even if the object is DA protected and the TPM is in
1600*5c591343SA. Cody Schuffelen // lockout.
1601*5c591343SA. Cody Schuffelen if(session->attributes.isDaBound == SET)
1602*5c591343SA. Cody Schuffelen {
1603*5c591343SA. Cody Schuffelen result = CheckLockedOut(session->attributes.isLockoutBound == SET);
1604*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1605*5c591343SA. Cody Schuffelen return result;
1606*5c591343SA. Cody Schuffelen }
1607*5c591343SA. Cody Schuffelen // If this session is for auditing, make sure the cpHash is computed.
1608*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit))
1609*5c591343SA. Cody Schuffelen ComputeCpHash(command, session->authHashAlg);
1610*5c591343SA. Cody Schuffelen }
1611*5c591343SA. Cody Schuffelen
1612*5c591343SA. Cody Schuffelen // if the session has an associated handle, check the authorization
1613*5c591343SA. Cody Schuffelen if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
1614*5c591343SA. Cody Schuffelen {
1615*5c591343SA. Cody Schuffelen result = CheckAuthSession(command, sessionIndex);
1616*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1617*5c591343SA. Cody Schuffelen return RcSafeAddToResult(result, errorIndex);
1618*5c591343SA. Cody Schuffelen }
1619*5c591343SA. Cody Schuffelen else
1620*5c591343SA. Cody Schuffelen {
1621*5c591343SA. Cody Schuffelen // a session that is not for authorization must either be encrypt,
1622*5c591343SA. Cody Schuffelen // decrypt, or audit
1623*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)
1624*5c591343SA. Cody Schuffelen && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)
1625*5c591343SA. Cody Schuffelen && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
1626*5c591343SA. Cody Schuffelen return TPM_RCS_ATTRIBUTES + errorIndex;
1627*5c591343SA. Cody Schuffelen
1628*5c591343SA. Cody Schuffelen // no authValue included in any of the HMAC computations
1629*5c591343SA. Cody Schuffelen pAssert(session != NULL);
1630*5c591343SA. Cody Schuffelen session->attributes.includeAuth = CLEAR;
1631*5c591343SA. Cody Schuffelen
1632*5c591343SA. Cody Schuffelen // check HMAC for encrypt/decrypt/audit only sessions
1633*5c591343SA. Cody Schuffelen result = CheckSessionHMAC(command, sessionIndex);
1634*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1635*5c591343SA. Cody Schuffelen return RcSafeAddToResult(result, errorIndex);
1636*5c591343SA. Cody Schuffelen }
1637*5c591343SA. Cody Schuffelen }
1638*5c591343SA. Cody Schuffelen #ifdef TPM_CC_GetCommandAuditDigest
1639*5c591343SA. Cody Schuffelen // Check if the command should be audited. Need to do this before any parameter
1640*5c591343SA. Cody Schuffelen // encryption so that the cpHash for the audit is correct
1641*5c591343SA. Cody Schuffelen if(CommandAuditIsRequired(command->index))
1642*5c591343SA. Cody Schuffelen {
1643*5c591343SA. Cody Schuffelen result = CheckCommandAudit(command);
1644*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1645*5c591343SA. Cody Schuffelen return result; // No session number to reference
1646*5c591343SA. Cody Schuffelen }
1647*5c591343SA. Cody Schuffelen #endif
1648*5c591343SA. Cody Schuffelen // Decrypt the first parameter if applicable. This should be the last operation
1649*5c591343SA. Cody Schuffelen // in session processing.
1650*5c591343SA. Cody Schuffelen // If the encrypt session is associated with a handle and the handle's
1651*5c591343SA. Cody Schuffelen // authValue is available, then authValue is concatenated with sessionKey to
1652*5c591343SA. Cody Schuffelen // generate encryption key, no matter if the handle is the session bound entity
1653*5c591343SA. Cody Schuffelen // or not.
1654*5c591343SA. Cody Schuffelen if(s_decryptSessionIndex != UNDEFINED_INDEX)
1655*5c591343SA. Cody Schuffelen {
1656*5c591343SA. Cody Schuffelen // If this is an authorization session, include the authValue in the
1657*5c591343SA. Cody Schuffelen // generation of the decryption key
1658*5c591343SA. Cody Schuffelen if(s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED)
1659*5c591343SA. Cody Schuffelen {
1660*5c591343SA. Cody Schuffelen EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex],
1661*5c591343SA. Cody Schuffelen &extraKey);
1662*5c591343SA. Cody Schuffelen }
1663*5c591343SA. Cody Schuffelen else
1664*5c591343SA. Cody Schuffelen {
1665*5c591343SA. Cody Schuffelen extraKey.b.size = 0;
1666*5c591343SA. Cody Schuffelen }
1667*5c591343SA. Cody Schuffelen size = DecryptSize(command->index);
1668*5c591343SA. Cody Schuffelen result = CryptParameterDecryption(s_sessionHandles[s_decryptSessionIndex],
1669*5c591343SA. Cody Schuffelen &s_nonceCaller[s_decryptSessionIndex].b,
1670*5c591343SA. Cody Schuffelen command->parameterSize, (UINT16)size,
1671*5c591343SA. Cody Schuffelen &extraKey,
1672*5c591343SA. Cody Schuffelen command->parameterBuffer);
1673*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1674*5c591343SA. Cody Schuffelen return RcSafeAddToResult(result,
1675*5c591343SA. Cody Schuffelen TPM_RC_S + g_rcIndex[s_decryptSessionIndex]);
1676*5c591343SA. Cody Schuffelen }
1677*5c591343SA. Cody Schuffelen
1678*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1679*5c591343SA. Cody Schuffelen }
1680*5c591343SA. Cody Schuffelen
1681*5c591343SA. Cody Schuffelen //*** CheckAuthNoSession()
1682*5c591343SA. Cody Schuffelen // Function to process a command with no session associated.
1683*5c591343SA. Cody Schuffelen // The function makes sure all the handles in the command require no authorization.
1684*5c591343SA. Cody Schuffelen //
1685*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1686*5c591343SA. Cody Schuffelen // TPM_RC_AUTH_MISSING failure - one or more handles require
1687*5c591343SA. Cody Schuffelen // authorization
1688*5c591343SA. Cody Schuffelen TPM_RC
CheckAuthNoSession(COMMAND * command)1689*5c591343SA. Cody Schuffelen CheckAuthNoSession(
1690*5c591343SA. Cody Schuffelen COMMAND *command // IN: command parsing structure
1691*5c591343SA. Cody Schuffelen )
1692*5c591343SA. Cody Schuffelen {
1693*5c591343SA. Cody Schuffelen UINT32 i;
1694*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1695*5c591343SA. Cody Schuffelen //
1696*5c591343SA. Cody Schuffelen // Check if the command requires authorization
1697*5c591343SA. Cody Schuffelen for(i = 0; i < command->handleNum; i++)
1698*5c591343SA. Cody Schuffelen {
1699*5c591343SA. Cody Schuffelen if(CommandAuthRole(command->index, i) != AUTH_NONE)
1700*5c591343SA. Cody Schuffelen return TPM_RC_AUTH_MISSING;
1701*5c591343SA. Cody Schuffelen }
1702*5c591343SA. Cody Schuffelen #ifdef TPM_CC_GetCommandAuditDigest
1703*5c591343SA. Cody Schuffelen // Check if the command should be audited.
1704*5c591343SA. Cody Schuffelen if(CommandAuditIsRequired(command->index))
1705*5c591343SA. Cody Schuffelen {
1706*5c591343SA. Cody Schuffelen result = CheckCommandAudit(command);
1707*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1708*5c591343SA. Cody Schuffelen return result;
1709*5c591343SA. Cody Schuffelen }
1710*5c591343SA. Cody Schuffelen #endif
1711*5c591343SA. Cody Schuffelen // Initialize number of sessions to be 0
1712*5c591343SA. Cody Schuffelen command->sessionNum = 0;
1713*5c591343SA. Cody Schuffelen
1714*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1715*5c591343SA. Cody Schuffelen }
1716*5c591343SA. Cody Schuffelen
1717*5c591343SA. Cody Schuffelen //** Response Session Processing
1718*5c591343SA. Cody Schuffelen //*** Introduction
1719*5c591343SA. Cody Schuffelen //
1720*5c591343SA. Cody Schuffelen // The following functions build the session area in a response and handle
1721*5c591343SA. Cody Schuffelen // the audit sessions (if present).
1722*5c591343SA. Cody Schuffelen //
1723*5c591343SA. Cody Schuffelen
1724*5c591343SA. Cody Schuffelen //*** ComputeRpHash()
1725*5c591343SA. Cody Schuffelen // Function to compute rpHash (Response Parameter Hash). The rpHash is only
1726*5c591343SA. Cody Schuffelen // computed if there is an HMAC authorization session and the return code is
1727*5c591343SA. Cody Schuffelen // TPM_RC_SUCCESS.
1728*5c591343SA. Cody Schuffelen static TPM2B_DIGEST *
ComputeRpHash(COMMAND * command,TPM_ALG_ID hashAlg)1729*5c591343SA. Cody Schuffelen ComputeRpHash(
1730*5c591343SA. Cody Schuffelen COMMAND *command, // IN: command structure
1731*5c591343SA. Cody Schuffelen TPM_ALG_ID hashAlg // IN: hash algorithm to compute rpHash
1732*5c591343SA. Cody Schuffelen )
1733*5c591343SA. Cody Schuffelen {
1734*5c591343SA. Cody Schuffelen TPM2B_DIGEST *rpHash = GetRpHashPointer(command, hashAlg);
1735*5c591343SA. Cody Schuffelen HASH_STATE hashState;
1736*5c591343SA. Cody Schuffelen //
1737*5c591343SA. Cody Schuffelen if(rpHash->t.size == 0)
1738*5c591343SA. Cody Schuffelen {
1739*5c591343SA. Cody Schuffelen // rpHash := hash(responseCode || commandCode || parameters)
1740*5c591343SA. Cody Schuffelen
1741*5c591343SA. Cody Schuffelen // Initiate hash creation.
1742*5c591343SA. Cody Schuffelen rpHash->t.size = CryptHashStart(&hashState, hashAlg);
1743*5c591343SA. Cody Schuffelen
1744*5c591343SA. Cody Schuffelen // Add hash constituents.
1745*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hashState, sizeof(TPM_RC), TPM_RC_SUCCESS);
1746*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);
1747*5c591343SA. Cody Schuffelen CryptDigestUpdate(&hashState, command->parameterSize,
1748*5c591343SA. Cody Schuffelen command->parameterBuffer);
1749*5c591343SA. Cody Schuffelen // Complete hash computation.
1750*5c591343SA. Cody Schuffelen CryptHashEnd2B(&hashState, &rpHash->b);
1751*5c591343SA. Cody Schuffelen }
1752*5c591343SA. Cody Schuffelen return rpHash;
1753*5c591343SA. Cody Schuffelen }
1754*5c591343SA. Cody Schuffelen
1755*5c591343SA. Cody Schuffelen //*** InitAuditSession()
1756*5c591343SA. Cody Schuffelen // This function initializes the audit data in an audit session.
1757*5c591343SA. Cody Schuffelen static void
InitAuditSession(SESSION * session)1758*5c591343SA. Cody Schuffelen InitAuditSession(
1759*5c591343SA. Cody Schuffelen SESSION *session // session to be initialized
1760*5c591343SA. Cody Schuffelen )
1761*5c591343SA. Cody Schuffelen {
1762*5c591343SA. Cody Schuffelen // Mark session as an audit session.
1763*5c591343SA. Cody Schuffelen session->attributes.isAudit = SET;
1764*5c591343SA. Cody Schuffelen
1765*5c591343SA. Cody Schuffelen // Audit session can not be bound.
1766*5c591343SA. Cody Schuffelen session->attributes.isBound = CLEAR;
1767*5c591343SA. Cody Schuffelen
1768*5c591343SA. Cody Schuffelen // Size of the audit log is the size of session hash algorithm digest.
1769*5c591343SA. Cody Schuffelen session->u2.auditDigest.t.size = CryptHashGetDigestSize(session->authHashAlg);
1770*5c591343SA. Cody Schuffelen
1771*5c591343SA. Cody Schuffelen // Set the original digest value to be 0.
1772*5c591343SA. Cody Schuffelen MemorySet(&session->u2.auditDigest.t.buffer,
1773*5c591343SA. Cody Schuffelen 0,
1774*5c591343SA. Cody Schuffelen session->u2.auditDigest.t.size);
1775*5c591343SA. Cody Schuffelen return;
1776*5c591343SA. Cody Schuffelen }
1777*5c591343SA. Cody Schuffelen
1778*5c591343SA. Cody Schuffelen //*** UpdateAuditDigest
1779*5c591343SA. Cody Schuffelen // Function to update an audit digest
1780*5c591343SA. Cody Schuffelen static void
UpdateAuditDigest(COMMAND * command,TPMI_ALG_HASH hashAlg,TPM2B_DIGEST * digest)1781*5c591343SA. Cody Schuffelen UpdateAuditDigest(
1782*5c591343SA. Cody Schuffelen COMMAND *command,
1783*5c591343SA. Cody Schuffelen TPMI_ALG_HASH hashAlg,
1784*5c591343SA. Cody Schuffelen TPM2B_DIGEST *digest
1785*5c591343SA. Cody Schuffelen )
1786*5c591343SA. Cody Schuffelen {
1787*5c591343SA. Cody Schuffelen HASH_STATE hashState;
1788*5c591343SA. Cody Schuffelen TPM2B_DIGEST *cpHash = GetCpHash(command, hashAlg);
1789*5c591343SA. Cody Schuffelen TPM2B_DIGEST *rpHash = ComputeRpHash(command, hashAlg);
1790*5c591343SA. Cody Schuffelen //
1791*5c591343SA. Cody Schuffelen pAssert(cpHash != NULL);
1792*5c591343SA. Cody Schuffelen
1793*5c591343SA. Cody Schuffelen // digestNew := hash (digestOld || cpHash || rpHash)
1794*5c591343SA. Cody Schuffelen // Start hash computation.
1795*5c591343SA. Cody Schuffelen digest->t.size = CryptHashStart(&hashState, hashAlg);
1796*5c591343SA. Cody Schuffelen // Add old digest.
1797*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &digest->b);
1798*5c591343SA. Cody Schuffelen // Add cpHash
1799*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &cpHash->b);
1800*5c591343SA. Cody Schuffelen // Add rpHash
1801*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hashState, &rpHash->b);
1802*5c591343SA. Cody Schuffelen // Finalize the hash.
1803*5c591343SA. Cody Schuffelen CryptHashEnd2B(&hashState, &digest->b);
1804*5c591343SA. Cody Schuffelen }
1805*5c591343SA. Cody Schuffelen
1806*5c591343SA. Cody Schuffelen
1807*5c591343SA. Cody Schuffelen //*** Audit()
1808*5c591343SA. Cody Schuffelen //This function updates the audit digest in an audit session.
1809*5c591343SA. Cody Schuffelen static void
Audit(COMMAND * command,SESSION * auditSession)1810*5c591343SA. Cody Schuffelen Audit(
1811*5c591343SA. Cody Schuffelen COMMAND *command, // IN: primary control structure
1812*5c591343SA. Cody Schuffelen SESSION *auditSession // IN: loaded audit session
1813*5c591343SA. Cody Schuffelen )
1814*5c591343SA. Cody Schuffelen {
1815*5c591343SA. Cody Schuffelen UpdateAuditDigest(command, auditSession->authHashAlg,
1816*5c591343SA. Cody Schuffelen &auditSession->u2.auditDigest);
1817*5c591343SA. Cody Schuffelen return;
1818*5c591343SA. Cody Schuffelen }
1819*5c591343SA. Cody Schuffelen
1820*5c591343SA. Cody Schuffelen #ifdef TPM_CC_GetCommandAuditDigest
1821*5c591343SA. Cody Schuffelen //*** CommandAudit()
1822*5c591343SA. Cody Schuffelen // This function updates the command audit digest.
1823*5c591343SA. Cody Schuffelen static void
CommandAudit(COMMAND * command)1824*5c591343SA. Cody Schuffelen CommandAudit(
1825*5c591343SA. Cody Schuffelen COMMAND *command // IN:
1826*5c591343SA. Cody Schuffelen )
1827*5c591343SA. Cody Schuffelen {
1828*5c591343SA. Cody Schuffelen // If the digest.size is one, it indicates the special case of changing
1829*5c591343SA. Cody Schuffelen // the audit hash algorithm. For this case, no audit is done on exit.
1830*5c591343SA. Cody Schuffelen // NOTE: When the hash algorithm is changed, g_updateNV is set in order to
1831*5c591343SA. Cody Schuffelen // force an update to the NV on exit so that the change in digest will
1832*5c591343SA. Cody Schuffelen // be recorded. So, it is safe to exit here without setting any flags
1833*5c591343SA. Cody Schuffelen // because the digest change will be written to NV when this code exits.
1834*5c591343SA. Cody Schuffelen if(gr.commandAuditDigest.t.size == 1)
1835*5c591343SA. Cody Schuffelen {
1836*5c591343SA. Cody Schuffelen gr.commandAuditDigest.t.size = 0;
1837*5c591343SA. Cody Schuffelen return;
1838*5c591343SA. Cody Schuffelen }
1839*5c591343SA. Cody Schuffelen // If the digest size is zero, need to start a new digest and increment
1840*5c591343SA. Cody Schuffelen // the audit counter.
1841*5c591343SA. Cody Schuffelen if(gr.commandAuditDigest.t.size == 0)
1842*5c591343SA. Cody Schuffelen {
1843*5c591343SA. Cody Schuffelen gr.commandAuditDigest.t.size = CryptHashGetDigestSize(gp.auditHashAlg);
1844*5c591343SA. Cody Schuffelen MemorySet(gr.commandAuditDigest.t.buffer,
1845*5c591343SA. Cody Schuffelen 0,
1846*5c591343SA. Cody Schuffelen gr.commandAuditDigest.t.size);
1847*5c591343SA. Cody Schuffelen
1848*5c591343SA. Cody Schuffelen // Bump the counter and save its value to NV.
1849*5c591343SA. Cody Schuffelen gp.auditCounter++;
1850*5c591343SA. Cody Schuffelen NV_SYNC_PERSISTENT(auditCounter);
1851*5c591343SA. Cody Schuffelen }
1852*5c591343SA. Cody Schuffelen UpdateAuditDigest(command, gp.auditHashAlg, &gr.commandAuditDigest);
1853*5c591343SA. Cody Schuffelen return;
1854*5c591343SA. Cody Schuffelen }
1855*5c591343SA. Cody Schuffelen #endif
1856*5c591343SA. Cody Schuffelen
1857*5c591343SA. Cody Schuffelen //*** UpdateAuditSessionStatus()
1858*5c591343SA. Cody Schuffelen // This function updates the internal audit related states of a session. It will:
1859*5c591343SA. Cody Schuffelen // a) initialize the session as audit session and set it to be exclusive if this
1860*5c591343SA. Cody Schuffelen // is the first time it is used for audit or audit reset was requested;
1861*5c591343SA. Cody Schuffelen // b) report exclusive audit session;
1862*5c591343SA. Cody Schuffelen // c) extend audit log; and
1863*5c591343SA. Cody Schuffelen // d) clear exclusive audit session if no audit session found in the command.
1864*5c591343SA. Cody Schuffelen static void
UpdateAuditSessionStatus(COMMAND * command)1865*5c591343SA. Cody Schuffelen UpdateAuditSessionStatus(
1866*5c591343SA. Cody Schuffelen COMMAND *command // IN: primary control structure
1867*5c591343SA. Cody Schuffelen )
1868*5c591343SA. Cody Schuffelen {
1869*5c591343SA. Cody Schuffelen UINT32 i;
1870*5c591343SA. Cody Schuffelen TPM_HANDLE auditSession = TPM_RH_UNASSIGNED;
1871*5c591343SA. Cody Schuffelen //
1872*5c591343SA. Cody Schuffelen // Iterate through sessions
1873*5c591343SA. Cody Schuffelen for(i = 0; i < command->sessionNum; i++)
1874*5c591343SA. Cody Schuffelen {
1875*5c591343SA. Cody Schuffelen SESSION *session;
1876*5c591343SA. Cody Schuffelen //
1877*5c591343SA. Cody Schuffelen // PW session do not have a loaded session and can not be an audit
1878*5c591343SA. Cody Schuffelen // session either. Skip it.
1879*5c591343SA. Cody Schuffelen if(s_sessionHandles[i] == TPM_RS_PW)
1880*5c591343SA. Cody Schuffelen continue;
1881*5c591343SA. Cody Schuffelen session = SessionGet(s_sessionHandles[i]);
1882*5c591343SA. Cody Schuffelen
1883*5c591343SA. Cody Schuffelen // If a session is used for audit
1884*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit))
1885*5c591343SA. Cody Schuffelen {
1886*5c591343SA. Cody Schuffelen // An audit session has been found
1887*5c591343SA. Cody Schuffelen auditSession = s_sessionHandles[i];
1888*5c591343SA. Cody Schuffelen
1889*5c591343SA. Cody Schuffelen // If the session has not been an audit session yet, or
1890*5c591343SA. Cody Schuffelen // the auditSetting bits indicate a reset, initialize it and set
1891*5c591343SA. Cody Schuffelen // it to be the exclusive session
1892*5c591343SA. Cody Schuffelen if(session->attributes.isAudit == CLEAR
1893*5c591343SA. Cody Schuffelen || IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset))
1894*5c591343SA. Cody Schuffelen {
1895*5c591343SA. Cody Schuffelen InitAuditSession(session);
1896*5c591343SA. Cody Schuffelen g_exclusiveAuditSession = auditSession;
1897*5c591343SA. Cody Schuffelen }
1898*5c591343SA. Cody Schuffelen else
1899*5c591343SA. Cody Schuffelen {
1900*5c591343SA. Cody Schuffelen // Check if the audit session is the current exclusive audit
1901*5c591343SA. Cody Schuffelen // session and, if not, clear previous exclusive audit session.
1902*5c591343SA. Cody Schuffelen if(g_exclusiveAuditSession != auditSession)
1903*5c591343SA. Cody Schuffelen g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
1904*5c591343SA. Cody Schuffelen }
1905*5c591343SA. Cody Schuffelen // Report audit session exclusivity.
1906*5c591343SA. Cody Schuffelen if(g_exclusiveAuditSession == auditSession)
1907*5c591343SA. Cody Schuffelen {
1908*5c591343SA. Cody Schuffelen SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);
1909*5c591343SA. Cody Schuffelen }
1910*5c591343SA. Cody Schuffelen else
1911*5c591343SA. Cody Schuffelen {
1912*5c591343SA. Cody Schuffelen CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);
1913*5c591343SA. Cody Schuffelen }
1914*5c591343SA. Cody Schuffelen // Extend audit log.
1915*5c591343SA. Cody Schuffelen Audit(command, session);
1916*5c591343SA. Cody Schuffelen }
1917*5c591343SA. Cody Schuffelen }
1918*5c591343SA. Cody Schuffelen // If no audit session is found in the command, and the command allows
1919*5c591343SA. Cody Schuffelen // a session then, clear the current exclusive
1920*5c591343SA. Cody Schuffelen // audit session.
1921*5c591343SA. Cody Schuffelen if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(command->index))
1922*5c591343SA. Cody Schuffelen {
1923*5c591343SA. Cody Schuffelen g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
1924*5c591343SA. Cody Schuffelen }
1925*5c591343SA. Cody Schuffelen return;
1926*5c591343SA. Cody Schuffelen }
1927*5c591343SA. Cody Schuffelen
1928*5c591343SA. Cody Schuffelen //*** ComputeResponseHMAC()
1929*5c591343SA. Cody Schuffelen // Function to compute HMAC for authorization session in a response.
1930*5c591343SA. Cody Schuffelen /*(See part 1 specification)
1931*5c591343SA. Cody Schuffelen // Function: Compute HMAC for response sessions
1932*5c591343SA. Cody Schuffelen // The sessionAuth value
1933*5c591343SA. Cody Schuffelen // authHMAC := HMACsHASH((sessionAuth | authValue),
1934*5c591343SA. Cody Schuffelen // (pHash | nonceTPM | nonceCaller | sessionAttributes))
1935*5c591343SA. Cody Schuffelen // Where:
1936*5c591343SA. Cody Schuffelen // HMACsHASH() The HMAC algorithm using the hash algorithm specified when
1937*5c591343SA. Cody Schuffelen // the session was started.
1938*5c591343SA. Cody Schuffelen //
1939*5c591343SA. Cody Schuffelen // sessionAuth A TPMB_MEDIUM computed in a protocol-dependent way, using
1940*5c591343SA. Cody Schuffelen // KDFa. In an HMAC or KDF, only sessionAuth.buffer is used.
1941*5c591343SA. Cody Schuffelen //
1942*5c591343SA. Cody Schuffelen // authValue A TPM2B_AUTH that is found in the sensitive area of an
1943*5c591343SA. Cody Schuffelen // object. In an HMAC or KDF, only authValue.buffer is used
1944*5c591343SA. Cody Schuffelen // and all trailing zeros are removed.
1945*5c591343SA. Cody Schuffelen //
1946*5c591343SA. Cody Schuffelen // pHash Response parameters (rpHash) using the session hash. When
1947*5c591343SA. Cody Schuffelen // using a pHash in an HMAC computation, both the algorithm ID
1948*5c591343SA. Cody Schuffelen // and the digest are included.
1949*5c591343SA. Cody Schuffelen //
1950*5c591343SA. Cody Schuffelen // nonceTPM A TPM2B_NONCE that is generated by the entity using the
1951*5c591343SA. Cody Schuffelen // session. In an HMAC or KDF, only nonceTPM.buffer is used.
1952*5c591343SA. Cody Schuffelen //
1953*5c591343SA. Cody Schuffelen // nonceCaller a TPM2B_NONCE that was received the previous time the
1954*5c591343SA. Cody Schuffelen // session was used. In an HMAC or KDF, only
1955*5c591343SA. Cody Schuffelen // nonceCaller.buffer is used.
1956*5c591343SA. Cody Schuffelen //
1957*5c591343SA. Cody Schuffelen // sessionAttributes A TPMA_SESSION that indicates the attributes associated
1958*5c591343SA. Cody Schuffelen // with a particular use of the session.
1959*5c591343SA. Cody Schuffelen */
1960*5c591343SA. Cody Schuffelen static void
ComputeResponseHMAC(COMMAND * command,UINT32 sessionIndex,SESSION * session,TPM2B_DIGEST * hmac)1961*5c591343SA. Cody Schuffelen ComputeResponseHMAC(
1962*5c591343SA. Cody Schuffelen COMMAND *command, // IN: command structure
1963*5c591343SA. Cody Schuffelen UINT32 sessionIndex, // IN: session index to be processed
1964*5c591343SA. Cody Schuffelen SESSION *session, // IN: loaded session
1965*5c591343SA. Cody Schuffelen TPM2B_DIGEST *hmac // OUT: authHMAC
1966*5c591343SA. Cody Schuffelen )
1967*5c591343SA. Cody Schuffelen {
1968*5c591343SA. Cody Schuffelen TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));
1969*5c591343SA. Cody Schuffelen TPM2B_KEY key; // HMAC key
1970*5c591343SA. Cody Schuffelen BYTE marshalBuffer[sizeof(TPMA_SESSION)];
1971*5c591343SA. Cody Schuffelen BYTE *buffer;
1972*5c591343SA. Cody Schuffelen UINT32 marshalSize;
1973*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
1974*5c591343SA. Cody Schuffelen TPM2B_DIGEST *rpHash = ComputeRpHash(command, session->authHashAlg);
1975*5c591343SA. Cody Schuffelen //
1976*5c591343SA. Cody Schuffelen // Generate HMAC key
1977*5c591343SA. Cody Schuffelen MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
1978*5c591343SA. Cody Schuffelen
1979*5c591343SA. Cody Schuffelen // Add the object authValue if required
1980*5c591343SA. Cody Schuffelen if(session->attributes.includeAuth == SET)
1981*5c591343SA. Cody Schuffelen {
1982*5c591343SA. Cody Schuffelen // Note: includeAuth may be SET for a policy that is used in
1983*5c591343SA. Cody Schuffelen // UndefineSpaceSpecial(). At this point, the Index has been deleted
1984*5c591343SA. Cody Schuffelen // so the includeAuth will have no meaning. However, the
1985*5c591343SA. Cody Schuffelen // s_associatedHandles[] value for the session is now set to TPM_RH_NULL so
1986*5c591343SA. Cody Schuffelen // this will return the authValue associated with TPM_RH_NULL and that is
1987*5c591343SA. Cody Schuffelen // and empty buffer.
1988*5c591343SA. Cody Schuffelen TPM2B_AUTH authValue;
1989*5c591343SA. Cody Schuffelen //
1990*5c591343SA. Cody Schuffelen // Get the authValue with trailing zeros removed
1991*5c591343SA. Cody Schuffelen EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);
1992*5c591343SA. Cody Schuffelen
1993*5c591343SA. Cody Schuffelen // Add it to the key
1994*5c591343SA. Cody Schuffelen MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));
1995*5c591343SA. Cody Schuffelen }
1996*5c591343SA. Cody Schuffelen
1997*5c591343SA. Cody Schuffelen // if the HMAC key size is 0, the response HMAC is computed according to the
1998*5c591343SA. Cody Schuffelen // input HMAC
1999*5c591343SA. Cody Schuffelen if(key.t.size == 0
2000*5c591343SA. Cody Schuffelen && s_inputAuthValues[sessionIndex].t.size == 0)
2001*5c591343SA. Cody Schuffelen {
2002*5c591343SA. Cody Schuffelen hmac->t.size = 0;
2003*5c591343SA. Cody Schuffelen return;
2004*5c591343SA. Cody Schuffelen }
2005*5c591343SA. Cody Schuffelen // Start HMAC computation.
2006*5c591343SA. Cody Schuffelen hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);
2007*5c591343SA. Cody Schuffelen
2008*5c591343SA. Cody Schuffelen // Add hash components.
2009*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &rpHash->b);
2010*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);
2011*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);
2012*5c591343SA. Cody Schuffelen
2013*5c591343SA. Cody Schuffelen // Add session attributes.
2014*5c591343SA. Cody Schuffelen buffer = marshalBuffer;
2015*5c591343SA. Cody Schuffelen marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL);
2016*5c591343SA. Cody Schuffelen CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);
2017*5c591343SA. Cody Schuffelen
2018*5c591343SA. Cody Schuffelen // Finalize HMAC.
2019*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &hmac->b);
2020*5c591343SA. Cody Schuffelen
2021*5c591343SA. Cody Schuffelen return;
2022*5c591343SA. Cody Schuffelen }
2023*5c591343SA. Cody Schuffelen
2024*5c591343SA. Cody Schuffelen //*** UpdateInternalSession()
2025*5c591343SA. Cody Schuffelen // This function updates internal sessions by:
2026*5c591343SA. Cody Schuffelen // a) restarting session time; and
2027*5c591343SA. Cody Schuffelen // b) clearing a policy session since nonce is rolling.
2028*5c591343SA. Cody Schuffelen static void
UpdateInternalSession(SESSION * session,UINT32 i)2029*5c591343SA. Cody Schuffelen UpdateInternalSession(
2030*5c591343SA. Cody Schuffelen SESSION *session, // IN: the session structure
2031*5c591343SA. Cody Schuffelen UINT32 i // IN: session number
2032*5c591343SA. Cody Schuffelen )
2033*5c591343SA. Cody Schuffelen {
2034*5c591343SA. Cody Schuffelen // If nonce is rolling in a policy session, the policy related data
2035*5c591343SA. Cody Schuffelen // will be re-initialized.
2036*5c591343SA. Cody Schuffelen if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION
2037*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
2038*5c591343SA. Cody Schuffelen {
2039*5c591343SA. Cody Schuffelen // When the nonce rolls it starts a new timing interval for the
2040*5c591343SA. Cody Schuffelen // policy session.
2041*5c591343SA. Cody Schuffelen SessionResetPolicyData(session);
2042*5c591343SA. Cody Schuffelen SessionSetStartTime(session);
2043*5c591343SA. Cody Schuffelen }
2044*5c591343SA. Cody Schuffelen return;
2045*5c591343SA. Cody Schuffelen }
2046*5c591343SA. Cody Schuffelen
2047*5c591343SA. Cody Schuffelen //*** BuildSingleResponseAuth()
2048*5c591343SA. Cody Schuffelen // Function to compute response HMAC value for a policy or HMAC session.
2049*5c591343SA. Cody Schuffelen static TPM2B_NONCE *
BuildSingleResponseAuth(COMMAND * command,UINT32 sessionIndex,TPM2B_AUTH * auth)2050*5c591343SA. Cody Schuffelen BuildSingleResponseAuth(
2051*5c591343SA. Cody Schuffelen COMMAND *command, // IN: command structure
2052*5c591343SA. Cody Schuffelen UINT32 sessionIndex, // IN: session index to be processed
2053*5c591343SA. Cody Schuffelen TPM2B_AUTH *auth // OUT: authHMAC
2054*5c591343SA. Cody Schuffelen )
2055*5c591343SA. Cody Schuffelen {
2056*5c591343SA. Cody Schuffelen // Fill in policy/HMAC based session response.
2057*5c591343SA. Cody Schuffelen SESSION *session = SessionGet(s_sessionHandles[sessionIndex]);
2058*5c591343SA. Cody Schuffelen //
2059*5c591343SA. Cody Schuffelen // If the session is a policy session with isPasswordNeeded SET, the
2060*5c591343SA. Cody Schuffelen // authorization field is empty.
2061*5c591343SA. Cody Schuffelen if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION
2062*5c591343SA. Cody Schuffelen && session->attributes.isPasswordNeeded == SET)
2063*5c591343SA. Cody Schuffelen auth->t.size = 0;
2064*5c591343SA. Cody Schuffelen else
2065*5c591343SA. Cody Schuffelen // Compute response HMAC.
2066*5c591343SA. Cody Schuffelen ComputeResponseHMAC(command, sessionIndex, session, auth);
2067*5c591343SA. Cody Schuffelen
2068*5c591343SA. Cody Schuffelen UpdateInternalSession(session, sessionIndex);
2069*5c591343SA. Cody Schuffelen return &session->nonceTPM;
2070*5c591343SA. Cody Schuffelen }
2071*5c591343SA. Cody Schuffelen
2072*5c591343SA. Cody Schuffelen //*** UpdateAllNonceTPM()
2073*5c591343SA. Cody Schuffelen // Updates TPM nonce for all sessions in command.
2074*5c591343SA. Cody Schuffelen static void
UpdateAllNonceTPM(COMMAND * command)2075*5c591343SA. Cody Schuffelen UpdateAllNonceTPM(
2076*5c591343SA. Cody Schuffelen COMMAND *command // IN: controlling structure
2077*5c591343SA. Cody Schuffelen )
2078*5c591343SA. Cody Schuffelen {
2079*5c591343SA. Cody Schuffelen UINT32 i;
2080*5c591343SA. Cody Schuffelen SESSION *session;
2081*5c591343SA. Cody Schuffelen //
2082*5c591343SA. Cody Schuffelen for(i = 0; i < command->sessionNum; i++)
2083*5c591343SA. Cody Schuffelen {
2084*5c591343SA. Cody Schuffelen // If not a PW session, compute the new nonceTPM.
2085*5c591343SA. Cody Schuffelen if(s_sessionHandles[i] != TPM_RS_PW)
2086*5c591343SA. Cody Schuffelen {
2087*5c591343SA. Cody Schuffelen session = SessionGet(s_sessionHandles[i]);
2088*5c591343SA. Cody Schuffelen // Update nonceTPM in both internal session and response.
2089*5c591343SA. Cody Schuffelen CryptRandomGenerate(session->nonceTPM.t.size,
2090*5c591343SA. Cody Schuffelen session->nonceTPM.t.buffer);
2091*5c591343SA. Cody Schuffelen }
2092*5c591343SA. Cody Schuffelen }
2093*5c591343SA. Cody Schuffelen return;
2094*5c591343SA. Cody Schuffelen }
2095*5c591343SA. Cody Schuffelen
2096*5c591343SA. Cody Schuffelen
2097*5c591343SA. Cody Schuffelen
2098*5c591343SA. Cody Schuffelen //*** BuildResponseSession()
2099*5c591343SA. Cody Schuffelen // Function to build Session buffer in a response. The authorization data is added
2100*5c591343SA. Cody Schuffelen // to the end of command->responseBuffer. The size of the authorization area is
2101*5c591343SA. Cody Schuffelen // accumulated in command->authSize.
2102*5c591343SA. Cody Schuffelen // When this is called, command->responseBuffer is pointing at the next location
2103*5c591343SA. Cody Schuffelen // in the response buffer to be filled. This is where the authorization sessions
2104*5c591343SA. Cody Schuffelen // will go, if any. command->parameterSize is the number of bytes that have been
2105*5c591343SA. Cody Schuffelen // marshaled as parameters in the output buffer.
2106*5c591343SA. Cody Schuffelen void
BuildResponseSession(COMMAND * command)2107*5c591343SA. Cody Schuffelen BuildResponseSession(
2108*5c591343SA. Cody Schuffelen COMMAND *command // IN: structure that has relevant command
2109*5c591343SA. Cody Schuffelen // information
2110*5c591343SA. Cody Schuffelen )
2111*5c591343SA. Cody Schuffelen {
2112*5c591343SA. Cody Schuffelen pAssert(command->authSize == 0);
2113*5c591343SA. Cody Schuffelen
2114*5c591343SA. Cody Schuffelen // Reset the parameter buffer to point to the start of the parameters so that
2115*5c591343SA. Cody Schuffelen // there is a starting point for any rpHash that might be generated and so there
2116*5c591343SA. Cody Schuffelen // is a place where parameter encryption would start
2117*5c591343SA. Cody Schuffelen command->parameterBuffer = command->responseBuffer - command->parameterSize;
2118*5c591343SA. Cody Schuffelen
2119*5c591343SA. Cody Schuffelen // Session nonces should be updated before parameter encryption
2120*5c591343SA. Cody Schuffelen if(command->tag == TPM_ST_SESSIONS)
2121*5c591343SA. Cody Schuffelen {
2122*5c591343SA. Cody Schuffelen UpdateAllNonceTPM(command);
2123*5c591343SA. Cody Schuffelen
2124*5c591343SA. Cody Schuffelen // Encrypt first parameter if applicable. Parameter encryption should
2125*5c591343SA. Cody Schuffelen // happen after nonce update and before any rpHash is computed.
2126*5c591343SA. Cody Schuffelen // If the encrypt session is associated with a handle, the authValue of
2127*5c591343SA. Cody Schuffelen // this handle will be concatenated with sessionKey to generate
2128*5c591343SA. Cody Schuffelen // encryption key, no matter if the handle is the session bound entity
2129*5c591343SA. Cody Schuffelen // or not. The authValue is added to sessionKey only when the authValue
2130*5c591343SA. Cody Schuffelen // is available.
2131*5c591343SA. Cody Schuffelen if(s_encryptSessionIndex != UNDEFINED_INDEX)
2132*5c591343SA. Cody Schuffelen {
2133*5c591343SA. Cody Schuffelen UINT32 size;
2134*5c591343SA. Cody Schuffelen TPM2B_AUTH extraKey;
2135*5c591343SA. Cody Schuffelen //
2136*5c591343SA. Cody Schuffelen extraKey.b.size = 0;
2137*5c591343SA. Cody Schuffelen // If this is an authorization session, include the authValue in the
2138*5c591343SA. Cody Schuffelen // generation of the encryption key
2139*5c591343SA. Cody Schuffelen if(s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED)
2140*5c591343SA. Cody Schuffelen {
2141*5c591343SA. Cody Schuffelen EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex],
2142*5c591343SA. Cody Schuffelen &extraKey);
2143*5c591343SA. Cody Schuffelen }
2144*5c591343SA. Cody Schuffelen size = EncryptSize(command->index);
2145*5c591343SA. Cody Schuffelen CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex],
2146*5c591343SA. Cody Schuffelen &s_nonceCaller[s_encryptSessionIndex].b,
2147*5c591343SA. Cody Schuffelen (UINT16)size,
2148*5c591343SA. Cody Schuffelen &extraKey,
2149*5c591343SA. Cody Schuffelen command->parameterBuffer);
2150*5c591343SA. Cody Schuffelen }
2151*5c591343SA. Cody Schuffelen }
2152*5c591343SA. Cody Schuffelen // Audit sessions should be processed regardless of the tag because
2153*5c591343SA. Cody Schuffelen // a command with no session may cause a change of the exclusivity state.
2154*5c591343SA. Cody Schuffelen UpdateAuditSessionStatus(command);
2155*5c591343SA. Cody Schuffelen #if CC_GetCommandAuditDigest
2156*5c591343SA. Cody Schuffelen // Command Audit
2157*5c591343SA. Cody Schuffelen if(CommandAuditIsRequired(command->index))
2158*5c591343SA. Cody Schuffelen CommandAudit(command);
2159*5c591343SA. Cody Schuffelen #endif
2160*5c591343SA. Cody Schuffelen // Process command with sessions.
2161*5c591343SA. Cody Schuffelen if(command->tag == TPM_ST_SESSIONS)
2162*5c591343SA. Cody Schuffelen {
2163*5c591343SA. Cody Schuffelen UINT32 i;
2164*5c591343SA. Cody Schuffelen //
2165*5c591343SA. Cody Schuffelen pAssert(command->sessionNum > 0);
2166*5c591343SA. Cody Schuffelen
2167*5c591343SA. Cody Schuffelen // Iterate over each session in the command session area, and create
2168*5c591343SA. Cody Schuffelen // corresponding sessions for response.
2169*5c591343SA. Cody Schuffelen for(i = 0; i < command->sessionNum; i++)
2170*5c591343SA. Cody Schuffelen {
2171*5c591343SA. Cody Schuffelen TPM2B_NONCE *nonceTPM;
2172*5c591343SA. Cody Schuffelen TPM2B_DIGEST responseAuth;
2173*5c591343SA. Cody Schuffelen // Make sure that continueSession is SET on any Password session.
2174*5c591343SA. Cody Schuffelen // This makes it marginally easier for the management software
2175*5c591343SA. Cody Schuffelen // to keep track of the closed sessions.
2176*5c591343SA. Cody Schuffelen if(s_sessionHandles[i] == TPM_RS_PW)
2177*5c591343SA. Cody Schuffelen {
2178*5c591343SA. Cody Schuffelen SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession);
2179*5c591343SA. Cody Schuffelen responseAuth.t.size = 0;
2180*5c591343SA. Cody Schuffelen nonceTPM = (TPM2B_NONCE *)&responseAuth;
2181*5c591343SA. Cody Schuffelen }
2182*5c591343SA. Cody Schuffelen else
2183*5c591343SA. Cody Schuffelen {
2184*5c591343SA. Cody Schuffelen // Compute the response HMAC and get a pointer to the nonce used.
2185*5c591343SA. Cody Schuffelen // This function will also update the values if needed. Note, the
2186*5c591343SA. Cody Schuffelen nonceTPM = BuildSingleResponseAuth(command, i, &responseAuth);
2187*5c591343SA. Cody Schuffelen }
2188*5c591343SA. Cody Schuffelen command->authSize += TPM2B_NONCE_Marshal(nonceTPM,
2189*5c591343SA. Cody Schuffelen &command->responseBuffer,
2190*5c591343SA. Cody Schuffelen NULL);
2191*5c591343SA. Cody Schuffelen command->authSize += TPMA_SESSION_Marshal(&s_attributes[i],
2192*5c591343SA. Cody Schuffelen &command->responseBuffer,
2193*5c591343SA. Cody Schuffelen NULL);
2194*5c591343SA. Cody Schuffelen command->authSize += TPM2B_DIGEST_Marshal(&responseAuth,
2195*5c591343SA. Cody Schuffelen &command->responseBuffer,
2196*5c591343SA. Cody Schuffelen NULL);
2197*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
2198*5c591343SA. Cody Schuffelen SessionFlush(s_sessionHandles[i]);
2199*5c591343SA. Cody Schuffelen }
2200*5c591343SA. Cody Schuffelen }
2201*5c591343SA. Cody Schuffelen return;
2202*5c591343SA. Cody Schuffelen }
2203*5c591343SA. Cody Schuffelen
2204*5c591343SA. Cody Schuffelen //*** SessionRemoveAssociationToHandle()
2205*5c591343SA. Cody Schuffelen // This function deals with the case where an entity associated with an authorization
2206*5c591343SA. Cody Schuffelen // is deleted during command processing. The primary use of this is to support
2207*5c591343SA. Cody Schuffelen // UndefineSpaceSpecial().
2208*5c591343SA. Cody Schuffelen void
SessionRemoveAssociationToHandle(TPM_HANDLE handle)2209*5c591343SA. Cody Schuffelen SessionRemoveAssociationToHandle(
2210*5c591343SA. Cody Schuffelen TPM_HANDLE handle
2211*5c591343SA. Cody Schuffelen )
2212*5c591343SA. Cody Schuffelen {
2213*5c591343SA. Cody Schuffelen UINT32 i;
2214*5c591343SA. Cody Schuffelen //
2215*5c591343SA. Cody Schuffelen for(i = 0; i < MAX_SESSION_NUM; i++)
2216*5c591343SA. Cody Schuffelen {
2217*5c591343SA. Cody Schuffelen if(s_associatedHandles[i] == handle)
2218*5c591343SA. Cody Schuffelen {
2219*5c591343SA. Cody Schuffelen s_associatedHandles[i] = TPM_RH_NULL;
2220*5c591343SA. Cody Schuffelen }
2221*5c591343SA. Cody Schuffelen }
2222*5c591343SA. Cody Schuffelen }