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

stefanberger / libtpms / #1996

10 Jun 2025 01:38PM UTC coverage: 76.794% (+0.02%) from 76.773%
#1996

push

travis-ci

web-flow
Merge e65bedd5e into 06a717f7c

33760 of 43962 relevant lines covered (76.79%)

87788.18 hits per line

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

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

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