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 }