Coverage Report

Created: 2025-05-12 07:04

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