• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2001

10 Jun 2025 05:34PM UTC coverage: 76.734% (-0.5%) from 77.211%
#2001

push

travis-ci

web-flow
Merge 953b57ed4 into 9d6d76cc6

26 of 29 new or added lines in 2 files covered. (89.66%)

2807 existing lines in 74 files now uncovered.

33291 of 43385 relevant lines covered (76.73%)

61752.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.07
/src/tpm2/SessionProcess.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                Process the Authorization Sessions                                     */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*            $Id: SessionProcess.c 1493 2019-09-04 13:31:35Z kgoldman $        */
7
/*                                                                                */
8
/*  Licenses and Notices                                                        */
9
/*                                                                                */
10
/*  1. Copyright Licenses:                                                        */
11
/*                                                                                */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in        */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,                 */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create         */
15
/*    derivative works, distribute, display and perform the Source Code and        */
16
/*    derivative works thereof, and to grant others the rights granted herein.        */
17
/*                                                                                */
18
/*  - The TCG grants to the user of the other parts of the specification         */
19
/*    (other than the Source Code) the rights to reproduce, distribute,         */
20
/*    display, and perform the specification solely for the purpose of                 */
21
/*    developing products based on such documents.                                */
22
/*                                                                                */
23
/*  2. Source Code Distribution Conditions:                                        */
24
/*                                                                                */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,         */
26
/*    this list of conditions and the following disclaimers.                        */
27
/*                                                                                */
28
/*  - Redistributions in binary form must reproduce the above copyright         */
29
/*    licenses, this list of conditions        and the following disclaimers in the         */
30
/*    documentation and/or other materials provided with the distribution.        */
31
/*                                                                                */
32
/*  3. Disclaimers:                                                                */
33
/*                                                                                */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF        */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH        */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)        */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.                */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for                 */
39
/*  information on specification licensing rights available through TCG         */
40
/*  membership agreements.                                                        */
41
/*                                                                                */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED         */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR         */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR                 */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY                 */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.                */
47
/*                                                                                */
48
/*  - Without limitation, TCG and its members and licensors disclaim all         */
49
/*    liability, including liability for infringement of any proprietary         */
50
/*    rights, relating to use of information in this specification and to the        */
51
/*    implementation of this specification, and TCG disclaims all liability for        */
52
/*    cost of procurement of substitute goods or services, lost profits, loss         */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,         */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,         */
55
/*    arising in any way out of use or reliance upon this specification or any         */
56
/*    information herein.                                                        */
57
/*                                                                                */
58
/*  (c) Copyright IBM Corp. and others, 2016 - 2018                                */
59
/*                                                                                */
60
/********************************************************************************/
61

62
/* 6.4 SessionProcess.c */
63
/* 6.4.1 Introduction */
64
/* This file contains the subsystem that process the authorization sessions including implementation
65
   of the Dictionary Attack logic. ExecCommand() uses ParseSessionBuffer() to process the
66
   authorization session area of a command and BuildResponseSession() to create the authorization
67
   session area of a response */
68
#define SESSION_PROCESS_C
69
#include "Tpm.h"
70
/* 6.4.3.1 IsDAExempted() */
71
/* This function indicates if a handle is exempted from DA logic. A handle is exempted if it is */
72
/* a) a primary seed handle, */
73
/* b) an object with noDA bit SET, */
74
/* c) an NV Index with TPMA_NV_NO_DA bit SET, or */
75
/* d)        a PCR handle. */
76
BOOL
77
IsDAExempted(
5,806✔
78
             TPM_HANDLE       handle         // IN: entity handle
79
             )
80
{
81
    BOOL        result = FALSE;
5,806✔
82
    //
83
    switch(HandleGetType(handle))
5,806✔
84
        {
85
          case TPM_HT_PERMANENT:
3,339✔
86
            // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from
87
            // DA protection.
88
            result = (handle != TPM_RH_LOCKOUT);
3,339✔
89
            break;
3,339✔
90
            // When this function is called, a persistent object will have been loaded
91
            // into an object slot and assigned a transient handle.
92
          case TPM_HT_TRANSIENT:
1,667✔
93
              {
94
                  TPMA_OBJECT     attributes = ObjectGetPublicAttributes(handle);
1,667✔
95
                  result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA);
1,667✔
96
                  break;
1,667✔
97
              }
98
          case TPM_HT_NV_INDEX:
512✔
99
              {
100
                  NV_INDEX            *nvIndex = NvGetIndexInfo(handle, NULL);
512✔
101
                  result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA);
512✔
102
                  break;
512✔
103
              }
104
          case TPM_HT_PCR:
288✔
105
            // PCRs are always exempted from DA.
106
            result = TRUE;
288✔
107
            break;
288✔
108
          default:
109
            break;
110
        }
111
    return result;
5,806✔
112
}
113
/* 6.4.3.2 IncrementLockout() */
114
/* This function is called after an authorization failure that involves use of an authValue. If the
115
   entity referenced by the handle is not exempt from DA protection, then the failedTries counter
116
   will be incremented. */
117
static TPM_RC
118
IncrementLockout(
88✔
119
                 UINT32           sessionIndex
120
                 )
121
{
122
    TPM_HANDLE       handle = s_associatedHandles[sessionIndex];
88✔
123
    TPM_HANDLE       sessionHandle = s_sessionHandles[sessionIndex];
88✔
124
    SESSION         *session = NULL;
88✔
125
    //
126
    // Don't increment lockout unless the handle associated with the session
127
    // is DA protected or the session is bound to a DA protected entity.
128
    if(sessionHandle == TPM_RS_PW)
88✔
129
        {
130
            if(IsDAExempted(handle))
77✔
131
                return TPM_RC_BAD_AUTH;
132
        }
133
    else
134
        {
135
            session = SessionGet(sessionHandle);
11✔
136
            // If the session is bound to lockout, then use that as the relevant
137
            // handle. This means that an authorization failure with a bound session
138
            // bound to lockoutAuth will take precedence over any other
139
            // lockout check
140
            if(session->attributes.isLockoutBound == SET)
11✔
UNCOV
141
                handle = TPM_RH_LOCKOUT;
×
142
            if(session->attributes.isDaBound == CLEAR
11✔
143
               && (IsDAExempted(handle) || session->attributes.includeAuth == CLEAR))
11✔
144
                // If the handle was changed to TPM_RH_LOCKOUT, this will not return
145
                // TPM_RC_BAD_AUTH
146
                return TPM_RC_BAD_AUTH;
147
        }
148
    if(handle == TPM_RH_LOCKOUT)
19✔
149
        {
150
            pAssert(gp.lockOutAuthEnabled == TRUE);
4✔
151
            // lockout is no longer enabled
152
            gp.lockOutAuthEnabled = FALSE;
4✔
153
            // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since
154
            // the lockout authorization will be reset at startup.
155
            if(gp.lockoutRecovery != 0)
4✔
156
                {
157
                    if(NV_IS_AVAILABLE)
4✔
158
                        // Update NV.
159
                        NV_SYNC_PERSISTENT(lockOutAuthEnabled);
4✔
160
                    else
161
                        // No NV access for now. Put the TPM in pending mode.
UNCOV
162
                        s_DAPendingOnNV = TRUE;
×
163
                }
164
        }
165
    else
166
        {
167
            if(gp.recoveryTime != 0)
15✔
168
                {
169
                    gp.failedTries++;
15✔
170
                    if(NV_IS_AVAILABLE)
15✔
171
                        // Record changes to NV. NvWrite will SET g_updateNV
172
                        NV_SYNC_PERSISTENT(failedTries);
15✔
173
                    else
174
                        // No NV access for now.  Put the TPM in pending mode.
UNCOV
175
                        s_DAPendingOnNV = TRUE;
×
176
                }
177
        }
178
    // Register a DA failure and reset the timers.
179
    DARegisterFailure(handle);
19✔
180
    return TPM_RC_AUTH_FAIL;
19✔
181
}
182
/* 6.4.3.3 IsSessionBindEntity() */
183
/* This function indicates if the entity associated with the handle is the entity, to which this
184
   session is bound. The binding would occur by making the bind parameter in TPM2_StartAuthSession()
185
   not equal to TPM_RH_NULL. The binding only occurs if the session is an HMAC session. The bind
186
   value is a combination of the Name and the authValue of the entity. */
187
static BOOL
188
IsSessionBindEntity(
727✔
189
                    TPM_HANDLE       associatedHandle,  // IN: handle to be authorized
190
                    SESSION         *session            // IN: associated session
191
                    )
192
{
193
    TPM2B_NAME     entity;             // The bind value for the entity
727✔
194
    // If the session is not bound, return FALSE.
195
    if(session->attributes.isBound)
727✔
196
        {
197
            // Compute the bind value for the entity.
198
            SessionComputeBoundEntity(associatedHandle, &entity);
60✔
199
            // Compare to the bind value in the session.
200
            return MemoryEqual2B(&entity.b, &session->u1.boundEntity.b);
60✔
201
        }
202
    return FALSE;
203
}
204
/* 6.4.3.4 IsPolicySessionRequired() */
205
/* Checks if a policy session is required for a command. If a command requires DUP or ADMIN role
206
   authorization, then the handle that requires that role is the first handle in the command. This
207
   simplifies this checking. If a new command is created that requires multiple ADMIN role
208
   authorizations, then it will have to be special-cased in this function. A policy session is
209
   required if: */
210
/* a) the command requires the DUP role, */
211
/* b) the command requires the ADMIN role and the authorized entity is an object and its
212
   adminWithPolicy bit is SET, or */
213
/* c) the command requires the ADMIN role and the authorized entity is a permanent handle or an NV
214
   Index. */
215
/* d) The authorized entity is a PCR belonging to a policy group, and has its policy initialized */
216
/* Return Values Meaning */
217
/* TRUE policy session is required */
218
/* FALSE policy session is not required */
219
static BOOL
220
IsPolicySessionRequired(
5,670✔
221
                        COMMAND_INDEX    commandIndex,  // IN: command index
222
                        UINT32           sessionIndex   // IN: session index
223
                        )
224
{
225
    AUTH_ROLE       role = CommandAuthRole(commandIndex, sessionIndex);
5,670✔
226
    TPM_HT          type = HandleGetType(s_associatedHandles[sessionIndex]);
5,670✔
227
    if(role == AUTH_DUP)
5,670✔
228
        return TRUE;
229
    if(role == AUTH_ADMIN)
5,670✔
230
        {
231
            // We allow an exception for ADMIN role in a transient object. If the object
232
            // allows ADMIN role actions with authorization, then policy is not
233
            // required. For all other cases, there is no way to override the command
234
            // requirement that a policy be used
235
            if(type == TPM_HT_TRANSIENT)
220✔
236
                {
237
                    OBJECT      *object = HandleToObject(s_associatedHandles[sessionIndex]);
207✔
238
                    if(!IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
207✔
239
                                     adminWithPolicy))
240
                        return FALSE;
241
                }
242
            return TRUE;
13✔
243
        }
244
    if(type == TPM_HT_PCR)
5,450✔
245
        {
246
            if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex]))
276✔
247
                {
248
                    TPM2B_DIGEST        policy;
8✔
249
                    TPMI_ALG_HASH       policyAlg;
8✔
250
                    policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex],
8✔
251
                                                 &policy);
252
                    if(policyAlg != TPM_ALG_NULL)
8✔
UNCOV
253
                        return TRUE;
×
254
                }
255
        }
256
    return FALSE;
257
}
258
/* 6.4.3.5 IsAuthValueAvailable() */
259
/* This function indicates if authValue is available and allowed for USER role authorization of an
260
   entity. */
261
/* This function is similar to IsAuthPolicyAvailable() except that it does not check the size of the
262
   authValue as IsAuthPolicyAvailable() does (a null authValue is a valid authorization, but a null
263
   policy is not a valid policy). */
264
/* This function does not check that the handle reference is valid or if the entity is in an
265
   enabled hierarchy. Those checks are assumed to have been performed during the handle
266
   unmarshaling. */
267
static BOOL
268
IsAuthValueAvailable(
5,633✔
269
                     TPM_HANDLE       handle,        // IN: handle of entity
270
                     COMMAND_INDEX    commandIndex,  // IN: command index
271
                     UINT32           sessionIndex   // IN: session index
272
                     )
273
{
274
    BOOL             result = FALSE;
5,633✔
275
    //
276
    switch(HandleGetType(handle))
5,633✔
277
        {
278
          case TPM_HT_PERMANENT:
3,266✔
279
            switch(handle)
3,266✔
280
                {
281
                    // At this point hierarchy availability has already been
282
                    // checked so primary seed handles are always available here
283
                  case TPM_RH_OWNER:
3,266✔
284
                  case TPM_RH_ENDORSEMENT:
285
                  case TPM_RH_PLATFORM:
286
#ifdef VENDOR_PERMANENT
287
                    // This vendor defined handle associated with the
288
                    // manufacturer's shared secret
289
                  case VENDOR_PERMANENT:
290
#endif
291
                    // The DA checking has been performed on LockoutAuth but we
292
                    // bypass the DA logic if we are using lockout policy. The
293
                    // policy would allow execution to continue an lockoutAuth
294
                    // could be used, even if direct use of lockoutAuth is disabled
295
                  case TPM_RH_LOCKOUT:
296
                    // NullAuth is always available.
297
                  case TPM_RH_NULL:
298
                    result = TRUE;
3,266✔
299
                    break;
3,266✔
300
                  default:
301
                    // Otherwise authValue is not available.
302
                    break;
303
                }
304
            break;
305
          case TPM_HT_TRANSIENT:
1,656✔
306
            // A persistent object has already been loaded and the internal
307
            // handle changed.
308
              {
309
                  OBJECT          *object;
1,656✔
310
                  TPMA_OBJECT      attributes;
1,656✔
311
                  //
312
                  object = HandleToObject(handle);
1,656✔
313
                  attributes = object->publicArea.objectAttributes;
1,656✔
314
                  // authValue is always available for a sequence object.
315
                  // An alternative for this is to
316
                  // SET_ATTRIBUTE(object->publicArea, TPMA_OBJECT, userWithAuth) when the
317
                  // sequence is started.
318
                  if(ObjectIsSequence(object))
1,656✔
319
                      {
320
                          result = TRUE;
321
                          break;
322
                      }
323
                  // authValue is available for an object if it has its sensitive
324
                  // portion loaded and
325
                  //  1. userWithAuth bit is SET, or
326
                  //  2. ADMIN role is required
327
                  if(object->attributes.publicOnly == CLEAR
1,547✔
328
                     && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth)
1,547✔
329
                         || (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN
4✔
UNCOV
330
                             && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, adminWithPolicy))))
×
331
                      result = TRUE;
332
              }
333
              break;
334
          case TPM_HT_NV_INDEX:
435✔
335
            // NV Index.
336
              {
337
                  NV_REF           locator;
435✔
338
                  NV_INDEX        *nvIndex = NvGetIndexInfo(handle, &locator);
435✔
339
                  TPMA_NV          nvAttributes;
435✔
340
                  //
341
                  pAssert(nvIndex != 0);
435✔
342
                  nvAttributes = nvIndex->publicArea.attributes;
435✔
343
                  if(IsWriteOperation(commandIndex))
435✔
344
                      {
345
                          // AuthWrite can't be set for a PIN index
346
                          if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE))
221✔
347
                              result = TRUE;
217✔
348
                      }
349
                  else
350
                      {
351
                          // A "read" operation
352
                          // For a PIN Index, the authValue is available as long as the
353
                          // Index has been written and the pinCount is less than pinLimit
354
                          if(IsNvPinFailIndex(nvAttributes)
214✔
355
                             || IsNvPinPassIndex(nvAttributes))
214✔
356
                              {
357
                                  NV_PIN          pin;
32✔
358
                                  if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
32✔
359
                                      break; // return false
360
                                  // get the index values
361
                                  pin.intVal = NvGetUINT64Data(nvIndex, locator);
31✔
362
                                  if(pin.pin.pinCount < pin.pin.pinLimit)
31✔
363
                                      result = TRUE;
21✔
364
                              }
365
                          // For non-PIN Indexes, need to allow use of the authValue
366
                          else if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD))
182✔
367
                              result = TRUE;
178✔
368
                      }
369
              }
370
              break;
434✔
371
          case TPM_HT_PCR:
276✔
372
            // PCR handle.
373
            // authValue is always allowed for PCR
374
            result = TRUE;
276✔
375
            break;
276✔
376
          default:
377
            // Otherwise, authValue is not available
378
            break;
379
        }
380
    return result;
5,633✔
381
}
382

383
/* 6.4.3.6        IsAuthPolicyAvailable() */
384
/* This function indicates if an authPolicy is available and allowed. */
385
/* This function does not check that the handle reference is valid or if the entity is in an enabled
386
   hierarchy. Those checks are assumed to have been performed during the handle unmarshaling. */
387
/* Return Values Meaning */
388
/* TRUE authPolicy is available */
389
/* FALSE authPolicy is not available */
390
static BOOL
391
IsAuthPolicyAvailable(
202✔
392
                      TPM_HANDLE       handle,        // IN: handle of entity
393
                      COMMAND_INDEX    commandIndex,  // IN: command index
394
                      UINT32           sessionIndex   // IN: session index
395
                      )
396
{
397
    BOOL            result = FALSE;
202✔
398
    //
399
    switch(HandleGetType(handle))
202✔
400
        {
401
          case TPM_HT_PERMANENT:
7✔
402
            switch(handle)
7✔
403
                {
404
                    // At this point hierarchy availability has already been checked.
UNCOV
405
                  case TPM_RH_OWNER:
×
UNCOV
406
                    if(gp.ownerPolicy.t.size != 0)
×
UNCOV
407
                        result = TRUE;
×
408
                    break;
UNCOV
409
                  case TPM_RH_ENDORSEMENT:
×
UNCOV
410
                    if(gp.endorsementPolicy.t.size != 0)
×
UNCOV
411
                        result = TRUE;
×
412
                    break;
413
                  case TPM_RH_PLATFORM:
7✔
414
                    if(gc.platformPolicy.t.size != 0)
7✔
415
                        result = TRUE;
7✔
416
                    break;
UNCOV
417
                  case TPM_RH_LOCKOUT:
×
UNCOV
418
                    if(gp.lockoutPolicy.t.size != 0)
×
UNCOV
419
                        result = TRUE;
×
420
                    break;
421
                  default:
422
                    break;
423
                }
424
            break;
425
          case TPM_HT_TRANSIENT:
160✔
426
              {
427
                  // Object handle.
428
                  // An evict object would already have been loaded and given a
429
                  // transient object handle by this point.
430
                  OBJECT  *object = HandleToObject(handle);
160✔
431
                  // Policy authorization is not available for an object with only
432
                  // public portion loaded.
433
                  if(object->attributes.publicOnly == CLEAR)
160✔
434
                      {
435
                          // Policy authorization is always available for an object but
436
                          // is never available for a sequence.
437
                          if(!ObjectIsSequence(object))
160✔
438
                              result = TRUE;
160✔
439
                      }
440
                  break;
441
              }
442
          case TPM_HT_NV_INDEX:
35✔
443
            // An NV Index.
444
              {
445
                  NV_INDEX         *nvIndex = NvGetIndexInfo(handle, NULL);
35✔
446
                  TPMA_NV           nvAttributes = nvIndex->publicArea.attributes;
35✔
447
                  //
448
                  // If the policy size is not zero, check if policy can be used.
449
                  if(nvIndex->publicArea.authPolicy.t.size != 0)
35✔
450
                      {
451
                          // If policy session is required for this handle, always
452
                          // uses policy regardless of the attributes bit setting
453
                          if(IsPolicySessionRequired(commandIndex, sessionIndex))
35✔
454
                              result = TRUE;
455
                          // Otherwise, the presence of the policy depends on the NV
456
                          // attributes.
457
                          else if(IsWriteOperation(commandIndex))
24✔
458
                              {
459
                                  if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE))
16✔
460
                                      result = TRUE;
16✔
461
                              }
462
                          else
463
                              {
464
                                  if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD))
8✔
465
                                      result = TRUE;
8✔
466
                              }
467
                      }
468
              }
469
              break;
UNCOV
470
          case TPM_HT_PCR:
×
471
            // PCR handle.
UNCOV
472
            if(PCRPolicyIsAvailable(handle))
×
UNCOV
473
                result = TRUE;
×
474
            break;
475
          default:
476
            break;
477
        }
478
    return result;
202✔
479
}
480
/* 6.4.4 Session Parsing Functions */
481
/* 6.4.4.1 ClearCpRpHashes() */
482
void
483
ClearCpRpHashes(
15,351✔
484
                COMMAND         *command
485
                )
486
{
487
#if ALG_SHA1
488
    command->sha1CpHash.t.size = 0;
15,351✔
489
    command->sha1RpHash.t.size = 0;
15,351✔
490
#endif
491
#if ALG_SHA256
492
    command->sha256CpHash.t.size = 0;
15,351✔
493
    command->sha256RpHash.t.size = 0;
15,351✔
494
#endif
495
#if ALG_SHA384
496
    command->sha384CpHash.t.size = 0;
15,351✔
497
    command->sha384RpHash.t.size = 0;
15,351✔
498
#endif
499
#if ALG_SHA512
500
    command->sha512CpHash.t.size = 0;
15,351✔
501
    command->sha512RpHash.t.size = 0;
15,351✔
502
#endif
503
#if ALG_SM3_256
504
    command->sm3_256CpHash.t.size = 0;
505
    command->sm3_256RpHash.t.size = 0;
506
#endif
507
}
15,351✔
508
/* 6.4.4.2 GetCpHashPointer() */
509
/* Function to get a pointer to the cpHash of the command */
510
static TPM2B_DIGEST *
511
GetCpHashPointer(
1,012✔
512
                 COMMAND         *command,
513
                 TPMI_ALG_HASH    hashAlg
514
                 )
515
{
516
    switch(hashAlg)
1,012✔
517
        {
518
#if ALG_SHA1
519
          case TPM_ALG_SHA1:
24✔
520
            return (TPM2B_DIGEST *)&command->sha1CpHash;
24✔
521
#endif
522
#if ALG_SHA256
523
          case TPM_ALG_SHA256:
858✔
524
            return (TPM2B_DIGEST *)&command->sha256CpHash;
858✔
525
#endif
526
#if ALG_SHA384
527
          case TPM_ALG_SHA384:
24✔
528
            return (TPM2B_DIGEST *)&command->sha384CpHash;
24✔
529
#endif
530
#if ALG_SHA512
531
          case TPM_ALG_SHA512:
106✔
532
            return (TPM2B_DIGEST *)&command->sha512CpHash;
106✔
533
#endif
534
#if ALG_SM3_256
535
          case TPM_ALG_SM3_256:
536
            return (TPM2B_DIGEST *)&command->sm3_256CpHash;
537
#endif
538
          default:
539
            break;
540
        }
541
    return NULL;
542
}
543
/* 6.4.4.3 GetRpHashPointer() */
544
/* Function to get a pointer to the RpHash() of the command */
545
static TPM2B_DIGEST *
546
GetRpHashPointer(
979✔
547
                 COMMAND         *command,
548
                 TPMI_ALG_HASH    hashAlg
549
                 )
550
{
551
    switch(hashAlg)
979✔
552
        {
553
#if ALG_SHA1
554
          case TPM_ALG_SHA1:
19✔
555
            return (TPM2B_DIGEST *)&command->sha1RpHash;
19✔
556
#endif
557
#if ALG_SHA256
558
          case TPM_ALG_SHA256:
901✔
559
            return (TPM2B_DIGEST *)&command->sha256RpHash;
901✔
560
#endif
561
#if ALG_SHA384
562
          case TPM_ALG_SHA384:
22✔
563
            return (TPM2B_DIGEST *)&command->sha384RpHash;
22✔
564
#endif
565
#if ALG_SHA512
566
          case TPM_ALG_SHA512:
37✔
567
            return (TPM2B_DIGEST *)&command->sha512RpHash;
37✔
568
#endif
569
#if ALG_SM3_256
570
          case TPM_ALG_SM3_256:
571
            return (TPM2B_DIGEST *)&command->sm3_256RpHash;
572
#endif
573
          default:
574
            break;
575
        }
576
    return NULL;
577
}
578
/* 6.4.4.4 ComputeCpHash() */
579
/* This function computes the cpHash as defined in Part 2 and described in Part 1. */
580
static TPM2B_DIGEST *
581
ComputeCpHash(
960✔
582
              COMMAND         *command,       // IN: command parsing structure
583
              TPMI_ALG_HASH    hashAlg        // IN: hash algorithm
584
              )
585
{
586
    UINT32               i;
960✔
587
    HASH_STATE           hashState;
960✔
588
    TPM2B_NAME           name;
960✔
589
    TPM2B_DIGEST        *cpHash;
960✔
590
    // cpHash = hash(commandCode [ || authName1
591
    //                           [ || authName2
592
    //                           [ || authName 3 ]]]
593
    //                           [ || parameters])
594
    // A cpHash can contain just a commandCode only if the lone session is
595
    // an audit session.
596
    // Get pointer to the hash value
597
    cpHash = GetCpHashPointer(command, hashAlg);
960✔
598
    if(cpHash->t.size == 0)
960✔
599
        {
600
            cpHash->t.size = CryptHashStart(&hashState, hashAlg);
683✔
601
            //  Add commandCode.
602
            CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);
683✔
603
            //  Add authNames for each of the handles.
604
            for(i = 0; i < command->handleNum; i++)
2,376✔
605
                CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],
1,010✔
606
                                                               &name)->b);
607
            //  Add the parameters.
608
            CryptDigestUpdate(&hashState, command->parameterSize,
683✔
609
                              command->parameterBuffer);
683✔
610
            //  Complete the hash.
611
            CryptHashEnd2B(&hashState, &cpHash->b);
683✔
612
        }
613
    return cpHash;
960✔
614
}
615
/* 6.4.4.5 GetCpHash() */
616
/* This function is used to access a precomputed cpHash. */
617
static TPM2B_DIGEST *
618
GetCpHash(
52✔
619
          COMMAND         *command,
620
          TPMI_ALG_HASH    hashAlg
621
          )
622
{
623
    TPM2B_DIGEST        *cpHash = GetCpHashPointer(command, hashAlg);
52✔
624
    //
625
    pAssert(cpHash->t.size != 0);
52✔
626
    return cpHash;
52✔
627
}
628
/* 6.4.4.6 CompareTemplateHash() */
629
/* This function computes the template hash and compares it to the session templateHash. It is the
630
   hash of the second parameter assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or
631
   TPM2_CreateLoaded() */
632
static BOOL
633
CompareTemplateHash(
3✔
634
                    COMMAND         *command,       // IN: parsing structure
635
                    SESSION         *session        // IN: session data
636
                    )
637
{
638
    BYTE                *pBuffer = command->parameterBuffer;
3✔
639
    INT32                pSize = command->parameterSize;
3✔
640
    TPM2B_DIGEST         tHash;
3✔
641
    UINT16               size;
3✔
642
    //
643
    // Only try this for the three commands for which it is intended
644
    if(command->code != TPM_CC_Create
3✔
645
       && command->code != TPM_CC_CreatePrimary
3✔
646
#if CC_CreateLoaded
647
       && command->code != TPM_CC_CreateLoaded
1✔
648
#endif
649
       )
650
        return FALSE;
651
    // Assume that the first parameter is a TPM2B and unmarshal the size field
652
    // Note: this will not affect the parameter buffer and size in the calling
653
    // function.
654
    if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
3✔
655
        return FALSE;
656
    // reduce the space in the buffer.
657
    // NOTE: this could make pSize go negative if the parameters are not correct but
658
    // the unmarshaling code does not try to unmarshal if the remaining size is
659
    // negative.
660
    pSize -= size;
3✔
661
    // Advance the pointer
662
    pBuffer += size;
3✔
663
    // Get the size of what should be the template
664
    if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
3✔
665
        return FALSE;
666
    // See if this is reasonable
667
    if(size > pSize)
3✔
668
        return FALSE;
669
    // Hash the template data
670
    tHash.t.size = CryptHashBlock(session->authHashAlg, size, pBuffer,
3✔
671
                                  sizeof(tHash.t.buffer), tHash.t.buffer);
672
    return(MemoryEqual2B(&session->u1.templateHash.b, &tHash.b));
3✔
673
}
674
/* 6.4.4.7 CompareNameHash() */
675
/* This function computes the name hash and compares it to the nameHash in the session data. */
676
BOOL
677
CompareNameHash(
3✔
678
                COMMAND         *command,       // IN: main parsing structure
679
                SESSION         *session        // IN: session structure with nameHash
680
                )
681
{
682
    HASH_STATE           hashState;
3✔
683
    TPM2B_DIGEST         nameHash;
3✔
684
    UINT32               i;
3✔
685
    TPM2B_NAME           name;
3✔
686
    //
687
    nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg);
3✔
688
    //  Add names.
689
    for(i = 0; i < command->handleNum; i++)
8✔
690
        CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],
5✔
691
                                                       &name)->b);
692
    //  Complete hash.
693
    CryptHashEnd2B(&hashState, &nameHash.b);
3✔
694
    // and compare
695
    return MemoryEqual(session->u1.nameHash.t.buffer, nameHash.t.buffer,
6✔
696
                       nameHash.t.size);
3✔
697
}
698
/* 6.4.4.8 CheckPWAuthSession() */
699
/* This function validates the authorization provided in a PWAP session. It compares the input value
700
   to authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the
701
   referenced entities from s_inputAuthValues[] and s_associatedHandles[]. */
702
/* Error Returns Meaning */
703
/* TPM_RC_AUTH_FAIL authorization fails and increments DA failure count */
704
/* TPM_RC_BAD_AUTH authorization fails but DA does not apply */
705
static TPM_RC
706
CheckPWAuthSession(
4,893✔
707
                   UINT32           sessionIndex   // IN: index of session to be processed
708
                   )
709
{
710
    TPM2B_AUTH      authValue;
4,893✔
711
    TPM_HANDLE      associatedHandle = s_associatedHandles[sessionIndex];
4,893✔
712
    // Strip trailing zeros from the password.
713
    MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]);
4,893✔
714
    // Get the authValue with trailing zeros removed
715
    EntityGetAuthValue(associatedHandle, &authValue);
4,893✔
716
    // Success if the values are identical.
717
    if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b))
4,893✔
718
        {
719
            return TPM_RC_SUCCESS;
720
        }
721
    else                    // if the digests are not identical
722
        {
723
            // Invoke DA protection if applicable.
724
            return IncrementLockout(sessionIndex);
78✔
725
        }
726
}
727
/* 6.4.4.9 ComputeCommandHMAC() */
728
/* This function computes the HMAC for an authorization session in a command. */
729
static TPM2B_DIGEST *
730
ComputeCommandHMAC(
978✔
731
                   COMMAND         *command,       // IN: primary control structure
732
                   UINT32           sessionIndex,  // IN: index of session to be processed
733
                   TPM2B_DIGEST    *hmac           // OUT: authorization HMAC
734
                   )
735
{
736
    TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));
978✔
737
    TPM2B_KEY        key;
978✔
738
    BYTE             marshalBuffer[sizeof(TPMA_SESSION)];
978✔
739
    BYTE            *buffer;
978✔
740
    UINT32           marshalSize;
978✔
741
    HMAC_STATE       hmacState;
978✔
742
    TPM2B_NONCE     *nonceDecrypt;
978✔
743
    TPM2B_NONCE     *nonceEncrypt;
978✔
744
    SESSION         *session;
978✔
745
    nonceDecrypt = NULL;
978✔
746
    nonceEncrypt = NULL;
978✔
747
    // Determine if extra nonceTPM values are going to be required.
748
    // If this is the first session (sessionIndex = 0) and it is an authorization
749
    // session that uses an HMAC, then check if additional session nonces are to be
750
    // included.
751
    if(sessionIndex == 0
978✔
752
       && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
734✔
753
        {
754
            // If there is a decrypt session and if this is not the decrypt session,
755
            // then an extra nonce may be needed.
756
            if(s_decryptSessionIndex != UNDEFINED_INDEX
723✔
757
               && s_decryptSessionIndex != sessionIndex)
158✔
758
                {
759
                    // Will add the nonce for the decrypt session.
760
                    SESSION *decryptSession
84✔
761
                        = SessionGet(s_sessionHandles[s_decryptSessionIndex]);
84✔
762
                    nonceDecrypt = &decryptSession->nonceTPM;
84✔
763
                }
764
            // Now repeat for the encrypt session.
765
            if(s_encryptSessionIndex != UNDEFINED_INDEX
723✔
766
               && s_encryptSessionIndex != sessionIndex
152✔
767
               && s_encryptSessionIndex != s_decryptSessionIndex)
84✔
768
                {
769
                    // Have to have the nonce for the encrypt session.
770
                    SESSION *encryptSession
64✔
771
                        = SessionGet(s_sessionHandles[s_encryptSessionIndex]);
64✔
772
                    nonceEncrypt = &encryptSession->nonceTPM;
64✔
773
                }
774
        }
775
    // Continue with the HMAC processing.
776
    session = SessionGet(s_sessionHandles[sessionIndex]);
978✔
777
    // Generate HMAC key.
778
    MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
978✔
779
    // Check if the session has an associated handle and if the associated entity
780
    // is the one to which the session is bound. If not, add the authValue of
781
    // this entity to the HMAC key.
782
    // If the session is bound to the object or the session is a policy session
783
    // with no authValue required, do not include the authValue in the HMAC key.
784
    // Note: For a policy session, its isBound attribute is CLEARED.
785
    // Include the entity authValue if it is needed
786
    if(session->attributes.includeAuth == SET)
978✔
787
        {
788
            TPM2B_AUTH          authValue;
690✔
789
            // Get the entity authValue with trailing zeros removed
790
            EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);
690✔
791
            // add the authValue to the HMAC key
792
            MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));
690✔
793
        }
794
    // if the HMAC key size is 0, a NULL string HMAC is allowed
795
    if(key.t.size == 0
978✔
796
       && s_inputAuthValues[sessionIndex].t.size == 0)
238✔
797
        {
798
            hmac->t.size = 0;
122✔
799
            return hmac;
122✔
800
        }
801
    // Start HMAC
802
    hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);
856✔
803
    //  Add cpHash
804
    CryptDigestUpdate2B(&hmacState.hashState,
1,712✔
805
                        &ComputeCpHash(command, session->authHashAlg)->b);
856✔
806
    //  Add nonces as required
807
    CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);
856✔
808
    CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);
856✔
809
    if(nonceDecrypt != NULL)
856✔
810
        CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b);
84✔
811
    if(nonceEncrypt != NULL)
856✔
812
        CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b);
64✔
813
    //  Add sessionAttributes
814
    buffer = marshalBuffer;
856✔
815
    marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]),
856✔
816
                                       &buffer, NULL);
817
    CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);
856✔
818
    // Complete the HMAC computation
819
    CryptHmacEnd2B(&hmacState, &hmac->b);
856✔
820
    return hmac;
856✔
821
}
822
/* 6.4.4.10 CheckSessionHMAC() */
823
/* This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the
824
   expected HMAC value and then compares the result with the HMAC in the authorization session. The
825
   authorization is successful if they are the same. */
826
/* If the authorizations are not the same, IncrementLockout() is called. It will return
827
   TPM_RC_AUTH_FAIL if the failure caused the failureCount to increment. Otherwise, it will return
828
   TPM_RC_BAD_AUTH. */
829
/* Error Returns Meaning */
830
/* TPM_RC_AUTH_FAIL authorization failure caused failureCount increment */
831
/* TPM_RC_BAD_AUTH authorization failure did not cause failureCount increment */
832
static TPM_RC
833
CheckSessionHMAC(
978✔
834
                 COMMAND         *command,       // IN: primary control structure
835
                 UINT32           sessionIndex   // IN: index of session to be processed
836
                 )
837
{
838
    TPM2B_DIGEST        hmac;           // authHMAC for comparing
978✔
839
    // Compute authHMAC
840
   ComputeCommandHMAC(command, sessionIndex, &hmac);
978✔
841
    // Compare the input HMAC with the authHMAC computed above.
842
    if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b))
978✔
843
        {
844
            // If an HMAC session has a failure, invoke the anti-hammering
845
            // if it applies to the authorized entity or the session.
846
            // Otherwise, just indicate that the authorization is bad.
847
            return IncrementLockout(sessionIndex);
10✔
848
        }
849
    return TPM_RC_SUCCESS;
850
}
851
/* 6.4.4.11 CheckPolicyAuthSession() */
852
/* This function is used to validate the authorization in a policy session. This function performs
853
   the following comparisons to see if a policy authorization is properly provided. The check
854
   are: */
855
/* a) compare policyDigest in session with authPolicy associated with the entity to be
856
   authorized; */
857
/* b) compare timeout if applicable; */
858
/* c) compare commandCode if applicable; */
859
/* d) compare cpHash if applicable; and */
860
/* e) see if PCR values have changed since computed. */
861
/* If all the above checks succeed, the handle is authorized. The order of these comparisons is not
862
   important because any failure will result in the same error code. */
863
/* Error Returns Meaning */
864
/* TPM_RC_PCR_CHANGED PCR value is not current */
865
/* TPM_RC_POLICY_FAIL policy session fails */
866
/* TPM_RC_LOCALITY command locality is not allowed */
867
/* TPM_RC_POLICY_CC CC doesn't match */
868
/* TPM_RC_EXPIRED policy session has expired */
869
/* TPM_RC_PP PP is required but not asserted */
870
/* TPM_RC_NV_UNAVAILABLE NV is not available for write */
871
/* TPM_RC_NV_RATE NV is rate limiting */
872
static TPM_RC
873
CheckPolicyAuthSession(
202✔
874
                       COMMAND         *command,       // IN: primary parsing structure
875
                       UINT32           sessionIndex   // IN: index of session to be processed
876
                       )
877
{
878
    SESSION             *session;
202✔
879
    TPM2B_DIGEST         authPolicy;
202✔
880
    TPMI_ALG_HASH        policyAlg;
202✔
881
    UINT8                locality;
202✔
882
    // Initialize pointer to the authorization session.
883
    session = SessionGet(s_sessionHandles[sessionIndex]);
202✔
884
    // If the command is TPM2_PolicySecret(), make sure that
885
    // either password or authValue is required
886
    if(command->code == TPM_CC_PolicySecret
202✔
887
       &&  session->attributes.isPasswordNeeded == CLEAR
UNCOV
888
       &&  session->attributes.isAuthValueNeeded == CLEAR)
×
889
        return TPM_RC_MODE;
890
    // See if the PCR counter for the session is still valid.
891
    if(!SessionPCRValueIsCurrent(session))
202✔
892
        return TPM_RC_PCR_CHANGED;
893
    // Get authPolicy.
894
    policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex],
201✔
895
                                    &authPolicy);
896
    // Compare authPolicy.
897
    if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b))
201✔
898
        return TPM_RC_POLICY_FAIL;
899
    // Policy is OK so check if the other factors are correct
900
    // Compare policy hash algorithm.
901
    if(policyAlg != session->authHashAlg)
167✔
902
        return TPM_RC_POLICY_FAIL;
903
    // Compare timeout.
904
    if(session->timeout != 0)
167✔
905
        {
906
            // Cannot compare time if clock stop advancing.  An TPM_RC_NV_UNAVAILABLE
907
            // or TPM_RC_NV_RATE error may be returned here. This doesn't mean that
908
            // a new nonce will be created just that, because TPM time can't advance
909
            // we can't do time-based operations.
910
            RETURN_IF_NV_IS_NOT_AVAILABLE;
11✔
911
            if((session->timeout < g_time)
11✔
912
               || (session->epoch != g_timeEpoch))
11✔
913
                return TPM_RC_EXPIRED;
914
        }
915
    // If command code is provided it must match
916
    if(session->commandCode != 0)
167✔
917
        {
918
            if(session->commandCode != command->code)
88✔
919
                return TPM_RC_POLICY_CC;
920
        }
921
    else
922
        {
923
            // If command requires a DUP or ADMIN authorization, the session must have
924
            // command code set.
925
            AUTH_ROLE   role = CommandAuthRole(command->index, sessionIndex);
79✔
926
            if(role == AUTH_ADMIN || role == AUTH_DUP)
79✔
927
                return TPM_RC_POLICY_FAIL;
928
        }
929
    // Check command locality.
930
    {
931
        BYTE         sessionLocality[sizeof(TPMA_LOCALITY)];
164✔
932
        BYTE        *buffer = sessionLocality;
164✔
933
        // Get existing locality setting in canonical form
934
        sessionLocality[0] = 0;
164✔
935
        TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
164✔
936
        // See if the locality has been set
937
        if(sessionLocality[0] != 0)
164✔
938
            {
939
                // If so, get the current locality
UNCOV
940
                locality = _plat__LocalityGet();
×
UNCOV
941
                if(locality < 5)
×
942
                    {
UNCOV
943
                        if(((sessionLocality[0] & (1 << locality)) == 0)
×
UNCOV
944
                           || sessionLocality[0] > 31)
×
UNCOV
945
                            return TPM_RC_LOCALITY;
×
946
                    }
UNCOV
947
                else if(locality > 31)
×
948
                    {
UNCOV
949
                        if(sessionLocality[0] != locality)
×
950
                            return TPM_RC_LOCALITY;
951
                    }
952
                else
953
                    {
954
                        // Could throw an assert here but a locality error is just
955
                        // as good. It just means that, whatever the locality is, it isn't
956
                        // the locality requested so...
957
                        return TPM_RC_LOCALITY;
958
                    }
959
            }
960
    } // end of locality check
961
    // Check physical presence.
962
    if(session->attributes.isPPRequired == SET
164✔
UNCOV
963
       && !_plat__PhysicalPresenceAsserted())
×
964
        return TPM_RC_PP;
965
    // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or
966
    // DUP role for this handle.
967
    if(session->u1.cpHash.b.size != 0)
164✔
968
        {
969
            BOOL        OK;
10✔
970
            if(session->attributes.isCpHashDefined)
10✔
971
                // Compare cpHash.
972
                OK = MemoryEqual2B(&session->u1.cpHash.b,
8✔
973
                                   &ComputeCpHash(command, session->authHashAlg)->b);
4✔
974
            else if(session->attributes.isTemplateSet)
6✔
975
                OK = CompareTemplateHash(command, session);
3✔
976
            else
977
                OK = CompareNameHash(command, session);
3✔
978
            if(!OK)
10✔
979
                return TPM_RCS_POLICY_FAIL;
980
        }
981
    if(session->attributes.checkNvWritten)
163✔
982
        {
983
            NV_REF           locator;
4✔
984
            NV_INDEX        *nvIndex;
4✔
985
            // If this is not an NV index, the policy makes no sense so fail it.
986
            if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX)
4✔
987
                return TPM_RC_POLICY_FAIL;
1✔
988
            // Get the index data
989
            nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator);
4✔
990
            // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state
991
            if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
4✔
992
               != (session->attributes.nvWrittenState == SET))
4✔
993
                return TPM_RC_POLICY_FAIL;
994
        }
995
    return TPM_RC_SUCCESS;
996
}
997
/* 6.4.4.12 RetrieveSessionData() */
998
/* This function will unmarshal the sessions in the session area of a command. The values are placed
999
   in the arrays that are defined at the beginning of this file. The normal unmarshaling errors are
1000
   possible. */
1001
/* Error Returns Meaning */
1002
/* TPM_RC_SUCCSS unmarshaled without error */
1003
/* TPM_RC_SIZE the number of bytes unmarshaled is not the same as the value for authorizationSize in
1004
   the command */
1005
static TPM_RC
1006
RetrieveSessionData(
5,661✔
1007
                    COMMAND         *command        // IN: main parsing structure for command
1008
                    )
1009
{
1010
    int              i;
5,661✔
1011
    TPM_RC           result;
5,661✔
1012
    SESSION         *session;
5,661✔
1013
    TPMA_SESSION     sessionAttributes;
5,661✔
1014
    TPM_HT           sessionType;
5,661✔
1015
    INT32            sessionIndex;
5,661✔
1016
    TPM_RC           errorIndex;
5,661✔
1017
    s_decryptSessionIndex = UNDEFINED_INDEX;
5,661✔
1018
    s_encryptSessionIndex = UNDEFINED_INDEX;
5,661✔
1019
    s_auditSessionIndex = UNDEFINED_INDEX;
5,661✔
1020
    for(sessionIndex = 0; command->authSize > 0; sessionIndex++)
11,699✔
1021
        {
1022
            errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];
6,088✔
1023
            // If maximum allowed number of sessions has been parsed, return a size
1024
            // error with a session number that is larger than the number of allowed
1025
            // sessions
1026
            if(sessionIndex == MAX_SESSION_NUM)
6,088✔
1027
                return TPM_RCS_SIZE + errorIndex;
4✔
1028
            // make sure that the associated handle for each session starts out
1029
            // unassigned
1030
            s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
6,084✔
1031
            // First parameter: Session handle.
1032
            result = TPMI_SH_AUTH_SESSION_Unmarshal(
12,168✔
1033
                                                    &s_sessionHandles[sessionIndex],
6,084✔
1034
                                                    &command->parameterBuffer,
1035
                                                    &command->authSize, TRUE);
1036
            if(result != TPM_RC_SUCCESS)
6,084✔
1037
                return result + TPM_RC_S + g_rcIndex[sessionIndex];
16✔
1038
            // Second parameter: Nonce.
1039
            result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex],
6,068✔
1040
                                           &command->parameterBuffer,
1041
                                           &command->authSize);
1042
            if(result != TPM_RC_SUCCESS)
6,068✔
1043
                return result + TPM_RC_S + g_rcIndex[sessionIndex];
8✔
1044
            // Third parameter: sessionAttributes.
1045
            result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex],
6,060✔
1046
                                            &command->parameterBuffer,
1047
                                            &command->authSize);
1048
            if(result != TPM_RC_SUCCESS)
6,060✔
1049
                return result + TPM_RC_S + g_rcIndex[sessionIndex];
4✔
1050
            // Fourth parameter: authValue (PW or HMAC).
1051
            result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex],
6,056✔
1052
                                          &command->parameterBuffer,
1053
                                          &command->authSize);
1054
            if(result != TPM_RC_SUCCESS)
6,056✔
1055
                return result + errorIndex;
4✔
1056
            sessionAttributes = s_attributes[sessionIndex];
6,052✔
1057
            if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
6,052✔
1058
                {
1059
                    // A PWAP session needs additional processing.
1060
                    //     Can't have any attributes set other than continueSession bit
1061
                    if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)
5,018✔
1062
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)
1063
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)
5,018✔
1064
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
1065
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset))
5,014✔
1066
                        return TPM_RCS_ATTRIBUTES + errorIndex;
4✔
1067
                    //     The nonce size must be zero.
1068
                    if(s_nonceCaller[sessionIndex].t.size != 0)
5,014✔
1069
                        return TPM_RCS_NONCE + errorIndex;
4✔
1070
                    continue;
5,010✔
1071
                }
1072
            // For not password sessions...
1073
            // Find out if the session is loaded.
1074
            if(!SessionIsLoaded(s_sessionHandles[sessionIndex]))
1,034✔
1075
                return TPM_RC_REFERENCE_S0 + sessionIndex;
6✔
1076
            sessionType = HandleGetType(s_sessionHandles[sessionIndex]);
1,028✔
1077
            session = SessionGet(s_sessionHandles[sessionIndex]);
1,028✔
1078
            // Check if the session is an HMAC/policy session.
1079
            if((session->attributes.isPolicy == SET
1,028✔
1080
                && sessionType == TPM_HT_HMAC_SESSION)
202✔
1081
               || (session->attributes.isPolicy == CLEAR
1,028✔
1082
                   && sessionType == TPM_HT_POLICY_SESSION))
826✔
UNCOV
1083
                return TPM_RCS_HANDLE + errorIndex;
×
1084
            // Check that this handle has not previously been used.
1085
            for(i = 0; i < sessionIndex; i++)
1,359✔
1086
                {
1087
                    if(s_sessionHandles[i] == s_sessionHandles[sessionIndex])
331✔
UNCOV
1088
                        return TPM_RCS_HANDLE + errorIndex;
×
1089
                }
1090
            // If the session is used for parameter encryption or audit as well, set
1091
            // the corresponding Indexes.
1092
            // First process decrypt.
1093
            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt))
1,028✔
1094
                {
1095
                    // Check if the commandCode allows command parameter encryption.
1096
                    if(DecryptSize(command->index) == 0)
160✔
1097
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1098
                    // Encrypt attribute can only appear in one session
1099
                    if(s_decryptSessionIndex != UNDEFINED_INDEX)
160✔
UNCOV
1100
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1101
                    // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL
1102
                    if(session->symmetric.algorithm == TPM_ALG_NULL)
160✔
UNCOV
1103
                        return TPM_RCS_SYMMETRIC + errorIndex;
×
1104
                    // All checks passed, so set the index for the session used to decrypt
1105
                    // a command parameter.
1106
                    s_decryptSessionIndex = sessionIndex;
160✔
1107
                }
1108
            // Now process encrypt.
1109
            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt))
1,028✔
1110
                {
1111
                    // Check if the commandCode allows response parameter encryption.
1112
                    if(EncryptSize(command->index) == 0)
154✔
UNCOV
1113
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1114
                    // Encrypt attribute can only appear in one session.
1115
                    if(s_encryptSessionIndex != UNDEFINED_INDEX)
154✔
UNCOV
1116
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1117
                    // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL
1118
                    if(session->symmetric.algorithm == TPM_ALG_NULL)
154✔
UNCOV
1119
                        return TPM_RCS_SYMMETRIC + errorIndex;
×
1120
                    // All checks passed, so set the index for the session used to encrypt
1121
                    // a response parameter.
1122
                    s_encryptSessionIndex = sessionIndex;
154✔
1123
                }
1124
            // At last process audit.
1125
            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit))
1,028✔
1126
                {
1127
                    // Audit attribute can only appear in one session.
1128
                    if(s_auditSessionIndex != UNDEFINED_INDEX)
35✔
UNCOV
1129
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1130
                    // An audit session can not be policy session.
1131
                    if(HandleGetType(s_sessionHandles[sessionIndex])
35✔
1132
                       == TPM_HT_POLICY_SESSION)
UNCOV
1133
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1134
                    // If this is a reset of the audit session, or the first use
1135
                    // of the session as an audit session, it doesn't matter what
1136
                    // the exclusive state is. The session will become exclusive.
1137
                    if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)
35✔
1138
                       && session->attributes.isAudit == SET)
35✔
1139
                        {
1140
                            // Not first use or reset. If auditExlusive is SET, then this
1141
                            // session must be the current exclusive session.
1142
                            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
14✔
UNCOV
1143
                               && g_exclusiveAuditSession != s_sessionHandles[sessionIndex])
×
1144
                                return TPM_RC_EXCLUSIVE;
1145
                        }
1146
                    s_auditSessionIndex = sessionIndex;
35✔
1147
                }
1148
            // Initialize associated handle as undefined. This will be changed when
1149
            // the handles are processed.
1150
            s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
1,028✔
1151
        }
1152
    command->sessionNum = sessionIndex;
5,611✔
1153
    return TPM_RC_SUCCESS;
5,611✔
1154
}
1155
/* 6.4.4.13 CheckLockedOut() */
1156
/* This function checks to see if the TPM is in lockout. This function should only be called if the
1157
   entity being checked is subject to DA protection. The TPM is in lockout if the NV is not
1158
   available and a DA write is pending. Otherwise the TPM is locked out if checking for lockoutAuth
1159
   (lockoutAuthCheck == TRUE) and use of lockoutAuth is disabled, or failedTries >= maxTries */
1160
/* Error Returns Meaning */
1161
/* TPM_RC_NV_RATE NV is rate limiting */
1162
/* TPM_RC_NV_UNAVAILABLE NV is not available at this time */
1163
/* TPM_RC_LOCKOUT TPM is in lockout */
1164
static TPM_RC
1165
CheckLockedOut(
164✔
1166
               BOOL             lockoutAuthCheck   // IN: TRUE if checking is for lockoutAuth
1167
               )
1168
{
1169
    // If NV is unavailable, and current cycle state recorded in NV is not
1170
    // SU_NONE_VALUE, refuse to check any authorization because we would
1171
    // not be able to handle a DA failure.
1172
    if(!NV_IS_AVAILABLE && NV_IS_ORDERLY)
164✔
1173
        return g_NvStatus;
1174
    // Check if DA info needs to be updated in NV.
1175
    if(s_DAPendingOnNV)
164✔
1176
        {
1177
            // If NV is accessible,
UNCOV
1178
            RETURN_IF_NV_IS_NOT_AVAILABLE;
×
1179
            // ... write the pending DA data and proceed.
UNCOV
1180
            NV_SYNC_PERSISTENT(lockOutAuthEnabled);
×
UNCOV
1181
            NV_SYNC_PERSISTENT(failedTries);
×
UNCOV
1182
            s_DAPendingOnNV = FALSE;
×
1183
        }
1184
    // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth
1185
    // is disabled...
1186
    if(lockoutAuthCheck)
164✔
1187
        {
1188
            if(gp.lockOutAuthEnabled == FALSE)
80✔
UNCOV
1189
                return TPM_RC_LOCKOUT;
×
1190
        }
1191
    else
1192
        {
1193
            // ... or if the number of failed tries has been maxed out.
1194
            if(gp.failedTries >= gp.maxTries)
84✔
1195
                return TPM_RC_LOCKOUT;
1196
#if USE_DA_USED
1197
            // If the daUsed flag is not SET, then no DA validation until the
1198
            // daUsed state is written to NV
1199
            if(!g_daUsed)
46✔
1200
                {
1201
                    RETURN_IF_NV_IS_NOT_AVAILABLE;
10✔
1202
                    g_daUsed = TRUE;
10✔
1203
                    gp.orderlyState = SU_DA_USED_VALUE;
10✔
1204
                    NV_SYNC_PERSISTENT(orderlyState);
10✔
1205
                    return TPM_RC_RETRY;
10✔
1206
                }
1207
#endif
1208
        }
1209
    return TPM_RC_SUCCESS;
1210
}
1211
/* 6.4.4.14 CheckAuthSession() */
1212
/* This function checks that the authorization session properly authorizes the use of the associated
1213
   handle. */
1214
/* Error Returns Meaning */
1215
/* TPM_RC_LOCKOUT entity is protected by DA and TPM is in lockout, or TPM is locked out on NV update
1216
   pending on DA parameters */
1217
/* TPM_RC_PP Physical Presence is required but not provided */
1218
/* TPM_RC_AUTH_FAIL HMAC or PW authorization failed with DA side-effects (can be a policy
1219
   session) */
1220
/* TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA side-effects (can be a policy
1221
   session) */
1222
/* TPM_RC_POLICY_FAIL if policy session fails */
1223
/* TPM_RC_POLICY_CC command code of policy was wrong */
1224
/* TPM_RC_EXPIRED the policy session has expired */
1225
/* TPM_RC_PCR ??? */
1226
/* TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable */
1227
static TPM_RC
1228
CheckAuthSession(
5,897✔
1229
                 COMMAND         *command,       // IN: primary parsing structure
1230
                 UINT32           sessionIndex   // IN: index of session to be processed
1231
                 )
1232
{
1233
    TPM_RC           result = TPM_RC_SUCCESS;
5,897✔
1234
    SESSION         *session = NULL;
5,897✔
1235
    TPM_HANDLE       sessionHandle = s_sessionHandles[sessionIndex];
5,897✔
1236
    TPM_HANDLE       associatedHandle = s_associatedHandles[sessionIndex];
5,897✔
1237
    TPM_HT           sessionHandleType = HandleGetType(sessionHandle);
5,897✔
1238
    BOOL             authUsed;
5,897✔
1239

1240
    pAssert(sessionHandle != TPM_RH_UNASSIGNED);
5,897✔
1241
    
1242
    // Take care of physical presence
1243
    if(associatedHandle == TPM_RH_PLATFORM)
5,897✔
1244
        {
1245
            // If the physical presence is required for this command, check for PP
1246
            // assertion. If it isn't asserted, no point going any further.
1247
            if(PhysicalPresenceIsRequired(command->index)
773✔
1248
               && !_plat__PhysicalPresenceAsserted())
12✔
1249
                return TPM_RC_PP;
1250
        }
1251
    if(sessionHandle != TPM_RS_PW)
5,885✔
1252
        {
1253
            session = SessionGet(sessionHandle);
929✔
1254
            // Set includeAuth to indicate if DA checking will be required and if the
1255
            // authValue will be included in any HMAC.
1256
            if(sessionHandleType == TPM_HT_POLICY_SESSION)
929✔
1257
                {
1258
                    // For a policy session, will check the DA status of the entity if either
1259
                    // isAuthValueNeeded or isPasswordNeeded is SET.
1260
                    session->attributes.includeAuth =
202✔
1261
                        session->attributes.isAuthValueNeeded
1262
                        || session->attributes.isPasswordNeeded;
202✔
1263
                }
1264
            else
1265
                {
1266
                    // For an HMAC session, need to check unless the session
1267
                    // is bound.
1268
                    session->attributes.includeAuth =
1,454✔
1269
                        !IsSessionBindEntity(s_associatedHandles[sessionIndex], session);
727✔
1270
                }
1271
            authUsed = session->attributes.includeAuth;
929✔
1272
        }
1273
    else
1274
        // Password session
1275
        authUsed = TRUE;
1276
    // If the authorization session is going to use an authValue, then make sure
1277
    // that access to that authValue isn't locked out.
1278
    if(authUsed)
929✔
1279
        {
1280
            // See if entity is subject to lockout.
1281
            if(!IsDAExempted(associatedHandle))
5,656✔
1282
                {
1283
                    // See if in lockout
1284
                    result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT);
164✔
1285
                    if(result != TPM_RC_SUCCESS)
164✔
1286
                        return result;
1287
                }
1288
        }
1289
    // Policy or HMAC+PW?
1290
    if(sessionHandleType != TPM_HT_POLICY_SESSION)
5,837✔
1291
        {
1292
            // for non-policy session make sure that a policy session is not required
1293
            if(IsPolicySessionRequired(command->index, sessionIndex))
5,635✔
1294
                return TPM_RC_AUTH_TYPE;
1295
            // The authValue must be available.
1296
            // Note: The authValue is going to be "used" even if it is an EmptyAuth.
1297
            // and the session is bound.
1298
            if(!IsAuthValueAvailable(associatedHandle, command->index, sessionIndex))
5,633✔
1299
                return TPM_RC_AUTH_UNAVAILABLE;
1300
        }
1301
    else
1302
        {
1303
            // ... see if the entity has a policy, ...
1304
            // Note: IsAuthPolicyAvailable will return FALSE if the sensitive area of the
1305
            // object is not loaded
1306
            if(!IsAuthPolicyAvailable(associatedHandle, command->index, sessionIndex))
202✔
1307
                return TPM_RC_AUTH_UNAVAILABLE;
1308
            // ... and check the policy session.
1309
            result = CheckPolicyAuthSession(command, sessionIndex);
202✔
1310
            if(result != TPM_RC_SUCCESS)
202✔
1311
                return result;
1312
        }
1313
    // Check authorization according to the type
1314
    if(session == NULL || session->attributes.isPasswordNeeded == SET)
5,772✔
1315
        result = CheckPWAuthSession(sessionIndex);
4,893✔
1316
    else
1317
        result = CheckSessionHMAC(command, sessionIndex);
879✔
1318
    // Do processing for PIN Indexes are only three possibilities for 'result' at
1319
    // this point: TPM_RC_SUCCESS, TPM_RC_AUTH_FAIL, TPM_RC_BAD_AUTH
1320
    // For all these cases, we would have to process a PIN index if the
1321
    // authValue of the index was used for authorization.
1322
    if((TPM_HT_NV_INDEX == HandleGetType(associatedHandle)) && authUsed)
5,772✔
1323
        {
1324
            NV_REF           locator;
417✔
1325
            NV_INDEX        *nvIndex = NvGetIndexInfo(associatedHandle, &locator);
417✔
1326
            NV_PIN           pinData;
417✔
1327
            TPMA_NV          nvAttributes;
417✔
1328
            
1329
            pAssert(nvIndex != NULL);
417✔
1330
            nvAttributes = nvIndex->publicArea.attributes;
417✔
1331
            // If this is a PIN FAIL index and the value has been written
1332
            // then we can update the counter (increment or clear)
1333
            if(IsNvPinFailIndex(nvAttributes)
417✔
1334
               && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN))
13✔
1335
                {
1336
                    pinData.intVal = NvGetUINT64Data(nvIndex, locator);
13✔
1337
                    if(result != TPM_RC_SUCCESS)
13✔
1338
                        pinData.pin.pinCount++;
6✔
1339
                    else
1340
                        pinData.pin.pinCount = 0;
7✔
1341
                    NvWriteUINT64Data(nvIndex, pinData.intVal);
13✔
1342
                }
1343
            // If this is a PIN PASS Index, increment if we have used the
1344
            // authorization value.
1345
            // NOTE: If the counter has already hit the limit, then we
1346
            // would not get here because the authorization value would not
1347
            // be available and the TPM would have returned before it gets here
1348
            else if(IsNvPinPassIndex(nvAttributes)
404✔
1349
                    && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)
8✔
1350
                    && result == TPM_RC_SUCCESS)
8✔
1351
                {
1352
                    // If the access is valid, then increment the use counter
1353
                    pinData.intVal = NvGetUINT64Data(nvIndex, locator);
7✔
1354
                    pinData.pin.pinCount++;
7✔
1355
                    NvWriteUINT64Data(nvIndex, pinData.intVal);
7✔
1356
                }
1357
        }
1358
    return result;
1359
}
1360
#if CC_GetCommandAuditDigest
1361
/* 6.4.4.15 CheckCommandAudit() */
1362
/* This function is called before the command is processed if audit is enabled for the command. It
1363
   will check to see if the audit can be performed and will ensure that the cpHash is available for
1364
   the audit. */
1365
/* Error Returns Meaning */
1366
/* TPM_RC_NV_UNAVAILABLE NV is not available for write */
1367
/* TPM_RC_NV_RATE NV is rate limiting */
1368
static TPM_RC
1369
CheckCommandAudit(
65✔
1370
                  COMMAND         *command
1371
                  )
1372
{
1373
    // If the audit digest is clear and command audit is required, NV must be
1374
    // available so that TPM2_GetCommandAuditDigest() is able to increment
1375
    // audit counter. If NV is not available, the function bails out to prevent
1376
    // the TPM from attempting an operation that would fail anyway.
1377
    if(gr.commandAuditDigest.t.size == 0
65✔
UNCOV
1378
       || GetCommandCode(command->index) == TPM_CC_GetCommandAuditDigest)
×
1379
        {
1380
            RETURN_IF_NV_IS_NOT_AVAILABLE;
65✔
1381
        }
1382
    // Make sure that the cpHash is computed for the algorithm
1383
    ComputeCpHash(command, gp.auditHashAlg);
65✔
1384
    return TPM_RC_SUCCESS;
65✔
1385
}
1386
#endif
1387
/* 6.4.4.16 ParseSessionBuffer() */
1388
/* This function is the entry function for command session processing. It iterates sessions in
1389
   session area and reports if the required authorization has been properly provided. It also
1390
   processes audit session and passes the information of encryption sessions to parameter encryption
1391
   module. */
1392
/* Error Returns Meaning */
1393
/* various parsing failure or authorization failure */
1394
TPM_RC
1395
ParseSessionBuffer(
5,661✔
1396
                   COMMAND         *command        // IN: the structure that contains
1397
                   )
1398
{
1399
    TPM_RC               result;
5,661✔
1400
    UINT32               i;
5,661✔
1401
    INT32                size = 0;
5,661✔
1402
    TPM2B_AUTH           extraKey;
5,661✔
1403
    UINT32               sessionIndex;
5,661✔
1404
    TPM_RC               errorIndex;
5,661✔
1405
    SESSION             *session = NULL;
5,661✔
1406
    // Check if a command allows any session in its session area.
1407
    if(!IsSessionAllowed(command->index))
5,661✔
1408
        return TPM_RC_AUTH_CONTEXT;
1409
    // Default-initialization.
1410
    command->sessionNum = 0;
5,661✔
1411
    result = RetrieveSessionData(command);
5,661✔
1412
    if(result != TPM_RC_SUCCESS)
5,661✔
1413
        return result;
1414
    // There is no command in the TPM spec that has more handles than
1415
    // MAX_SESSION_NUM.
1416
    pAssert(command->handleNum <= MAX_SESSION_NUM);
5,611✔
1417
    // Associate the session with an authorization handle.
1418
    for(i = 0; i < command->handleNum; i++)
13,147✔
1419
        {
1420
            if(CommandAuthRole(command->index, i) != AUTH_NONE)
7,536✔
1421
                {
1422
                    // If the received session number is less than the number of handles
1423
                    // that requires authorization, an error should be returned.
1424
                    // Note: for all the TPM 2.0 commands, handles requiring
1425
                    // authorization come first in a command input and there are only ever
1426
                    // two values requiring authorization
1427
                    if(i > (command->sessionNum - 1))
5,903✔
1428
                        return TPM_RC_AUTH_MISSING;
1429
                    // Record the handle associated with the authorization session
1430
                    s_associatedHandles[i] = command->handles[i];
5,903✔
1431
                }
1432
        }
1433
    // Consistency checks are done first to avoid authorization failure when the
1434
    // command will not be executed anyway.
1435
    for(sessionIndex = 0; sessionIndex < command->sessionNum; sessionIndex++)
11,394✔
1436
        {
1437
            errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];
6,008✔
1438
            // PW session must be an authorization session
1439
            if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
6,008✔
1440
                {
1441
                    if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED)
4,980✔
1442
                        return TPM_RCS_HANDLE + errorIndex;
12✔
1443
                    // a password session can't be audit, encrypt or decrypt
1444
                    if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)
4,968✔
1445
                       || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)
1446
                       || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
4,968✔
UNCOV
1447
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1448
                    session = NULL;
1449
                }
1450
            else
1451
                {
1452
                    session = SessionGet(s_sessionHandles[sessionIndex]);
1,028✔
1453
                    // A trial session can not appear in session area, because it cannot
1454
                    // be used for authorization, audit or encrypt/decrypt.
1455
                    if(session->attributes.isTrialPolicy == SET)
1,028✔
UNCOV
1456
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1457
                    // See if the session is bound to a DA protected entity
1458
                    // NOTE: Since a policy session is never bound, a policy is still
1459
                    // usable even if the object is DA protected and the TPM is in
1460
                    // lockout.
1461
                    if(session->attributes.isDaBound == SET)
1,028✔
1462
                        {
UNCOV
1463
                            result = CheckLockedOut(session->attributes.isLockoutBound == SET);
×
UNCOV
1464
                            if(result != TPM_RC_SUCCESS)
×
UNCOV
1465
                                return result;
×
1466
                        }
1467
                    // If this session is for auditing, make sure the cpHash is computed.
1468
                    if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit))
1,028✔
1469
                        ComputeCpHash(command, session->authHashAlg);
35✔
1470
                }
1471
            // if the session has an associated handle, check the authorization
1472
            if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
5,996✔
1473
                {
1474
                    result = CheckAuthSession(command, sessionIndex);
5,897✔
1475
                    if(result != TPM_RC_SUCCESS)
5,897✔
1476
                        return RcSafeAddToResult(result, errorIndex);
213✔
1477
                }
1478
            else
1479
                {
1480
                    // a session that is not for authorization must either be encrypt,
1481
                    // decrypt, or audit
1482
                    if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)
99✔
1483
                       &&  !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt)
1484
                       &&  !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt))
88✔
UNCOV
1485
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1486
                    // no authValue included in any of the HMAC computations
1487
                    pAssert(session != NULL);
99✔
1488
                    session->attributes.includeAuth = CLEAR;
99✔
1489
                    // check HMAC for encrypt/decrypt/audit only sessions
1490
                    result = CheckSessionHMAC(command, sessionIndex);
99✔
1491
                    if(result != TPM_RC_SUCCESS)
99✔
UNCOV
1492
                        return RcSafeAddToResult(result, errorIndex);
×
1493
                }
1494
        }
1495
#if CC_GetCommandAuditDigest
1496
    // Check if the command should be audited. Need to do this before any parameter
1497
    // encryption so that the cpHash for the audit is correct
1498
    if(CommandAuditIsRequired(command->index))
5,386✔
1499
        {
1500
            result = CheckCommandAudit(command);
65✔
1501
            if(result != TPM_RC_SUCCESS)
65✔
1502
                return result;              // No session number to reference
1503
        }
1504
#endif
1505
    // Decrypt the first parameter if applicable. This should be the last operation
1506
    // in session processing.
1507
    // If the encrypt session is associated with a handle and the handle's
1508
    // authValue is available, then authValue is concatenated with sessionKey to
1509
    // generate encryption key, no matter if the handle is the session bound entity
1510
    // or not.
1511
    if(s_decryptSessionIndex != UNDEFINED_INDEX)
5,386✔
1512
        {
1513
            // If this is an authorization session, include the authValue in the
1514
            // generation of the decryption key
1515
            if(s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED)
158✔
1516
                {
1517
                    EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex],
108✔
1518
                                       &extraKey);
1519
                }
1520
            else
1521
                {
1522
                    extraKey.b.size = 0;
50✔
1523
                }
1524
            size = DecryptSize(command->index);
158✔
1525
            result = CryptParameterDecryption(s_sessionHandles[s_decryptSessionIndex],
316✔
1526
                                              &s_nonceCaller[s_decryptSessionIndex].b,
158✔
1527
                                              command->parameterSize, (UINT16)size,
158✔
1528
                                              &extraKey,
1529
                                              command->parameterBuffer);
1530
            if(result != TPM_RC_SUCCESS)
158✔
UNCOV
1531
                return RcSafeAddToResult(result,
×
UNCOV
1532
                                         TPM_RC_S + g_rcIndex[s_decryptSessionIndex]);
×
1533
        }
1534
    return TPM_RC_SUCCESS;
1535
}
1536
/* 6.4.4.17 CheckAuthNoSession() */
1537
/* Function to process a command with no session associated. The function makes sure all the handles
1538
   in the command require no authorization. */
1539
/* Error Returns Meaning */
1540
/* TPM_RC_AUTH_MISSING failure - one or more handles require authorization */
1541
TPM_RC
1542
CheckAuthNoSession(
9,662✔
1543
                   COMMAND         *command        // IN: command parsing structure
1544
                   )
1545
{
1546
    UINT32 i;
9,662✔
1547
    TPM_RC           result = TPM_RC_SUCCESS;
9,662✔
1548
    // Check if the command requires authorization
1549
    for(i = 0; i < command->handleNum; i++)
11,936✔
1550
        {
1551
            if(CommandAuthRole(command->index, i) != AUTH_NONE)
2,298✔
1552
                return TPM_RC_AUTH_MISSING;
1553
        }
1554
#if CC_GetCommandAuditDigest
1555
    // Check if the command should be audited.
1556
    if(CommandAuditIsRequired(command->index))
9,638✔
1557
        {
UNCOV
1558
            result = CheckCommandAudit(command);
×
UNCOV
1559
            if(result != TPM_RC_SUCCESS)
×
1560
                return result;
1561
        }
1562
#endif
1563
    // Initialize number of sessions to be 0
1564
    command->sessionNum = 0;
9,638✔
1565
    return TPM_RC_SUCCESS;
9,638✔
1566
}
1567
/* 6.4.5 Response Session Processing */
1568
/* 6.4.5.1 Introduction */
1569
/* The following functions build the session area in a response, and handle the audit sessions (if
1570
   present). */
1571
/* 6.4.5.2 ComputeRpHash() */
1572
/* Function to compute rpHash (Response Parameter Hash). The rpHash is only computed if there is an
1573
   HMAC authorization session and the return code is TPM_RC_SUCCESS. */
1574
static TPM2B_DIGEST *
1575
ComputeRpHash(
979✔
1576
              COMMAND         *command,       // IN: command structure
1577
              TPM_ALG_ID       hashAlg        // IN: hash algorithm to compute rpHash
1578
              )
1579
{
1580
    TPM2B_DIGEST    *rpHash = GetRpHashPointer(command, hashAlg);
979✔
1581
    HASH_STATE       hashState;
979✔
1582
    if(rpHash->t.size == 0)
979✔
1583
        {
1584
            //   rpHash := hash(responseCode || commandCode || parameters)
1585
            // Initiate hash creation.
1586
            rpHash->t.size = CryptHashStart(&hashState, hashAlg);
702✔
1587
            // Add hash constituents.
1588
            CryptDigestUpdateInt(&hashState, sizeof(TPM_RC), TPM_RC_SUCCESS);
702✔
1589
            CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);
702✔
1590
            CryptDigestUpdate(&hashState, command->parameterSize,
702✔
1591
                              command->parameterBuffer);
702✔
1592
            // Complete hash computation.
1593
            CryptHashEnd2B(&hashState, &rpHash->b);
702✔
1594
        }
1595
    return rpHash;
979✔
1596
}
1597
/* 6.4.5.3 InitAuditSession() */
1598
/* This function initializes the audit data in an audit session. */
1599
static void
1600
InitAuditSession(
21✔
1601
                 SESSION         *session        // session to be initialized
1602
                 )
1603
{
1604
    // Mark session as an audit session.
1605
    session->attributes.isAudit = SET;
21✔
1606
    // Audit session can not be bound.
1607
    session->attributes.isBound = CLEAR;
21✔
1608
    // Size of the audit log is the size of session hash algorithm digest.
1609
    session->u2.auditDigest.t.size = CryptHashGetDigestSize(session->authHashAlg);
21✔
1610
    // Set the original digest value to be 0.
1611
    MemorySet(&session->u2.auditDigest.t.buffer,
21✔
1612
              0,
1613
              session->u2.auditDigest.t.size);
1614
    return;
21✔
1615
}
1616
/* 6.4.5.4 UpdateAuditDigest */
1617
/* Function to update an audit digest */
1618
static void
1619
UpdateAuditDigest(
52✔
1620
                  COMMAND         *command,
1621
                  TPMI_ALG_HASH    hashAlg,
1622
                  TPM2B_DIGEST    *digest
1623
                  )
1624
{
1625
    HASH_STATE       hashState;
52✔
1626
    TPM2B_DIGEST    *cpHash = GetCpHash(command, hashAlg);
52✔
1627
    TPM2B_DIGEST    *rpHash = ComputeRpHash(command, hashAlg);
52✔
1628
    //
1629
    pAssert(cpHash != NULL);
52✔
1630
    // digestNew :=  hash (digestOld || cpHash || rpHash)
1631
    // Start hash computation.
1632
    digest->t.size = CryptHashStart(&hashState, hashAlg);
52✔
1633
    // Add old digest.
1634
    CryptDigestUpdate2B(&hashState, &digest->b);
52✔
1635
    // Add cpHash
1636
    CryptDigestUpdate2B(&hashState, &cpHash->b);
52✔
1637
    // Add rpHash
1638
    CryptDigestUpdate2B(&hashState, &rpHash->b);
52✔
1639
    // Finalize the hash.
1640
    CryptHashEnd2B(&hashState, &digest->b);
52✔
1641
}
52✔
1642
/* 6.4.5.5 Audit() */
1643
/* This function updates the audit digest in an audit session. */
1644
static void
1645
Audit(
35✔
1646
      COMMAND         *command,       // IN: primary control structure
1647
      SESSION         *auditSession   // IN: loaded audit session
1648
      )
1649
{
1650
    UpdateAuditDigest(command, auditSession->authHashAlg,
35✔
1651
                      &auditSession->u2.auditDigest);
1652
    return;
35✔
1653
}
1654
#if CC_GetCommandAuditDigest
1655
/* 6.4.5.6 CommandAudit() */
1656
/* This function updates the command audit digest. */
1657
static void
1658
CommandAudit(
17✔
1659
             COMMAND         *command        // IN:
1660
             )
1661
{
1662
    // If the digest.size is one, it indicates the special case of changing
1663
    // the audit hash algorithm. For this case, no audit is done on exit.
1664
    // NOTE: When the hash algorithm is changed, g_updateNV is set in order to
1665
    // force an update to the NV on exit so that the change in digest will
1666
    // be recorded. So, it is safe to exit here without setting any flags
1667
    // because the digest change will be written to NV when this code exits.
1668
    if(gr.commandAuditDigest.t.size == 1)
17✔
1669
        {
UNCOV
1670
            gr.commandAuditDigest.t.size = 0;
×
UNCOV
1671
            return;
×
1672
        }
1673
    // If the digest size is zero, need to start a new digest and increment
1674
    // the audit counter.
1675
    if(gr.commandAuditDigest.t.size == 0)
17✔
1676
        {
1677
            gr.commandAuditDigest.t.size = CryptHashGetDigestSize(gp.auditHashAlg);
17✔
1678
            MemorySet(gr.commandAuditDigest.t.buffer,
17✔
1679
                      0,
1680
                      gr.commandAuditDigest.t.size);
1681
            // Bump the counter and save its value to NV.
1682
            gp.auditCounter++;
17✔
1683
            NV_SYNC_PERSISTENT(auditCounter);
17✔
1684
        }
1685
    UpdateAuditDigest(command, gp.auditHashAlg, &gr.commandAuditDigest);
17✔
1686
    return;
17✔
1687
}
1688
#endif
1689
/* 6.4.5.7 UpdateAuditSessionStatus() */
1690
/* Function to update the internal audit related states of a session. It */
1691
/* a) initializes the session as audit session and sets it to be exclusive if this is the first time
1692
   it is used for audit or audit reset was requested; */
1693
/* b) reports exclusive audit session; */
1694
/* c) extends audit log; and */
1695
/* d) clears exclusive audit session if no audit session found in the command. */
1696
static void
1697
UpdateAuditSessionStatus(
13,134✔
1698
                         COMMAND         *command        // IN: primary control structure
1699
                         )
1700
{
1701
    UINT32           i;
13,134✔
1702
    TPM_HANDLE       auditSession = TPM_RH_UNASSIGNED;
13,134✔
1703
    // Iterate through sessions
1704
    for(i = 0; i < command->sessionNum; i++)
18,127✔
1705
        {
1706
            SESSION     *session;
4,993✔
1707
            // PW session do not have a loaded session and can not be an audit
1708
            // session either.  Skip it.
1709
            if(s_sessionHandles[i] == TPM_RS_PW)
4,993✔
1710
                continue;
4,062✔
1711
            session = SessionGet(s_sessionHandles[i]);
931✔
1712
            // If a session is used for audit
1713
            if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit))
931✔
1714
                {
1715
                    // An audit session has been found
1716
                    auditSession = s_sessionHandles[i];
35✔
1717
                    // If the session has not been an audit session yet, or
1718
                    // the auditSetting bits indicate a reset, initialize it and set
1719
                    // it to be the exclusive session
1720
                    if(session->attributes.isAudit == CLEAR
35✔
1721
                       || IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset))
14✔
1722
                        {
1723
                            InitAuditSession(session);
21✔
1724
                            g_exclusiveAuditSession = auditSession;
21✔
1725
                        }
1726
                    else
1727
                        {
1728
                            // Check if the audit session is the current exclusive audit
1729
                            // session and, if not, clear previous exclusive audit session.
1730
                            if(g_exclusiveAuditSession != auditSession)
14✔
1731
                                g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
5✔
1732
                        }
1733
                    // Report audit session exclusivity.
1734
                    if(g_exclusiveAuditSession == auditSession)
35✔
1735
                        {
1736
                            SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);
30✔
1737
                        }
1738
                    else
1739
                        {
1740
                            CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive);
5✔
1741
                        }
1742
                    // Extend audit log.
1743
                    Audit(command, session);
5,028✔
1744
                }
1745
        }
1746
    // If no audit session is found in the command, and the command allows
1747
    // a session then, clear the current exclusive
1748
    // audit session.
1749
    if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(command->index))
13,134✔
1750
        {
1751
            g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
8,071✔
1752
        }
1753
    return;
13,134✔
1754
}
1755
/* 6.4.5.8 ComputeResponseHMAC() */
1756
/* Function to compute HMAC for authorization session in a response. */
1757
static void
1758
ComputeResponseHMAC(
927✔
1759
                    COMMAND         *command,       // IN: command structure
1760
                    UINT32           sessionIndex,  // IN: session index to be processed
1761
                    SESSION         *session,       // IN: loaded session
1762
                    TPM2B_DIGEST    *hmac           // OUT: authHMAC
1763
                    )
1764
{
1765
    TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));
927✔
1766
    TPM2B_KEY        key;       // HMAC key
927✔
1767
    BYTE             marshalBuffer[sizeof(TPMA_SESSION)];
927✔
1768
    BYTE            *buffer;
927✔
1769
    UINT32           marshalSize;
927✔
1770
    HMAC_STATE       hmacState;
927✔
1771
    TPM2B_DIGEST    *rpHash = ComputeRpHash(command, session->authHashAlg);
927✔
1772
    // Generate HMAC key
1773
    MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
927✔
1774
    // Add the object authValue if required
1775
    if(session->attributes.includeAuth == SET)
927✔
1776
        {
1777
            // Note: includeAuth may be SET for a policy that is used in
1778
            // UndefineSpaceSpecial(). At this point, the Index has been deleted
1779
            // so the includeAuth will have no meaning. However, the
1780
            // s_associatedHandles[] value for the session is now set to TPM_RH_NULL so
1781
            // this will return the authValue associated with TPM_RH_NULL and that is
1782
            // and empty buffer.
1783
            TPM2B_AUTH          authValue;
640✔
1784
            // Get the authValue with trailing zeros removed
1785
            EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);
640✔
1786
            // Add it to the key
1787
            MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));
640✔
1788
        }
1789
    // if the HMAC key size is 0, the response HMAC is computed according to the
1790
    // input HMAC
1791
    if(key.t.size == 0
927✔
1792
       && s_inputAuthValues[sessionIndex].t.size == 0)
237✔
1793
        {
1794
            hmac->t.size = 0;
122✔
1795
            return;
122✔
1796
        }
1797
    // Start HMAC computation.
1798
    hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);
805✔
1799
    // Add hash components.
1800
    CryptDigestUpdate2B(&hmacState.hashState, &rpHash->b);
805✔
1801
    CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);
805✔
1802
    CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);
805✔
1803
    // Add session attributes.
1804
    buffer = marshalBuffer;
805✔
1805
    marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL);
805✔
1806
    CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);
805✔
1807
    // Finalize HMAC.
1808
    CryptHmacEnd2B(&hmacState, &hmac->b);
805✔
1809
    return;
805✔
1810
}
1811
/* 6.4.5.9 UpdateInternalSession() */
1812
/* Updates internal sessions: */
1813
/* a) Restarts session time. */
1814
/* b) Clears a policy session since nonce is rolling. */
1815
static void
1816
UpdateInternalSession(
931✔
1817
                      SESSION         *session,       // IN: the session structure
1818
                      UINT32           i              // IN: session number
1819
                      )
1820
{
1821
    // If nonce is rolling in a policy session, the policy related data
1822
    // will be re-initialized.
1823
    if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION
931✔
1824
       && IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
160✔
1825
        {
1826
            // When the nonce rolls it starts a new timing interval for the
1827
            // policy session.
1828
            SessionResetPolicyData(session);
119✔
1829
            SessionSetStartTime(session);
119✔
1830
        }
1831
    return;
931✔
1832
}
1833
/* 6.4.5.10 BuildSingleResponseAuth() */
1834
/* Function to compute response HMAC value for a policy or HMAC session. */
1835
static TPM2B_NONCE *
1836
BuildSingleResponseAuth(
931✔
1837
                        COMMAND         *command,       // IN: command structure
1838
                        UINT32           sessionIndex,  // IN: session index to be processed
1839
                        TPM2B_AUTH      *auth           // OUT: authHMAC
1840
                        )
1841
{
1842
    // Fill in policy/HMAC based session response.
1843
    SESSION     *session = SessionGet(s_sessionHandles[sessionIndex]);
931✔
1844
    // If the session is a policy session with isPasswordNeeded SET, the
1845
    // authorization field is empty.
1846
    if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION
931✔
1847
       && session->attributes.isPasswordNeeded == SET)
160✔
1848
        auth->t.size = 0;
4✔
1849
    else
1850
        // Compute response HMAC.
1851
        ComputeResponseHMAC(command, sessionIndex, session, auth);
927✔
1852
    UpdateInternalSession(session, sessionIndex);
931✔
1853
    return &session->nonceTPM;
931✔
1854
}
1855
/* 6.4.5.11 UpdateAllNonceTPM() */
1856
/* Updates TPM nonce for all sessions in command. */
1857
static void
1858
UpdateAllNonceTPM(
4,601✔
1859
                  COMMAND         *command        // IN: controlling structure
1860
                  )
1861
{
1862
    UINT32      i;
4,601✔
1863
    SESSION     *session;
4,601✔
1864
    for(i = 0; i < command->sessionNum; i++)
9,594✔
1865
        {
1866
            // If not a PW session, compute the new nonceTPM.
1867
            if(s_sessionHandles[i] != TPM_RS_PW)
4,993✔
1868
                {
1869
                    session = SessionGet(s_sessionHandles[i]);
931✔
1870
                    // Update nonceTPM in both internal session and response.
1871
                    CryptRandomGenerate(session->nonceTPM.t.size,
931✔
1872
                                        session->nonceTPM.t.buffer);
931✔
1873
                }
1874
        }
1875
    return;
4,601✔
1876
}
1877
/* 6.4.5.12 BuildResponseSession() */
1878
/* Function to build Session buffer in a response. The authorization data is added to the end of
1879
   command->responseBuffer. The size of the authorization area is accumulated in
1880
   command->authSize. When this is called, command->responseBuffer is pointing at the next location
1881
   in the response buffer to be filled. This is where the authorization sessions will go, if
1882
   any. command->parameterSize is the number of bytes that have been marshaled as parameters in the
1883
   output buffer. */
1884
void
1885
BuildResponseSession(
13,134✔
1886
                     COMMAND         *command        // IN: structure that has relevant command
1887
                     //     information
1888
                     )
1889
{
1890
    pAssert(command->authSize == 0);
13,134✔
1891
    // Reset the parameter buffer to point to the start of the parameters so that
1892
    // there is a starting point for any rpHash that might be generated and so there
1893
    // is a place where parameter encryption would start
1894
    command->parameterBuffer = command->responseBuffer - command->parameterSize;
13,134✔
1895
    // Session nonces should be updated before parameter encryption
1896
    if(command->tag == TPM_ST_SESSIONS)
13,134✔
1897
        {
1898
            UpdateAllNonceTPM(command);
4,601✔
1899
            // Encrypt first parameter if applicable. Parameter encryption should
1900
            // happen after nonce update and before any rpHash is computed.
1901
            // If the encrypt session is associated with a handle, the authValue of
1902
            // this handle will be concatenated with sessionKey to generate
1903
            // encryption key, no matter if the handle is the session bound entity
1904
            // or not. The authValue is added to sessionKey only when the authValue
1905
            // is available.
1906
            if(s_encryptSessionIndex != UNDEFINED_INDEX)
4,601✔
1907
                {
1908
                    UINT32          size;
152✔
1909
                    TPM2B_AUTH      extraKey;
152✔
1910
                    extraKey.b.size = 0;
152✔
1911
                    // If this is an authorization session, include the authValue in the
1912
                    // generation of the encryption key
1913
                    if(s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED)
152✔
1914
                        {
1915
                            EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex],
102✔
1916
                                               &extraKey);
1917
                        }
1918
                    size = EncryptSize(command->index);
152✔
1919
                    CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex],
152✔
1920
                                             &s_nonceCaller[s_encryptSessionIndex].b,
152✔
1921
                                             (UINT16)size,
1922
                                             &extraKey,
1923
                                             command->parameterBuffer);
1924
                }
1925
        }
1926
    // Audit sessions should be processed regardless of the tag because
1927
    // a command with no session may cause a change of the exclusivity state.
1928
    UpdateAuditSessionStatus(command);
13,134✔
1929
#if CC_GetCommandAuditDigest
1930
    // Command Audit
1931
    if(CommandAuditIsRequired(command->index))
13,134✔
1932
        CommandAudit(command);
17✔
1933
#endif
1934
    // Process command with sessions.
1935
    if(command->tag == TPM_ST_SESSIONS)
13,134✔
1936
        {
1937
            UINT32           i;
4,601✔
1938
            pAssert(command->sessionNum > 0);
4,601✔
1939
            // Iterate over each session in the command session area, and create
1940
            // corresponding sessions for response.
1941
            for(i = 0; i < command->sessionNum; i++)
9,594✔
1942
                {
1943
                    TPM2B_NONCE     *nonceTPM;
4,993✔
1944
                    TPM2B_DIGEST     responseAuth;
4,993✔
1945
                    // Make sure that continueSession is SET on any Password session.
1946
                    // This makes it marginally easier for the management software
1947
                    // to keep track of the closed sessions.
1948
                    if(s_sessionHandles[i] == TPM_RS_PW)
4,993✔
1949
                        {
1950
                            SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession);
4,062✔
1951
                            responseAuth.t.size = 0;
4,062✔
1952
                            nonceTPM = (TPM2B_NONCE *)&responseAuth;
4,062✔
1953
                        }
1954
                    else
1955
                        {
1956
                            // Compute the response HMAC and get a pointer to the nonce used.
1957
                            // This function will also update the values if needed. Note, the
1958
                            nonceTPM = BuildSingleResponseAuth(command, i, &responseAuth);
931✔
1959
                        }
1960
                    command->authSize += TPM2B_NONCE_Marshal(nonceTPM,
4,993✔
1961
                                                             &command->responseBuffer,
1962
                                                             NULL);
1963
                    command->authSize += TPMA_SESSION_Marshal(&s_attributes[i],
4,993✔
1964
                                                              &command->responseBuffer,
1965
                                                              NULL);
1966
                    command->authSize += TPM2B_DIGEST_Marshal(&responseAuth,
4,993✔
1967
                                                              &command->responseBuffer,
1968
                                                              NULL);
1969
                    if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession))
4,993✔
1970
                        SessionFlush(s_sessionHandles[i]);
82✔
1971
                }
1972
        }
1973
    return;
13,134✔
1974
}
1975
/* 6.4.5.13 SessionRemoveAssociationToHandle() */
1976
/* This function deals with the case where an entity associated with an authorization is deleted
1977
   during command processing. The primary use of this is to support UndefineSpaceSpecial(). */
1978
void
1979
SessionRemoveAssociationToHandle(
2✔
1980
                                 TPM_HANDLE       handle
1981
                                 )
1982
{
1983
    UINT32               i;
2✔
1984
    for(i = 0; i < MAX_SESSION_NUM; i++)
8✔
1985
        {
1986
            if(s_associatedHandles[i] == handle)
6✔
1987
                {
1988
                    s_associatedHandles[i] = TPM_RH_NULL;
2✔
1989
                }
1990
        }
1991
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc