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