xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
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 }