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

stefanberger / libtpms / 2698

pending completion
2698

Pull #353

travis-ci-com

web-flow
Merge a8cae3f5d into d08b929de
Pull Request #353: Travis: Update from bionic to focal and from xenial to bionic

33875 of 43923 relevant lines covered (77.12%)

93992.6 hits per line

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

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

392
/* 6.4.3.6        IsAuthPolicyAvailable() */
393
/* This function indicates if an authPolicy is available and allowed. */
394
/* This function does not check that the handle reference is valid or if the entity is in an enabled
395
   hierarchy. Those checks are assumed to have been performed during the handle unmarshaling. */
396
/* Return Values Meaning */
397
/* TRUE authPolicy is available */
398
/* FALSE authPolicy is not available */
399
static BOOL
400
IsAuthPolicyAvailable(
192✔
401
                      TPM_HANDLE       handle,        // IN: handle of entity
402
                      COMMAND_INDEX    commandIndex,  // IN: command index
403
                      UINT32           sessionIndex   // IN: session index
404
                      )
405
{
406
    BOOL            result = FALSE;
192✔
407
    //
408
    switch(HandleGetType(handle))
192✔
409
        {
410
          case TPM_HT_PERMANENT:
7✔
411
            switch(handle)
7✔
412
                {
413
                    // At this point hierarchy availability has already been checked.
414
                  case TPM_RH_OWNER:
×
415
                    if(gp.ownerPolicy.t.size != 0)
×
416
                        result = TRUE;
×
417
                    break;
418
                  case TPM_RH_ENDORSEMENT:
×
419
                    if(gp.endorsementPolicy.t.size != 0)
×
420
                        result = TRUE;
×
421
                    break;
422
                  case TPM_RH_PLATFORM:
7✔
423
                    if(gc.platformPolicy.t.size != 0)
7✔
424
                        result = TRUE;
7✔
425
                    break;
426
#define ACT_GET_POLICY(N)                                                \
427
                    case TPM_RH_ACT_##N:                                \
428
                      if(go.ACT_##N.authPolicy.t.size != 0)                \
429
                          result = TRUE;                                \
430
                      break;
431
                    
432
                    FOR_EACH_ACT(ACT_GET_POLICY)
433
                        
434
                  case TPM_RH_LOCKOUT:
×
435
                    if(gp.lockoutPolicy.t.size != 0)
×
436
                        result = TRUE;
×
437
                    break;
438
                  default:
439
                    break;
440
                }
441
            break;
442
          case TPM_HT_TRANSIENT:
152✔
443
              {
444
                  // Object handle.
445
                  // An evict object would already have been loaded and given a
446
                  // transient object handle by this point.
447
                  OBJECT  *object = HandleToObject(handle);
152✔
448
                  // Policy authorization is not available for an object with only
449
                  // public portion loaded.
450
                  if(object->attributes.publicOnly == CLEAR)
152✔
451
                      {
452
                          // Policy authorization is always available for an object but
453
                          // is never available for a sequence.
454
                          if(!ObjectIsSequence(object))
152✔
455
                              result = TRUE;
152✔
456
                      }
457
                  break;
458
              }
459
          case TPM_HT_NV_INDEX:
33✔
460
            // An NV Index.
461
              {
462
                  NV_INDEX         *nvIndex = NvGetIndexInfo(handle, NULL);
33✔
463
                  TPMA_NV           nvAttributes = nvIndex->publicArea.attributes;
33✔
464
                  //
465
                  // If the policy size is not zero, check if policy can be used.
466
                  if(nvIndex->publicArea.authPolicy.t.size != 0)
33✔
467
                      {
468
                          // If policy session is required for this handle, always
469
                          // uses policy regardless of the attributes bit setting
470
                          if(IsPolicySessionRequired(commandIndex, sessionIndex))
33✔
471
                              result = TRUE;
472
                          // Otherwise, the presence of the policy depends on the NV
473
                          // attributes.
474
                          else if(IsWriteOperation(commandIndex))
24✔
475
                              {
476
                                  if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE))
16✔
477
                                      result = TRUE;
16✔
478
                              }
479
                          else
480
                              {
481
                                  if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD))
8✔
482
                                      result = TRUE;
8✔
483
                              }
484
                      }
485
              }
486
              break;
487
          case TPM_HT_PCR:
×
488
            // PCR handle.
489
            if(PCRPolicyIsAvailable(handle))
×
490
                result = TRUE;
×
491
            break;
492
          default:
493
            break;
494
        }
495
    return result;
192✔
496
}
497
/* 6.4.4 Session Parsing Functions */
498
/* 6.4.4.1 ClearCpRpHashes() */
499

500
void
501
ClearCpRpHashes(
15,887✔
502
                COMMAND         *command
503
                )
504
{
505
    // The macros expand according to the implemented hash algorithms. An IDE may
506
    // complain that COMMAND does not contain SHA1CpHash or SHA1RpHash because of the
507
    // complexity of the macro expansion where the data space is defined; but, if SHA1
508
    // is implemented, it actually does  and the compiler is happy.
509
#define CLEAR_CP_HASH(HASH, Hash)     command->Hash##CpHash.b.size = 0;
510
    FOR_EACH_HASH(CLEAR_CP_HASH)
15,887✔
511
#define CLEAR_RP_HASH(HASH, Hash)     command->Hash##RpHash.b.size = 0;
512
        FOR_EACH_HASH(CLEAR_RP_HASH)
15,887✔
513
}
15,887✔
514

515
/* 6.4.4.2 GetCpHashPointer() */
516
/* Function to get a pointer to the cpHash of the command */
517
static TPM2B_DIGEST *
518
GetCpHashPointer(
962✔
519
                 COMMAND         *command,
520
                 TPMI_ALG_HASH    hashAlg
521
                 )
522
{
523
    TPM2B_DIGEST     *retVal;
962✔
524
    //
525
    // Define the macro that will expand for each implemented algorithm in the switch
526
    // statement below.
527
#define GET_CP_HASH_POINTER(HASH, Hash)                                        \
528
    case ALG_##HASH##_VALUE:                                                \
529
      retVal = (TPM2B_DIGEST *)&command->Hash##CpHash;                        \
530
      break;
531

532
    switch(hashAlg)
962✔
533
        {
534
            // For each implemented hash, this will expand as defined above
535
            // by GET_CP_HASH_POINTER. Your IDE may complain that
536
            // 'struct "COMMAND" has no field "SHA1CpHash"' but the compiler says
537
            // it does, so...
538
            FOR_EACH_HASH(GET_CP_HASH_POINTER)
962✔
539
          default:
540
            retVal = NULL;
541
            break;
542
        }
543
    return retVal;
962✔
544
}
545

546
/* 6.4.4.3 GetRpHashPointer() */
547
/* Function to get a pointer to the RpHash() of the command */
548
static TPM2B_DIGEST *
549
GetRpHashPointer(
943✔
550
                 COMMAND         *command,
551
                 TPMI_ALG_HASH    hashAlg
552
                 )
553
{
554
    TPM2B_DIGEST    *retVal;
943✔
555
    //
556
    // Define the macro that will expand for each implemented algorithm in the switch
557
    // statement below.
558
#define GET_RP_HASH_POINTER(HASH, Hash)                                        \
559
    case ALG_##HASH##_VALUE:                                                \
560
      retVal = (TPM2B_DIGEST *)&command->Hash##RpHash;                        \
561
      break;
562

563
    switch(hashAlg)
943✔
564
        {
565
            // For each implemented hash, this will expand as defined above
566
            // by GET_RP_HASH_POINTER. Your IDE may complain that
567
            // 'struct "COMMAND" has no field 'SHA1RpHash'" but the compiler says
568
            // it does, so...
569
            FOR_EACH_HASH(GET_RP_HASH_POINTER)
943✔
570
          default:
571
            retVal = NULL;
572
            break;
573
        }
574
    return retVal;
943✔
575
}
576

577
/* 6.4.4.4 ComputeCpHash() */
578
/* This function computes the cpHash as defined in Part 2 and described in Part 1. */
579
static TPM2B_DIGEST *
580
ComputeCpHash(
911✔
581
              COMMAND         *command,       // IN: command parsing structure
582
              TPMI_ALG_HASH    hashAlg        // IN: hash algorithm
583
              )
584
{
585
    UINT32               i;
911✔
586
    HASH_STATE           hashState;
911✔
587
    TPM2B_NAME           name;
911✔
588
    TPM2B_DIGEST        *cpHash;
911✔
589
    // cpHash = hash(commandCode [ || authName1
590
    //                           [ || authName2
591
    //                           [ || authName 3 ]]]
592
    //                           [ || parameters])
593
    // A cpHash can contain just a commandCode only if the lone session is
594
    // an audit session.
595
    // Get pointer to the hash value
596
    cpHash = GetCpHashPointer(command, hashAlg);
911✔
597
    if(cpHash->t.size == 0)
911✔
598
        {
599
            cpHash->t.size = CryptHashStart(&hashState, hashAlg);
636✔
600
            //  Add commandCode.
601
            CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code);
636✔
602
            //  Add authNames for each of the handles.
603
            for(i = 0; i < command->handleNum; i++)
2,222✔
604
                CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],
950✔
605
                                                               &name)->b);
606
            //  Add the parameters.
607
            CryptDigestUpdate(&hashState, command->parameterSize,
636✔
608
                              command->parameterBuffer);
636✔
609
            //  Complete the hash.
610
            CryptHashEnd2B(&hashState, &cpHash->b);
636✔
611
        }
612
    return cpHash;
911✔
613
}
614
/* 6.4.4.5 GetCpHash() */
615
/* This function is used to access a precomputed cpHash. */
616
static TPM2B_DIGEST *
617
GetCpHash(
51✔
618
          COMMAND         *command,
619
          TPMI_ALG_HASH    hashAlg
620
          )
621
{
622
    TPM2B_DIGEST        *cpHash = GetCpHashPointer(command, hashAlg);
51✔
623
    //
624
    pAssert(cpHash->t.size != 0);
51✔
625
    return cpHash;
51✔
626
}
627
/* 6.4.4.6 CompareTemplateHash() */
628
/* This function computes the template hash and compares it to the session templateHash. It is the
629
   hash of the second parameter assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or
630
   TPM2_CreateLoaded() */
631
static BOOL
632
CompareTemplateHash(
3✔
633
                    COMMAND         *command,       // IN: parsing structure
634
                    SESSION         *session        // IN: session data
635
                    )
636
{
637
    BYTE                *pBuffer = command->parameterBuffer;
3✔
638
    INT32                pSize = command->parameterSize;
3✔
639
    TPM2B_DIGEST         tHash;
3✔
640
    UINT16               size;
3✔
641
    //
642
    // Only try this for the three commands for which it is intended
643
    if(command->code != TPM_CC_Create
3✔
644
       && command->code != TPM_CC_CreatePrimary
3✔
645
#if CC_CreateLoaded
646
       && command->code != TPM_CC_CreateLoaded
1✔
647
#endif
648
       )
649
        return FALSE;
650
    // Assume that the first parameter is a TPM2B and unmarshal the size field
651
    // Note: this will not affect the parameter buffer and size in the calling
652
    // function.
653
    if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
3✔
654
        return FALSE;
655
    // reduce the space in the buffer.
656
    // NOTE: this could make pSize go negative if the parameters are not correct but
657
    // the unmarshaling code does not try to unmarshal if the remaining size is
658
    // negative.
659
    pSize -= size;
3✔
660
    // Advance the pointer
661
    pBuffer += size;
3✔
662
    // Get the size of what should be the template
663
    if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS)
3✔
664
        return FALSE;
665
    // See if this is reasonable
666
    if(size > pSize)
3✔
667
        return FALSE;
668
    // Hash the template data
669
    tHash.t.size = CryptHashBlock(session->authHashAlg, size, pBuffer,
3✔
670
                                  sizeof(tHash.t.buffer), tHash.t.buffer);
671
    return(MemoryEqual2B(&session->u1.templateHash.b, &tHash.b));
3✔
672
}
673
/* 6.4.4.7 CompareNameHash() */
674
/* This function computes the name hash and compares it to the nameHash in the session data. */
675
BOOL
676
CompareNameHash(
3✔
677
                COMMAND         *command,       // IN: main parsing structure
678
                SESSION         *session        // IN: session structure with nameHash
679
                )
680
{
681
    HASH_STATE           hashState;
3✔
682
    TPM2B_DIGEST         nameHash;
3✔
683
    UINT32               i;
3✔
684
    TPM2B_NAME           name;
3✔
685
    //
686
    nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg);
3✔
687
    //  Add names.
688
    for(i = 0; i < command->handleNum; i++)
8✔
689
        CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i],
5✔
690
                                                       &name)->b);
691
    //  Complete hash.
692
    CryptHashEnd2B(&hashState, &nameHash.b);
3✔
693
    // and compare
694
    return MemoryEqual(session->u1.nameHash.t.buffer, nameHash.t.buffer,
6✔
695
                       nameHash.t.size);
3✔
696
}
697
/* 6.4.4.8 CheckPWAuthSession() */
698
/* This function validates the authorization provided in a PWAP session. It compares the input value
699
   to authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the
700
   referenced entities from s_inputAuthValues[] and s_associatedHandles[]. */
701
/* Error Returns Meaning */
702
/* TPM_RC_AUTH_FAIL authorization fails and increments DA failure count */
703
/* TPM_RC_BAD_AUTH authorization fails but DA does not apply */
704
static TPM_RC
705
CheckPWAuthSession(
5,731✔
706
                   UINT32           sessionIndex   // IN: index of session to be processed
707
                   )
708
{
709
    TPM2B_AUTH      authValue;
5,731✔
710
    TPM_HANDLE      associatedHandle = s_associatedHandles[sessionIndex];
5,731✔
711
    // Strip trailing zeros from the password.
712
    MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]);
5,731✔
713
    // Get the authValue with trailing zeros removed
714
    EntityGetAuthValue(associatedHandle, &authValue);
5,731✔
715
    // Success if the values are identical.
716
    if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b))
5,731✔
717
        {
718
            return TPM_RC_SUCCESS;
719
        }
720
    else                    // if the digests are not identical
721
        {
722
            // Invoke DA protection if applicable.
723
            return IncrementLockout(sessionIndex);
57✔
724
        }
725
}
726
/* 6.4.4.9 ComputeCommandHMAC() */
727
/* This function computes the HMAC for an authorization session in a command. */
728
static TPM2B_DIGEST *
729
ComputeCommandHMAC(
926✔
730
                   COMMAND         *command,       // IN: primary control structure
731
                   UINT32           sessionIndex,  // IN: index of session to be processed
732
                   TPM2B_DIGEST    *hmac           // OUT: authorization HMAC
733
                   )
734
{
735
    TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2));
926✔
736
    TPM2B_KEY        key;
926✔
737
    BYTE             marshalBuffer[sizeof(TPMA_SESSION)];
926✔
738
    BYTE            *buffer;
926✔
739
    UINT32           marshalSize;
926✔
740
    HMAC_STATE       hmacState;
926✔
741
    TPM2B_NONCE     *nonceDecrypt;
926✔
742
    TPM2B_NONCE     *nonceEncrypt;
926✔
743
    SESSION         *session;
926✔
744
    nonceDecrypt = NULL;
926✔
745
    nonceEncrypt = NULL;
926✔
746
    // Determine if extra nonceTPM values are going to be required.
747
    // If this is the first session (sessionIndex = 0) and it is an authorization
748
    // session that uses an HMAC, then check if additional session nonces are to be
749
    // included.
750
    if(sessionIndex == 0
926✔
751
       && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED)
686✔
752
        {
753
            // If there is a decrypt session and if this is not the decrypt session,
754
            // then an extra nonce may be needed.
755
            if(s_decryptSessionIndex != UNDEFINED_INDEX
675✔
756
               && s_decryptSessionIndex != sessionIndex)
154✔
757
                {
758
                    // Will add the nonce for the decrypt session.
759
                    SESSION *decryptSession
84✔
760
                        = SessionGet(s_sessionHandles[s_decryptSessionIndex]);
84✔
761
                    nonceDecrypt = &decryptSession->nonceTPM;
84✔
762
                }
763
            // Now repeat for the encrypt session.
764
            if(s_encryptSessionIndex != UNDEFINED_INDEX
675✔
765
               && s_encryptSessionIndex != sessionIndex
151✔
766
               && s_encryptSessionIndex != s_decryptSessionIndex)
84✔
767
                {
768
                    // Have to have the nonce for the encrypt session.
769
                    SESSION *encryptSession
64✔
770
                        = SessionGet(s_sessionHandles[s_encryptSessionIndex]);
64✔
771
                    nonceEncrypt = &encryptSession->nonceTPM;
64✔
772
                }
773
        }
774
    // Continue with the HMAC processing.
775
    session = SessionGet(s_sessionHandles[sessionIndex]);
926✔
776
    // Generate HMAC key.
777
    MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
926✔
778
    // Check if the session has an associated handle and if the associated entity
779
    // is the one to which the session is bound. If not, add the authValue of
780
    // this entity to the HMAC key.
781
    // If the session is bound to the object or the session is a policy session
782
    // with no authValue required, do not include the authValue in the HMAC key.
783
    // Note: For a policy session, its isBound attribute is CLEARED.
784
    // Include the entity authValue if it is needed
785
    if(session->attributes.includeAuth == SET)
926✔
786
        {
787
            TPM2B_AUTH          authValue;
651✔
788
            // Get the entity authValue with trailing zeros removed
789
            EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue);
651✔
790
            // add the authValue to the HMAC key
791
            MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer));
651✔
792
        }
793
    // if the HMAC key size is 0, a NULL string HMAC is allowed
794
    if(key.t.size == 0
926✔
795
       && s_inputAuthValues[sessionIndex].t.size == 0)
213✔
796
        {
797
            hmac->t.size = 0;
118✔
798
            return hmac;
118✔
799
        }
800
    // Start HMAC
801
    hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b);
808✔
802
    //  Add cpHash
803
    CryptDigestUpdate2B(&hmacState.hashState,
1,616✔
804
                        &ComputeCpHash(command, session->authHashAlg)->b);
808✔
805
    //  Add nonces as required
806
    CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b);
808✔
807
    CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b);
808✔
808
    if(nonceDecrypt != NULL)
808✔
809
        CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b);
84✔
810
    if(nonceEncrypt != NULL)
808✔
811
        CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b);
64✔
812
    //  Add sessionAttributes
813
    buffer = marshalBuffer;
808✔
814
    marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]),
808✔
815
                                       &buffer, NULL);
816
    CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer);
808✔
817
    // Complete the HMAC computation
818
    CryptHmacEnd2B(&hmacState, &hmac->b);
808✔
819
    return hmac;
808✔
820
}
821
/* 6.4.4.10 CheckSessionHMAC() */
822
/* This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the
823
   expected HMAC value and then compares the result with the HMAC in the authorization session. The
824
   authorization is successful if they are the same. */
825
/* If the authorizations are not the same, IncrementLockout() is called. It will return
826
   TPM_RC_AUTH_FAIL if the failure caused the failureCount to increment. Otherwise, it will return
827
   TPM_RC_BAD_AUTH. */
828
/* Error Returns Meaning */
829
/* TPM_RC_AUTH_FAIL authorization failure caused failureCount increment */
830
/* TPM_RC_BAD_AUTH authorization failure did not cause failureCount increment */
831
static TPM_RC
832
CheckSessionHMAC(
926✔
833
                 COMMAND         *command,       // IN: primary control structure
834
                 UINT32           sessionIndex   // IN: index of session to be processed
835
                 )
836
{
837
    TPM2B_DIGEST        hmac;           // authHMAC for comparing
926✔
838
    // Compute authHMAC
839
   ComputeCommandHMAC(command, sessionIndex, &hmac);
926✔
840
    // Compare the input HMAC with the authHMAC computed above.
841
    if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b))
926✔
842
        {
843
            // If an HMAC session has a failure, invoke the anti-hammering
844
            // if it applies to the authorized entity or the session.
845
            // Otherwise, just indicate that the authorization is bad.
846
            return IncrementLockout(sessionIndex);
9✔
847
        }
848
    return TPM_RC_SUCCESS;
849
}
850
/* 6.4.4.11 CheckPolicyAuthSession() */
851
/* This function is used to validate the authorization in a policy session. This function performs
852
   the following comparisons to see if a policy authorization is properly provided. The check
853
   are: */
854
/* a) compare policyDigest in session with authPolicy associated with the entity to be
855
   authorized; */
856
/* b) compare timeout if applicable; */
857
/* c) compare commandCode if applicable; */
858
/* d) compare cpHash if applicable; and */
859
/* e) see if PCR values have changed since computed. */
860
/* If all the above checks succeed, the handle is authorized. The order of these comparisons is not
861
   important because any failure will result in the same error code. */
862
/* Error Returns Meaning */
863
/* TPM_RC_PCR_CHANGED PCR value is not current */
864
/* TPM_RC_POLICY_FAIL policy session fails */
865
/* TPM_RC_LOCALITY command locality is not allowed */
866
/* TPM_RC_POLICY_CC CC doesn't match */
867
/* TPM_RC_EXPIRED policy session has expired */
868
/* TPM_RC_PP PP is required but not asserted */
869
/* TPM_RC_NV_UNAVAILABLE NV is not available for write */
870
/* TPM_RC_NV_RATE NV is rate limiting */
871
static TPM_RC
872
CheckPolicyAuthSession(
192✔
873
                       COMMAND         *command,       // IN: primary parsing structure
874
                       UINT32           sessionIndex   // IN: index of session to be processed
875
                       )
876
{
877
    SESSION             *session;
192✔
878
    TPM2B_DIGEST         authPolicy;
192✔
879
    TPMI_ALG_HASH        policyAlg;
192✔
880
    UINT8                locality;
192✔
881
    // Initialize pointer to the authorization session.
882
    session = SessionGet(s_sessionHandles[sessionIndex]);
192✔
883
    // If the command is TPM2_PolicySecret(), make sure that
884
    // either password or authValue is required
885
    if(command->code == TPM_CC_PolicySecret
192✔
886
       &&  session->attributes.isPasswordNeeded == CLEAR
887
       &&  session->attributes.isAuthValueNeeded == CLEAR)
×
888
        return TPM_RC_MODE;
889
    // See if the PCR counter for the session is still valid.
890
    if(!SessionPCRValueIsCurrent(session))
192✔
891
        return TPM_RC_PCR_CHANGED;
892
    // Get authPolicy.
893
    policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex],
191✔
894
                                    &authPolicy);
895
    // Compare authPolicy.
896
    if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b))
191✔
897
        return TPM_RC_POLICY_FAIL;
898
    // Policy is OK so check if the other factors are correct
899
    // Compare policy hash algorithm.
900
    if(policyAlg != session->authHashAlg)
157✔
901
        return TPM_RC_POLICY_FAIL;
902
    // Compare timeout.
903
    if(session->timeout != 0)
157✔
904
        {
905
            // Cannot compare time if clock stop advancing.  An TPM_RC_NV_UNAVAILABLE
906
            // or TPM_RC_NV_RATE error may be returned here. This doesn't mean that
907
            // a new nonce will be created just that, because TPM time can't advance
908
            // we can't do time-based operations.
909
            RETURN_IF_NV_IS_NOT_AVAILABLE;
11✔
910
            if((session->timeout < g_time)
11✔
911
               || (session->epoch != g_timeEpoch))
11✔
912
                return TPM_RC_EXPIRED;
913
        }
914
    // If command code is provided it must match
915
    if(session->commandCode != 0)
157✔
916
        {
917
            if(session->commandCode != command->code)
84✔
918
                return TPM_RC_POLICY_CC;
919
        }
920
    else
921
        {
922
            // If command requires a DUP or ADMIN authorization, the session must have
923
            // command code set.
924
            AUTH_ROLE   role = CommandAuthRole(command->index, sessionIndex);
73✔
925
            if(role == AUTH_ADMIN || role == AUTH_DUP)
73✔
926
                return TPM_RC_POLICY_FAIL;
927
        }
928
    // Check command locality.
929
    {
930
        BYTE         sessionLocality[sizeof(TPMA_LOCALITY)];
154✔
931
        BYTE        *buffer = sessionLocality;
154✔
932
        // Get existing locality setting in canonical form
933
        sessionLocality[0] = 0;
154✔
934
        TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
154✔
935
        // See if the locality has been set
936
        if(sessionLocality[0] != 0)
154✔
937
            {
938
                // If so, get the current locality
939
                locality = _plat__LocalityGet();
×
940
                if(locality < 5)
×
941
                    {
942
                        if(((sessionLocality[0] & (1 << locality)) == 0)
×
943
                           || sessionLocality[0] > 31)
×
944
                            return TPM_RC_LOCALITY;
×
945
                    }
946
                else if(locality > 31)
×
947
                    {
948
                        if(sessionLocality[0] != locality)
×
949
                            return TPM_RC_LOCALITY;
950
                    }
951
                else
952
                    {
953
                        // Could throw an assert here but a locality error is just
954
                        // as good. It just means that, whatever the locality is, it isn't
955
                        // the locality requested so...
956
                        return TPM_RC_LOCALITY;
957
                    }
958
            }
959
    } // end of locality check
960
    // Check physical presence.
961
    if(session->attributes.isPPRequired == SET
154✔
962
       && !_plat__PhysicalPresenceAsserted())
×
963
        return TPM_RC_PP;
964
    // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or
965
    // DUP role for this handle.
966
    if(session->u1.cpHash.b.size != 0)
154✔
967
        {
968
            BOOL        OK;
10✔
969
            if(session->attributes.isCpHashDefined)
10✔
970
                // Compare cpHash.
971
                OK = MemoryEqual2B(&session->u1.cpHash.b,
8✔
972
                                   &ComputeCpHash(command, session->authHashAlg)->b);
4✔
973
            else if(session->attributes.isTemplateSet)
6✔
974
                OK = CompareTemplateHash(command, session);
3✔
975
            else
976
                OK = CompareNameHash(command, session);
3✔
977
            if(!OK)
10✔
978
                return TPM_RCS_POLICY_FAIL;
979
        }
980
    if(session->attributes.checkNvWritten)
153✔
981
        {
982
            NV_REF           locator;
4✔
983
            NV_INDEX        *nvIndex;
4✔
984
            // If this is not an NV index, the policy makes no sense so fail it.
985
            if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX)
4✔
986
                return TPM_RC_POLICY_FAIL;
1✔
987
            // Get the index data
988
            nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator);
4✔
989
            // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state
990
            if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
4✔
991
               != (session->attributes.nvWrittenState == SET))
4✔
992
                return TPM_RC_POLICY_FAIL;
993
        }
994
    return TPM_RC_SUCCESS;
995
}
996
/* 6.4.4.12 RetrieveSessionData() */
997
/* This function will unmarshal the sessions in the session area of a command. The values are placed
998
   in the arrays that are defined at the beginning of this file. The normal unmarshaling errors are
999
   possible. */
1000
/* Error Returns Meaning */
1001
/* TPM_RC_SUCCSS unmarshaled without error */
1002
/* TPM_RC_SIZE the number of bytes unmarshaled is not the same as the value for authorizationSize in
1003
   the command */
1004
static TPM_RC
1005
RetrieveSessionData(
6,371✔
1006
                    COMMAND         *command        // IN: main parsing structure for command
1007
                    )
1008
{
1009
    int              i;
6,371✔
1010
    TPM_RC           result;
6,371✔
1011
    SESSION         *session;
6,371✔
1012
    TPMA_SESSION     sessionAttributes;
6,371✔
1013
    TPM_HT           sessionType;
6,371✔
1014
    INT32            sessionIndex;
6,371✔
1015
    TPM_RC           errorIndex;
6,371✔
1016
    s_decryptSessionIndex = UNDEFINED_INDEX;
6,371✔
1017
    s_encryptSessionIndex = UNDEFINED_INDEX;
6,371✔
1018
    s_auditSessionIndex = UNDEFINED_INDEX;
6,371✔
1019
    for(sessionIndex = 0; command->authSize > 0; sessionIndex++)
13,195✔
1020
        {
1021
            errorIndex = TPM_RC_S + g_rcIndex[sessionIndex];
6,874✔
1022
            // If maximum allowed number of sessions has been parsed, return a size
1023
            // error with a session number that is larger than the number of allowed
1024
            // sessions
1025
            if(sessionIndex == MAX_SESSION_NUM)
6,874✔
1026
                return TPM_RCS_SIZE + errorIndex;
4✔
1027
            // make sure that the associated handle for each session starts out
1028
            // unassigned
1029
            s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
6,870✔
1030
            // First parameter: Session handle.
1031
            result = TPMI_SH_AUTH_SESSION_Unmarshal(
13,740✔
1032
                                                    &s_sessionHandles[sessionIndex],
6,870✔
1033
                                                    &command->parameterBuffer,
1034
                                                    &command->authSize, TRUE);
1035
            if(result != TPM_RC_SUCCESS)
6,870✔
1036
                return result + TPM_RC_S + g_rcIndex[sessionIndex];
16✔
1037
            // Second parameter: Nonce.
1038
            result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex],
6,854✔
1039
                                           &command->parameterBuffer,
1040
                                           &command->authSize);
1041
            if(result != TPM_RC_SUCCESS)
6,854✔
1042
                return result + TPM_RC_S + g_rcIndex[sessionIndex];
8✔
1043
            // Third parameter: sessionAttributes.
1044
            result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex],
6,846✔
1045
                                            &command->parameterBuffer,
1046
                                            &command->authSize);
1047
            if(result != TPM_RC_SUCCESS)
6,846✔
1048
                return result + TPM_RC_S + g_rcIndex[sessionIndex];
4✔
1049
            // Fourth parameter: authValue (PW or HMAC).
1050
            result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex],
6,842✔
1051
                                          &command->parameterBuffer,
1052
                                          &command->authSize);
1053
            if(result != TPM_RC_SUCCESS)
6,842✔
1054
                return result + errorIndex;
4✔
1055
            sessionAttributes = s_attributes[sessionIndex];
6,838✔
1056
            if(s_sessionHandles[sessionIndex] == TPM_RS_PW)
6,838✔
1057
                {
1058
                    // A PWAP session needs additional processing.
1059
                    //     Can't have any attributes set other than continueSession bit
1060
                    if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)
5,857✔
1061
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)
1062
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)
5,857✔
1063
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
1064
                       || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset))
5,853✔
1065
                        return TPM_RCS_ATTRIBUTES + errorIndex;
4✔
1066
                    //     The nonce size must be zero.
1067
                    if(s_nonceCaller[sessionIndex].t.size != 0)
5,853✔
1068
                        return TPM_RCS_NONCE + errorIndex;
4✔
1069
                    continue;
5,849✔
1070
                }
1071
            // For not password sessions...
1072
            // Find out if the session is loaded.
1073
            if(!SessionIsLoaded(s_sessionHandles[sessionIndex]))
981✔
1074
                return TPM_RC_REFERENCE_S0 + sessionIndex;
6✔
1075
            sessionType = HandleGetType(s_sessionHandles[sessionIndex]);
975✔
1076
            session = SessionGet(s_sessionHandles[sessionIndex]);
975✔
1077
            // Check if the session is an HMAC/policy session.
1078
            if((session->attributes.isPolicy == SET
975✔
1079
                && sessionType == TPM_HT_HMAC_SESSION)
192✔
1080
               || (session->attributes.isPolicy == CLEAR
975✔
1081
                   && sessionType == TPM_HT_POLICY_SESSION))
783✔
1082
                return TPM_RCS_HANDLE + errorIndex;
×
1083
            // Check that this handle has not previously been used.
1084
            for(i = 0; i < sessionIndex; i++)
1,300✔
1085
                {
1086
                    if(s_sessionHandles[i] == s_sessionHandles[sessionIndex])
325✔
1087
                        return TPM_RCS_HANDLE + errorIndex;
×
1088
                }
1089
            // If the session is used for parameter encryption or audit as well, set
1090
            // the corresponding Indexes.
1091
            // First process decrypt.
1092
            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt))
975✔
1093
                {
1094
                    // Check if the commandCode allows command parameter encryption.
1095
                    if(DecryptSize(command->index) == 0)
154✔
1096
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1097
                    // Encrypt attribute can only appear in one session
1098
                    if(s_decryptSessionIndex != UNDEFINED_INDEX)
154✔
1099
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1100
                    // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL
1101
                    if(session->symmetric.algorithm == TPM_ALG_NULL)
154✔
1102
                        return TPM_RCS_SYMMETRIC + errorIndex;
×
1103
                    // All checks passed, so set the index for the session used to decrypt
1104
                    // a command parameter.
1105
                    s_decryptSessionIndex = sessionIndex;
154✔
1106
                }
1107
            // Now process encrypt.
1108
            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt))
975✔
1109
                {
1110
                    // Check if the commandCode allows response parameter encryption.
1111
                    if(EncryptSize(command->index) == 0)
151✔
1112
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1113
                    // Encrypt attribute can only appear in one session.
1114
                    if(s_encryptSessionIndex != UNDEFINED_INDEX)
151✔
1115
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1116
                    // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL
1117
                    if(session->symmetric.algorithm == TPM_ALG_NULL)
151✔
1118
                        return TPM_RCS_SYMMETRIC + errorIndex;
×
1119
                    // All checks passed, so set the index for the session used to encrypt
1120
                    // a response parameter.
1121
                    s_encryptSessionIndex = sessionIndex;
151✔
1122
                }
1123
            // At last process audit.
1124
            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit))
975✔
1125
                {
1126
                    // Audit attribute can only appear in one session.
1127
                    if(s_auditSessionIndex != UNDEFINED_INDEX)
35✔
1128
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1129
                    // An audit session can not be policy session.
1130
                    if(HandleGetType(s_sessionHandles[sessionIndex])
35✔
1131
                       == TPM_HT_POLICY_SESSION)
1132
                        return TPM_RCS_ATTRIBUTES + errorIndex;
×
1133
                    // If this is a reset of the audit session, or the first use
1134
                    // of the session as an audit session, it doesn't matter what
1135
                    // the exclusive state is. The session will become exclusive.
1136
                    if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)
35✔
1137
                       && session->attributes.isAudit == SET)
35✔
1138
                        {
1139
                            // Not first use or reset. If auditExlusive is SET, then this
1140
                            // session must be the current exclusive session.
1141
                            if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive)
14✔
1142
                               && g_exclusiveAuditSession != s_sessionHandles[sessionIndex])
×
1143
                                return TPM_RC_EXCLUSIVE;
1144
                        }
1145
                    s_auditSessionIndex = sessionIndex;
35✔
1146
                }
1147
            // Initialize associated handle as undefined. This will be changed when
1148
            // the handles are processed.
1149
            s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED;
975✔
1150
        }
1151
    command->sessionNum = sessionIndex;
6,321✔
1152
    return TPM_RC_SUCCESS;
6,321✔
1153
}
1154
/* 6.4.4.13 CheckLockedOut() */
1155
/* This function checks to see if the TPM is in lockout. This function should only be called if the
1156
   entity being checked is subject to DA protection. The TPM is in lockout if the NV is not
1157
   available and a DA write is pending. Otherwise the TPM is locked out if checking for lockoutAuth
1158
   (lockoutAuthCheck == TRUE) and use of lockoutAuth is disabled, or failedTries >= maxTries */
1159
/* Error Returns Meaning */
1160
/* TPM_RC_NV_RATE NV is rate limiting */
1161
/* TPM_RC_NV_UNAVAILABLE NV is not available at this time */
1162
/* TPM_RC_LOCKOUT TPM is in lockout */
1163
static TPM_RC
1164
CheckLockedOut(
155✔
1165
               BOOL             lockoutAuthCheck   // IN: TRUE if checking is for lockoutAuth
1166
               )
1167
{
1168
    // If NV is unavailable, and current cycle state recorded in NV is not
1169
    // SU_NONE_VALUE, refuse to check any authorization because we would
1170
    // not be able to handle a DA failure.
1171
    if(!NV_IS_AVAILABLE && NV_IS_ORDERLY)
155✔
1172
        return g_NvStatus;
1173
    // Check if DA info needs to be updated in NV.
1174
    if(s_DAPendingOnNV)
155✔
1175
        {
1176
            // If NV is accessible,
1177
            RETURN_IF_NV_IS_NOT_AVAILABLE;
×
1178
            // ... write the pending DA data and proceed.
1179
            NV_SYNC_PERSISTENT(lockOutAuthEnabled);
×
1180
            NV_SYNC_PERSISTENT(failedTries);
×
1181
            s_DAPendingOnNV = FALSE;
×
1182
        }
1183
    // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth
1184
    // is disabled...
1185
    if(lockoutAuthCheck)
155✔
1186
        {
1187
            if(gp.lockOutAuthEnabled == FALSE)
75✔
1188
                return TPM_RC_LOCKOUT;
×
1189
        }
1190
    else
1191
        {
1192
            // ... or if the number of failed tries has been maxed out.
1193
            if(gp.failedTries >= gp.maxTries)
80✔
1194
                return TPM_RC_LOCKOUT;
1195
#if USE_DA_USED
1196
            // If the daUsed flag is not SET, then no DA validation until the
1197
            // daUsed state is written to NV
1198
            if(!g_daUsed)
42✔
1199
                {
1200
                    RETURN_IF_NV_IS_NOT_AVAILABLE;
10✔
1201
                    g_daUsed = TRUE;
10✔
1202
                    gp.orderlyState = SU_DA_USED_VALUE;
10✔
1203
                    NV_SYNC_PERSISTENT(orderlyState);
10✔
1204
                    return TPM_RC_RETRY;
10✔
1205
                }
1206
#endif
1207
        }
1208
    return TPM_RC_SUCCESS;
1209
}
1210
/* 6.4.4.14 CheckAuthSession() */
1211
/* This function checks that the authorization session properly authorizes the use of the associated
1212
   handle. */
1213
/* Error Returns Meaning */
1214
/* TPM_RC_LOCKOUT entity is protected by DA and TPM is in lockout, or TPM is locked out on NV update
1215
   pending on DA parameters */
1216
/* TPM_RC_PP Physical Presence is required but not provided */
1217
/* TPM_RC_AUTH_FAIL HMAC or PW authorization failed with DA side-effects (can be a policy
1218
   session) */
1219
/* TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA side-effects (can be a policy
1220
   session) */
1221
/* TPM_RC_POLICY_FAIL if policy session fails */
1222
/* TPM_RC_POLICY_CC command code of policy was wrong */
1223
/* TPM_RC_EXPIRED the policy session has expired */
1224
/* TPM_RC_PCR ??? */
1225
/* TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable */
1226
static TPM_RC
1227
CheckAuthSession(
6,687✔
1228
                 COMMAND         *command,       // IN: primary parsing structure
1229
                 UINT32           sessionIndex   // IN: index of session to be processed
1230
                 )
1231
{
1232
    TPM_RC           result = TPM_RC_SUCCESS;
6,687✔
1233
    SESSION         *session = NULL;
6,687✔
1234
    TPM_HANDLE       sessionHandle = s_sessionHandles[sessionIndex];
6,687✔
1235
    TPM_HANDLE       associatedHandle = s_associatedHandles[sessionIndex];
6,687✔
1236
    TPM_HT           sessionHandleType = HandleGetType(sessionHandle);
6,687✔
1237
    BOOL             authUsed;
6,687✔
1238

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