Coverage Report

Created: 2025-08-03 06:18

/src/libtpms/src/tpm12/tpm_delegate.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*        Delegate Handler        */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*        $Id: tpm_delegate.c 4580 2011-06-10 17:55:41Z kgoldman $    */
7
/*                    */
8
/* (c) Copyright IBM Corporation 2006, 2010.          */
9
/*                    */
10
/* All rights reserved.               */
11
/*                    */
12
/* Redistribution and use in source and binary forms, with or without   */
13
/* modification, are permitted provided that the following conditions are */
14
/* met:                   */
15
/*                    */
16
/* Redistributions of source code must retain the above copyright notice, */
17
/* this list of conditions and the following disclaimer.      */
18
/*                    */
19
/* Redistributions in binary form must reproduce the above copyright    */
20
/* notice, this list of conditions and the following disclaimer in the    */
21
/* documentation and/or other materials provided with the distribution.   */
22
/*                    */
23
/* Neither the names of the IBM Corporation nor the names of its    */
24
/* contributors may be used to endorse or promote products derived from   */
25
/* this software without specific prior written permission.     */
26
/*                    */
27
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    */
28
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    */
29
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  */
30
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT   */
31
/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT   */
33
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  */
34
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  */
35
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT    */
36
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  */
37
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   */
38
/********************************************************************************/
39
40
#include <stdio.h>
41
#include <stdlib.h>
42
43
#include "tpm_auth.h"
44
#include "tpm_crypto.h"
45
#include "tpm_cryptoh.h"
46
#include "tpm_debug.h"
47
#include "tpm_digest.h"
48
#include "tpm_error.h"
49
#include "tpm_key.h"
50
#include "tpm_pcr.h"
51
#include "tpm_permanent.h"
52
#include "tpm_process.h"
53
#include "tpm_secret.h"
54
55
#include "tpm_delegate.h"
56
57
/*
58
  TPM_DELEGATE_PUBLIC
59
*/
60
61
/* TPM_DelegatePublic_Init()
62
63
   sets members to default values
64
   sets all pointers to NULL and sizes to 0
65
   always succeeds - no return code
66
*/
67
68
void TPM_DelegatePublic_Init(TPM_DELEGATE_PUBLIC *tpm_delegate_public)
69
0
{
70
0
    printf(" TPM_DelegatePublic_Init:\n");
71
0
    tpm_delegate_public->rowLabel = 0;
72
0
    TPM_PCRInfoShort_Init(&(tpm_delegate_public->pcrInfo));
73
0
    TPM_Delegations_Init(&(tpm_delegate_public->permissions));
74
0
    tpm_delegate_public->familyID = 0;
75
0
    tpm_delegate_public->verificationCount = 0;
76
0
    return;
77
0
}
78
79
/* TPM_DelegatePublic_Load()
80
81
   deserialize the structure from a 'stream'
82
   'stream_size' is checked for sufficient data
83
   returns 0 or error codes
84
85
   After use, call TPM_DelegatePublic_Delete() to free memory
86
*/
87
88
TPM_RESULT TPM_DelegatePublic_Load(TPM_DELEGATE_PUBLIC *tpm_delegate_public,
89
           unsigned char **stream,
90
           uint32_t *stream_size)
91
0
{
92
0
    TPM_RESULT  rc = 0;
93
    
94
0
    printf(" TPM_DelegatePublic_Load:\n");
95
    /* check the tag */
96
0
    if (rc == 0) {
97
0
  rc = TPM_CheckTag(TPM_TAG_DELEGATE_PUBLIC, stream, stream_size);
98
0
    }
99
    /* load rowLabel */
100
0
    if (rc == 0) {
101
0
  rc = TPM_Load8(&(tpm_delegate_public->rowLabel), stream, stream_size);
102
0
    }
103
    /* load pcrInfo */
104
0
    if (rc == 0) {
105
0
  rc = TPM_PCRInfoShort_Load(&(tpm_delegate_public->pcrInfo), stream, stream_size, FALSE);
106
0
    }
107
    /* load permissions */
108
0
    if (rc == 0) {
109
0
  rc = TPM_Delegations_Load(&(tpm_delegate_public->permissions), stream, stream_size);
110
0
    }
111
    /* load the familyID */
112
0
    if (rc == 0) {
113
0
  rc = TPM_Load32(&(tpm_delegate_public->familyID), stream, stream_size);
114
0
    }
115
    /* load the verificationCount */
116
0
    if (rc == 0) {
117
0
  rc = TPM_Load32(&(tpm_delegate_public->verificationCount), stream, stream_size);
118
0
    }
119
0
    return rc;
120
0
}
121
122
/* TPM_DelegatePublic_Store()
123
   
124
   serialize the structure to a stream contained in 'sbuffer'
125
   returns 0 or error codes
126
*/
127
128
TPM_RESULT TPM_DelegatePublic_Store(TPM_STORE_BUFFER *sbuffer,
129
            const TPM_DELEGATE_PUBLIC *tpm_delegate_public)
130
0
{
131
0
    TPM_RESULT  rc = 0;
132
    
133
0
    printf(" TPM_DelegatePublic_Store:\n");
134
    /* store tag */
135
0
    if (rc == 0) {
136
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_PUBLIC);
137
0
    }
138
    /* store rowLabel */
139
0
    if (rc == 0) {
140
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_delegate_public->rowLabel),
141
0
             sizeof(TPM_DELEGATE_LABEL)); 
142
0
    }
143
    /* store pcrInfo */
144
0
    if (rc == 0) {
145
0
  rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_delegate_public->pcrInfo), FALSE); 
146
0
    } 
147
    /* store permissions */
148
0
    if (rc == 0) {
149
0
  rc = TPM_Delegations_Store(sbuffer, &(tpm_delegate_public->permissions)); 
150
0
    }
151
    /* store familyID */
152
0
    if (rc == 0) {
153
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegate_public->familyID);
154
0
    }
155
    /* store verificationCount */
156
0
    if (rc == 0) {
157
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegate_public->verificationCount);
158
0
    }
159
0
    return rc;
160
0
}
161
162
/* TPM_DelegatePublic_Delete()
163
164
   No-OP if the parameter is NULL, else:
165
   frees memory allocated for the object
166
   sets pointers to NULL
167
   calls TPM_DelegatePublic_Init to set members back to default values
168
   The object itself is not freed
169
*/   
170
171
void TPM_DelegatePublic_Delete(TPM_DELEGATE_PUBLIC *tpm_delegate_public)
172
0
{
173
0
    printf(" TPM_DeleteDelegatePublic:\n");
174
0
    if (tpm_delegate_public != NULL) {
175
0
  TPM_PCRInfoShort_Delete(&(tpm_delegate_public->pcrInfo));
176
0
  TPM_Delegations_Delete(&(tpm_delegate_public->permissions));
177
0
  TPM_DelegatePublic_Init(tpm_delegate_public);
178
0
    }
179
0
    return;
180
0
}
181
182
/* TPM_DelegatePublic_Copy() copies the 'src' to the 'dest' structure
183
184
*/
185
186
TPM_RESULT TPM_DelegatePublic_Copy(TPM_DELEGATE_PUBLIC *dest,
187
           TPM_DELEGATE_PUBLIC *src)
188
0
{
189
0
    TPM_RESULT  rc = 0;
190
    
191
0
    printf(" TPM_DelegatePublic_Copy:\n");
192
0
    if (rc == 0) {
193
  /* copy rowLabel */
194
0
  dest->rowLabel = src->rowLabel;
195
  /* copy pcrInfo */
196
0
  rc = TPM_PCRInfoShort_Copy(&(dest->pcrInfo), &(src->pcrInfo));
197
0
    }
198
0
    if (rc == 0) {
199
  /* copy permissions */
200
0
  TPM_Delegations_Copy(&(dest->permissions), &(src->permissions));
201
  /* copy familyID */
202
0
  dest->familyID = src->familyID;
203
  /* copy verificationCount */
204
0
  dest->verificationCount = src->verificationCount;
205
0
    }
206
0
    return rc;
207
0
}
208
209
/*
210
  TPM_DELEGATE_SENSITIVE
211
*/
212
213
/* TPM_DelegateSensitive_Init()
214
215
   sets members to default values
216
   sets all pointers to NULL and sizes to 0
217
   always succeeds - no return code
218
*/
219
220
void TPM_DelegateSensitive_Init(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive)
221
0
{
222
0
    printf(" TPM_DelegateSensitive_Init:\n");
223
0
    TPM_Secret_Init(tpm_delegate_sensitive->authValue);
224
0
    return;
225
0
}
226
227
/* TPM_DelegateSensitive_Load()
228
229
   deserialize the structure from a 'stream'
230
   'stream_size' is checked for sufficient data
231
   returns 0 or error codes
232
233
   After use, call TPM_DelegateSensitive_Delete() to free memory
234
*/
235
236
TPM_RESULT TPM_DelegateSensitive_Load(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive,
237
              unsigned char **stream,
238
              uint32_t *stream_size)
239
0
{
240
0
    TPM_RESULT  rc = 0;
241
    
242
0
    printf(" TPM_DelegateSensitive_Load:\n");
243
    /* check the tag */
244
0
    if (rc == 0) {
245
0
  rc = TPM_CheckTag(TPM_TAG_DELEGATE_SENSITIVE, stream, stream_size);
246
0
    }
247
    /* load authValue */
248
0
    if (rc == 0) {
249
0
  rc = TPM_Secret_Load(tpm_delegate_sensitive->authValue, stream, stream_size);
250
0
    }
251
0
    return rc;
252
0
}
253
254
/* TPM_DelegateSensitive_Store()
255
   
256
   serialize the structure to a stream contained in 'sbuffer'
257
   returns 0 or error codes
258
*/
259
260
TPM_RESULT TPM_DelegateSensitive_Store(TPM_STORE_BUFFER *sbuffer,
261
               const TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive)
262
0
{
263
0
    TPM_RESULT  rc = 0;
264
    
265
0
    printf(" TPM_DelegateSensitive_Store:\n");
266
0
    if (rc == 0) {
267
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_SENSITIVE);
268
0
    }
269
0
    if (rc == 0) {
270
0
  rc = TPM_Secret_Store(sbuffer, tpm_delegate_sensitive->authValue);
271
0
    }
272
0
    return rc;
273
0
}
274
275
/* TPM_DelegateSensitive_Delete()
276
277
   No-OP if the parameter is NULL, else:
278
   frees memory allocated for the object
279
   sets pointers to NULL
280
   calls TPM_DelegateSensitive_Init to set members back to default values
281
   The object itself is not freed
282
*/   
283
284
void TPM_DelegateSensitive_Delete(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive)
285
0
{
286
0
    printf(" TPM_DeleteDelegateSensitive:\n");
287
0
    if (tpm_delegate_sensitive != NULL) {
288
0
  TPM_DelegateSensitive_Init(tpm_delegate_sensitive);
289
0
    }
290
0
    return;
291
0
}
292
293
/* TPM_DelegateSensitive_DecryptEncData() decrypts 'sensitiveArea' to a stream using 'delegateKey'
294
   and then deserializes the stream to a TPM_DELEGATE_SENSITIVE
295
*/
296
297
TPM_RESULT TPM_DelegateSensitive_DecryptEncData(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive,
298
            TPM_SIZED_BUFFER *sensitiveArea,
299
            TPM_SYMMETRIC_KEY_TOKEN delegateKey)
300
0
{
301
0
    TPM_RESULT  rc = 0;
302
0
    unsigned char   *s1;      /* decrypted sensitive data */
303
0
    uint32_t      s1_length;  
304
0
    unsigned char   *stream;    /* temp input stream */
305
0
    uint32_t      stream_size;
306
307
0
    printf(" TPM_DelegateSensitive_DecryptEncData:\n");
308
0
    s1 = NULL;            /* freed @1 */
309
0
    if (rc == 0) {
310
0
  rc = TPM_SymmetricKeyData_Decrypt(&s1,    /* decrypted data */
311
0
            &s1_length, /* length decrypted data */
312
0
            sensitiveArea->buffer, 
313
0
            sensitiveArea->size,
314
0
            delegateKey);
315
0
    }
316
0
    if (rc == 0) {
317
0
  stream = s1;
318
0
  stream_size = s1_length;
319
0
  rc = TPM_DelegateSensitive_Load(tpm_delegate_sensitive, &stream, &stream_size);
320
0
    }
321
0
    free(s1);   /* @1 */
322
0
    return rc;
323
0
}
324
325
/*
326
  TPM_DELEGATIONS
327
*/
328
329
/* TPM_Delegations_Init()
330
331
   sets members to default values
332
   sets all pointers to NULL and sizes to 0
333
   always succeeds - no return code
334
*/
335
336
void TPM_Delegations_Init(TPM_DELEGATIONS *tpm_delegations)
337
0
{
338
0
    printf(" TPM_Delegations_Init:\n");
339
0
    tpm_delegations->delegateType = TPM_DEL_KEY_BITS; /* any legal value */
340
0
    tpm_delegations->per1 = 0;
341
0
    tpm_delegations->per2 = 0;
342
0
    return;
343
0
}
344
345
/* TPM_Delegations_Load()
346
347
   deserialize the structure from a 'stream'
348
   'stream_size' is checked for sufficient data
349
   returns 0 or error codes
350
351
   After use, call TPM_DeleteDelegations() to free memory
352
*/
353
354
TPM_RESULT TPM_Delegations_Load(TPM_DELEGATIONS *tpm_delegations,
355
        unsigned char **stream,
356
        uint32_t *stream_size)
357
0
{
358
0
    TPM_RESULT  rc = 0;
359
    
360
0
    printf(" TPM_Delegations_Load:\n");
361
    /* check tag */
362
0
    if (rc == 0) {
363
0
  rc = TPM_CheckTag(TPM_TAG_DELEGATIONS, stream, stream_size);
364
0
    }
365
    /* load delegateType */
366
0
    if (rc == 0) {
367
0
  rc = TPM_Load32(&(tpm_delegations->delegateType), stream, stream_size);
368
0
    }
369
    /* load per1 */
370
0
    if (rc == 0) {
371
0
  rc = TPM_Load32(&(tpm_delegations->per1), stream, stream_size);
372
0
    }
373
    /* load per2 */
374
0
    if (rc == 0) {
375
0
  rc = TPM_Load32(&(tpm_delegations->per2), stream, stream_size);
376
0
    }
377
    /* validate parameters */
378
0
    if (rc == 0) {
379
0
  if (tpm_delegations->delegateType == TPM_DEL_OWNER_BITS) {
380
0
      if (tpm_delegations->per1 & ~TPM_DELEGATE_PER1_MASK) {
381
0
    printf("TPM_Delegations_Load: Error, owner per1 %08x\n", tpm_delegations->per1);
382
0
    rc = TPM_BAD_PARAMETER;
383
0
      }
384
0
      if (tpm_delegations->per2 & ~TPM_DELEGATE_PER2_MASK) {
385
0
    printf("TPM_Delegations_Load: Error, owner per2 %08x\n", tpm_delegations->per2);
386
0
    rc = TPM_BAD_PARAMETER;
387
0
      }
388
0
  }
389
0
  else if (tpm_delegations->delegateType == TPM_DEL_KEY_BITS) {
390
0
      if (tpm_delegations->per1 & ~TPM_KEY_DELEGATE_PER1_MASK) {
391
0
    printf("TPM_Delegations_Load: Error, key per1 %08x\n", tpm_delegations->per1);
392
0
    rc = TPM_BAD_PARAMETER;
393
0
      }
394
0
      if (tpm_delegations->per2 & ~TPM_KEY_DELEGATE_PER2_MASK) {
395
0
    printf("TPM_Delegations_Load: Error, key per2 %08x\n", tpm_delegations->per2);
396
0
    rc = TPM_BAD_PARAMETER;
397
0
      }
398
0
  }
399
0
  else {
400
0
      printf("TPM_Delegations_Load: Error, delegateType %08x\n",
401
0
       tpm_delegations->delegateType);
402
0
      rc = TPM_BAD_PARAMETER;
403
0
  }
404
0
    }  
405
0
    return rc;
406
0
}
407
408
/* TPM_Delegations_Store()
409
   
410
   serialize the structure to a stream contained in 'sbuffer'
411
   returns 0 or error codes
412
*/
413
414
TPM_RESULT TPM_Delegations_Store(TPM_STORE_BUFFER *sbuffer,
415
         const TPM_DELEGATIONS *tpm_delegations)
416
0
{
417
0
    TPM_RESULT  rc = 0;
418
    
419
0
    printf(" TPM_Delegations_Store:\n");
420
    /* store tag */
421
0
    if (rc == 0) {
422
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATIONS);
423
0
    }
424
    /* store delegateType */
425
0
    if (rc == 0) {
426
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->delegateType);
427
0
    }
428
    /* store per1 */
429
0
    if (rc == 0) {
430
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->per1);
431
0
    }
432
    /* store per2 */
433
0
    if (rc == 0) {
434
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->per2);
435
0
    }
436
0
    return rc;
437
0
}
438
439
/* TPM_Delegations_Delete()
440
441
   No-OP if the parameter is NULL, else:
442
   frees memory allocated for the object
443
   sets pointers to NULL
444
   calls TPM_Delegations_Init to set members back to default values
445
   The object itself is not freed
446
*/   
447
448
void TPM_Delegations_Delete(TPM_DELEGATIONS *tpm_delegations)
449
0
{
450
0
    printf(" TPM_Delegations_Delete:\n");
451
0
    if (tpm_delegations != NULL) {
452
0
  TPM_Delegations_Init(tpm_delegations);
453
0
    }
454
0
    return;
455
0
}
456
457
/* TPM_Delegations_Copy() copies the source to the destination
458
 */
459
460
void TPM_Delegations_Copy(TPM_DELEGATIONS *dest,
461
        TPM_DELEGATIONS *src)
462
0
{
463
0
    dest->delegateType = src->delegateType;
464
0
    dest->per1 = src->per1;
465
0
    dest->per2 = src->per2;
466
0
    return;
467
0
}
468
469
/* TPM_Delegations_CheckPermissionDelegation() verifies that the new delegation bits do not grant
470
   more permissions then currently delegated.  Otherwise return error TPM_AUTHFAIL.
471
472
   An error occurs if a bit is set in newDelegations -> per and clear in currentDelegations -> per
473
*/
474
475
TPM_RESULT TPM_Delegations_CheckPermissionDelegation(TPM_DELEGATIONS *newDelegations,
476
                 TPM_DELEGATIONS *currentDelegations)
477
0
{
478
0
    TPM_RESULT  rc = 0;
479
480
0
    printf(" TPM_Delegations_CheckPermissionDelegation:\n");
481
    /* check per1 */
482
0
    if (rc == 0) {
483
0
  if (newDelegations->per1 & ~currentDelegations->per1) {
484
0
      printf("TPM_Delegations_CheckPermissionDelegation: Error, "
485
0
       "new per1 %08x current per1 %08x\n",
486
0
       newDelegations->per1, currentDelegations->per1);
487
0
      rc = TPM_AUTHFAIL;
488
0
  }
489
0
    }
490
    /* check per2 */
491
0
    if (rc == 0) {
492
0
  if (newDelegations->per2 & ~currentDelegations->per2) {
493
0
      printf("TPM_Delegations_CheckPermissionDelegation: Error, "
494
0
       "new per1 %08x current per1 %08x\n",
495
0
       newDelegations->per1, currentDelegations->per1);
496
0
      rc = TPM_AUTHFAIL;
497
0
  }
498
0
    }
499
0
    return rc;
500
0
}
501
502
/* TPM_Delegations_CheckPermission() verifies that the 'ordinal' has been delegated for execution
503
   based on the TPM_DELEGATE_PUBLIC.
504
505
   It verifies that the TPM_DELEGATIONS is appropriate for the entityType.  Currently, only key or
506
   owner authorization can be delegated.
507
508
   It verifies that the TPM_DELEGATE_PUBLIC PCR's allow the delegation.
509
*/
510
511
TPM_RESULT TPM_Delegations_CheckPermission(tpm_state_t *tpm_state,
512
             TPM_DELEGATE_PUBLIC *delegatePublic,
513
             TPM_ENT_TYPE entityType,   /* required */
514
             TPM_COMMAND_CODE ordinal)
515
0
{
516
0
    TPM_RESULT  rc = 0;
517
518
0
    printf(" TPM_Delegations_CheckPermission: ordinal %08x\n", ordinal);
519
0
    if (rc == 0) {
520
0
  switch (entityType) {
521
0
    case TPM_ET_KEYHANDLE:
522
0
      rc = TPM_Delegations_CheckKeyPermission(&(delegatePublic->permissions), ordinal);
523
0
      break;
524
0
    case TPM_ET_OWNER:
525
0
      rc = TPM_Delegations_CheckOwnerPermission(&(delegatePublic->permissions), ordinal);
526
0
      break;
527
0
    default:
528
0
      printf("TPM_Delegations_CheckPermission: Error, "
529
0
       "DSAP session does not support entity type %02x\n",
530
0
       entityType);
531
0
      rc = TPM_AUTHFAIL;
532
0
      break;
533
0
  }
534
0
    }
535
    /* check that the TPM_DELEGATE_PUBLIC PCR's allow the delegation */
536
0
    if (rc == 0) {
537
0
  rc = TPM_PCRInfoShort_CheckDigest(&(delegatePublic->pcrInfo),
538
0
            tpm_state->tpm_stclear_data.PCRS,
539
0
            tpm_state->tpm_stany_flags.localityModifier);
540
0
    }
541
0
    return rc;
542
0
}
543
544
/* TPM_Delegations_CheckOwnerPermission() verifies that the 'ordinal' has been delegated for
545
   execution based on the TPM_DELEGATIONS.
546
*/
547
548
TPM_RESULT TPM_Delegations_CheckOwnerPermission(TPM_DELEGATIONS *tpm_delegations,
549
            TPM_COMMAND_CODE ordinal)
550
0
{
551
0
    TPM_RESULT  rc = 0;
552
0
    uint16_t  ownerPermissionBlock;   /* 0:unused, 1:per1 2:per2 */
553
0
    uint32_t  ownerPermissionPosition;  /* owner permission bit position */
554
555
0
    printf(" TPM_Delegations_CheckOwnerPermission: ordinal %08x\n", ordinal);
556
    /* check that the TPM_DELEGATIONS structure is the correct type */
557
0
    if (rc == 0) {
558
0
  if (tpm_delegations->delegateType != TPM_DEL_OWNER_BITS) {
559
0
      printf("TPM_Delegations_CheckOwnerPermission: Error,"
560
0
       "Ordinal requires owner auth but delegateType is %08x\n",
561
0
       tpm_delegations->delegateType);
562
0
      rc = TPM_AUTHFAIL;
563
0
  }
564
0
    }
565
    /* get the block and position in the block from the ordinals table */
566
0
    if (rc == 0) {
567
0
  rc = TPM_OrdinalTable_GetOwnerPermission(&ownerPermissionBlock,
568
0
             &ownerPermissionPosition,
569
0
             ordinal);
570
0
    }
571
    /* check that the permission bit is set in the TPM_DELEGATIONS bit map */
572
0
    if (rc == 0) {
573
0
  printf("  TPM_Delegations_CheckOwnerPermission: block %u position %u\n",
574
0
         ownerPermissionBlock, ownerPermissionPosition);
575
0
  switch (ownerPermissionBlock) {
576
0
    case 1: /* per1 */
577
0
      if (!(tpm_delegations->per1 & (1 << ownerPermissionPosition))) {
578
0
    printf("TPM_Delegations_CheckOwnerPermission: Error, per1 %08x\n",
579
0
           tpm_delegations->per1);
580
0
    rc = TPM_AUTHFAIL;
581
0
      }
582
0
      break;
583
0
    case 2: /* per2 */
584
0
      if (!(tpm_delegations->per2 & (1 << ownerPermissionPosition))) {
585
0
    printf("TPM_Delegations_CheckOwnerPermission: Error, per2 %08x\n",
586
0
           tpm_delegations->per2);
587
0
    rc = TPM_AUTHFAIL;
588
0
      }
589
0
      break;
590
0
    default:
591
0
      printf("TPM_Delegations_CheckOwnerPermission: Error, block not 1 or 2\n");
592
0
      rc = TPM_AUTHFAIL;
593
0
      break;
594
0
  }
595
0
    }
596
0
    return rc;
597
0
}
598
599
/* TPM_Delegations_CheckKeyPermission() verifies that the 'ordinal' has been delegated for
600
   execution based on the TPM_DELEGATIONS.
601
*/
602
603
TPM_RESULT TPM_Delegations_CheckKeyPermission(TPM_DELEGATIONS *tpm_delegations,
604
                TPM_COMMAND_CODE ordinal)
605
0
{
606
0
    TPM_RESULT  rc = 0;
607
0
    uint16_t  keyPermissionBlock;   /* 0:unused, 1:per1 2:per2 */
608
0
    uint32_t  keyPermissionPosition;    /* key permission bit position */
609
610
0
    printf(" TPM_Delegations_CheckKeyPermission: ordinal %08x\n", ordinal);
611
    /* check that the TPM_DELEGATIONS structure is the correct type */
612
0
    if (rc == 0) {
613
0
  if (tpm_delegations->delegateType != TPM_DEL_KEY_BITS) {
614
0
      printf("TPM_Delegations_CheckKeyPermission: Error,"
615
0
       "Ordinal requires key auth but delegateType is %08x\n",
616
0
       tpm_delegations->delegateType);
617
0
      rc = TPM_AUTHFAIL;
618
0
  }
619
0
    }
620
    /* get the block and position in the block from the ordinals table */
621
0
    if (rc == 0) {
622
0
  rc = TPM_OrdinalTable_GetKeyPermission(&keyPermissionBlock,
623
0
                 &keyPermissionPosition,
624
0
                 ordinal);
625
0
    }
626
    /* check that the permission bit is set in the TPM_DELEGATIONS bit map */
627
0
    if (rc == 0) {
628
0
  printf("  TPM_Delegations_CheckKeyPermission: block %u position %u\n",
629
0
         keyPermissionBlock, keyPermissionPosition);
630
0
  switch (keyPermissionBlock) {
631
0
    case 1: /* per1 */
632
0
      if (!(tpm_delegations->per1 & (1 << keyPermissionPosition))) {
633
0
    printf("TPM_Delegations_CheckKeyPermission: Error, per1 %08x\n",
634
0
           tpm_delegations->per1);
635
0
    rc = TPM_AUTHFAIL;
636
0
      }
637
0
      break;
638
0
    case 2: /* per2 */
639
0
      if (!(tpm_delegations->per2 & (1 << keyPermissionPosition))) {
640
0
    printf("TPM_Delegations_CheckKeyPermission: Error, per2 %08x\n",
641
0
           tpm_delegations->per2);
642
0
    rc = TPM_AUTHFAIL;
643
0
      }
644
0
      break;
645
0
    default:
646
0
      printf("TPM_Delegations_CheckKeyPermission: Error, block not 1 or 2\n");
647
0
      rc = TPM_AUTHFAIL;
648
0
      break;
649
0
  }
650
0
    }
651
0
    return rc;
652
0
}
653
654
/*
655
  TPM_DELEGATE_OWNER_BLOB
656
*/
657
658
/* TPM_DelegateOwnerBlob_Init()
659
660
   sets members to default values
661
   sets all pointers to NULL and sizes to 0
662
   always succeeds - no return code
663
*/
664
665
void TPM_DelegateOwnerBlob_Init(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob)
666
0
{
667
0
    printf(" TPM_DelegateOwnerBlob_Init:\n");
668
0
    TPM_DelegatePublic_Init(&(tpm_delegate_owner_blob->pub));
669
0
    TPM_Digest_Init(tpm_delegate_owner_blob->integrityDigest);
670
0
    TPM_SizedBuffer_Init(&(tpm_delegate_owner_blob->additionalArea));
671
0
    TPM_SizedBuffer_Init(&(tpm_delegate_owner_blob->sensitiveArea));
672
0
    return;
673
0
}
674
675
/* TPM_DelegateOwnerBlob_Load()
676
677
   deserialize the structure from a 'stream'
678
   'stream_size' is checked for sufficient data
679
   returns 0 or error codes
680
   
681
   Before use, call TPM_DelegateOwnerBlob_Init()
682
   After use, call TPM_DelegateOwnerBlob_Delete() to free memory
683
*/
684
685
TPM_RESULT TPM_DelegateOwnerBlob_Load(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob,
686
              unsigned char **stream,
687
              uint32_t *stream_size)
688
0
{
689
0
    TPM_RESULT    rc = 0;
690
691
0
    printf(" TPM_DelegateOwnerBlob_Load:\n");
692
    /* check tag */
693
0
    if (rc == 0) {
694
0
  rc = TPM_CheckTag(TPM_TAG_DELEGATE_OWNER_BLOB, stream, stream_size);
695
0
    }
696
    /* load pub */
697
0
    if (rc == 0) {
698
0
  rc = TPM_DelegatePublic_Load(&(tpm_delegate_owner_blob->pub), stream, stream_size);
699
0
    }
700
    /* check that permissions are owner */
701
0
    if (rc == 0) {
702
0
  if (tpm_delegate_owner_blob->pub.permissions.delegateType != TPM_DEL_OWNER_BITS) {
703
0
      printf("TPM_DelegateOwnerBlob_Load: Error, delegateType expected %08x found %08x\n",
704
0
       TPM_DEL_OWNER_BITS, tpm_delegate_owner_blob->pub.permissions.delegateType);
705
0
      rc = TPM_INVALID_STRUCTURE;
706
0
  }
707
0
    }
708
    /* load integrityDigest */
709
0
    if (rc == 0) {
710
0
  rc = TPM_Digest_Load(tpm_delegate_owner_blob->integrityDigest, stream, stream_size);
711
0
    }
712
    /* load additionalArea */
713
0
    if (rc == 0) {
714
0
  rc = TPM_SizedBuffer_Load(&(tpm_delegate_owner_blob->additionalArea), stream, stream_size);
715
0
    }
716
    /* load sensitiveArea */
717
0
    if (rc == 0) {
718
0
  rc = TPM_SizedBuffer_Load(&(tpm_delegate_owner_blob->sensitiveArea), stream, stream_size);
719
0
    }
720
0
    return rc;
721
0
}
722
723
/* TPM_DelegateOwnerBlob_Store()
724
   
725
   serialize the structure to a stream contained in 'sbuffer'
726
   returns 0 or error codes
727
*/
728
729
TPM_RESULT TPM_DelegateOwnerBlob_Store(TPM_STORE_BUFFER *sbuffer,
730
               const TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob)
731
0
{
732
0
    TPM_RESULT    rc = 0;
733
734
0
    printf(" TPM_DelegateOwnerBlob_Store:\n");
735
    /* store tag */
736
0
    if (rc == 0) {
737
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_OWNER_BLOB);
738
0
    }
739
    /* store pub */
740
0
    if (rc == 0) {
741
0
  rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_owner_blob->pub));
742
0
    }
743
    /* store integrityDigest */
744
0
    if (rc == 0) {
745
0
  rc = TPM_Digest_Store(sbuffer, tpm_delegate_owner_blob->integrityDigest);
746
0
    }
747
    /* store additionalArea */
748
0
    if (rc == 0) {
749
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_owner_blob->additionalArea));
750
0
    }
751
    /* store sensitiveArea */
752
0
    if (rc == 0) {
753
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_owner_blob->sensitiveArea));
754
0
    }
755
0
    return rc;
756
0
}
757
758
/* TPM_DelegateOwnerBlob_Delete()
759
760
   No-OP if the parameter is NULL, else:
761
   frees memory allocated for the object
762
   sets pointers to NULL
763
   calls TPM_DelegateOwnerBlob_Init to set members back to default values
764
   The object itself is not freed
765
*/   
766
767
void TPM_DelegateOwnerBlob_Delete(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob)
768
0
{
769
0
    printf(" TPM_DelegateOwnerBlob_Delete:\n");
770
0
    if (tpm_delegate_owner_blob != NULL) {
771
0
  TPM_DelegatePublic_Delete(&(tpm_delegate_owner_blob->pub));
772
0
  TPM_SizedBuffer_Delete(&(tpm_delegate_owner_blob->additionalArea));
773
0
  TPM_SizedBuffer_Delete(&(tpm_delegate_owner_blob->sensitiveArea));
774
0
  TPM_DelegateOwnerBlob_Init(tpm_delegate_owner_blob);
775
0
    }
776
0
    return;
777
0
}
778
779
/*
780
  TPM_DELEGATE_KEY_BLOB
781
*/
782
783
/* TPM_DelegateKeyBlob_Init()
784
785
   sets members to default values
786
   sets all pointers to NULL and sizes to 0
787
   always succeeds - no return code
788
*/
789
790
void TPM_DelegateKeyBlob_Init(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob)
791
0
{
792
0
    printf(" TPM_DelegateKeyBlob_Init:\n");
793
0
    TPM_DelegatePublic_Init(&(tpm_delegate_key_blob->pub));
794
0
    TPM_Digest_Init(tpm_delegate_key_blob->integrityDigest);
795
0
    TPM_Digest_Init(tpm_delegate_key_blob->pubKeyDigest);
796
0
    TPM_SizedBuffer_Init(&(tpm_delegate_key_blob->additionalArea));
797
0
    TPM_SizedBuffer_Init(&(tpm_delegate_key_blob->sensitiveArea));
798
0
    return;
799
0
}
800
801
/* TPM_DelegateKeyBlob_Load()
802
803
   deserialize the structure from a 'stream'
804
   'stream_size' is checked for sufficient data
805
   returns 0 or error codes
806
   
807
   Before use, call TPM_DelegateKeyBlob_Init()
808
   After use, call TPM_DelegateKeyBlob_Delete() to free memory
809
*/
810
811
TPM_RESULT TPM_DelegateKeyBlob_Load(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob,
812
            unsigned char **stream,
813
            uint32_t *stream_size)
814
0
{
815
0
    TPM_RESULT    rc = 0;
816
817
0
    printf(" TPM_DelegateKeyBlob_Load:\n");
818
    /* check tag */
819
0
    if (rc == 0) {
820
0
  rc = TPM_CheckTag(TPM_TAG_DELG_KEY_BLOB, stream, stream_size);
821
0
    }
822
    /* load pub */
823
0
    if (rc == 0) {
824
0
  rc = TPM_DelegatePublic_Load(&(tpm_delegate_key_blob->pub), stream, stream_size);
825
0
    }
826
    /* check that permissions are key */
827
0
    if (rc == 0) {
828
0
  if (tpm_delegate_key_blob->pub.permissions.delegateType != TPM_DEL_KEY_BITS) {
829
0
      printf("TPM_DelegateKeyBlob_Load: Error, delegateType expected %08x found %08x\n",
830
0
       TPM_DEL_KEY_BITS, tpm_delegate_key_blob->pub.permissions.delegateType);
831
0
      rc = TPM_INVALID_STRUCTURE;
832
0
  }
833
0
    }
834
    /* load integrityDigest */
835
0
    if (rc == 0) {
836
0
  rc = TPM_Digest_Load(tpm_delegate_key_blob->integrityDigest, stream, stream_size);
837
0
    }
838
    /* load pubKeyDigest */
839
0
    if (rc == 0) {
840
0
  rc = TPM_Digest_Load(tpm_delegate_key_blob->pubKeyDigest, stream, stream_size);
841
0
    }
842
    /* load additionalArea */
843
0
    if (rc == 0) {
844
0
  rc = TPM_SizedBuffer_Load(&(tpm_delegate_key_blob->additionalArea), stream, stream_size);
845
0
    }
846
    /* load sensitiveArea */
847
0
    if (rc == 0) {
848
0
  rc = TPM_SizedBuffer_Load(&(tpm_delegate_key_blob->sensitiveArea), stream, stream_size);
849
0
    }
850
0
    return rc;
851
0
}
852
853
/* TPM_DelegateKeyBlob_Store()
854
   
855
   serialize the structure to a stream contained in 'sbuffer'
856
   returns 0 or error codes
857
*/
858
859
TPM_RESULT TPM_DelegateKeyBlob_Store(TPM_STORE_BUFFER *sbuffer,
860
             const TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob)
861
0
{
862
0
    TPM_RESULT    rc = 0;
863
864
0
    printf(" TPM_DelegateKeyBlob_Store:\n");
865
    /* store tag */
866
0
    if (rc == 0) {
867
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELG_KEY_BLOB);
868
0
    }
869
    /* store pub */
870
0
    if (rc == 0) {
871
0
  rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_key_blob->pub));
872
0
    }
873
    /* store integrityDigest */
874
0
    if (rc == 0) {
875
0
  rc = TPM_Digest_Store(sbuffer, tpm_delegate_key_blob->integrityDigest);
876
0
    }
877
    /* store pubKeyDigest */
878
0
    if (rc == 0) {
879
0
  rc = TPM_Digest_Store(sbuffer, tpm_delegate_key_blob->pubKeyDigest);
880
0
    }
881
    /* store additionalArea */
882
0
    if (rc == 0) {
883
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_key_blob->additionalArea));
884
0
    }
885
    /* store sensitiveArea */
886
0
    if (rc == 0) {
887
0
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_key_blob->sensitiveArea));
888
0
    }
889
0
    return rc;
890
0
}
891
892
/* TPM_DelegateKeyBlob_Delete()
893
894
   No-OP if the parameter is NULL, else:
895
   frees memory allocated for the object
896
   sets pointers to NULL
897
   calls TPM_DelegateKeyBlob_Init to set members back to default values
898
   The object itself is not freed
899
*/   
900
901
void TPM_DelegateKeyBlob_Delete(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob)
902
0
{
903
0
    printf(" TPM_DelegateKeyBlob_Delete:\n");
904
0
    if (tpm_delegate_key_blob != NULL) {
905
0
  TPM_DelegatePublic_Delete(&(tpm_delegate_key_blob->pub));
906
0
  TPM_SizedBuffer_Delete(&(tpm_delegate_key_blob->additionalArea));
907
0
  TPM_SizedBuffer_Delete(&(tpm_delegate_key_blob->sensitiveArea));
908
0
  TPM_DelegateKeyBlob_Init(tpm_delegate_key_blob);
909
0
    }
910
0
    return;
911
0
}
912
913
/*
914
  TPM_FAMILY_TABLE
915
*/
916
917
/* TPM_FamilyTable_Init()
918
919
   sets members to default values
920
   sets all pointers to NULL and sizes to 0
921
   always succeeds - no return code
922
*/
923
924
void TPM_FamilyTable_Init(TPM_FAMILY_TABLE *tpm_family_table)
925
0
{
926
0
    size_t i;
927
928
0
    printf(" TPM_FamilyTable_Init: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN);
929
0
    for (i = 0 ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN ; i++) {
930
0
  TPM_FamilyTableEntry_Init(&(tpm_family_table->famTableRow[i]));
931
0
    }
932
0
    return;
933
0
}
934
935
/* TPM_FamilyTable_Load()
936
937
   deserialize the structure from a 'stream'
938
   'stream_size' is checked for sufficient data
939
   returns 0 or error codes
940
   
941
   Before use, call TPM_FamilyTable_Init()
942
   After use, call TPM_FamilyTable_Delete() to free memory
943
*/
944
945
TPM_RESULT TPM_FamilyTable_Load(TPM_FAMILY_TABLE *tpm_family_table,
946
        unsigned char **stream,
947
        uint32_t *stream_size)
948
0
{
949
0
    TPM_RESULT  rc = 0;
950
0
    size_t  i;
951
952
0
    printf(" TPM_FamilyTable_Load: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN);
953
0
    for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) {
954
0
  rc = TPM_FamilyTableEntry_Load(&(tpm_family_table->famTableRow[i]),
955
0
               stream,
956
0
               stream_size);
957
0
    }
958
0
    return rc;
959
0
}
960
961
/* TPM_FamilyTable_Store()
962
   
963
   If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored.
964
965
   serialize the structure to a stream contained in 'sbuffer'
966
   returns 0 or error codes
967
*/
968
969
TPM_RESULT TPM_FamilyTable_Store(TPM_STORE_BUFFER *sbuffer,
970
         const TPM_FAMILY_TABLE *tpm_family_table,
971
         TPM_BOOL store_tag)
972
0
{
973
0
    TPM_RESULT    rc = 0;
974
0
    size_t i;
975
976
0
    printf(" TPM_FamilyTable_Store: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN);
977
0
    for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) {
978
0
  rc = TPM_FamilyTableEntry_Store(sbuffer,
979
0
          &(tpm_family_table->famTableRow[i]), store_tag);
980
0
    }
981
0
    return rc;
982
0
}
983
984
/* TPM_FamilyTable_Delete()
985
986
   No-OP if the parameter is NULL, else:
987
   frees memory allocated for the object
988
   sets pointers to NULL
989
   calls TPM_FamilyTable_Init to set members back to default values
990
   The object itself is not freed
991
*/   
992
993
void TPM_FamilyTable_Delete(TPM_FAMILY_TABLE *tpm_family_table)
994
0
{
995
0
    size_t i;
996
997
0
    printf(" TPM_FamilyTable_Delete: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN);
998
0
    if (tpm_family_table != NULL) {
999
0
  for (i = 0 ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN ; i++) {
1000
0
      TPM_FamilyTableEntry_Delete(&(tpm_family_table->famTableRow[i]));
1001
0
  }
1002
0
  TPM_FamilyTable_Init(tpm_family_table);
1003
0
    }
1004
0
    return;
1005
0
}
1006
1007
/* TPM_FamilyTable_GetEntry() searches all entries for the entry matching the familyID, and returns
1008
   the TPM_FAMILY_TABLE_ENTRY associated with the familyID.
1009
1010
   Returns
1011
  0 for success
1012
  TPM_BADINDEX if the familyID is not found
1013
*/
1014
1015
TPM_RESULT TPM_FamilyTable_GetEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, /* output */
1016
            TPM_FAMILY_TABLE *tpm_family_table,
1017
            TPM_FAMILY_ID familyID)
1018
0
{
1019
0
    TPM_RESULT  rc = 0;
1020
0
    size_t  i;
1021
0
    TPM_BOOL  found;
1022
1023
0
    printf(" TPM_FamilyTable_GetEntry: familyID %08x\n", familyID);
1024
0
    for (i = 0, found = FALSE ; (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) && !found ; i++) {
1025
0
  if (tpm_family_table->famTableRow[i].valid &&
1026
0
      (tpm_family_table->famTableRow[i].familyID == familyID)) { /* found */
1027
0
      found = TRUE;
1028
0
      *tpm_family_table_entry = &(tpm_family_table->famTableRow[i]);
1029
0
  }
1030
0
    }
1031
0
    if (!found) {
1032
0
  printf("TPM_FamilyTable_GetEntry: Error, familyID %08x not found\n", familyID);
1033
0
  rc = TPM_BADINDEX;
1034
0
    }
1035
0
    return rc;
1036
0
}
1037
1038
/* TPM_FamilyTable_GetEnabledEntry() searches all entries for the entry matching the familyID, and
1039
   returns the TPM_FAMILY_TABLE_ENTRY associated with the familyID.
1040
1041
   Similar to TPM_FamilyTable_GetEntry() but returns an error if the entry is disabled.
1042
  
1043
   Returns
1044
  0 for success
1045
  TPM_BADINDEX if the familyID is not found
1046
  TPM_DISABLED_CMD if the TPM_FAMILY_TABLE_ENTRY -> TPM_FAMFLAG_ENABLED is FALSE 
1047
*/
1048
1049
TPM_RESULT TPM_FamilyTable_GetEnabledEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry,
1050
             TPM_FAMILY_TABLE *tpm_family_table,
1051
             TPM_FAMILY_ID familyID)
1052
0
{
1053
0
    TPM_RESULT  rc = 0;
1054
1055
0
    printf(" TPM_FamilyTable_GetEnabledEntry: familyID %08x\n", familyID);
1056
0
    if (rc == 0) {
1057
0
  rc = TPM_FamilyTable_GetEntry(tpm_family_table_entry,
1058
0
              tpm_family_table,
1059
0
              familyID);
1060
0
    }
1061
0
    if (rc == 0) {
1062
0
  if (!((*tpm_family_table_entry)->flags & TPM_FAMFLAG_ENABLED)) {
1063
0
      printf("TPM_FamilyTable_GetEnabledEntry: Error, family %08x disabled\n", familyID);
1064
0
      rc = TPM_DISABLED_CMD;
1065
0
  }
1066
0
    }
1067
0
    return rc;
1068
0
}
1069
1070
/* TPM_FamilyTable_IsSpace() returns success if an entry is available, an error if not.
1071
1072
   If success, 'family_table_entry' holds the first free family table row.
1073
*/
1074
1075
TPM_RESULT TPM_FamilyTable_IsSpace(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, /* output */
1076
           TPM_FAMILY_TABLE *tpm_family_table)
1077
0
{
1078
0
    size_t  i;
1079
0
    TPM_BOOL  isSpace;
1080
0
    TPM_RESULT  rc = 0;
1081
    
1082
    
1083
0
    printf(" TPM_FamilyTable_IsSpace:\n");
1084
0
    for (i = 0, isSpace = FALSE ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN; i++) {
1085
0
  *tpm_family_table_entry = &(tpm_family_table->famTableRow[i]);
1086
0
  if (!((*tpm_family_table_entry)->valid)) {
1087
0
      printf("  TPM_FamilyTable_IsSpace: Found space at %lu\n", (unsigned long)i);
1088
0
      isSpace = TRUE;
1089
0
      break;
1090
0
  }     
1091
0
    }
1092
0
    if (!isSpace) {
1093
0
  printf("  TPM_FamilyTable_IsSpace: Error, no space found\n");
1094
0
  rc = TPM_RESOURCES;
1095
0
    }
1096
0
    return rc;
1097
0
}
1098
1099
/* TPM_FamilyTable_StoreValid() stores only the valid (occupied) entries
1100
1101
   If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored.
1102
   
1103
   serialize the structure to a stream contained in 'sbuffer'
1104
   returns 0 or error codes
1105
*/
1106
1107
TPM_RESULT TPM_FamilyTable_StoreValid(TPM_STORE_BUFFER *sbuffer,
1108
              const TPM_FAMILY_TABLE *tpm_family_table,
1109
              TPM_BOOL store_tag)
1110
0
{
1111
0
    TPM_RESULT  rc = 0;
1112
0
    size_t  i;
1113
1114
0
    printf(" TPM_FamilyTable_StoreValid: \n");
1115
0
    for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) {
1116
  /* store only the valid rows */
1117
0
  if (tpm_family_table->famTableRow[i].valid) {
1118
      /* store only the publicly visible members */
1119
0
      printf("  TPM_FamilyTable_StoreValid: Entry %lu is valid\n", (unsigned long)i);
1120
0
      printf("  TPM_FamilyTable_StoreValid: Entry family ID is %08x\n",
1121
0
       tpm_family_table->famTableRow[i].familyID);
1122
0
      rc = TPM_FamilyTableEntry_StorePublic(sbuffer,
1123
0
              &(tpm_family_table->famTableRow[i]), store_tag);
1124
0
  }
1125
0
    }
1126
0
    return rc;
1127
0
}
1128
1129
/*
1130
  TPM_FAMILY_TABLE_ENTRY
1131
*/
1132
1133
/* TPM_FamilyTableEntry_Init()
1134
1135
   sets members to default values
1136
   sets all pointers to NULL and sizes to 0
1137
   always succeeds - no return code
1138
*/
1139
1140
void TPM_FamilyTableEntry_Init(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry)
1141
0
{
1142
0
    printf(" TPM_FamilyTableEntry_Init:\n");
1143
0
    tpm_family_table_entry->familyLabel = 0;
1144
0
    tpm_family_table_entry->familyID = 0;
1145
0
    tpm_family_table_entry->verificationCount = 0;
1146
0
    tpm_family_table_entry->flags = 0;
1147
0
    tpm_family_table_entry->valid = FALSE;
1148
0
    return;
1149
0
}
1150
1151
/* TPM_FamilyTableEntry_Load()
1152
1153
   deserialize the structure from a 'stream'
1154
   'stream_size' is checked for sufficient data
1155
   returns 0 or error codes
1156
   
1157
   Before use, call TPM_FamilyTableEntry_Init()
1158
   After use, call TPM_FamilyTableEntry_Delete() to free memory
1159
*/
1160
1161
TPM_RESULT TPM_FamilyTableEntry_Load(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry,
1162
             unsigned char **stream,
1163
             uint32_t *stream_size)
1164
0
{
1165
0
    TPM_RESULT    rc = 0;
1166
1167
0
    printf(" TPM_FamilyTableEntry_Load:\n");
1168
    /* load tag */
1169
    /* the tag is not serialized when storing TPM_PERMANENT_DATA, to save NV space */
1170
    /* load familyLabel */
1171
0
    if (rc == 0) {
1172
0
  rc = TPM_Load8(&(tpm_family_table_entry->familyLabel), stream, stream_size);
1173
0
    }
1174
    /* load familyID */
1175
0
    if (rc == 0) {
1176
0
  rc = TPM_Load32(&(tpm_family_table_entry->familyID), stream, stream_size);
1177
0
    }
1178
    /* load verificationCount */
1179
0
    if (rc == 0) {
1180
0
  rc = TPM_Load32(&(tpm_family_table_entry->verificationCount), stream, stream_size);
1181
0
    }
1182
    /* load flags */
1183
0
    if (rc == 0) {
1184
0
  rc = TPM_Load32(&(tpm_family_table_entry->flags), stream, stream_size);
1185
0
    }
1186
    /* load valid */
1187
0
    if (rc == 0) {
1188
0
  rc = TPM_LoadBool(&(tpm_family_table_entry->valid), stream, stream_size);
1189
0
    }
1190
0
    if (rc == 0) {
1191
0
  printf("  TPM_FamilyTableEntry_Load: label %02x familyID %08x valid %u\n",
1192
0
         tpm_family_table_entry->familyLabel,
1193
0
         tpm_family_table_entry->familyID,
1194
0
         tpm_family_table_entry->valid);
1195
0
    }
1196
0
    return rc;
1197
0
}
1198
1199
/* TPM_FamilyTableEntry_Store() stores all members of the structure
1200
1201
   If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored.
1202
   
1203
   serialize the structure to a stream contained in 'sbuffer'
1204
   returns 0 or error codes
1205
*/
1206
1207
TPM_RESULT TPM_FamilyTableEntry_Store(TPM_STORE_BUFFER *sbuffer,
1208
              const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry,
1209
              TPM_BOOL store_tag)
1210
0
{
1211
0
    TPM_RESULT    rc = 0;
1212
1213
0
    printf(" TPM_FamilyTableEntry_Store:\n");
1214
    /* store public, visible members */
1215
0
    if (rc == 0) {
1216
0
  rc = TPM_FamilyTableEntry_StorePublic(sbuffer, tpm_family_table_entry, store_tag); 
1217
0
    }
1218
    /* store valid */
1219
0
    if (rc == 0) {
1220
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_family_table_entry->valid),
1221
0
        sizeof(TPM_BOOL));
1222
0
    }
1223
0
    return rc;
1224
0
}
1225
1226
/* TPM_FamilyTableEntry_StorePublic() stores only the public, visible members of the structure
1227
   
1228
   If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored.
1229
1230
   serialize the structure to a stream contained in 'sbuffer'
1231
   returns 0 or error codes
1232
*/
1233
1234
TPM_RESULT TPM_FamilyTableEntry_StorePublic(TPM_STORE_BUFFER *sbuffer,
1235
              const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry,
1236
              TPM_BOOL store_tag)
1237
0
{
1238
0
    TPM_RESULT    rc = 0;
1239
1240
0
    printf(" TPM_FamilyTableEntry_StorePublic:\n");
1241
    /* store tag */
1242
0
    if ((rc == 0) && (store_tag)) {
1243
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_FAMILY_TABLE_ENTRY); 
1244
0
    }
1245
    /* store familyLabel */
1246
0
    if (rc == 0) {
1247
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_family_table_entry->familyLabel),  // libtpms changed: assign rc
1248
0
        sizeof(TPM_FAMILY_LABEL));
1249
0
    }
1250
    /* store familyID */
1251
0
    if (rc == 0) {
1252
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->familyID); 
1253
0
    }            
1254
    /* store verificationCount */
1255
0
    if (rc == 0) {       
1256
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->verificationCount); 
1257
0
    }            
1258
    /* store flags */
1259
0
    if (rc == 0) {       
1260
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->flags); 
1261
0
    }
1262
0
    return rc;
1263
0
}
1264
1265
/* TPM_FamilyTableEntry_Delete()
1266
1267
   No-OP if the parameter is NULL, else:
1268
   frees memory allocated for the object
1269
   sets pointers to NULL
1270
   calls TPM_FamilyTableEntry_Init to set members back to default values
1271
   The object itself is not freed
1272
*/   
1273
1274
void TPM_FamilyTableEntry_Delete(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry)
1275
0
{
1276
0
    printf(" TPM_FamilyTableEntry_Delete:\n");
1277
0
    if (tpm_family_table_entry != NULL) {
1278
0
  TPM_FamilyTableEntry_Init(tpm_family_table_entry);
1279
0
    }
1280
0
    return;
1281
0
}
1282
1283
/*
1284
  TPM_DELEGATE_TABLE
1285
*/
1286
1287
/* TPM_DelegateTable_Init()
1288
1289
   sets members to default values
1290
   sets all pointers to NULL and sizes to 0
1291
   always succeeds - no return code
1292
*/
1293
1294
void TPM_DelegateTable_Init(TPM_DELEGATE_TABLE *tpm_delegate_table)
1295
0
{
1296
0
    size_t i;
1297
1298
0
    printf(" TPM_DelegateTable_Init: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN);
1299
0
    for (i = 0 ; i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN ; i++) {
1300
0
  TPM_DelegateTableRow_Init(&(tpm_delegate_table->delRow[i]));
1301
0
    }
1302
0
    return;
1303
0
}
1304
1305
/* TPM_DelegateTable_Load()
1306
1307
   deserialize the structure from a 'stream'
1308
   'stream_size' is checked for sufficient data
1309
   returns 0 or error codes
1310
   
1311
   Before use, call TPM_DelegateTable_Init()
1312
   After use, call TPM_DelegateTable_Delete() to free memory
1313
*/
1314
1315
TPM_RESULT TPM_DelegateTable_Load(TPM_DELEGATE_TABLE *tpm_delegate_table,
1316
          unsigned char **stream,
1317
          uint32_t *stream_size)
1318
0
{
1319
0
    TPM_RESULT  rc = 0;
1320
0
    size_t  i;
1321
1322
0
    printf(" TPM_DelegateTable_Load: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN);
1323
0
    for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN)  ; i++) {
1324
0
  rc = TPM_DelegateTableRow_Load(&(tpm_delegate_table->delRow[i]),
1325
0
           stream,
1326
0
           stream_size);
1327
0
    }
1328
0
    return rc;
1329
0
}
1330
1331
/* TPM_DelegateTable_Store()
1332
   
1333
   serialize the structure to a stream contained in 'sbuffer'
1334
   returns 0 or error codes
1335
*/
1336
1337
TPM_RESULT TPM_DelegateTable_Store(TPM_STORE_BUFFER *sbuffer,
1338
           const TPM_DELEGATE_TABLE *tpm_delegate_table)
1339
0
{
1340
0
    TPM_RESULT    rc = 0;
1341
0
    size_t i;
1342
1343
0
    printf(" TPM_DelegateTable_Store: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN);
1344
0
    for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) {
1345
0
  rc = TPM_DelegateTableRow_Store(sbuffer, &(tpm_delegate_table->delRow[i]));
1346
0
    }
1347
0
    return rc;
1348
0
}
1349
1350
/* TPM_DelegateTable_Delete()
1351
1352
   No-OP if the parameter is NULL, else:
1353
   frees memory allocated for the object
1354
   sets pointers to NULL
1355
   calls TPM_DelegateTable_Init to set members back to default values
1356
   The object itself is not freed
1357
*/   
1358
1359
void TPM_DelegateTable_Delete(TPM_DELEGATE_TABLE *tpm_delegate_table)
1360
0
{
1361
0
    size_t i;
1362
1363
0
    printf(" TPM_DelegateTable_Delete: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN);
1364
0
    if (tpm_delegate_table != NULL) {
1365
0
  for (i = 0 ; i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN ; i++) {
1366
0
      TPM_DelegateTableRow_Delete(&(tpm_delegate_table->delRow[i]));
1367
0
  }
1368
0
  TPM_DelegateTable_Init(tpm_delegate_table);
1369
0
    }
1370
0
    return;
1371
0
}
1372
1373
/* TPM_DelegateTable_StoreValid() store only the valid (occupied) entries.  Each entry is prepended
1374
   with it's index.
1375
   
1376
   serialize the structure to a stream contained in 'sbuffer'
1377
   returns 0 or error codes
1378
*/
1379
1380
TPM_RESULT TPM_DelegateTable_StoreValid(TPM_STORE_BUFFER *sbuffer,
1381
          const TPM_DELEGATE_TABLE *tpm_delegate_table)
1382
0
{
1383
0
    TPM_RESULT  rc = 0;
1384
0
    uint32_t  i;
1385
1386
0
    printf(" TPM_DelegateTable_StoreValid:\n");
1387
0
    for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) {
1388
  /* store only the valid rows */
1389
0
  if (tpm_delegate_table->delRow[i].valid) {
1390
      /* a. Write the TPM_DELEGATE_INDEX to delegateTable */
1391
0
      printf("  TPM_DelegateTable_StoreValid: Entry %u is valid\n", i);
1392
0
      printf("  TPM_DelegateTable_StoreValid: Entry family ID is %08x\n",
1393
0
       tpm_delegate_table->delRow[i].pub.familyID);
1394
0
      if (rc == 0) {
1395
0
    rc = TPM_Sbuffer_Append32(sbuffer, i);
1396
0
      }
1397
      /* b. Copy the TPM_DELEGATE_PUBLIC to delegateTable */
1398
0
      if (rc == 0) {
1399
0
    rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_table->delRow[i].pub));
1400
0
      }
1401
0
  }
1402
0
    }
1403
0
    return rc;
1404
0
}
1405
1406
/* TPM_DelegateTable_GetRow() maps 'rowIndex' to a TPM_DELEGATE_TABLE_ROW in the delegate table.
1407
1408
   The row may not have valid data.
1409
 */
1410
1411
TPM_RESULT TPM_DelegateTable_GetRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow,
1412
            TPM_DELEGATE_TABLE *tpm_delegate_table,
1413
            uint32_t rowIndex)
1414
0
{
1415
0
    TPM_RESULT  rc = 0;
1416
1417
0
    printf(" TPM_DelegateTable_GetRow: index %u\n", rowIndex);
1418
0
    if (rc == 0) {
1419
0
  if (rowIndex >= TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) {
1420
0
      printf("TPM_DelegateTable_GetRow: index %u out of range\n", rowIndex);
1421
0
      rc = TPM_BADINDEX;
1422
0
  }
1423
0
    }
1424
0
    if (rc == 0) {
1425
0
  *delegateTableRow = &(tpm_delegate_table->delRow[rowIndex]);
1426
0
    }
1427
0
    return rc;
1428
0
}
1429
1430
/* TPM_DelegateTable_GetValidRow() maps 'rowIndex' to a TPM_DELEGATE_TABLE_ROW in the delegate
1431
   table.
1432
1433
   The row must have valid data.
1434
 */
1435
1436
TPM_RESULT TPM_DelegateTable_GetValidRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow,
1437
           TPM_DELEGATE_TABLE *tpm_delegate_table,
1438
           uint32_t rowIndex)
1439
0
{
1440
0
    TPM_RESULT  rc = 0;
1441
1442
0
    if (rc == 0) {
1443
0
  rc = TPM_DelegateTable_GetRow(delegateTableRow,
1444
0
              tpm_delegate_table,
1445
0
              rowIndex);
1446
0
    }
1447
0
    if (rc == 0) {
1448
0
  *delegateTableRow = &(tpm_delegate_table->delRow[rowIndex]);
1449
0
  if (!(*delegateTableRow)->valid) {
1450
0
      printf("TPM_DelegateTable_GetValidRow: index %u invalid\n", rowIndex);
1451
0
      rc = TPM_BADINDEX;
1452
0
  }
1453
0
    }
1454
0
    return rc;
1455
0
}
1456
1457
/*
1458
  TPM_DELEGATE_TABLE_ROW
1459
*/
1460
1461
/* TPM_DelegateTableRow_Init()
1462
1463
   sets members to default values
1464
   sets all pointers to NULL and sizes to 0
1465
   always succeeds - no return code
1466
*/
1467
1468
void TPM_DelegateTableRow_Init(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row)
1469
0
{
1470
0
    printf(" TPM_DelegateTableRow_Init:\n");
1471
0
    TPM_DelegatePublic_Init(&(tpm_delegate_table_row->pub));
1472
0
    TPM_Secret_Init(tpm_delegate_table_row->authValue);
1473
0
    tpm_delegate_table_row->valid = FALSE;
1474
0
    return;
1475
0
}
1476
1477
/* TPM_DelegateTableRow_Load()
1478
1479
   deserialize the structure from a 'stream'
1480
   'stream_size' is checked for sufficient data
1481
   returns 0 or error codes
1482
   
1483
   Before use, call TPM_DelegateTableRow_Init()
1484
   After use, call TPM_DelegateTableRow_Delete() to free memory
1485
*/
1486
1487
TPM_RESULT TPM_DelegateTableRow_Load(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row,
1488
             unsigned char **stream,
1489
             uint32_t *stream_size)
1490
0
{
1491
0
    TPM_RESULT    rc = 0;
1492
1493
0
    printf(" TPM_DelegateTableRow_Load:\n");
1494
    /* check the tag */
1495
0
    if (rc == 0) {
1496
0
  rc = TPM_CheckTag(TPM_TAG_DELEGATE_TABLE_ROW, stream, stream_size);
1497
0
    }
1498
    /* load pub */
1499
0
    if (rc == 0) {
1500
0
  rc = TPM_DelegatePublic_Load(&(tpm_delegate_table_row->pub), stream, stream_size);
1501
0
    }
1502
    /* load authValue */
1503
0
    if (rc == 0) {
1504
0
  rc = TPM_Secret_Load(tpm_delegate_table_row->authValue, stream, stream_size);
1505
0
    }
1506
    /* load valid */
1507
0
    if (rc == 0) {
1508
0
  rc = TPM_LoadBool(&(tpm_delegate_table_row->valid), stream, stream_size);
1509
0
    }
1510
0
    return rc;
1511
0
}
1512
1513
/* TPM_DelegateTableRow_Store()
1514
   
1515
   serialize the structure to a stream contained in 'sbuffer'
1516
   returns 0 or error codes
1517
*/
1518
1519
TPM_RESULT TPM_DelegateTableRow_Store(TPM_STORE_BUFFER *sbuffer,
1520
              const TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row)
1521
0
{
1522
0
    TPM_RESULT    rc = 0;
1523
1524
0
    printf(" TPM_DelegateTableRow_Store:\n");
1525
    /* store tag */
1526
0
    if (rc == 0) {
1527
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_TABLE_ROW);
1528
0
    }
1529
    /* store pub */
1530
0
    if (rc == 0) {
1531
0
  rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_table_row->pub)); 
1532
0
    }
1533
    /* store authValue */
1534
0
    if (rc == 0) {
1535
0
  rc = TPM_Secret_Store(sbuffer, tpm_delegate_table_row->authValue);
1536
0
    }
1537
    /* store valid */
1538
0
    if (rc == 0) {
1539
0
  rc = TPM_Sbuffer_Append(sbuffer, &(tpm_delegate_table_row->valid), sizeof(TPM_BOOL));
1540
0
    }
1541
0
    return rc;
1542
0
}
1543
1544
/* TPM_DelegateTableRow_Delete()
1545
1546
   No-OP if the parameter is NULL, else:
1547
   frees memory allocated for the object
1548
   sets pointers to NULL
1549
   calls TPM_DelegateTableRow_Init to set members back to default values
1550
   The object itself is not freed
1551
*/   
1552
1553
void TPM_DelegateTableRow_Delete(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row)
1554
0
{
1555
0
    printf(" TPM_DelegateTableRow_Delete:\n");
1556
0
    if (tpm_delegate_table_row != NULL) {
1557
0
  TPM_DelegatePublic_Delete(&(tpm_delegate_table_row->pub));
1558
0
  TPM_DelegateTableRow_Init(tpm_delegate_table_row);
1559
0
    }
1560
0
    return;
1561
0
}
1562
1563
/*
1564
  Processing Functions
1565
*/
1566
1567
/* 19.1 TPM_Delegate_Manage rev 115
1568
   
1569
   TPM_Delegate_Manage is the fundamental process for managing the Family tables, including
1570
   enabling/disabling Delegation for a selected Family. Normally TPM_Delegate_Manage must be
1571
   executed at least once (to create Family tables for a particular family) before any other type of
1572
   Delegation command in that family can succeed.
1573
1574
   Delegate_Manage is authorized by the TPM Owner if an Owner is installed, because changing a table
1575
   is a privileged Owner operation. If no Owner is installed, Delegate_Manage requires no privilege
1576
   to execute. This does not disenfranchise an Owner, since there is no Owner, and simplifies
1577
   loading of tables during platform manufacture or on first-boot. Burn-out of TPM non-volatile
1578
   storage by inappropriate use is mitigated by the TPM's normal limits on NV-writes in the absence
1579
   of an Owner. Tables can be locked after loading, to prevent subsequent tampering, and only
1580
   unlocked by the Owner, his delegate, or the act of removing the Owner (even if there is no
1581
   Owner).
1582
1583
   TPM_Delegate_Manage command is customized by opcode:
1584
1585
   (1) TPM_FAMILY_ENABLE enables/disables use of a family and all the rows of the delegate table
1586
   belonging to that family,
1587
1588
   (2) TPM_FAMILY_ADMIN can be used to prevent further management of the Tables until an Owner is
1589
   installed, or until the Owner is removed from the TPM. (Note that the Physical Presence command
1590
   TPM_ForceClear always enables further management, even if TPM_ForceClear is used when no Owner is
1591
   installed.)
1592
1593
   (3) TPM_FAMILY_CREATE creates a new family.
1594
1595
   (4) TPM_FAMILY_INVALIDATE invalidates an existing family.
1596
*/
1597
1598
TPM_RESULT TPM_Process_DelegateManage(tpm_state_t *tpm_state,
1599
              TPM_STORE_BUFFER *response,
1600
              TPM_TAG tag,
1601
              uint32_t paramSize,
1602
              TPM_COMMAND_CODE ordinal,
1603
              unsigned char *command,
1604
              TPM_TRANSPORT_INTERNAL *transportInternal)
1605
0
{
1606
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1607
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1608
1609
    /* input parameters */
1610
0
    TPM_FAMILY_ID   familyID; /* The familyID that is to be managed */
1611
0
    TPM_FAMILY_OPERATION  opCode = 0; /* Operation to be performed by this command. */
1612
0
    TPM_SIZED_BUFFER    opData;   /* Data necessary to implement opCode */
1613
0
    TPM_AUTHHANDLE    authHandle; /* The authorization session handle used for owner
1614
               authentication. */
1615
0
    TPM_NONCE     nonceOdd; /* Nonce generated by system associated with
1616
               authHandle */
1617
0
    TPM_BOOL    continueAuthSession = TRUE; /* The continue use flag for the
1618
               authorization session handle */
1619
0
    TPM_AUTHDATA    ownerAuth;  /* HMAC key: ownerAuth. */
1620
1621
    /* processing parameters */
1622
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
1623
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
1624
0
    TPM_DIGEST      inParamDigest;
1625
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1626
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1627
0
    TPM_BOOL      authHandleValid = FALSE;
1628
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
1629
0
    TPM_SECRET      *hmacKey;
1630
0
    TPM_SECRET      savedAuth;    /* saved copy for response */
1631
0
    TPM_DELEGATE_PUBLIC   *delegatePublic;  /* from DSAP session */
1632
0
    TPM_FAMILY_TABLE_ENTRY  *familyRow = NULL;  /* family table row containing familyID */
1633
0
    uint32_t      nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite;
1634
              /* temp for noOwnerNVWrite, initialize to
1635
                 silence compiler */
1636
0
    TPM_BOOL      nv1Incremented = FALSE; /* flag that nv1 was incremented */
1637
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back data */
1638
1639
    /* output parameters  */
1640
0
    uint32_t      outParamStart;  /* starting point of outParam's */
1641
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
1642
0
    TPM_DIGEST      outParamDigest;
1643
0
    TPM_STORE_BUFFER    retData;  /* Returned data */
1644
1645
0
    printf("TPM_Process_DelegateManage: Ordinal Entry\n");
1646
0
    TPM_SizedBuffer_Init(&opData);    /* freed @1 */
1647
0
    TPM_Sbuffer_Init(&retData);     /* freed @2 */
1648
    /*
1649
      get inputs
1650
    */
1651
    /* save the starting point of inParam's for authorization and auditing */
1652
0
    inParamStart = command;
1653
    /* get familyID parameter */
1654
0
    if (returnCode == TPM_SUCCESS) {
1655
0
  returnCode = TPM_Load32(&familyID, &command, &paramSize);
1656
0
    }
1657
    /* get opCode parameter */
1658
0
    if (returnCode == TPM_SUCCESS) {
1659
0
  printf("TPM_Process_DelegateManage: familyID %08x\n", familyID);
1660
0
  returnCode = TPM_Load32(&opCode, &command, &paramSize);
1661
0
    }
1662
    /* get opData parameter */
1663
0
    if (returnCode == TPM_SUCCESS) {
1664
0
  printf("TPM_Process_DelegateManage: opCode %u\n", opCode);
1665
0
  returnCode = TPM_SizedBuffer_Load(&opData, &command, &paramSize);
1666
0
    }
1667
    /* save the ending point of inParam's for authorization and auditing */
1668
0
    inParamEnd = command;
1669
    /* digest the input parameters */
1670
0
    if (returnCode == TPM_SUCCESS) {
1671
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1672
0
            &auditStatus,   /* output */
1673
0
            &transportEncrypt,  /* output */
1674
0
            tpm_state,
1675
0
            tag,
1676
0
            ordinal,
1677
0
            inParamStart,
1678
0
            inParamEnd,
1679
0
            transportInternal);
1680
0
    }
1681
    /* check state */
1682
0
    if (returnCode == TPM_SUCCESS) {
1683
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
1684
0
    }
1685
    /* check tag */
1686
0
    if (returnCode == TPM_SUCCESS) {
1687
0
  returnCode = TPM_CheckRequestTag10(tag);
1688
0
    }
1689
    /* get the optional 'below the line' authorization parameters */
1690
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1691
0
  returnCode = TPM_AuthParams_Get(&authHandle,
1692
0
          &authHandleValid,
1693
0
          nonceOdd,
1694
0
          &continueAuthSession,
1695
0
          ownerAuth,
1696
0
          &command, &paramSize);
1697
0
    }
1698
0
    if (returnCode == TPM_SUCCESS) {
1699
0
  if (paramSize != 0) {
1700
0
      printf("TPM_Process_DelegateManage: Error, command has %u extra bytes\n",
1701
0
       paramSize);
1702
0
      returnCode = TPM_BAD_PARAM_SIZE;
1703
0
  }
1704
0
    }
1705
    /* do not terminate sessions if the command did not parse correctly */
1706
0
    if (returnCode != TPM_SUCCESS) {
1707
0
  authHandleValid = FALSE;
1708
0
    }
1709
    /*
1710
      Processing
1711
    */
1712
    /* 1. If opCode != TPM_FAMILY_CREATE */
1713
    /* a. Locate familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return
1714
       TPM_BADINDEX if not found */
1715
    /* b. Set FR, a TPM_FAMILY_TABLE_ENTRY, to TPM_FAMILY_TABLE. famTableRow[familyRow] */
1716
0
    if ((returnCode == TPM_SUCCESS) && (opCode != TPM_FAMILY_CREATE)) {
1717
0
  printf("TPM_Process_DelegateManage: Not creating, get entry for familyID %08x\n",
1718
0
         familyID);
1719
0
  returnCode = TPM_FamilyTable_GetEntry(&familyRow,
1720
0
                &(tpm_state->tpm_permanent_data.familyTable),
1721
0
                familyID);
1722
0
    }
1723
    /* 2. If tag = TPM_TAG_RQU_AUTH1_COMMAND */
1724
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1725
  /* a. Validate the command and parameters using ownerAuth, return TPM_AUTHFAIL on error */
1726
0
  returnCode =
1727
0
      TPM_AuthSessions_GetData(&auth_session_data,
1728
0
             &hmacKey,
1729
0
             tpm_state,
1730
0
             authHandle,
1731
0
             TPM_PID_NONE,
1732
0
             TPM_ET_OWNER,
1733
0
             ordinal,
1734
0
             NULL,
1735
0
             &(tpm_state->tpm_permanent_data.ownerAuth),/* OIAP */
1736
0
             tpm_state->tpm_permanent_data.ownerAuth);  /* OSAP */
1737
0
    }
1738
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1739
  /* make a copy of the HMAC key for the response, since it MAY be invalidated */
1740
0
  TPM_Secret_Copy(savedAuth, *hmacKey);
1741
0
  returnCode = TPM_Authdata_Check(tpm_state,
1742
0
          *hmacKey,   /* owner HMAC key */
1743
0
          inParamDigest,
1744
0
          auth_session_data,  /* authorization session */
1745
0
          nonceOdd,   /* Nonce generated by system
1746
                   associated with authHandle */
1747
0
          continueAuthSession,
1748
0
          ownerAuth);   /* Authorization digest for input */
1749
0
    }
1750
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1751
  /* b. If the command is delegated (authHandle session type is TPM_PID_DSAP or through
1752
     ownerReference delegation) */
1753
0
  if ((auth_session_data->protocolID == TPM_PID_DSAP) ||
1754
0
      (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER)) {
1755
      /* i. If opCode = TPM_FAMILY_CREATE */
1756
      /* (1) The TPM MUST ignore familyID */
1757
      /* ii. Else */
1758
0
      if (opCode != TPM_FAMILY_CREATE) {
1759
    /* get the TPM_DELEGATE_PUBLIC from the DSAP session */
1760
0
    if (returnCode == TPM_SUCCESS) {
1761
0
        returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic,
1762
0
                       auth_session_data);
1763
0
    }
1764
    /* (1) Verify that the familyID associated with authHandle matches the familyID
1765
       parameter, return TPM_DELEGATE_FAMILY on error */
1766
0
    if (returnCode == TPM_SUCCESS) {
1767
0
        if (delegatePublic->familyID != familyID) {
1768
0
      printf("TPM_Process_DelegateManage: Error, familyID %08x should be %08x\n",
1769
0
             familyID, delegatePublic->familyID);
1770
0
      returnCode = TPM_DELEGATE_FAMILY;
1771
0
        }
1772
0
    }
1773
0
      }
1774
0
  }
1775
0
    }
1776
    /* 3. Else */
1777
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) {
1778
  /* a. If TPM_PERMANENT_DATA -> ownerAuth is valid, return TPM_AUTHFAIL */
1779
0
  if (tpm_state->tpm_permanent_data.ownerInstalled) {
1780
0
      printf("TPM_Process_DelegateManage: Error, owner installed but no authorization\n");
1781
0
      returnCode = TPM_AUTHFAIL ;
1782
0
  }
1783
0
    }
1784
    /* b. If opCode != TPM_FAMILY_CREATE and FR -> flags -> TPM_DELEGATE_ADMIN_LOCK is TRUE, return
1785
       TPM_DELEGATE_LOCK */
1786
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) {
1787
0
  if ((opCode != TPM_FAMILY_CREATE) && (familyRow->flags & TPM_DELEGATE_ADMIN_LOCK)) {
1788
0
      printf("TPM_Process_DelegateManage: Error, row locked\n");
1789
0
      returnCode = TPM_DELEGATE_LOCK;
1790
0
  }
1791
0
    }
1792
    /* c. Validate max NV writes without an owner */
1793
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) {
1794
  /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */
1795
0
  nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite;
1796
  /* ii. Increment NV1 by 1 */
1797
0
  nv1++;
1798
  /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */
1799
0
  if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) {
1800
0
      printf("TPM_Process_DelegateManage: Error, max NV writes %d w/o owner reached\n",
1801
0
       tpm_state->tpm_permanent_data.noOwnerNVWrite);
1802
0
      returnCode = TPM_MAXNVWRITES;
1803
0
  }
1804
0
  if (returnCode == TPM_SUCCESS){
1805
      /* iv. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */
1806
      /* NOTE Don't update the noOwnerNVWrite value until determining that the write will be
1807
         performed */
1808
0
      nv1Incremented = TRUE;
1809
0
  }
1810
0
    } 
1811
    /* 4. The TPM invalidates sessions */
1812
0
    if (returnCode == TPM_SUCCESS) {
1813
0
  printf("TPM_Process_DelegateManage: Invalidate sessions\n");
1814
  /* a. MUST invalidate all DSAP sessions */
1815
  /* b. MUST invalidate all OSAP sessions associated with the delegation table */
1816
  /* d. MAY invalidate any other session */
1817
0
  TPM_AuthSessions_TerminatexSAP(&continueAuthSession,
1818
0
               authHandle,
1819
0
               tpm_state->tpm_stclear_data.authSessions);
1820
  /* c. MUST set TPM_STCLEAR_DATA -> ownerReference to TPM_KH_OWNER */
1821
0
  tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER;
1822
0
    }
1823
    /*
1824
      5. If opCode == TPM_FAMILY_CREATE
1825
    */
1826
0
    if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_CREATE)) {
1827
0
  printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_CREATE\n");
1828
  /* a. Validate that sufficient space exists within the TPM to store an additional family and
1829
     map F2 to the newly allocated space. */
1830
0
  if (returnCode == TPM_SUCCESS) {
1831
0
      returnCode = TPM_FamilyTable_IsSpace(&familyRow,  /* output */
1832
0
             &(tpm_state->tpm_permanent_data.familyTable));
1833
0
  }
1834
  /* b. Validate that opData is a TPM_FAMILY_LABEL */
1835
0
  if (returnCode == TPM_SUCCESS) {
1836
      /* i. If opDataSize != sizeof(TPM_FAMILY_LABEL) return TPM_BAD_PARAM_SIZE */
1837
0
      if (opData.size != sizeof(TPM_FAMILY_LABEL)) {
1838
0
    printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size);
1839
0
    returnCode = TPM_BAD_PARAM_SIZE;
1840
0
      }
1841
0
  }
1842
  /* c. Map F2 to a TPM_FAMILY_TABLE_ENTRY */
1843
  /* NOTE Done by TPM_FamilyTable_IsSpace() */
1844
  /* i. Set F2 -> tag to TPM_TAG_FAMILY_TABLE_ENTRY */
1845
  /* NOTE Done by TPM_FamilyTableEntry_Init() */
1846
0
  if (returnCode == TPM_SUCCESS) {
1847
      /* ii. Set F2 -> familyLabel to opData */
1848
0
      familyRow->familyLabel = *(opData.buffer);
1849
      /* d. Increment TPM_PERMANENT_DATA -> lastFamilyID by 1 */
1850
0
      tpm_state->tpm_permanent_data.lastFamilyID++;
1851
      /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after NVRAM is written */
1852
0
      writeAllNV = TRUE;
1853
      /* e. Set F2 -> familyID = TPM_PERMANENT_DATA -> lastFamilyID */
1854
0
      familyRow->familyID = tpm_state->tpm_permanent_data.lastFamilyID;
1855
      /* f. Set F2 -> verificationCount = 1 */
1856
0
      familyRow->verificationCount = 1;
1857
      /* g. Set F2 -> flags -> TPM_FAMFLAG_ENABLED to FALSE */
1858
0
      familyRow->flags &= ~TPM_FAMFLAG_ENABLED;
1859
      /* h. Set F2 -> flags -> TPM_DELEGATE_ADMIN_LOCK to FALSE */
1860
0
      familyRow->flags &= ~TPM_DELEGATE_ADMIN_LOCK;
1861
      /* i. Set retDataSize = 4 */
1862
      /* j. Set retData = F2 -> familyID */
1863
0
      printf("TPM_Process_DelegateManage: Created familyID %08x\n", familyRow->familyID);
1864
0
      familyRow->valid = TRUE;
1865
0
      returnCode = TPM_Sbuffer_Append32(&retData, familyRow->familyID);
1866
0
  }
1867
  /* k. Return TPM_SUCCESS */
1868
0
    }
1869
    /* 6. If authHandle is of type DSAP then continueAuthSession MUST set to FALSE */
1870
0
    if ((returnCode == TPM_SUCCESS) && (opCode != TPM_FAMILY_CREATE) &&
1871
0
  (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { /* only if auth-1 */
1872
1873
0
  if (auth_session_data->protocolID == TPM_PID_DSAP) {
1874
0
      continueAuthSession = FALSE;
1875
0
  }
1876
0
    }
1877
    /* 7. If opCode == TPM_FAMILY_ADMIN */
1878
0
    if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_ADMIN)) {
1879
0
  printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_ADMIN\n");
1880
  /* a. Validate that opDataSize == 1, and that opData is a Boolean value. */
1881
0
  if (returnCode == TPM_SUCCESS) {
1882
0
      if (opData.size != sizeof(TPM_BOOL)) {
1883
0
    printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size);
1884
0
    returnCode = TPM_BAD_PARAM_SIZE;
1885
0
      }
1886
0
  }
1887
  /* b. Set (FR -> flags -> TPM_DELEGATE_ADMIN_LOCK) = opData */
1888
0
  if (returnCode == TPM_SUCCESS) {
1889
0
      printf("TPM_Process_DelegateManage: TPM_FAMILY_ADMIN opData %02x\n",
1890
0
       opData.buffer[0]);
1891
0
      if (*(TPM_BOOL *)(opData.buffer)) {
1892
0
    familyRow->flags |= TPM_DELEGATE_ADMIN_LOCK;
1893
0
      }
1894
0
      else {
1895
0
    familyRow->flags &= ~TPM_DELEGATE_ADMIN_LOCK;
1896
0
      }
1897
0
      printf("TPM_Process_DelegateManage: new TPM_FAMILY_TABLE_ENTRY.flags %08x\n",
1898
0
       familyRow->flags);
1899
      /* c. Set retDataSize = 0 */
1900
      /* NOTE Done by TPM_Sbuffer_Init() */
1901
      /* d. Return TPM_SUCCESS */
1902
0
  }
1903
0
  if (returnCode == TPM_SUCCESS) {
1904
0
      writeAllNV = TRUE;
1905
0
  }
1906
0
    }
1907
    /* 8. else If opflag == TPM_FAMILY_ENABLE */
1908
0
    if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_ENABLE)) {
1909
0
  printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_ENABLE\n");
1910
  /* a. Validate that opDataSize == 1, and that opData is a Boolean value. */
1911
0
  if (returnCode == TPM_SUCCESS) {
1912
0
      if (opData.size != sizeof(TPM_BOOL)) {
1913
0
    printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size);
1914
0
    returnCode = TPM_BAD_PARAM_SIZE;
1915
0
      }
1916
0
  }
1917
  /* b. Set FR -> flags-> TPM_FAMFLAG_ENABLED = opData */
1918
0
  if (returnCode == TPM_SUCCESS) {
1919
0
      printf("TPM_Process_DelegateManage: TPM_FAMILY_ENABLE opData %02x\n",
1920
0
       opData.buffer[0]);
1921
0
      if (*(TPM_BOOL *)(opData.buffer)) {
1922
0
    familyRow->flags |= TPM_FAMFLAG_ENABLED; 
1923
0
      }
1924
0
      else {
1925
0
    familyRow->flags &= ~TPM_FAMFLAG_ENABLED;
1926
0
      }
1927
0
      printf("TPM_Process_DelegateManage: new TPM_FAMILY_TABLE_ENTRY.flags %08x\n",
1928
0
       familyRow->flags);
1929
      /* c. Set retDataSize = 0 */
1930
      /* NOTE Done by TPM_Sbuffer_Init() */
1931
      /* d. Return TPM_SUCCESS */
1932
0
  }
1933
0
  if (returnCode == TPM_SUCCESS) {
1934
0
      writeAllNV = TRUE;
1935
0
  }
1936
0
    }
1937
    /* 9. else If opflag == TPM_FAMILY_INVALIDATE */
1938
0
    if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_INVALIDATE)) {
1939
0
  printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_INVALIDATE\n");
1940
  /* a. Invalidate all data associated with familyRow */
1941
  /* i. All data is all information pointed to by FR */
1942
  /* ii. return TPM_SELFTEST_FAILED on failure */
1943
0
  TPM_FamilyTableEntry_Delete(familyRow);
1944
  /* b.The TPM MAY invalidate delegate rows that contain the same familyID. */
1945
  /* c. Set retDataSize = 0 */
1946
  /* NOTE Done by TPM_Sbuffer_Init() */
1947
  /* d. Return TPM_SUCCESS */
1948
0
  writeAllNV = TRUE;
1949
0
    }
1950
    /* 10. Else return TPM_BAD_PARAMETER */
1951
0
    if (returnCode == TPM_SUCCESS) {
1952
0
  if ((opCode != TPM_FAMILY_CREATE) &&
1953
0
      (opCode != TPM_FAMILY_ADMIN) &&
1954
0
      (opCode != TPM_FAMILY_ENABLE) &&
1955
0
      (opCode != TPM_FAMILY_INVALIDATE)) {
1956
0
      printf("TPM_Process_DelegateManage: Error, bad opCode %08x\n", opCode);
1957
0
      returnCode = TPM_BAD_PARAMETER;
1958
0
  }
1959
0
    }
1960
    /* if writing NV and this is a no owner NV write, update the count with the previously
1961
       incremented value */
1962
0
    if (returnCode == TPM_SUCCESS) {
1963
0
  if (writeAllNV && nv1Incremented) {
1964
0
      printf("TPM_Process_DelegateManage: noOwnerNVWrite %u\n", nv1);
1965
0
      tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1;
1966
0
  }
1967
0
    }
1968
    /* write back TPM_PERMANENT_DATA if required */
1969
0
    returnCode = TPM_PermanentAll_NVStore(tpm_state,
1970
0
            writeAllNV,
1971
0
            returnCode);
1972
    /*
1973
      response
1974
    */
1975
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1976
0
    if (rcf == 0) {
1977
0
  printf("TPM_Process_DelegateManage: Ordinal returnCode %08x %u\n",
1978
0
         returnCode, returnCode);
1979
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1980
0
    }
1981
    /* success response, append the rest of the parameters.  */
1982
0
    if (rcf == 0) {
1983
0
  if (returnCode == TPM_SUCCESS) {
1984
      /* checkpoint the beginning of the outParam's */
1985
0
      outParamStart = response->buffer_current - response->buffer;
1986
      /* append retDataSize and retData */
1987
0
      returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &retData);
1988
      /* checkpoint the end of the outParam's */
1989
0
      outParamEnd = response->buffer_current - response->buffer;
1990
0
  }
1991
  /* digest the above the line output parameters */
1992
0
  if (returnCode == TPM_SUCCESS) {
1993
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1994
0
                 auditStatus, /* input audit status */
1995
0
                 transportEncrypt,
1996
0
                 tag,     
1997
0
                 returnCode,
1998
0
                 ordinal,   /* command ordinal */
1999
0
                 response->buffer + outParamStart,  /* start */
2000
0
                 outParamEnd - outParamStart);  /* length */
2001
0
  }
2002
  /* calculate and set the below the line parameters */
2003
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2004
0
      returnCode = TPM_AuthParams_Set(response,
2005
0
              savedAuth,    /* saved HMAC key */
2006
0
              auth_session_data,
2007
0
              outParamDigest,
2008
0
              nonceOdd,
2009
0
              continueAuthSession);
2010
0
  }
2011
  /* audit if required */
2012
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
2013
0
      returnCode = TPM_ProcessAudit(tpm_state,
2014
0
            transportEncrypt,
2015
0
            inParamDigest,
2016
0
            outParamDigest,
2017
0
            ordinal);
2018
0
  }
2019
  /* adjust the initial response */
2020
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2021
0
    }
2022
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
2023
0
    if (((rcf != 0) ||
2024
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2025
0
   !continueAuthSession) &&
2026
0
  authHandleValid) {
2027
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2028
0
    }
2029
    /*
2030
      cleanup
2031
    */
2032
0
    TPM_SizedBuffer_Delete(&opData);  /* @1 */
2033
0
    TPM_Sbuffer_Delete(&retData); /* @2 */
2034
0
    return rcf;
2035
0
}
2036
2037
/* 19.2 TPM_Delegate_CreateKeyDelegation rev 109
2038
   
2039
  This command delegates privilege to use a key by creating a blob that can be used by TPM_DSAP.
2040
2041
  There is no check for appropriateness of the key's key usage against the key permission
2042
  settings. If the key usage is incorrect, this command succeeds, but the delegated command will
2043
  fail.
2044
2045
  These blobs CANNOT be used as input data for TPM_LoadOwnerDelegation because the internal TPM
2046
  delegate table can store owner delegations only.
2047
  
2048
  (TPM_Delegate_CreateOwnerDelegation must be used to delegate Owner privilege.)
2049
2050
  The use restrictions that may be present on the key pointed to by keyHandle are not enforced for
2051
  this command. Stated another way CreateKeyDelegation is not a use of the key.
2052
2053
  The publicInfo -> familyID can specify a disabled family row.  The family row is checked when the
2054
  key delegation is used in a DSAP session, not when it is created.
2055
*/
2056
2057
TPM_RESULT TPM_Process_DelegateCreateKeyDelegation(tpm_state_t *tpm_state,
2058
               TPM_STORE_BUFFER *response,
2059
               TPM_TAG tag,
2060
               uint32_t paramSize,
2061
               TPM_COMMAND_CODE ordinal,
2062
               unsigned char *command,
2063
               TPM_TRANSPORT_INTERNAL *transportInternal)
2064
0
{
2065
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
2066
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
2067
2068
    /* input parameters */
2069
0
    TPM_KEY_HANDLE  keyHandle;  /* The keyHandle identifier of a loaded key. */
2070
0
    TPM_DELEGATE_PUBLIC publicInfo; /* The public information necessary to fill in the blob */
2071
0
    TPM_ENCAUTH   delAuth;  /* The encrypted new AuthData for the blob. The encryption
2072
             key is the shared secret from the authorization session
2073
             protocol.*/
2074
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle used for keyHandle
2075
             authorization */
2076
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
2077
0
    TPM_BOOL  continueAuthSession = TRUE; /* Ignored */
2078
0
    TPM_AUTHDATA  privAuth; /* The authorization session digest that authorizes the use
2079
             of keyHandle. HMAC key: key.usageAuth */
2080
2081
    /* processing parameters */
2082
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
2083
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
2084
0
    TPM_DIGEST      inParamDigest;
2085
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
2086
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
2087
0
    TPM_BOOL      authHandleValid = FALSE;
2088
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
2089
0
    TPM_SECRET      *hmacKey;
2090
0
    TPM_BOOL      parentPCRStatus;
2091
0
    TPM_KEY     *key = NULL;      /* the key specified by keyHandle */
2092
0
    TPM_SECRET      *keyUsageAuth;
2093
0
    TPM_DELEGATE_PUBLIC   *delegatePublic;  /* from DSAP session */
2094
0
    TPM_FAMILY_TABLE_ENTRY  *familyRow;   /* family table row containing familyID */
2095
0
    TPM_DIGEST      a1Auth;
2096
0
    TPM_DELEGATE_SENSITIVE  m1DelegateSensitive;
2097
0
    TPM_STORE_BUFFER    delegateSensitive_sbuffer;
2098
0
    TPM_DELEGATE_KEY_BLOB p1DelegateKeyBlob;
2099
2100
2101
    /* output parameters  */
2102
0
    uint32_t      outParamStart;  /* starting point of outParam's */
2103
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
2104
0
    TPM_DIGEST      outParamDigest;
2105
0
    TPM_STORE_BUFFER    blobSbuffer;  /* The partially encrypted delegation information.
2106
               */
2107
2108
0
    printf("TPM_Process_DelegateCreateKeyDelegation: Ordinal Entry\n");
2109
0
    TPM_DelegatePublic_Init(&publicInfo);   /* freed @1 */
2110
0
    TPM_DelegateSensitive_Init(&m1DelegateSensitive); /* freed @2 */
2111
0
    TPM_Sbuffer_Init(&delegateSensitive_sbuffer); /* freed @3 */
2112
0
    TPM_DelegateKeyBlob_Init(&p1DelegateKeyBlob); /* freed @4 */
2113
0
    TPM_Sbuffer_Init(&blobSbuffer);     /* freed @5 */
2114
    /*
2115
      get inputs
2116
    */
2117
    /* get keyHandle parameter */
2118
0
    if (returnCode == TPM_SUCCESS) {
2119
0
  returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
2120
0
    }
2121
    /* save the starting point of inParam's for authorization and auditing */
2122
0
    inParamStart = command;
2123
    /* get publicInfo parameter */
2124
0
    if (returnCode == TPM_SUCCESS) {
2125
0
  printf("TPM_Process_DelegateCreateKeyDelegation: keyHandle %08x\n", keyHandle);
2126
0
  returnCode = TPM_DelegatePublic_Load(&publicInfo, &command, &paramSize);
2127
0
    }
2128
    /* get delAuth parameter */
2129
0
    if (returnCode == TPM_SUCCESS) {
2130
0
  returnCode = TPM_Authdata_Load(delAuth, &command, &paramSize);
2131
0
    }
2132
    /* save the ending point of inParam's for authorization and auditing */
2133
0
    inParamEnd = command;
2134
    /* digest the input parameters */
2135
0
    if (returnCode == TPM_SUCCESS) {
2136
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
2137
0
            &auditStatus,   /* output */
2138
0
            &transportEncrypt,  /* output */
2139
0
            tpm_state,
2140
0
            tag,
2141
0
            ordinal,
2142
0
            inParamStart,
2143
0
            inParamEnd,
2144
0
            transportInternal);
2145
0
    }
2146
    /* check state */
2147
0
    if (returnCode == TPM_SUCCESS) {
2148
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
2149
0
    }
2150
    /* check tag */
2151
0
    if (returnCode == TPM_SUCCESS) {
2152
0
  returnCode = TPM_CheckRequestTag1(tag);
2153
0
    }
2154
    /* get the 'below the line' authorization parameters */
2155
0
    if (returnCode == TPM_SUCCESS) {
2156
0
  returnCode = TPM_AuthParams_Get(&authHandle,
2157
0
          &authHandleValid,
2158
0
          nonceOdd,
2159
0
          &continueAuthSession,
2160
0
          privAuth,
2161
0
          &command, &paramSize);
2162
0
    }
2163
0
    if (returnCode == TPM_SUCCESS) {
2164
0
  if (paramSize != 0) {
2165
0
      printf("TPM_Process_DelegateCreateKeyDelegation: Error, command has %u extra bytes\n",
2166
0
       paramSize);
2167
0
      returnCode = TPM_BAD_PARAM_SIZE;
2168
0
  }
2169
0
    }
2170
    /* do not terminate sessions if the command did not parse correctly */
2171
0
    if (returnCode != TPM_SUCCESS) {
2172
0
  authHandleValid = FALSE;
2173
0
    }
2174
    /*
2175
      Processing
2176
    */
2177
    /* 1. Verify AuthData for the command and parameters using privAuth */
2178
    /* get the key corresponding to the keyHandle parameter */
2179
0
    if (returnCode == TPM_SUCCESS) {
2180
0
  returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle,
2181
0
             FALSE,   /* not read-only */
2182
0
             FALSE,   /* do not ignore PCRs */
2183
0
             FALSE);  /* cannot use EK */
2184
0
    }
2185
    /* get keyHandle -> usageAuth */
2186
0
    if (returnCode == TPM_SUCCESS) {
2187
0
  returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key);
2188
0
    }   
2189
    /* get the session data */
2190
0
    if (returnCode == TPM_SUCCESS) {
2191
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
2192
0
                &hmacKey,
2193
0
                tpm_state,
2194
0
                authHandle,
2195
0
                TPM_PID_OSAP,
2196
0
                TPM_ET_KEYHANDLE,
2197
0
                ordinal,
2198
0
                key,
2199
0
                NULL,     /* OIAP */
2200
0
                key->tpm_store_asymkey->pubDataDigest); /* OSAP */
2201
0
    }
2202
    /* Validate the authorization */
2203
0
    if (returnCode == TPM_SUCCESS) {
2204
0
  returnCode = TPM_Authdata_Check(tpm_state,
2205
0
          *hmacKey,   /* HMAC key */
2206
0
          inParamDigest,
2207
0
          auth_session_data,  /* authorization session */
2208
0
          nonceOdd,   /* Nonce generated by system
2209
                   associated with authHandle */
2210
0
          continueAuthSession,
2211
0
          privAuth);    /* Authorization digest for input */
2212
0
    }
2213
    /* 2. Locate publicInfo -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row,
2214
       return TPM_BADINDEX if not found */
2215
0
    if (returnCode == TPM_SUCCESS) {
2216
0
  returnCode = TPM_FamilyTable_GetEntry(&familyRow,
2217
0
                &(tpm_state->tpm_permanent_data.familyTable),
2218
0
                publicInfo.familyID);
2219
0
    }
2220
    /* 3. If the key authentication is in fact a delegation, then the TPM SHALL validate the command
2221
       and parameters using Delegation authorisation, then */
2222
0
    if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) {
2223
0
  printf("TPM_Process_DelegateCreateKeyDelegation: Authentication is a delegation\n");
2224
  /* get the TPM_DELEGATE_PUBLIC from the DSAP session */
2225
0
  if (returnCode == TPM_SUCCESS) {
2226
0
      returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic,
2227
0
                     auth_session_data);
2228
0
  }
2229
  /* a. Validate that authHandle -> familyID equals publicInfo -> familyID return
2230
     TPM_DELEGATE_FAMILY on error */
2231
0
  if (returnCode == TPM_SUCCESS) {
2232
0
      if (publicInfo.familyID != delegatePublic->familyID) {
2233
0
    printf("TPM_Process_DelegateCreateKeyDelegation: Error, "
2234
0
           "familyID %u should be %u\n",
2235
0
           publicInfo.familyID, delegatePublic->familyID);
2236
0
    returnCode = TPM_DELEGATE_FAMILY;
2237
0
      }
2238
0
  }
2239
  /* b. If TPM_FAMILY_TABLE.famTableRow[ authHandle -> familyID] -> flags ->
2240
     TPM_FAMFLAG_ENABLED is FALSE, return error TPM_DISABLED_CMD. */
2241
0
  if (returnCode == TPM_SUCCESS) {
2242
0
      if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) {
2243
0
    printf("TPM_Process_DelegateCreateKeyDelegation: Error, family %u disabled\n",
2244
0
           publicInfo.familyID);
2245
0
    returnCode = TPM_DISABLED_CMD;
2246
0
      }
2247
0
  }
2248
  /* c. Verify that the delegation bits in publicInfo do not grant more permissions then
2249
     currently delegated.  Otherwise return error TPM_AUTHFAIL */
2250
0
  if (returnCode == TPM_SUCCESS) {
2251
0
      returnCode =
2252
0
    TPM_Delegations_CheckPermissionDelegation(&(publicInfo.permissions),
2253
0
                &(delegatePublic->permissions));
2254
0
  }
2255
0
    }
2256
    /* 4. Check that publicInfo -> delegateType is TPM_DEL_KEY_BITS */
2257
0
    if (returnCode == TPM_SUCCESS) {
2258
0
  if (publicInfo.permissions.delegateType  != TPM_DEL_KEY_BITS) {
2259
0
      printf("TPM_Process_DelegateCreateKeyDelegation: Error, "
2260
0
       "delegateType %08x not a key delegation\n",
2261
0
       publicInfo.permissions.delegateType);
2262
0
      returnCode = TPM_BAD_PARAMETER;
2263
0
  }
2264
0
    }
2265
    /* 5. Verify that authHandle indicates an OSAP or DSAP session return TPM_INVALID_AUTHHANDLE on
2266
    error */
2267
    /* NOTE Done by TPM_AuthSessions_GetData() */
2268
    /* 6. Create a1 by decrypting delAuth according to the ADIP indicated by authHandle. */
2269
0
    if (returnCode == TPM_SUCCESS) {
2270
0
  returnCode = TPM_AuthSessionData_Decrypt(a1Auth,
2271
0
             NULL,
2272
0
             delAuth,
2273
0
             auth_session_data,
2274
0
             NULL,
2275
0
             NULL,
2276
0
             FALSE);  /* even and odd */
2277
0
    }
2278
    /* 7. Create h1 the SHA-1 of TPM_STORE_PUBKEY structure of the key pointed to by keyHandle */
2279
0
    if (returnCode == TPM_SUCCESS) {
2280
0
  TPM_PrintFour("TPM_Process_DelegateCreateKeyDelegation: Decrypted a1", a1Auth);
2281
0
  returnCode = TPM_SHA1_GenerateStructure(p1DelegateKeyBlob.pubKeyDigest,
2282
0
            &(key->pubKey),
2283
0
            (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store);
2284
0
    }
2285
    /* 8. Create M1 a TPM_DELEGATE_SENSITIVE structure */
2286
    /* a. Set M1 -> tag to TPM_TAG_DELEGATE_SENSITIVE */
2287
    /* NOTE Done by TPM_DelegateSensitive_Init() */
2288
    /* b. Set M1 -> authValue to a1 */
2289
0
    if (returnCode == TPM_SUCCESS) {
2290
0
  TPM_Secret_Copy(m1DelegateSensitive.authValue, a1Auth);
2291
  /* c. The TPM MAY add additional information of a sensitive nature relative to the
2292
     delegation */
2293
  /* 9. Create M2 the encryption of M1 using TPM_DELEGATE_KEY */
2294
  /* serialize M1 */
2295
0
  returnCode = TPM_DelegateSensitive_Store(&delegateSensitive_sbuffer, &m1DelegateSensitive);
2296
0
    }
2297
    /* encrypt with delegate key */
2298
0
    if (returnCode == TPM_SUCCESS) {
2299
0
      printf("TPM_Process_DelegateCreateKeyDelegation: Encrypting TPM_DELEGATE_SENSITIVE\n");
2300
0
      returnCode =
2301
0
    TPM_SymmetricKeyData_EncryptSbuffer(&(p1DelegateKeyBlob.sensitiveArea),
2302
0
                &delegateSensitive_sbuffer,
2303
0
                tpm_state->tpm_permanent_data.delegateKey);
2304
0
    }
2305
    /* 10. Create P1 a TPM_DELEGATE_KEY_BLOB */
2306
    /* a. Set P1 -> tag to TPM_TAG_DELG_KEY_BLOB */
2307
    /* NOTE Done by TPM_DelegateKeyBlob_Init() */
2308
    /* b. Set P1 -> pubKeyDigest to H1 */
2309
    /* NOTE Done by TPM_StorePubkey_GenerateDigest() */
2310
    /* c. Set P1 -> pub to PublicInfo */
2311
0
    if (returnCode == TPM_SUCCESS) {
2312
0
  returnCode = TPM_DelegatePublic_Copy(&(p1DelegateKeyBlob.pub), &publicInfo);
2313
0
    }
2314
    /* d. Set P1 -> pub -> verificationCount to familyRow -> verificationCount */
2315
0
    if (returnCode == TPM_SUCCESS) {
2316
0
  p1DelegateKeyBlob.pub.verificationCount = familyRow->verificationCount;
2317
  /* e. Set P1 -> integrityDigest to NULL */
2318
  /* NOTE Done by TPM_DelegateKeyBlob_Init() */
2319
  /* f. The TPM sets additionalArea and additionalAreaSize appropriate for this TPM. The
2320
     information MAY include symmetric IV, symmetric mode of encryption and other data that
2321
     allows the TPM to process the blob in the future. */
2322
  /* g. Set P1 -> sensitiveSize to the size of M2 */
2323
  /* h. Set P1 -> sensitiveArea to M2 */
2324
  /* NOTE Encrypted directly into p1DelegateKeyBlob.sensitiveArea */
2325
  /* 11. Calculate H2 the HMAC of P1 using tpmProof as the secret */
2326
  /* 12. Set P1 -> integrityDigest to H2 */
2327
  /* NOTE It is safe to HMAC directly into TPM_DELEGATE_KEY_BLOB, since the structure
2328
     is serialized before the HMAC is performed */
2329
0
  returnCode = TPM_HMAC_GenerateStructure
2330
0
         (p1DelegateKeyBlob.integrityDigest,    /* HMAC */
2331
0
          tpm_state->tpm_permanent_data.tpmProof,   /* HMAC key */
2332
0
          &p1DelegateKeyBlob,       /* structure */
2333
0
          (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store); /* store function */
2334
0
    }
2335
    /* 13. Ignore continueAuthSession on input set continueAuthSession to FALSE on output */
2336
0
    if (returnCode == TPM_SUCCESS) {
2337
0
  continueAuthSession = FALSE;
2338
0
    }
2339
    /* 14. Return P1 as blob */
2340
0
    if (returnCode == TPM_SUCCESS) {
2341
0
  returnCode = TPM_DelegateKeyBlob_Store(&blobSbuffer, &p1DelegateKeyBlob);
2342
0
    }
2343
    /*
2344
      response
2345
    */
2346
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
2347
0
    if (rcf == 0) {
2348
0
  printf("TPM_Process_DelegateCreateKeyDelegation: Ordinal returnCode %08x %u\n",
2349
0
         returnCode, returnCode);
2350
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
2351
0
    }
2352
    /* success response, append the rest of the parameters.  */
2353
0
    if (rcf == 0) {
2354
0
  if (returnCode == TPM_SUCCESS) {
2355
      /* checkpoint the beginning of the outParam's */
2356
0
      outParamStart = response->buffer_current - response->buffer;
2357
      /* return blobSize and blob */
2358
0
      returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &blobSbuffer);
2359
      /* checkpoint the end of the outParam's */
2360
0
      outParamEnd = response->buffer_current - response->buffer;
2361
0
  }
2362
  /* digest the above the line output parameters */
2363
0
  if (returnCode == TPM_SUCCESS) {
2364
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
2365
0
                 auditStatus, /* input audit status */
2366
0
                 transportEncrypt,
2367
0
                 tag,     
2368
0
                 returnCode,
2369
0
                 ordinal,   /* command ordinal */
2370
0
                 response->buffer + outParamStart,  /* start */
2371
0
                 outParamEnd - outParamStart);  /* length */
2372
0
  }
2373
  /* calculate and set the below the line parameters */
2374
0
  if (returnCode == TPM_SUCCESS) {
2375
0
      returnCode = TPM_AuthParams_Set(response,
2376
0
              *hmacKey,   /* HMAC key */
2377
0
              auth_session_data,
2378
0
              outParamDigest,
2379
0
              nonceOdd,
2380
0
              continueAuthSession);
2381
0
  }
2382
  /* audit if required */
2383
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
2384
0
      returnCode = TPM_ProcessAudit(tpm_state,
2385
0
            transportEncrypt,
2386
0
            inParamDigest,
2387
0
            outParamDigest,
2388
0
            ordinal);
2389
0
  }
2390
  /* adjust the initial response */
2391
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2392
0
    }
2393
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
2394
0
    if (((rcf != 0) ||
2395
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2396
0
   !continueAuthSession) &&
2397
0
  authHandleValid) {
2398
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2399
0
    }
2400
    /*
2401
      cleanup
2402
    */
2403
0
    TPM_DelegatePublic_Delete(&publicInfo);   /* @1 */
2404
0
    TPM_DelegateSensitive_Delete(&m1DelegateSensitive); /* @2 */
2405
0
    TPM_Sbuffer_Delete(&delegateSensitive_sbuffer); /* @3 */
2406
0
    TPM_DelegateKeyBlob_Delete(&p1DelegateKeyBlob); /* @4 */
2407
0
    TPM_Sbuffer_Delete(&blobSbuffer);     /* @5 */
2408
0
    return rcf;
2409
0
}
2410
2411
/* 19.3 TPM_Delegate_CreateOwnerDelegation rev 98
2412
2413
   TPM_Delegate_CreateOwnerDelegation delegates the Owner's privilege to use a set of command
2414
   ordinals, by creating a blob. Such blobs can be used as input data for TPM_DSAP or
2415
   TPM_Delegate_LoadOwnerDelegation.
2416
2417
   TPM_Delegate_CreateOwnerDelegation includes the ability to void all existing delegations (by
2418
   incrementing the verification count) before creating the new delegation. This ensures that the
2419
   new delegation will be the only delegation that can operate at Owner privilege in this
2420
   family. This new delegation could be used to enable a security monitor (a local separate entity,
2421
   or remote separate entity, or local host entity) to reinitialize a family and perhaps perform
2422
   external verification of delegation settings. Normally the ordinals for a delegated security
2423
   monitor would include TPM_Delegate_CreateOwnerDelegation (this command) in order to permit the
2424
   monitor to create further delegations, and TPM_Delegate_UpdateVerification to reactivate some
2425
   previously voided delegations.
2426
   
2427
   If the verification count is incremented and the new delegation does not delegate any privileges
2428
   (to any ordinals) at all, or uses an authorisation value that is then discarded, this family's
2429
   delegations are all void and delegation must be managed using actual Owner authorisation.
2430
   
2431
   (TPM_Delegate_CreateKeyDelegation must be used to delegate privilege to use a key.)
2432
*/
2433
2434
TPM_RESULT TPM_Process_DelegateCreateOwnerDelegation(tpm_state_t *tpm_state,
2435
                 TPM_STORE_BUFFER *response,
2436
                 TPM_TAG tag,
2437
                 uint32_t paramSize,
2438
                 TPM_COMMAND_CODE ordinal,
2439
                 unsigned char *command,
2440
                 TPM_TRANSPORT_INTERNAL *transportInternal)
2441
0
{
2442
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
2443
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
2444
2445
    /* input parameters */
2446
0
    TPM_BOOL    increment;  /* Flag dictates whether verificationCount will be
2447
             incremented */
2448
0
    TPM_DELEGATE_PUBLIC publicInfo; /* The public parameters for the blob */
2449
0
    TPM_ENCAUTH   delAuth;  /* The encrypted new AuthData for the blob. The encryption
2450
             key is the shared secret from the OSAP protocol.*/
2451
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle TPM Owner authentication
2452
             */
2453
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
2454
0
    TPM_BOOL  continueAuthSession = TRUE; /* Ignored */
2455
0
    TPM_AUTHDATA  ownerAuth;  /* The authorization session digest. HMAC key:ownerAuth */
2456
2457
    /* processing parameters */
2458
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
2459
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
2460
0
    TPM_DIGEST      inParamDigest;
2461
0
    TPM_BOOL      auditStatus = FALSE; /* audit the ordinal */
2462
0
    TPM_BOOL      transportEncrypt = FALSE; /* wrapped in encrypted transport
2463
                   session */
2464
0
    TPM_BOOL      authHandleValid = FALSE;
2465
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
2466
0
    TPM_SECRET      *hmacKey;
2467
0
    TPM_SECRET      savedAuth;    /* saved copy for response */
2468
0
    TPM_FAMILY_TABLE_ENTRY  *familyRow;   /* family table row containing familyID */
2469
0
    TPM_DELEGATE_PUBLIC   *delegatePublic;  /* from DSAP session */
2470
0
    TPM_BOOL      writeAllNV = FALSE;
2471
0
    TPM_DIGEST      a1Auth;
2472
0
    TPM_DELEGATE_SENSITIVE  m1DelegateSensitive;
2473
0
    TPM_STORE_BUFFER    delegateSensitive_sbuffer; /* serialization of delegateSensitive */
2474
0
    TPM_DELEGATE_OWNER_BLOB b1DelegateOwnerBlob;
2475
    
2476
    /* output parameters  */
2477
0
    uint32_t      outParamStart;  /* starting point of outParam's */
2478
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
2479
0
    TPM_DIGEST      outParamDigest;
2480
0
    TPM_STORE_BUFFER    blobSbuffer;  /* The partially encrypted delegation
2481
               information. */
2482
2483
0
    printf("TPM_Process_DelegateCreateOwnerDelegation: Ordinal Entry\n");
2484
0
    TPM_DelegatePublic_Init(&publicInfo);   /* freed @1 */
2485
0
    TPM_DelegateSensitive_Init(&m1DelegateSensitive); /* freed @2 */
2486
0
    TPM_Sbuffer_Init(&delegateSensitive_sbuffer); /* freed @3 */
2487
0
    TPM_DelegateOwnerBlob_Init(&b1DelegateOwnerBlob); /* freed @4 */
2488
0
    TPM_Sbuffer_Init(&blobSbuffer);     /* freed @5 */
2489
    /*
2490
      get inputs
2491
    */
2492
    /* save the starting point of inParam's for authorization and auditing */
2493
0
    inParamStart = command;
2494
    /* get increment parameter */
2495
0
    if (returnCode == TPM_SUCCESS) {
2496
0
  returnCode = TPM_LoadBool(&increment, &command, &paramSize);
2497
0
    }
2498
    /* get publicInfo parameter */
2499
0
    if (returnCode == TPM_SUCCESS) {
2500
0
  printf("TPM_Process_DelegateCreateOwnerDelegation: increment %02x\n", increment);
2501
0
  returnCode = TPM_DelegatePublic_Load(&publicInfo, &command, &paramSize);
2502
0
    }
2503
    /* get delAuth parameter */
2504
0
    if (returnCode == TPM_SUCCESS) {
2505
0
  returnCode = TPM_Authdata_Load(delAuth, &command, &paramSize);
2506
0
    }
2507
    /* save the ending point of inParam's for authorization and auditing */
2508
0
    inParamEnd = command;
2509
    /* digest the input parameters */
2510
0
    if (returnCode == TPM_SUCCESS) {
2511
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
2512
0
            &auditStatus,   /* output */
2513
0
            &transportEncrypt,  /* output */
2514
0
            tpm_state,
2515
0
            tag,
2516
0
            ordinal,
2517
0
            inParamStart,
2518
0
            inParamEnd,
2519
0
            transportInternal);
2520
0
    }
2521
    /* check state */
2522
0
    if (returnCode == TPM_SUCCESS) {
2523
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
2524
0
    }
2525
    /* check tag */
2526
0
    if (returnCode == TPM_SUCCESS) {
2527
0
  returnCode = TPM_CheckRequestTag1(tag);
2528
0
    }
2529
    /* get the 'below the line' authorization parameters */
2530
0
    if (returnCode == TPM_SUCCESS) {
2531
0
  returnCode = TPM_AuthParams_Get(&authHandle,
2532
0
          &authHandleValid,
2533
0
          nonceOdd,
2534
0
          &continueAuthSession,
2535
0
          ownerAuth,
2536
0
          &command, &paramSize);
2537
0
    }
2538
0
    if (returnCode == TPM_SUCCESS) {
2539
0
  if (paramSize != 0) {
2540
0
      printf("TPM_Process_DelegateCreateOwnerDelegation: Error, "
2541
0
       "command has %u extra bytes\n", paramSize);
2542
0
      returnCode = TPM_BAD_PARAM_SIZE;
2543
0
  }
2544
0
    }
2545
    /* do not terminate sessions if the command did not parse correctly */
2546
0
    if (returnCode != TPM_SUCCESS) {
2547
0
  authHandleValid = FALSE;
2548
0
    }
2549
    /*
2550
      Processing
2551
    */
2552
    /* 1. The TPM SHALL authenticate the command using TPM Owner authentication. Return TPM_AUTHFAIL
2553
       on failure. */
2554
0
    if (returnCode == TPM_SUCCESS) {
2555
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
2556
0
                &hmacKey,
2557
0
                tpm_state,
2558
0
                authHandle,
2559
0
                TPM_PID_OSAP,
2560
0
                TPM_ET_OWNER,
2561
0
                ordinal,
2562
0
                NULL,
2563
0
                NULL,         /* OIAP */
2564
0
                tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */
2565
0
    }
2566
0
    if (returnCode == TPM_SUCCESS) {
2567
  /* make a copy of the HMAC key for the response, since it MAY be invalidated */
2568
0
  TPM_Secret_Copy(savedAuth, *hmacKey);
2569
0
  returnCode = TPM_Authdata_Check(tpm_state,
2570
0
          *hmacKey,   /* owner HMAC key */
2571
0
          inParamDigest,
2572
0
          auth_session_data,  /* authorization session */
2573
0
          nonceOdd,   /* Nonce generated by system
2574
                   associated with authHandle */
2575
0
          continueAuthSession,
2576
0
          ownerAuth);   /* Authorization digest for input */
2577
0
    }
2578
    /* 2. Locate publicInfo -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate the
2579
    row return TPM_BADINDEX if not found */
2580
    /* a. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */
2581
0
    if (returnCode == TPM_SUCCESS) {
2582
0
  returnCode = TPM_FamilyTable_GetEntry(&familyRow,
2583
0
                &(tpm_state->tpm_permanent_data.familyTable),
2584
0
                publicInfo.familyID);
2585
0
    }
2586
    /* 3. If the TPM Owner authentication is in fact a delegation, then the TPM SHALL validate the
2587
       command and parameters using Delegation authorisation, then */
2588
0
    if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) {
2589
  /* get the TPM_DELEGATE_PUBLIC from the DSAP session */
2590
0
  if (returnCode == TPM_SUCCESS) {
2591
0
      returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic,
2592
0
                     auth_session_data);
2593
0
  }
2594
  /* a. Validate that authHandle -> familyID equals publicInfo -> familyID return
2595
     TPM_DELEGATE_FAMILY */
2596
0
  if (returnCode == TPM_SUCCESS) {
2597
0
      if (publicInfo.familyID != delegatePublic->familyID) {
2598
0
    printf("TPM_Process_DelegateCreateOwnerDelegation: Error, "
2599
0
           "familyID %u should be %u\n",
2600
0
           publicInfo.familyID, delegatePublic->familyID);
2601
0
    returnCode = TPM_DELEGATE_FAMILY;
2602
0
      }
2603
0
  }
2604
  /* b. If FR -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return error TPM_DISABLED_CMD. */
2605
0
  if (returnCode == TPM_SUCCESS) {
2606
0
      if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) {
2607
0
    printf("TPM_Process_DelegateCreateOwnerDelegation: Error, family %u disabled\n",
2608
0
           publicInfo.familyID);
2609
0
    returnCode = TPM_DISABLED_CMD;
2610
0
      }
2611
0
  }
2612
  /* c. Verify that the delegation bits in publicInfo do not grant more permissions then
2613
     currently delegated.  Otherwise return error TPM_AUTHFAIL */
2614
0
  if (returnCode == TPM_SUCCESS) {
2615
0
      returnCode =
2616
0
    TPM_Delegations_CheckPermissionDelegation(&(publicInfo.permissions),
2617
0
                &(delegatePublic->permissions));
2618
0
  }
2619
0
    }
2620
    /* 4. Check that publicInfo -> delegateType is TPM_DEL_OWNER_BITS */
2621
0
    if (returnCode == TPM_SUCCESS) {
2622
0
  if (publicInfo.permissions.delegateType != TPM_DEL_OWNER_BITS) {
2623
0
      printf("TPM_Process_DelegateCreateOwnerDelegation: Error, bad delegateType %08x\n",
2624
0
       publicInfo.permissions.delegateType);
2625
0
      returnCode = TPM_BAD_PARAMETER;
2626
0
  }
2627
0
    }
2628
    /* 5. Verify that authHandle indicates an OSAP or DSAP session return TPM_INVALID_AUTHHANDLE on
2629
       error */
2630
    /* NOTE Done by TPM_AuthSessions_GetData() */
2631
    /* 7. Create a1 by decrypting delAuth according to the ADIP indicated by authHandle */
2632
    /* NOTE 7. moved before 6. because it needs the session data */
2633
0
    if (returnCode == TPM_SUCCESS) {
2634
0
  returnCode = TPM_AuthSessionData_Decrypt(a1Auth,
2635
0
             NULL,
2636
0
             delAuth,
2637
0
             auth_session_data,
2638
0
             NULL,
2639
0
             NULL,
2640
0
             FALSE);  /* even and odd */
2641
0
    }
2642
    /* 6. If increment == TRUE */
2643
0
    if ((returnCode == TPM_SUCCESS) && increment) {
2644
  /* a. Increment FR -> verificationCount */
2645
0
  familyRow->verificationCount++;
2646
0
  writeAllNV = TRUE;
2647
  /* b. Set TPM_STCLEAR_DATA -> ownerReference to TPM_KH_OWNER */
2648
0
  tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER;
2649
  /* c. The TPM invalidates sessions */
2650
  /* i. MUST invalidate all DSAP sessions */
2651
  /* ii. MUST invalidate all OSAP sessions associated with the delegation table */
2652
  /* iii. MAY invalidate any other session */
2653
0
  TPM_AuthSessions_TerminatexSAP(&continueAuthSession,
2654
0
               authHandle,
2655
0
               tpm_state->tpm_stclear_data.authSessions);
2656
0
    }
2657
    /* 8. Create M1 a TPM_DELEGATE_SENSITIVE structure */
2658
0
    if (returnCode == TPM_SUCCESS) {
2659
0
  printf("TPM_Process_DelegateCreateOwnerDelegation: Creating TPM_DELEGATE_SENSITIVE\n");
2660
  /* a. Set M1 -> tag to TPM_TAG_DELEGATE_SENSITIVE */
2661
  /* NOTE Done by TPM_DelegateSensitive_Init() */
2662
  /* b. Set M1 -> authValue to a1 */
2663
0
  TPM_Secret_Copy(m1DelegateSensitive.authValue, a1Auth);
2664
  /* c. Set other M1 fields as determined by the TPM vendor */
2665
0
    }
2666
    /* 9. Create M2 the encryption of M1 using TPM_DELEGATE_KEY */
2667
    /* serialize M1 */
2668
0
    if (returnCode == TPM_SUCCESS) {
2669
0
  returnCode = TPM_DelegateSensitive_Store(&delegateSensitive_sbuffer, &m1DelegateSensitive);
2670
0
    }
2671
    /* encrypt with delegate key */
2672
0
    if (returnCode == TPM_SUCCESS) {
2673
0
  printf("TPM_Process_DelegateCreateOwnerDelegation: Encrypting TPM_DELEGATE_SENSITIVE\n");
2674
0
  returnCode =
2675
0
      TPM_SymmetricKeyData_EncryptSbuffer(&(b1DelegateOwnerBlob.sensitiveArea),
2676
0
            &delegateSensitive_sbuffer,
2677
0
            tpm_state->tpm_permanent_data.delegateKey);
2678
0
    }
2679
    /* 10. Create B1 a TPM_DELEGATE_OWNER_BLOB */
2680
    /* a. Set B1 -> tag to TPM_TAG_DELG_OWNER_BLOB */
2681
    /* NOTE Done by TPM_DelegateOwnerBlob_Init() */
2682
    /* b. Set B1 -> pub to publicInfo */
2683
0
    if (returnCode == TPM_SUCCESS) {
2684
0
  printf("TPM_Process_DelegateCreateOwnerDelegation: Creating TPM_DELEGATE_OWNER_BLOB\n");
2685
0
  returnCode = TPM_DelegatePublic_Copy(&(b1DelegateOwnerBlob.pub), &publicInfo);
2686
0
    }
2687
    /* c. Set B1 -> sensitiveSize to the size of M2 */
2688
    /* d. Set B1 -> sensitiveArea to M2 */
2689
    /* NOTE Encrypted directly into b1DelegateOwnerBlob */
2690
    /* e. Set B1 -> integrityDigest to NULL */
2691
    /* NOTE Done by TPM_DelegateOwnerBlob_Init() */
2692
0
    if (returnCode == TPM_SUCCESS) {
2693
  /* f. Set B1 pub -> verificationCount to FR -> verificationCount */
2694
0
  b1DelegateOwnerBlob.pub.verificationCount = familyRow->verificationCount;
2695
  /* 11. The TPM sets additionalArea and additionalAreaSize appropriate for this TPM. The
2696
     information MAY include symmetric IV, symmetric mode of encryption and other data that
2697
     allows the TPM to process the blob in the future. */
2698
  /* 12. Create H1 the HMAC of B1 using tpmProof as the secret */
2699
  /* 13. Set B1 -> integrityDigest to H1 */
2700
  /* NOTE It is safe to HMAC directly into TPM_DELEGATE_OWNER_BLOB, since the structure
2701
     is serialized before the HMAC is performed */
2702
0
  returnCode = TPM_HMAC_GenerateStructure
2703
0
         (b1DelegateOwnerBlob.integrityDigest,    /* HMAC */
2704
0
          tpm_state->tpm_permanent_data.tpmProof,   /* HMAC key */
2705
0
          &b1DelegateOwnerBlob,       /* structure */
2706
0
          (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store); /* store function */
2707
0
    }
2708
    /* 14. Ignore continueAuthSession on input set continueAuthSession to FALSE on output */
2709
0
    if (returnCode == TPM_SUCCESS) {
2710
0
  continueAuthSession = FALSE;
2711
0
    }
2712
    /* 15. Return B1 as blob */
2713
0
    if (returnCode == TPM_SUCCESS) {
2714
0
  returnCode = TPM_DelegateOwnerBlob_Store(&blobSbuffer, &b1DelegateOwnerBlob);
2715
0
    }
2716
    /* write back TPM_PERMANENT_DATA if required */
2717
0
    returnCode = TPM_PermanentAll_NVStore(tpm_state,
2718
0
            writeAllNV,
2719
0
            returnCode);
2720
    /*
2721
      response
2722
    */
2723
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
2724
0
    if (rcf == 0) {
2725
0
  printf("TPM_Process_DelegateCreateOwnerDelegation: Ordinal returnCode %08x %u\n",
2726
0
         returnCode, returnCode);
2727
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
2728
0
    }
2729
    /* success response, append the rest of the parameters.  */
2730
0
    if (rcf == 0) {
2731
0
  if (returnCode == TPM_SUCCESS) {
2732
      /* checkpoint the beginning of the outParam's */
2733
0
      outParamStart = response->buffer_current - response->buffer;
2734
      /* return blobSize and blob */
2735
0
      returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &blobSbuffer);
2736
      /* checkpoint the end of the outParam's */
2737
0
      outParamEnd = response->buffer_current - response->buffer;
2738
0
  }
2739
  /* digest the above the line output parameters */
2740
0
  if (returnCode == TPM_SUCCESS) {
2741
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
2742
0
                 auditStatus, /* input audit status */
2743
0
                 transportEncrypt,
2744
0
                 tag,     
2745
0
                 returnCode,
2746
0
                 ordinal,   /* command ordinal */
2747
0
                 response->buffer + outParamStart,  /* start */
2748
0
                 outParamEnd - outParamStart);  /* length */
2749
0
  }
2750
  /* calculate and set the below the line parameters */
2751
0
  if (returnCode == TPM_SUCCESS) {
2752
0
      returnCode = TPM_AuthParams_Set(response,
2753
0
              savedAuth,    /* saved HMAC key */
2754
0
              auth_session_data,
2755
0
              outParamDigest,
2756
0
              nonceOdd,
2757
0
              continueAuthSession);
2758
0
  }
2759
  /* audit if required */
2760
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
2761
0
      returnCode = TPM_ProcessAudit(tpm_state,
2762
0
            transportEncrypt,
2763
0
            inParamDigest,
2764
0
            outParamDigest,
2765
0
            ordinal);
2766
0
  }
2767
  /* adjust the initial response */
2768
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2769
0
    }
2770
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
2771
0
    if (((rcf != 0) ||
2772
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2773
0
   !continueAuthSession) &&
2774
0
  authHandleValid) {
2775
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2776
0
    }
2777
    /*
2778
      cleanup
2779
    */
2780
0
    TPM_DelegatePublic_Delete(&publicInfo);   /* @1 */
2781
0
    TPM_DelegateSensitive_Delete(&m1DelegateSensitive); /* @2 */
2782
0
    TPM_Sbuffer_Delete(&delegateSensitive_sbuffer); /* @3 */
2783
0
    TPM_DelegateOwnerBlob_Delete(&b1DelegateOwnerBlob); /* @4 */
2784
0
    TPM_Sbuffer_Delete(&blobSbuffer);     /* @5 */
2785
0
    return rcf;
2786
0
}
2787
2788
/* 19.4 TPM_Delegate_LoadOwnerDelegation rev 109
2789
   
2790
  This command loads a delegate table row blob into a non-volatile delegate table row.
2791
  Delegate_LoadOwnerDelegation can be used during manufacturing or on first boot (when no Owner is
2792
  installed), or after an Owner is installed. If an Owner is installed, Delegate_LoadOwnerDelegation
2793
  requires Owner authorisation, and sensitive information must be encrypted.
2794
2795
  Burn-out of TPM non-volatile storage by inappropriate use is mitigated by the TPM's normal limits
2796
  on NV- writes in the absence of an Owner. Tables can be locked after loading using
2797
  TPM_Delegate_Manage, to prevent subsequent tampering.
2798
2799
  A management system outside the TPM is expected to manage the delegate table rows stored on the
2800
  TPM, and can overwrite any previously stored data.  There is no way to explicitly delete a
2801
  delegation entry.  A new entry can overwrite an invalid entry.
2802
2803
  This command cannot be used to load key delegation blobs into the TPM
2804
*/
2805
2806
TPM_RESULT TPM_Process_DelegateLoadOwnerDelegation(tpm_state_t *tpm_state,
2807
               TPM_STORE_BUFFER *response,
2808
               TPM_TAG tag,
2809
               uint32_t paramSize,
2810
               TPM_COMMAND_CODE ordinal,
2811
               unsigned char *command,
2812
               TPM_TRANSPORT_INTERNAL *transportInternal)
2813
0
{
2814
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
2815
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
2816
2817
    /* input parameters */
2818
0
    TPM_DELEGATE_INDEX    index;    /* The index of the delegate row to be written */
2819
0
    uint32_t      blobSize; /* The size of the delegate blob */
2820
0
    TPM_DELEGATE_OWNER_BLOB d1Blob;   /* Delegation information, including encrypted
2821
               portions as appropriate */
2822
0
    TPM_AUTHHANDLE    authHandle; /* The authorization session handle TPM Owner
2823
               authentication */
2824
0
    TPM_NONCE     nonceOdd; /* Nonce generated by system associated with
2825
               authHandle */
2826
0
    TPM_BOOL    continueAuthSession = TRUE; /* The continue use flag for the
2827
                 authorization session handle */
2828
0
    TPM_AUTHDATA    ownerAuth;  /* The authorization session digest. HMAC
2829
               key:ownerAuth */
2830
    /* processing parameters */
2831
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
2832
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
2833
0
    TPM_DIGEST      inParamDigest;
2834
0
    TPM_BOOL      auditStatus = FALSE; /* audit the ordinal */
2835
0
    TPM_BOOL      transportEncrypt = FALSE; /* wrapped in encrypted transport
2836
                   session */
2837
0
    TPM_BOOL      authHandleValid = FALSE;
2838
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
2839
0
    TPM_SECRET      *hmacKey;
2840
0
    TPM_SECRET      savedAuth;    /* saved copy for response */
2841
0
    TPM_DELEGATE_PUBLIC   *delegatePublic;  /* from DSAP session */
2842
0
    TPM_FAMILY_TABLE_ENTRY  *familyRow;   /* family table row containing familyID */
2843
0
    TPM_DELEGATE_SENSITIVE  s1DelegateSensitive;
2844
0
    TPM_DELEGATE_TABLE_ROW  *delegateTableRow;
2845
0
    unsigned char   *stream;
2846
0
    uint32_t      stream_size;
2847
0
    uint32_t      nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite;
2848
              /* temp for noOwnerNVWrite, initialize to
2849
                 silence compiler */
2850
0
    TPM_BOOL      nv1Incremented = FALSE; /* flag that nv1 was incremented */
2851
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back data */
2852
2853
    /* output parameters  */
2854
0
    uint32_t      outParamStart;  /* starting point of outParam's */
2855
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
2856
0
    TPM_DIGEST      outParamDigest;
2857
2858
0
    printf("TPM_Process_DelegateLoadOwnerDelegation: Ordinal Entry\n");
2859
0
    TPM_DelegateOwnerBlob_Init(&d1Blob);    /* freed @1 */
2860
0
    TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @2 */
2861
    /*
2862
      get inputs
2863
    */
2864
    /* save the starting point of inParam's for authorization and auditing */
2865
0
    inParamStart = command;
2866
    /* get index parameter */
2867
0
    if (returnCode == TPM_SUCCESS) {
2868
0
  returnCode = TPM_Load32(&index, &command, &paramSize);
2869
0
    }
2870
    /* get blobSize parameter */
2871
0
    if (returnCode == TPM_SUCCESS) {
2872
0
  printf("TPM_Process_DelegateLoadOwnerDelegation: index %u\n", index);
2873
0
  returnCode = TPM_Load32(&blobSize, &command, &paramSize);
2874
0
    }
2875
    /* get blob parameter */
2876
0
    if (returnCode == TPM_SUCCESS) {
2877
0
  returnCode = TPM_DelegateOwnerBlob_Load(&d1Blob, &command, &paramSize);
2878
0
    }
2879
    /* save the ending point of inParam's for authorization and auditing */
2880
0
    inParamEnd = command;
2881
    /* digest the input parameters */
2882
0
    if (returnCode == TPM_SUCCESS) {
2883
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
2884
0
            &auditStatus,   /* output */
2885
0
            &transportEncrypt,  /* output */
2886
0
            tpm_state,
2887
0
            tag,
2888
0
            ordinal,
2889
0
            inParamStart,
2890
0
            inParamEnd,
2891
0
            transportInternal);
2892
0
    }
2893
    /* check state */
2894
0
    if (returnCode == TPM_SUCCESS) {
2895
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
2896
0
    }
2897
    /* check tag */
2898
0
    if (returnCode == TPM_SUCCESS) {
2899
0
  returnCode = TPM_CheckRequestTag10(tag);
2900
0
    }
2901
    /* get the optional 'below the line' authorization parameters */
2902
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2903
0
  returnCode = TPM_AuthParams_Get(&authHandle,
2904
0
          &authHandleValid,
2905
0
          nonceOdd,
2906
0
          &continueAuthSession,
2907
0
          ownerAuth,
2908
0
          &command, &paramSize);
2909
0
    }
2910
0
    if (returnCode == TPM_SUCCESS) {
2911
0
  if (paramSize != 0) {
2912
0
      printf("TPM_Process_DelegateLoadOwnerDelegation: Error, command has %u extra bytes\n",
2913
0
       paramSize);
2914
0
      returnCode = TPM_BAD_PARAM_SIZE;
2915
0
  }
2916
0
    }
2917
    /* do not terminate sessions if the command did not parse correctly */
2918
0
    if (returnCode != TPM_SUCCESS) {
2919
0
  authHandleValid = FALSE;
2920
0
    }
2921
    /*
2922
      Processing
2923
    */
2924
    /* 1. Map blob to D1 a TPM_DELEGATE_OWNER_BLOB. */
2925
    /* a. Validate that D1 -> tag == TPM_TAG_DELEGATE_OWNER_BLOB */
2926
    /* Done by TPM_DelegateOwnerBlob_Load() */
2927
    /* 2. Locate D1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row,
2928
       return TPM_BADINDEX if not found */
2929
    /* 3. Set FR to TPM_FAMILY_TABLE -> famTableRow[familyRow] */
2930
0
    if (returnCode == TPM_SUCCESS) {
2931
0
  returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow,
2932
0
                 &(tpm_state->tpm_permanent_data.familyTable),
2933
0
                 d1Blob.pub.familyID);
2934
0
    }
2935
    /* 4. If TPM Owner is installed */
2936
0
    if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) {
2937
  /* a. Validate the command and parameters using TPM Owner authorization, return
2938
     TPM_AUTHFAIL on error */
2939
0
  if (returnCode == TPM_SUCCESS) {
2940
0
      if (tag != TPM_TAG_RQU_AUTH1_COMMAND) {
2941
0
    printf("TPM_Process_DelegateLoadOwnerDelegation: Error, "
2942
0
           "owner installed but no authorization\n");
2943
0
    returnCode = TPM_AUTHFAIL;
2944
0
      }
2945
0
  }
2946
0
  if (returnCode == TPM_SUCCESS) {
2947
0
      returnCode =
2948
0
    TPM_AuthSessions_GetData(&auth_session_data,
2949
0
           &hmacKey,
2950
0
           tpm_state,
2951
0
           authHandle,
2952
0
           TPM_PID_NONE,
2953
0
           TPM_ET_OWNER,
2954
0
           ordinal,
2955
0
           NULL,
2956
0
           &(tpm_state->tpm_permanent_data.ownerAuth),/* OIAP */
2957
0
           tpm_state->tpm_permanent_data.ownerAuth);  /* OSAP */
2958
0
  }
2959
0
  if (returnCode == TPM_SUCCESS) {
2960
      /* make a copy of the HMAC key for the response, since it MAY be invalidated */
2961
0
      TPM_Secret_Copy(savedAuth, *hmacKey);
2962
0
      returnCode = TPM_Authdata_Check(tpm_state,
2963
0
              *hmacKey,   /* owner HMAC key */
2964
0
              inParamDigest,
2965
0
              auth_session_data,  /* authorization session */
2966
0
              nonceOdd,   /* Nonce generated by system
2967
                   associated with authHandle */
2968
0
              continueAuthSession,
2969
0
              ownerAuth);   /* Authorization digest for input */
2970
0
  }
2971
  /* b. If the command is delegated (authHandle session type is TPM_PID_DSAP or through
2972
     ownerReference delegation), verify that D1 -> pub -> familyID matches authHandle ->
2973
     familyID, on error return TPM_DELEGATE_FAMILY */
2974
0
  if ((returnCode == TPM_SUCCESS) &&
2975
0
      ((auth_session_data->protocolID == TPM_PID_DSAP) ||
2976
0
       (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER))) {
2977
      /* get the TPM_DELEGATE_PUBLIC from the DSAP session */
2978
0
      if (returnCode == TPM_SUCCESS) {
2979
0
    returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic,
2980
0
                   auth_session_data);
2981
0
      }
2982
0
      if (returnCode == TPM_SUCCESS) {
2983
0
    if (d1Blob.pub.familyID != delegatePublic->familyID) {
2984
0
        printf("TPM_Process_DelegateLoadOwnerDelegation: Error, "
2985
0
         "familyID %u should be %u\n",
2986
0
         d1Blob.pub.familyID, delegatePublic->familyID);
2987
0
        returnCode = TPM_DELEGATE_FAMILY;
2988
0
    }
2989
0
      }
2990
0
  }
2991
0
    }
2992
    /* 5. Else */
2993
0
    if ((returnCode == TPM_SUCCESS) && !tpm_state->tpm_permanent_data.ownerInstalled) {
2994
  /* a. If FR -> flags -> TPM_DELEGATE_ADMIN_LOCK is TRUE return TPM_DELEGATE_LOCK */
2995
0
  if (returnCode == TPM_SUCCESS) {
2996
0
      if (familyRow->flags & TPM_DELEGATE_ADMIN_LOCK) {
2997
0
    printf("TPM_Process_DelegateLoadOwnerDelegation: Error, row locked\n");
2998
0
    returnCode = TPM_DELEGATE_LOCK;
2999
0
      }
3000
0
  }
3001
  /* b. Validate max NV writes without an owner */
3002
0
  if (returnCode == TPM_SUCCESS) {
3003
      /* i. Set NV1 to PD -> noOwnerNVWrite */
3004
0
      nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite;
3005
      /* ii. Increment NV1 by 1 */
3006
0
      nv1++;
3007
      /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */
3008
0
      if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) {
3009
0
    printf("TPM_Process_DelegateLoadOwnerDelegation: Error, "
3010
0
           "max NV writes %d w/o owner reached\n",
3011
0
           tpm_state->tpm_permanent_data.noOwnerNVWrite);
3012
0
    returnCode = TPM_MAXNVWRITES;
3013
0
      }
3014
0
  }
3015
  /* iv. Set PD -> noOwnerNVWrite to NV1 */
3016
0
  if (returnCode == TPM_SUCCESS) {
3017
      /* NOTE Don't update the noOwnerNVWrite value until determining that the write will be
3018
         performed */
3019
0
      nv1Incremented = TRUE;
3020
0
  }
3021
0
    }
3022
    /* 6. If FR -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */
3023
    /* NOTE Done by TPM_FamilyTable_GetEnabledEntry() */
3024
    /* 7. If TPM Owner is installed, validate the integrity of the blob */
3025
0
    if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) {
3026
0
  printf("TPM_Process_DelegateLoadOwnerDelegation: Checking integrityDigest\n");
3027
  /* a. Copy D1 -> integrityDigest to H2 */
3028
  /* b. Set D1 -> integrityDigest to NULL */
3029
  /* c. Create H3 the HMAC of D1 using tpmProof as the secret */
3030
  /* d. Compare H2 to H3, return TPM_AUTHFAIL on mismatch */
3031
0
  returnCode = TPM_HMAC_CheckStructure
3032
0
         (tpm_state->tpm_permanent_data.tpmProof,   /* key */
3033
0
          &d1Blob,            /* structure */
3034
0
          d1Blob.integrityDigest,       /* expected */
3035
0
          (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */
3036
0
          TPM_AUTHFAIL);          /* error code */
3037
0
    }
3038
    /* 8. If TPM Owner is installed, create S1 a TPM_DELEGATE_SENSITIVE area by decrypting D1 ->
3039
       sensitiveArea using TPM_DELEGATE_KEY. */
3040
0
    if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) {
3041
0
  if (returnCode == TPM_SUCCESS) {
3042
0
      printf("TPM_Process_DelegateLoadOwnerDelegation: Decrypting sensitiveArea\n");
3043
0
      returnCode =
3044
0
    TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive,  /* decrypted data */
3045
0
                 &(d1Blob.sensitiveArea), /* encrypted */
3046
0
                 tpm_state->tpm_permanent_data.delegateKey);
3047
0
  }
3048
0
    }
3049
    /* 8. Otherwise set S1 = D1 -> sensitiveArea */
3050
0
    if ((returnCode == TPM_SUCCESS) && !tpm_state->tpm_permanent_data.ownerInstalled) {
3051
0
  stream = d1Blob.sensitiveArea.buffer;
3052
0
  stream_size = d1Blob.sensitiveArea.size;
3053
0
  returnCode = TPM_DelegateSensitive_Load(&s1DelegateSensitive, &stream, &stream_size);
3054
0
    }
3055
    /* 9. Validate S1 */
3056
    /* a. Validate that S1 -> tag == TPM_TAG_DELEGATE_SENSITIVE, return TPM_INVALID_STRUCTURE on
3057
       error */
3058
    /* NOTE Done by TPM_DelegateSensitive_Load() */
3059
    /* 10. Validate that index is a valid value for delegateTable, return TPM_BADINDEX on error */
3060
0
    if (returnCode == TPM_SUCCESS) {
3061
0
  returnCode = TPM_DelegateTable_GetRow(&delegateTableRow,
3062
0
                &(tpm_state->tpm_permanent_data.delegateTable),
3063
0
                index);
3064
0
    }
3065
    /* 11. The TPM invalidates sessions */
3066
0
    if (returnCode == TPM_SUCCESS) {
3067
  /* a. MUST invalidate all DSAP sessions */
3068
  /* b. MUST invalidate all OSAP sessions associated with the delegation table */
3069
  /* c. MAY invalidate any other session */
3070
0
  TPM_AuthSessions_TerminatexSAP(&continueAuthSession,
3071
0
               authHandle,
3072
0
               tpm_state->tpm_stclear_data.authSessions);
3073
0
    }
3074
    /* 12. Copy data to the delegate table row */
3075
0
    if (returnCode == TPM_SUCCESS) {
3076
  /* a. Copy the TPM_DELEGATE_PUBLIC from D1 -> pub to TPM_DELEGATE_TABLE -> delRow[index] ->
3077
     pub. */
3078
0
  returnCode = TPM_DelegatePublic_Copy(&delegateTableRow->pub, &(d1Blob.pub));
3079
0
  writeAllNV = TRUE;
3080
0
    }
3081
0
    if (returnCode == TPM_SUCCESS) {
3082
0
  delegateTableRow->valid = TRUE;
3083
  /* b. Copy the TPM_SECRET from S1 -> authValue to TPM_DELEGATE_TABLE -> delRow[index] ->
3084
     authValue. */
3085
0
  TPM_Secret_Copy(delegateTableRow->authValue, s1DelegateSensitive.authValue);
3086
  /* c. Set TPM_STCLEAR_DATA-> ownerReference to TPM_KH_OWNER */
3087
0
  tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER;
3088
0
    }
3089
0
    if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) {
3090
  /* d. If authHandle is of type DSAP then continueAuthSession MUST set to FALSE */
3091
0
  if (auth_session_data->protocolID == TPM_PID_DSAP) {
3092
0
      continueAuthSession = FALSE;
3093
0
  }
3094
0
    }
3095
    /* if writing NV and this is a no owner NV write, update the count with the previously
3096
       incremented value */
3097
0
    if (returnCode == TPM_SUCCESS) {
3098
0
  if (writeAllNV && nv1Incremented) {
3099
0
      printf("TPM_Process_DelegateLoadOwnerDelegation: noOwnerNVWrite %u\n", nv1);
3100
0
      tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1;
3101
0
  }
3102
0
    }
3103
    /* write back TPM_PERMANENT_DATA */
3104
0
    returnCode = TPM_PermanentAll_NVStore(tpm_state,
3105
0
            writeAllNV,
3106
0
            returnCode);
3107
    /*
3108
      response
3109
    */
3110
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3111
0
    if (rcf == 0) {
3112
0
  printf("TPM_Process_DelegateLoadOwnerDelegation: Ordinal returnCode %08x %u\n",
3113
0
         returnCode, returnCode);
3114
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3115
0
    }
3116
    /* success response, append the rest of the parameters.  */
3117
0
    if (rcf == 0) {
3118
0
  if (returnCode == TPM_SUCCESS) {
3119
      /* checkpoint the beginning of the outParam's */
3120
0
      outParamStart = response->buffer_current - response->buffer;
3121
      /* checkpoint the end of the outParam's */
3122
0
      outParamEnd = response->buffer_current - response->buffer;
3123
0
  }
3124
  /* digest the above the line output parameters */
3125
0
  if (returnCode == TPM_SUCCESS) {
3126
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3127
0
                 auditStatus, /* input audit status */
3128
0
                 transportEncrypt,
3129
0
                 tag,     
3130
0
                 returnCode,
3131
0
                 ordinal,   /* command ordinal */
3132
0
                 response->buffer + outParamStart,  /* start */
3133
0
                 outParamEnd - outParamStart);  /* length */
3134
0
  }
3135
  /* calculate and set the below the line parameters */
3136
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3137
0
      returnCode = TPM_AuthParams_Set(response,
3138
0
              savedAuth,    /* saved HMAC key */
3139
0
              auth_session_data,
3140
0
              outParamDigest,
3141
0
              nonceOdd,
3142
0
              continueAuthSession);
3143
0
  }
3144
  /* audit if required */
3145
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3146
0
      returnCode = TPM_ProcessAudit(tpm_state,
3147
0
            transportEncrypt,
3148
0
            inParamDigest,
3149
0
            outParamDigest,
3150
0
            ordinal);
3151
0
  }
3152
  /* adjust the initial response */
3153
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3154
0
    }
3155
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
3156
0
    if (((rcf != 0) ||
3157
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
3158
0
   !continueAuthSession) &&
3159
0
  authHandleValid) {
3160
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
3161
0
    }
3162
    /*
3163
      cleanup
3164
    */
3165
0
    TPM_DelegateOwnerBlob_Delete(&d1Blob);    /* @1 */
3166
0
    TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @2 */
3167
0
    return rcf;
3168
0
}
3169
3170
/* 19.5 TPM_Delegate_ReadTable rev 87
3171
3172
   This command is used to read from the TPM the public contents of the family and delegate tables
3173
   that are stored on the TPM. Such data is required during external verification of tables.
3174
  
3175
   There are no restrictions on the execution of this command; anyone can read this information
3176
   regardless of the state of the PCRs, regardless of whether they know any specific AuthData value
3177
   and regardless of whether or not the enable and admin bits are set one way or the other.
3178
*/
3179
3180
TPM_RESULT TPM_Process_DelegateReadTable(tpm_state_t *tpm_state,
3181
           TPM_STORE_BUFFER *response,
3182
           TPM_TAG tag,
3183
           uint32_t paramSize,
3184
           TPM_COMMAND_CODE ordinal,
3185
           unsigned char *command,
3186
           TPM_TRANSPORT_INTERNAL *transportInternal)
3187
0
{
3188
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3189
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3190
3191
    /* input parameters */
3192
3193
    /* processing parameters */
3194
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3195
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3196
0
    TPM_DIGEST      inParamDigest;
3197
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3198
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3199
3200
    /* output parameters  */
3201
0
    uint32_t      outParamStart;    /* starting point of outParam's */
3202
0
    uint32_t      outParamEnd;    /* ending point of outParam's */
3203
0
    TPM_DIGEST      outParamDigest;
3204
0
    TPM_STORE_BUFFER    familySbuffer;    /* Array of TPM_FAMILY_TABLE_ENTRY
3205
                 elements */
3206
0
    TPM_STORE_BUFFER    delegateSbuffer;  /* Array of TPM_DELEGATE_INDEX and
3207
                 TPM_DELEGATE_PUBLIC elements */
3208
3209
0
    printf("TPM_Process_DelegateReadTable: Ordinal Entry\n");
3210
0
    TPM_Sbuffer_Init(&familySbuffer);   /* freed @1 */
3211
0
    TPM_Sbuffer_Init(&delegateSbuffer);   /* freed @2 */
3212
    /*
3213
      get inputs
3214
    */
3215
    /* save the starting point of inParam's for authorization and auditing */
3216
0
    inParamStart = command;
3217
    /* save the ending point of inParam's for authorization and auditing */
3218
0
    inParamEnd = command;
3219
    /* digest the input parameters */
3220
0
    if (returnCode == TPM_SUCCESS) {
3221
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3222
0
            &auditStatus,   /* output */
3223
0
            &transportEncrypt,  /* output */
3224
0
            tpm_state,
3225
0
            tag,
3226
0
            ordinal,
3227
0
            inParamStart,
3228
0
            inParamEnd,
3229
0
            transportInternal);
3230
0
    }
3231
    /* check state */
3232
0
    if (returnCode == TPM_SUCCESS) {
3233
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
3234
0
    }
3235
    /* check tag */
3236
0
    if (returnCode == TPM_SUCCESS) {
3237
0
  returnCode = TPM_CheckRequestTag0(tag);
3238
0
    }
3239
0
    if (returnCode == TPM_SUCCESS) {
3240
0
  if (paramSize != 0) {
3241
0
      printf("TPM_Process_DelegateReadTable: Error, command has %u extra bytes\n",
3242
0
       paramSize);
3243
0
      returnCode = TPM_BAD_PARAM_SIZE;
3244
0
  }
3245
0
    }
3246
    /*
3247
      Processing
3248
    */
3249
    /* 1. Set familyTableSize to the number of valid families on the TPM times
3250
       sizeof(TPM_FAMILY_TABLE_ELEMENT). */
3251
    /* NOTE Done below by TPM_Sbuffer_AppendAsSizedBuffer() */
3252
    /* 2. Copy the valid entries in the internal family table to the output array familyTable */
3253
0
    if (returnCode == TPM_SUCCESS) {
3254
0
  returnCode = TPM_FamilyTable_StoreValid(&familySbuffer,
3255
0
            &(tpm_state->tpm_permanent_data.familyTable),
3256
0
            TRUE);    /* standard, store the tag */
3257
0
    }
3258
    /* 3. Set delegateTableSize to the number of valid delegate table entries on the TPM times
3259
       (sizeof(TPM_DELEGATE_PUBLIC) + 4). */
3260
    /* NOTE Done below by TPM_Sbuffer_AppendAsSizedBuffer()  */
3261
    /* 4. For each valid entry */
3262
    /* a. Write the TPM_DELEGATE_INDEX to delegateTable */
3263
    /* b. Copy the TPM_DELEGATE_PUBLIC to delegateTable */
3264
0
    if (returnCode == TPM_SUCCESS) {
3265
0
  returnCode = TPM_DelegateTable_StoreValid(&delegateSbuffer,
3266
0
              &(tpm_state->tpm_permanent_data.delegateTable));
3267
0
    }
3268
    /* 5. Return TPM_SUCCESS */
3269
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3270
0
    if (rcf == 0) {
3271
0
  printf("TPM_Process_DelegateReadTable: Ordinal returnCode %08x %u\n",
3272
0
         returnCode, returnCode);
3273
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3274
0
    }
3275
    /* success response, append the rest of the parameters.  */
3276
0
    if (rcf == 0) {
3277
0
  if (returnCode == TPM_SUCCESS) {
3278
      /* checkpoint the beginning of the outParam's */
3279
0
      outParamStart = response->buffer_current - response->buffer;
3280
      /* append familyTableSize and familyTable */
3281
0
      returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &familySbuffer);
3282
0
  }
3283
0
  if (returnCode == TPM_SUCCESS) {
3284
      /* append delegateTableSize and delegateTable */
3285
0
      returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &delegateSbuffer);
3286
      /* checkpoint the end of the outParam's */
3287
0
      outParamEnd = response->buffer_current - response->buffer;
3288
0
  }
3289
  /* digest the above the line output parameters */
3290
0
  if (returnCode == TPM_SUCCESS) {
3291
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3292
0
                 auditStatus, /* input audit status */
3293
0
                 transportEncrypt,
3294
0
                 tag,     
3295
0
                 returnCode,
3296
0
                 ordinal,   /* command ordinal */
3297
0
                 response->buffer + outParamStart,  /* start */
3298
0
                 outParamEnd - outParamStart);  /* length */
3299
0
  }
3300
  /* audit if required */
3301
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3302
0
      returnCode = TPM_ProcessAudit(tpm_state,
3303
0
            transportEncrypt,
3304
0
            inParamDigest,
3305
0
            outParamDigest,
3306
0
            ordinal);
3307
0
  }
3308
  /* adjust the initial response */
3309
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3310
0
    }
3311
    /*
3312
      cleanup
3313
    */
3314
0
    TPM_Sbuffer_Delete(&familySbuffer);   /* @1 */
3315
0
    TPM_Sbuffer_Delete(&delegateSbuffer); /* @2 */
3316
0
    return rcf;
3317
0
}
3318
    
3319
/* 19.6 TPM_Delegate_UpdateVerification rev 87
3320
   
3321
   UpdateVerification sets the verificationCount in an entity (a blob or a delegation row) to the
3322
   current family value, in order that the delegations represented by that entity will continue to
3323
   be accepted by the TPM.
3324
*/
3325
3326
TPM_RESULT TPM_Process_DelegateUpdateVerification(tpm_state_t *tpm_state,
3327
              TPM_STORE_BUFFER *response,
3328
              TPM_TAG tag,
3329
              uint32_t paramSize,
3330
              TPM_COMMAND_CODE ordinal,
3331
              unsigned char *command,
3332
              TPM_TRANSPORT_INTERNAL *transportInternal)
3333
0
{
3334
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3335
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3336
3337
    /* input parameters */
3338
0
    TPM_SIZED_BUFFER  inputData;  /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB or 
3339
             TPM_DELEGATE_INDEX */
3340
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle used for owner
3341
             authentication. */
3342
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
3343
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization
3344
               session handle */
3345
0
    TPM_AUTHDATA  ownerAuth;  /* Authorization HMAC key: ownerAuth. */
3346
3347
    /* processing parameters */
3348
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3349
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3350
0
    TPM_DIGEST      inParamDigest;
3351
0
    TPM_BOOL      auditStatus = FALSE; /* audit the ordinal */
3352
0
    TPM_BOOL      transportEncrypt = FALSE; /* wrapped in encrypted transport
3353
                   session */
3354
0
    TPM_BOOL      authHandleValid = FALSE;
3355
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
3356
0
    TPM_SECRET      *hmacKey = NULL;
3357
0
    unsigned char   *stream;    /* temp input stream */
3358
0
    uint32_t      stream_size;
3359
0
    TPM_STRUCTURE_TAG   d1Tag;      /* input structure tag */
3360
0
    TPM_DELEGATE_INDEX    d1DelegateIndex;
3361
0
    TPM_DELEGATE_OWNER_BLOB d1DelegateOwnerBlob;
3362
0
    TPM_DELEGATE_KEY_BLOB d1DelegateKeyBlob;
3363
0
    TPM_DELEGATE_TABLE_ROW  *d1DelegateTableRow = NULL;
3364
0
    TPM_FAMILY_ID   familyID = 0;
3365
0
    TPM_FAMILY_TABLE_ENTRY  *familyRow;   /* family table row containing familyID */
3366
0
    TPM_DELEGATE_PUBLIC   *delegatePublic;  /* from DSAP session */
3367
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back NV */
3368
3369
    /* output parameters  */
3370
0
    uint32_t      outParamStart;    /* starting point of outParam's */
3371
0
    uint32_t      outParamEnd;    /* ending point of outParam's */
3372
0
    TPM_DIGEST      outParamDigest;
3373
0
    TPM_STORE_BUFFER    outputDataSbuffer;  /* TPM_DELEGATE_KEY_BLOB or
3374
                 TPM_DELEGATE_OWNER_BLOB */
3375
3376
0
    printf("TPM_Process_DelegateUpdateVerification: Ordinal Entry\n");
3377
0
    TPM_SizedBuffer_Init(&inputData);     /* freed @1 */
3378
0
    TPM_DelegateOwnerBlob_Init(&d1DelegateOwnerBlob); /* freed @2 */
3379
0
    TPM_DelegateKeyBlob_Init(&d1DelegateKeyBlob); /* freed @3 */
3380
0
    TPM_Sbuffer_Init(&outputDataSbuffer);   /* freed @4 */
3381
    /*
3382
      get inputs
3383
    */
3384
    /* save the starting point of inParam's for authorization and auditing */
3385
0
    inParamStart = command;
3386
    /* get inputData parameter */
3387
0
    if (returnCode == TPM_SUCCESS) {
3388
0
  returnCode = TPM_SizedBuffer_Load(&inputData, &command, &paramSize);
3389
0
    }
3390
    /* save the ending point of inParam's for authorization and auditing */
3391
0
    inParamEnd = command;
3392
    /* digest the input parameters */
3393
0
    if (returnCode == TPM_SUCCESS) {
3394
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3395
0
            &auditStatus,   /* output */
3396
0
            &transportEncrypt,  /* output */
3397
0
            tpm_state,
3398
0
            tag,
3399
0
            ordinal,
3400
0
            inParamStart,
3401
0
            inParamEnd,
3402
0
            transportInternal);
3403
0
    }
3404
    /* check state */
3405
0
    if (returnCode == TPM_SUCCESS) {
3406
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
3407
0
    }
3408
    /* check tag */
3409
0
    if (returnCode == TPM_SUCCESS) {
3410
0
  returnCode = TPM_CheckRequestTag1(tag);
3411
0
    }
3412
    /* get the 'below the line' authorization parameters */
3413
0
    if (returnCode == TPM_SUCCESS) {
3414
0
  returnCode = TPM_AuthParams_Get(&authHandle,
3415
0
          &authHandleValid,
3416
0
          nonceOdd,
3417
0
          &continueAuthSession,
3418
0
          ownerAuth,
3419
0
          &command, &paramSize);
3420
0
    }
3421
0
    if (returnCode == TPM_SUCCESS) {
3422
0
  if (paramSize != 0) {
3423
0
      printf("TPM_Process_DelegateUpdateVerification: Error, command has %u extra bytes\n",
3424
0
       paramSize);
3425
0
      returnCode = TPM_BAD_PARAM_SIZE;
3426
0
  }
3427
0
    }
3428
    /* do not terminate sessions if the command did not parse correctly */
3429
0
    if (returnCode != TPM_SUCCESS) {
3430
0
  authHandleValid = FALSE;
3431
0
    }
3432
    /*
3433
      Processing
3434
    */
3435
    /* 1. Verify the TPM Owner, directly or indirectly through delegation, authorizes the command
3436
       and parameters, on error return TPM_AUTHFAIL */
3437
0
    if (returnCode == TPM_SUCCESS) {
3438
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
3439
0
                &hmacKey,
3440
0
                tpm_state,
3441
0
                authHandle,
3442
0
                TPM_PID_NONE,
3443
0
                TPM_ET_OWNER,
3444
0
                ordinal,
3445
0
                NULL,
3446
0
                &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
3447
0
                tpm_state->tpm_permanent_data.ownerAuth);   /* OSAP */
3448
0
    }
3449
0
    if (returnCode == TPM_SUCCESS) {
3450
0
  returnCode = TPM_Authdata_Check(tpm_state,
3451
0
          *hmacKey,   /* owner HMAC key */
3452
0
          inParamDigest,
3453
0
          auth_session_data,  /* authorization session */
3454
0
          nonceOdd,   /* Nonce generated by system
3455
                   associated with authHandle */
3456
0
          continueAuthSession,
3457
0
          ownerAuth);   /* Authorization digest for input */
3458
0
    }
3459
    /* 2. Determine the type of inputData (TPM_DELEGATE_TABLE_ROW or TPM_DELEGATE_OWNER_BLOB
3460
       or TPM_DELEGATE_KEY_BLOB) and map D1 to that structure */
3461
0
    if (returnCode == TPM_SUCCESS) {
3462
  /* use a temporary copy so the original values are not moved */
3463
0
  stream = inputData.buffer;
3464
0
  stream_size = inputData.size;
3465
  /* the inputData is either a table index or a blob */
3466
0
  if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) {
3467
      /* if it's an index, get the index */
3468
0
      returnCode = TPM_Load32(&d1DelegateIndex, &stream, &stream_size); 
3469
0
  }
3470
0
  else {
3471
      /* if it's a blob, get the blob structure tag to determine the blob type */
3472
0
      returnCode = TPM_Load16(&d1Tag, &stream, &stream_size);
3473
0
  }
3474
0
    }
3475
0
    if (returnCode == TPM_SUCCESS) {
3476
  /* use a temporary copy so the original values are not moved */
3477
0
  stream = inputData.buffer;
3478
0
  stream_size = inputData.size;
3479
  /* if inputData is a table index */
3480
0
  if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) {
3481
      /* a. Mapping to TPM_DELEGATE_TABLE_ROW requires taking inputData as a tableIndex and
3482
         locating the appropriate row in the table */
3483
0
      returnCode =
3484
0
    TPM_DelegateTable_GetValidRow(&d1DelegateTableRow,
3485
0
                &(tpm_state->tpm_permanent_data.delegateTable),
3486
0
                d1DelegateIndex);
3487
0
      familyID = d1DelegateTableRow->pub.familyID;
3488
0
  }
3489
  /* if inputData is a blob */
3490
0
  else {
3491
0
      switch (d1Tag) {
3492
0
        case TPM_TAG_DELEGATE_OWNER_BLOB:
3493
0
    returnCode = TPM_DelegateOwnerBlob_Load(&d1DelegateOwnerBlob,
3494
0
              &stream, &stream_size);
3495
0
    familyID = d1DelegateOwnerBlob.pub.familyID;
3496
0
    break;
3497
0
        case TPM_TAG_DELG_KEY_BLOB:
3498
0
    returnCode = TPM_DelegateKeyBlob_Load(&d1DelegateKeyBlob,
3499
0
                  &stream, &stream_size);
3500
0
    familyID = d1DelegateKeyBlob.pub.familyID;
3501
0
    break;
3502
0
        default:
3503
0
    printf("TPM_Process_DelegateUpdateVerification: Error, invalid tag %04hx\n", d1Tag);
3504
0
    returnCode = TPM_BAD_PARAMETER;
3505
0
    break;
3506
0
      }
3507
0
  }
3508
0
    }
3509
    /* 3. If D1 is TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB Validate the integrity of
3510
       D1 */
3511
0
    if ((returnCode == TPM_SUCCESS) && (inputData.size != sizeof(TPM_DELEGATE_INDEX))) {
3512
  /* a. Copy D1 -> integrityDigest to H2 */
3513
  /* b. Set D1 -> integrityDigest to NULL */
3514
  /* c. Create H3 the HMAC of D1 using tpmProof as the secret */
3515
  /* d. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */
3516
0
  switch (d1Tag) {
3517
0
    case TPM_TAG_DELEGATE_OWNER_BLOB:
3518
0
      returnCode = TPM_HMAC_CheckStructure
3519
0
       (tpm_state->tpm_permanent_data.tpmProof,   /* key */
3520
0
        &d1DelegateOwnerBlob,         /* structure */
3521
0
        d1DelegateOwnerBlob.integrityDigest,      /* expected */
3522
0
        (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store,  /* store function */
3523
0
        TPM_AUTHFAIL);          /* error code */
3524
0
      break;
3525
0
    case TPM_TAG_DELG_KEY_BLOB:
3526
0
      returnCode = TPM_HMAC_CheckStructure
3527
0
       (tpm_state->tpm_permanent_data.tpmProof,   /* key */
3528
0
        &d1DelegateKeyBlob,         /* structure */
3529
0
        d1DelegateKeyBlob.integrityDigest,      /* expected */
3530
0
        (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store,  /* store function */
3531
0
        TPM_AUTHFAIL);          /* error code */
3532
0
      break;
3533
      /* default error tested above */
3534
0
  }
3535
0
    }
3536
    /* 4. Locate (D1 -> pub -> familyID) in the TPM_FAMILY_TABLE and set familyRow to indicate row,
3537
       return TPM_BADINDEX if not found */
3538
    /* 5. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */
3539
0
    if (returnCode == TPM_SUCCESS) {
3540
0
  returnCode = TPM_FamilyTable_GetEntry(&familyRow,
3541
0
                &(tpm_state->tpm_permanent_data.familyTable),
3542
0
                familyID);
3543
0
    }
3544
0
    if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) {
3545
  /* get the TPM_DELEGATE_PUBLIC from the DSAP session */
3546
0
  if (returnCode == TPM_SUCCESS) {
3547
0
      returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic,
3548
0
                     auth_session_data);
3549
0
  }
3550
  /* 6. If delegated, verify that family of the delegated Owner-auth is the same as D1:
3551
     (authHandle -> familyID) == (D1 -> pub -> familyID); otherwise return error
3552
     TPM_DELEGATE_FAMILY */
3553
0
  if (returnCode == TPM_SUCCESS) {
3554
0
      if (familyID != delegatePublic->familyID) {
3555
0
    printf("TPM_Process_DelegateUpdateVerification: Error, "
3556
0
           "familyID %u should be %u\n",
3557
0
           familyID, delegatePublic->familyID);
3558
0
    returnCode = TPM_DELEGATE_FAMILY;
3559
0
      }
3560
0
  }
3561
  /* 7. If delegated, verify that the family of the delegated Owner-auth is enabled: if
3562
     (authHandle -> familyID -> flags TPM_FAMFLAG_ENABLED) is FALSE, return
3563
     TPM_DISABLED_CMD */
3564
0
  if (returnCode == TPM_SUCCESS) {
3565
0
      if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) {
3566
0
    printf("TPM_Process_DelegateUpdateVerification: Error, family %u disabled\n",
3567
0
           familyID);
3568
0
    returnCode = TPM_DISABLED_CMD;
3569
0
      }
3570
0
  }
3571
0
    }
3572
    /* 8. Set D1 -> verificationCount to FR -> verificationCount */
3573
0
    if (returnCode == TPM_SUCCESS) {
3574
0
  if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) {
3575
0
      d1DelegateTableRow->pub.verificationCount = familyRow->verificationCount;
3576
0
      writeAllNV = TRUE;
3577
0
  }
3578
0
  else {
3579
0
      switch (d1Tag) {
3580
0
        case TPM_TAG_DELEGATE_OWNER_BLOB:
3581
0
    d1DelegateOwnerBlob.pub.verificationCount = familyRow->verificationCount;
3582
0
    break;
3583
0
        case TPM_TAG_DELG_KEY_BLOB:
3584
0
    d1DelegateKeyBlob.pub.verificationCount = familyRow->verificationCount;
3585
0
    break;
3586
    /* default error tested above */
3587
0
      }
3588
0
  }
3589
0
    }
3590
    /* 9. If D1 is TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB set the integrity of D1 */
3591
0
    if ((returnCode == TPM_SUCCESS) && (inputData.size != sizeof(TPM_DELEGATE_INDEX))) {
3592
  /* a. Set D1 -> integrityDigest to NULL */
3593
  /* NOTE Done by TPM_HMAC_GenerateStructure() */
3594
  /* b. Create H1 the HMAC of D1 using tpmProof as the secret */
3595
  /* c. Set D1 -> integrityDigest to H1 */
3596
  /* NOTE It is safe to HMAC directly into the blob, since the structure is serialized before
3597
     the HMAC is performed */
3598
0
  switch (d1Tag) {
3599
0
    case TPM_TAG_DELEGATE_OWNER_BLOB:
3600
0
      returnCode = TPM_HMAC_GenerateStructure
3601
0
       (d1DelegateOwnerBlob.integrityDigest,    /* HMAC */
3602
0
        tpm_state->tpm_permanent_data.tpmProof,   /* HMAC key */
3603
0
        &d1DelegateOwnerBlob,       /* structure */
3604
0
        (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store); /* store function */
3605
0
      break;
3606
0
    case TPM_TAG_DELG_KEY_BLOB:
3607
0
      returnCode = TPM_HMAC_GenerateStructure
3608
0
       (d1DelegateKeyBlob.integrityDigest,    /* HMAC */
3609
0
        tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */
3610
0
        &d1DelegateKeyBlob,       /* structure */
3611
0
        (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store); /* store function */
3612
0
      break;
3613
0
  }
3614
0
    }
3615
    /* If updating a delegate row, write back TPM_PERMANENT_DATA */
3616
0
    if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) {
3617
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
3618
0
                writeAllNV,
3619
0
                returnCode);
3620
0
    }
3621
    /* 10. If D1 is a blob recreate the blob and return it */
3622
0
    else {
3623
0
  if (returnCode == TPM_SUCCESS) {
3624
0
      switch (d1Tag) {
3625
0
        case TPM_TAG_DELEGATE_OWNER_BLOB:
3626
0
    returnCode = TPM_DelegateOwnerBlob_Store(&outputDataSbuffer,
3627
0
               &d1DelegateOwnerBlob);
3628
0
    break;
3629
0
        case TPM_TAG_DELG_KEY_BLOB:
3630
0
    returnCode = TPM_DelegateKeyBlob_Store(&outputDataSbuffer,
3631
0
                   &d1DelegateKeyBlob);
3632
0
    break;
3633
    /* default error tested above */
3634
0
      }
3635
0
  }
3636
0
    }
3637
    /*
3638
      response
3639
    */
3640
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3641
0
    if (rcf == 0) {
3642
0
  printf("TPM_Process_DelegateUpdateVerification: Ordinal returnCode %08x %u\n",
3643
0
         returnCode, returnCode);
3644
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3645
0
    }
3646
    /* success response, append the rest of the parameters.  */
3647
0
    if (rcf == 0) {
3648
0
  if (returnCode == TPM_SUCCESS) {
3649
      /* checkpoint the beginning of the outParam's */
3650
0
      outParamStart = response->buffer_current - response->buffer;
3651
      /* return outputSize and outputData */
3652
0
      returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &outputDataSbuffer);
3653
      /* checkpoint the end of the outParam's */
3654
0
      outParamEnd = response->buffer_current - response->buffer;
3655
0
  }
3656
  /* digest the above the line output parameters */
3657
0
  if (returnCode == TPM_SUCCESS) {
3658
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3659
0
                 auditStatus, /* input audit status */
3660
0
                 transportEncrypt,
3661
0
                 tag,     
3662
0
                 returnCode,
3663
0
                 ordinal,   /* command ordinal */
3664
0
                 response->buffer + outParamStart,  /* start */
3665
0
                 outParamEnd - outParamStart);  /* length */
3666
0
  }
3667
  /* calculate and set the below the line parameters */
3668
0
  if (returnCode == TPM_SUCCESS) {
3669
0
      returnCode = TPM_AuthParams_Set(response,
3670
0
              *hmacKey,   /* HMAC key */
3671
0
              auth_session_data,
3672
0
              outParamDigest,
3673
0
              nonceOdd,
3674
0
              continueAuthSession);
3675
0
  }
3676
  /* audit if required */
3677
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3678
0
      returnCode = TPM_ProcessAudit(tpm_state,
3679
0
            transportEncrypt,
3680
0
            inParamDigest,
3681
0
            outParamDigest,
3682
0
            ordinal);
3683
0
  }
3684
  /* adjust the initial response */
3685
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3686
0
    }
3687
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
3688
0
    if (((rcf != 0) ||
3689
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
3690
0
   !continueAuthSession) &&
3691
0
  authHandleValid) {
3692
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
3693
0
    }
3694
    /*
3695
      cleanup
3696
    */
3697
0
    TPM_SizedBuffer_Delete(&inputData);     /* @1 */
3698
0
    TPM_DelegateOwnerBlob_Delete(&d1DelegateOwnerBlob); /* @2 */
3699
0
    TPM_DelegateKeyBlob_Delete(&d1DelegateKeyBlob); /* @3 */
3700
0
    TPM_Sbuffer_Delete(&outputDataSbuffer);   /* @4 */
3701
0
    return rcf;
3702
0
}
3703
3704
/* 19.7 TPM_Delegate_VerifyDelegation rev 105
3705
3706
   VerifyDelegation interprets a delegate blob and returns success or failure, depending on whether
3707
   the blob is currently valid. The delegate blob is NOT loaded into the TPM.
3708
*/
3709
3710
TPM_RESULT TPM_Process_DelegateVerifyDelegation(tpm_state_t *tpm_state,
3711
            TPM_STORE_BUFFER *response,
3712
            TPM_TAG tag,
3713
            uint32_t paramSize,
3714
            TPM_COMMAND_CODE ordinal,
3715
            unsigned char *command,
3716
            TPM_TRANSPORT_INTERNAL *transportInternal)
3717
0
{
3718
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
3719
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
3720
3721
    /* input parameters */
3722
0
    TPM_SIZED_BUFFER  delegation; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB */
3723
3724
    /* processing parameters */
3725
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
3726
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
3727
0
    TPM_DIGEST      inParamDigest;
3728
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
3729
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
3730
0
    unsigned char   *stream;    /* temp input stream */
3731
0
    uint32_t      stream_size;
3732
0
    TPM_STRUCTURE_TAG   d1Tag;      /* input structure tag */
3733
0
    TPM_DELEGATE_OWNER_BLOB d1DelegateOwnerBlob;
3734
0
    TPM_DELEGATE_KEY_BLOB d1DelegateKeyBlob;
3735
0
    TPM_FAMILY_TABLE_ENTRY  *familyRow;   /* family table row containing familyID */
3736
0
    TPM_FAMILY_ID   familyID;
3737
0
    TPM_FAMILY_VERIFICATION verificationCount = 0;
3738
0
    TPM_DELEGATE_SENSITIVE  s1DelegateSensitive;
3739
    
3740
    /* output parameters  */
3741
0
    uint32_t      outParamStart;    /* starting point of outParam's */
3742
0
    uint32_t      outParamEnd;    /* ending point of outParam's */
3743
0
    TPM_DIGEST      outParamDigest;
3744
3745
0
    printf("TPM_Process_DelegateVerifyDelegation: Ordinal Entry\n");
3746
0
    TPM_SizedBuffer_Init(&delegation);      /* freed @1 */
3747
0
    TPM_DelegateOwnerBlob_Init(&d1DelegateOwnerBlob); /* freed @2 */
3748
0
    TPM_DelegateKeyBlob_Init(&d1DelegateKeyBlob); /* freed @3 */
3749
0
    TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @4 */
3750
    /*
3751
      get inputs
3752
    */
3753
    /* save the starting point of inParam's for authorization and auditing */
3754
0
    inParamStart = command;
3755
    /* get delegation parameter */
3756
0
    if (returnCode == TPM_SUCCESS) {
3757
0
  returnCode = TPM_SizedBuffer_Load(&delegation, &command, &paramSize);
3758
0
    }
3759
    /* save the ending point of inParam's for authorization and auditing */
3760
0
    inParamEnd = command;
3761
    /* digest the input parameters */
3762
0
    if (returnCode == TPM_SUCCESS) {
3763
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
3764
0
            &auditStatus,   /* output */
3765
0
            &transportEncrypt,  /* output */
3766
0
            tpm_state,
3767
0
            tag,
3768
0
            ordinal,
3769
0
            inParamStart,
3770
0
            inParamEnd,
3771
0
            transportInternal);
3772
0
    }
3773
    /* check state */
3774
0
    if (returnCode == TPM_SUCCESS) {
3775
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
3776
0
    }
3777
    /* check tag */
3778
0
    if (returnCode == TPM_SUCCESS) {
3779
0
  returnCode = TPM_CheckRequestTag0(tag);
3780
0
    }
3781
0
    if (returnCode == TPM_SUCCESS) {
3782
0
  if (paramSize != 0) {
3783
0
      printf("TPM_Process_DelegateVerifyDelegation: Error, command has %u extra bytes\n",
3784
0
       paramSize);
3785
0
      returnCode = TPM_BAD_PARAM_SIZE;
3786
0
  }
3787
0
    }
3788
    /*
3789
      Processing
3790
    */
3791
    /* 1. Determine the type of blob */
3792
0
    if (returnCode == TPM_SUCCESS) {
3793
  /* use a temporary copy so the original values are not moved */
3794
0
  stream = delegation.buffer;
3795
0
  stream_size = delegation.size;
3796
0
  returnCode = TPM_Load16(&d1Tag, &stream, &stream_size); 
3797
0
    }
3798
0
    if (returnCode == TPM_SUCCESS) {
3799
  /* use a temporary copy so the original values are not moved */
3800
0
  stream = delegation.buffer;
3801
0
  stream_size = delegation.size;
3802
0
  switch (d1Tag) {
3803
      /* 1. If delegation -> tag is equal to TPM_TAG_DELEGATE_OWNER_BLOB then */
3804
0
    case TPM_TAG_DELEGATE_OWNER_BLOB:
3805
      /* a. Map D1 a TPM_DELEGATE_BLOB_OWNER to delegation */
3806
0
      if (returnCode == TPM_SUCCESS) {
3807
0
    returnCode = TPM_DelegateOwnerBlob_Load(&d1DelegateOwnerBlob,
3808
0
              &stream, &stream_size);
3809
0
      }
3810
0
      if (returnCode == TPM_SUCCESS) {
3811
0
    familyID = d1DelegateOwnerBlob.pub.familyID;
3812
0
    verificationCount = d1DelegateOwnerBlob.pub.verificationCount;
3813
0
      }
3814
0
      break;
3815
      /* 2. Else if delegation -> tag = TPM_TAG_DELG_KEY_BLOB */
3816
0
    case TPM_TAG_DELG_KEY_BLOB:
3817
      /* a. Map D1 a TPM_DELEGATE_KEY_BLOB to delegation */
3818
0
      if (returnCode == TPM_SUCCESS) {
3819
0
    returnCode = TPM_DelegateKeyBlob_Load(&d1DelegateKeyBlob, &stream, &stream_size);
3820
0
      }
3821
0
      if (returnCode == TPM_SUCCESS) {
3822
0
    familyID = d1DelegateKeyBlob.pub.familyID;
3823
0
    verificationCount = d1DelegateKeyBlob.pub.verificationCount;
3824
0
      }
3825
0
      break;
3826
      /* 3. Else return TPM_BAD_PARAMETER */
3827
0
    default:
3828
0
      printf("TPM_Process_DelegateVerifyDelegation: Error, invalid tag %04hx\n", d1Tag);
3829
0
      returnCode = TPM_BAD_PARAMETER;
3830
0
      break;
3831
0
  }
3832
0
    }
3833
    /* 4. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return
3834
       TPM_BADINDEX if not found */
3835
    /* 5. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */
3836
    /* 6. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */
3837
0
    if (returnCode == TPM_SUCCESS) {
3838
0
  returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow,
3839
0
                 &(tpm_state->tpm_permanent_data.familyTable),
3840
0
                 familyID);
3841
0
    }
3842
    /* 7. Validate that D1 -> pub -> verificationCount matches FR -> verificationCount, on mismatch
3843
       return TPM_FAMILYCOUNT */
3844
0
    if (returnCode == TPM_SUCCESS) {
3845
0
  if (verificationCount != familyRow->verificationCount) {
3846
0
      printf("TPM_Process_DelegateVerifyDelegation: Error, "
3847
0
       "verificationCount mismatch %u %u\n",
3848
0
       verificationCount, familyRow->verificationCount);
3849
0
      returnCode = TPM_FAMILYCOUNT;
3850
0
  }
3851
0
    }
3852
    /* 8. Validate the integrity of D1 */
3853
    /* a. Copy D1 -> integrityDigest to H2 */
3854
    /* b. Set D1 -> integrityDigest to NULL */
3855
    /* c. Create H3 the HMAC of D1 using tpmProof as the secret */
3856
    /* d. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */
3857
0
    if (returnCode == TPM_SUCCESS) {
3858
0
  if (d1Tag == TPM_TAG_DELEGATE_OWNER_BLOB) {
3859
0
      returnCode = TPM_HMAC_CheckStructure
3860
0
       (tpm_state->tpm_permanent_data.tpmProof,   /* key */
3861
0
        &d1DelegateOwnerBlob,         /* structure */
3862
0
        d1DelegateOwnerBlob.integrityDigest,      /* expected */
3863
0
        (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store,  /* store function */
3864
0
        TPM_AUTHFAIL);          /* error code */
3865
0
  }
3866
0
  else {
3867
0
      returnCode = TPM_HMAC_CheckStructure
3868
0
       (tpm_state->tpm_permanent_data.tpmProof,   /* key */
3869
0
        &d1DelegateKeyBlob,         /* structure */
3870
0
        d1DelegateKeyBlob.integrityDigest,      /* expected */
3871
0
        (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store,  /* store function */
3872
0
        TPM_AUTHFAIL);          /* error code */
3873
0
  }
3874
0
    }
3875
    /* 9. Create S1 a TPM_DELEGATE_SENSITIVE area by decrypting D1 -> sensitiveArea using
3876
       TPM_DELEGATE_KEY */
3877
0
    if (returnCode == TPM_SUCCESS) {
3878
0
  printf("TPM_Process_DelegateVerifyDelegation: Decrypting sensitiveArea\n");
3879
0
  if (d1Tag == TPM_TAG_DELEGATE_OWNER_BLOB) {
3880
0
      returnCode =
3881
0
    TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, 
3882
0
                 &(d1DelegateOwnerBlob.sensitiveArea),
3883
0
                 tpm_state->tpm_permanent_data.delegateKey);
3884
0
  }
3885
0
  else {
3886
0
      returnCode =
3887
0
    TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, 
3888
0
                 &(d1DelegateKeyBlob.sensitiveArea),
3889
0
                 tpm_state->tpm_permanent_data.delegateKey);
3890
0
  }
3891
0
    }
3892
    /* 10. Validate S1 values */
3893
    /* a. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */
3894
    /* NOTE Done by TPM_DelegateSensitive_DecryptEncData() */
3895
    /* b. Return TPM_BAD_PARAMETER on error */
3896
    /* 11. Return TPM_SUCCESS */
3897
    /*
3898
      response
3899
    */
3900
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
3901
0
    if (rcf == 0) {
3902
0
  printf("TPM_Process_DelegateVerifyDelegation: Ordinal returnCode %08x %u\n",
3903
0
         returnCode, returnCode);
3904
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3905
0
    }
3906
    /* success response, append the rest of the parameters.  */
3907
0
    if (rcf == 0) {
3908
0
  if (returnCode == TPM_SUCCESS) {
3909
      /* checkpoint the beginning of the outParam's */
3910
0
      outParamStart = response->buffer_current - response->buffer;
3911
      /* checkpoint the end of the outParam's */
3912
0
      outParamEnd = response->buffer_current - response->buffer;
3913
0
  }
3914
  /* digest the above the line output parameters */
3915
0
  if (returnCode == TPM_SUCCESS) {
3916
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
3917
0
                 auditStatus, /* input audit status */
3918
0
                 transportEncrypt,
3919
0
                 tag,     
3920
0
                 returnCode,
3921
0
                 ordinal,   /* command ordinal */
3922
0
                 response->buffer + outParamStart,  /* start */
3923
0
                 outParamEnd - outParamStart);  /* length */
3924
0
  }
3925
  /* audit if required */
3926
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
3927
0
      returnCode = TPM_ProcessAudit(tpm_state,
3928
0
            transportEncrypt,
3929
0
            inParamDigest,
3930
0
            outParamDigest,
3931
0
            ordinal);
3932
0
  }
3933
  /* adjust the initial response */
3934
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3935
0
    }
3936
    /*
3937
      cleanup
3938
    */
3939
0
    TPM_SizedBuffer_Delete(&delegation);    /* @1 */
3940
0
    TPM_DelegateOwnerBlob_Delete(&d1DelegateOwnerBlob); /* @2 */
3941
0
    TPM_DelegateKeyBlob_Delete(&d1DelegateKeyBlob); /* @3 */
3942
0
    TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @4 */
3943
0
    return rcf;
3944
0
}