Coverage Report

Created: 2025-07-11 06:08

/src/libtpms/src/tpm12/tpm_audit.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*        Audit Handler         */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*        $Id: tpm_audit.c 4438 2011-02-13 23:03:56Z 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 <string.h>
42
43
#include "tpm_auth.h"
44
#include "tpm_counter.h"
45
#include "tpm_cryptoh.h"
46
#include "tpm_debug.h"
47
#include "tpm_digest.h"
48
#include "tpm_error.h"
49
#include "tpm_global.h"
50
#include "tpm_key.h"
51
#include "tpm_nonce.h"
52
#include "tpm_permanent.h"
53
#include "tpm_process.h"
54
55
#include "tpm_audit.h"
56
57
/*
58
  TPM_AUDIT_EVENT_IN 
59
*/
60
61
/* TPM_AuditEventIn_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_AuditEventIn_Init(TPM_AUDIT_EVENT_IN *tpm_audit_event_in)
69
0
{
70
0
    printf(" TPM_AuditEventIn_Init:\n");
71
0
    TPM_Digest_Init(tpm_audit_event_in->inputParms);
72
0
    TPM_CounterValue_Init(&(tpm_audit_event_in->auditCount));
73
0
    return;
74
0
}
75
76
/* TPM_AuditEventIn_Store()
77
   
78
   serialize the structure to a stream contained in 'sbuffer'
79
   returns 0 or error codes
80
*/
81
82
TPM_RESULT TPM_AuditEventIn_Store(TPM_STORE_BUFFER *sbuffer,
83
          const TPM_AUDIT_EVENT_IN *tpm_audit_event_in)
84
0
{
85
0
    TPM_RESULT    rc = 0;
86
87
0
    printf(" TPM_AuditEventIn_Store:\n");
88
    /* store tag */
89
0
    if (rc == 0) {
90
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_AUDIT_EVENT_IN); 
91
0
    }
92
    /* store inputParms */
93
0
    if (rc == 0) {
94
0
  rc = TPM_Digest_Store(sbuffer, tpm_audit_event_in->inputParms);
95
0
    }
96
    /* store auditCount */
97
0
    if (rc == 0) {
98
0
  rc = TPM_CounterValue_StorePublic(sbuffer, &(tpm_audit_event_in->auditCount));
99
0
    }
100
0
    return rc;
101
0
}
102
103
/* TPM_AuditEventIn_Delete()
104
105
   No-OP if the parameter is NULL, else:
106
   frees memory allocated for the object
107
   sets pointers to NULL
108
   calls TPM_AuditEventIn_Init to set members back to default values
109
   The object itself is not freed
110
*/   
111
112
void TPM_AuditEventIn_Delete(TPM_AUDIT_EVENT_IN *tpm_audit_event_in)
113
0
{
114
0
    printf(" TPM_AuditEventIn_Delete:\n");
115
0
    if (tpm_audit_event_in != NULL) {
116
0
  TPM_AuditEventIn_Init(tpm_audit_event_in);
117
0
    }
118
0
    return;
119
0
}
120
121
/*
122
  TPM_AUDIT_EVENT_OUT
123
*/
124
125
/* TPM_AuditEventOut_Init()
126
127
   sets members to default values
128
   sets all pointers to NULL and sizes to 0
129
   always succeeds - no return code
130
*/
131
132
void TPM_AuditEventOut_Init(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out)
133
0
{
134
0
    printf(" TPM_AuditEventOut_Init:\n");
135
0
    TPM_Digest_Init(tpm_audit_event_out->outputParms);
136
0
    TPM_CounterValue_Init(&(tpm_audit_event_out->auditCount));
137
0
    return;
138
0
}
139
140
/* TPM_AuditEventOut_Store()
141
   
142
   serialize the structure to a stream contained in 'sbuffer'
143
   returns 0 or error codes
144
*/
145
146
TPM_RESULT TPM_AuditEventOut_Store(TPM_STORE_BUFFER *sbuffer,
147
          const TPM_AUDIT_EVENT_OUT *tpm_audit_event_out)
148
0
{
149
0
    TPM_RESULT    rc = 0;
150
151
0
    printf(" TPM_AuditEventOut_Store:\n");
152
    /* store tag */
153
0
    if (rc == 0) {
154
0
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_AUDIT_EVENT_OUT); 
155
0
    }
156
    /* store outputParms */
157
0
    if (rc == 0) {
158
0
  rc = TPM_Digest_Store(sbuffer, tpm_audit_event_out->outputParms);
159
0
    }
160
    /* store auditCount */
161
0
    if (rc == 0) {
162
0
  rc = TPM_CounterValue_StorePublic(sbuffer, &(tpm_audit_event_out->auditCount));
163
0
    }
164
0
    return rc;
165
0
}
166
167
/* TPM_AuditEventOut_Delete()
168
169
   No-OP if the parameter is NULL, else:
170
   frees memory allocated for the object
171
   sets pointers to NULL
172
   calls TPM_AuditEventOut_Init to set members back to default values
173
   The object itself is not freed
174
*/   
175
176
void TPM_AuditEventOut_Delete(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out)
177
0
{
178
0
    printf(" TPM_AuditEventOut_Delete:\n");
179
0
    if (tpm_audit_event_out != NULL) {
180
0
  TPM_AuditEventOut_Init(tpm_audit_event_out);
181
0
    }
182
0
    return;
183
0
}
184
185
/*
186
  ordinalAuditStatus Processing
187
*/
188
189
/* TPM_OrdinalAuditStatus_Init() initializes the TPM_PERMANENT_DATA 'ordinalAuditStatus' to the
190
   default
191
192
   The flags are stored as a bit map to conserve NVRAM.
193
194
   The array is not written back to NVRAM.
195
*/
196
197
TPM_RESULT TPM_OrdinalAuditStatus_Init(TPM_PERMANENT_DATA *tpm_permanent_data)
198
0
{
199
0
    TPM_RESULT    rc = 0;
200
0
    TPM_COMMAND_CODE  ord;    /* iterate through all ordinals */
201
0
    TPM_BOOL    auditDefault; /* result for an ordinal */
202
0
    TPM_BOOL    altered;
203
    
204
0
    printf(" TPM_OrdinalAuditStatus_Init:\n");
205
206
0
    for (ord = 0 ; (rc == 0) && (ord < TPM_ORDINALS_MAX) ; ord++) {
207
  /* get the default audit state from the ordinals table */
208
0
  TPM_OrdinalTable_GetAuditDefault(&auditDefault, ord);
209
  /* write to the TPM_PERMANENT_DATA bit map */
210
0
  rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, ord);
211
0
    }
212
    /* hack for TSC ordinals */
213
0
    if (rc == 0) {
214
0
  TPM_OrdinalTable_GetAuditDefault(&auditDefault, TSC_ORD_PhysicalPresence);
215
0
  rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault,
216
0
               TSC_ORD_PhysicalPresence);
217
0
    }
218
0
    if (rc == 0) {
219
0
  TPM_OrdinalTable_GetAuditDefault(&auditDefault, TSC_ORD_ResetEstablishmentBit);
220
0
  rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault,
221
0
               TSC_ORD_ResetEstablishmentBit);
222
0
    }
223
0
    return rc;
224
0
}
225
226
/* TPM_OrdinalAuditStatus_Store() stores a list of all ordinals being audited
227
 */
228
229
TPM_RESULT TPM_OrdinalAuditStatus_Store(TPM_SIZED_BUFFER *ordinalList,
230
          TPM_PERMANENT_DATA *tpm_permanent_data,
231
          TPM_COMMAND_CODE startOrdinal)
232
0
{
233
0
    TPM_RESULT    rc = 0;
234
0
    TPM_STORE_BUFFER  sbuffer;
235
0
    TPM_COMMAND_CODE  ord;
236
0
    TPM_BOOL    auditStatus;
237
    
238
0
    printf(" TPM_OrdinalAuditStatus_Store\n");
239
0
    TPM_Sbuffer_Init(&sbuffer);     /* freed @1 */  
240
    /* scan through the ordinals array */
241
0
    for (ord = startOrdinal ; (rc == 0) && (ord < TPM_ORDINALS_MAX) ; ord++ ) {
242
  /* determine if the ordinal being audited */
243
0
  if (rc == 0) {
244
0
      rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, ord, tpm_permanent_data);
245
0
  }
246
  /* if being audited */
247
0
  if ((rc == 0) && auditStatus) {
248
0
      rc = TPM_Sbuffer_Append32(&sbuffer, ord); /* append ordinal to the list */
249
0
  }
250
0
    }
251
    /* scan the TSC ordinals */
252
0
    if (rc == 0) {
253
0
  if (rc == 0) {
254
0
      rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus,
255
0
                   TSC_ORD_PhysicalPresence,
256
0
                   tpm_permanent_data);
257
0
  }
258
0
  if ((rc == 0) && auditStatus) {
259
0
      rc = TPM_Sbuffer_Append32(&sbuffer, TSC_ORD_PhysicalPresence);
260
0
  }
261
0
  if (rc == 0) {
262
0
      rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus,
263
0
                   TSC_ORD_ResetEstablishmentBit,
264
0
                   tpm_permanent_data);
265
0
  }
266
  /* if being audited */
267
0
  if ((rc == 0) && auditStatus) {
268
0
      rc = TPM_Sbuffer_Append32(&sbuffer, TSC_ORD_ResetEstablishmentBit);
269
0
  }
270
0
    }
271
    /* convert the list to a TPM_SIZED_BUFFER */
272
0
    if (rc == 0) {
273
0
  rc = TPM_SizedBuffer_SetFromStore(ordinalList, &sbuffer);
274
0
    }
275
0
    TPM_Sbuffer_Delete(&sbuffer); /* @1 */
276
0
    return rc;
277
0
}
278
279
/* TPM_OrdinalAuditStatus_GetAuditState() gets the audit state for the ordinal
280
 */
281
282
TPM_RESULT TPM_OrdinalAuditStatus_GetAuditStatus(TPM_BOOL *auditStatus,
283
             TPM_COMMAND_CODE ordinal,
284
             TPM_PERMANENT_DATA *tpm_permanent_data)
285
0
{
286
0
    TPM_RESULT    rc = 0;
287
0
    size_t    index;    /* index of ordinal in array */
288
0
    unsigned int  offset;   /* bit position of ordinal in array */
289
0
    unsigned char bit;  
290
291
0
    if (rc == 0) {
292
  /* handle the TPM ordinals */
293
0
  if (ordinal < TPM_ORDINALS_MAX) {
294
0
      index = ordinal/CHAR_BIT;
295
0
      offset = ordinal % CHAR_BIT;
296
0
      bit = 0x01 << offset;
297
0
      *auditStatus = tpm_permanent_data->ordinalAuditStatus[index] & bit;
298
0
  }
299
  /* handle the TSC ordinals */
300
0
  else if (ordinal == TSC_ORD_PhysicalPresence) {
301
0
      *auditStatus = tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT;
302
0
  }
303
0
  else if (ordinal == TSC_ORD_ResetEstablishmentBit) {
304
0
      *auditStatus = tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT;
305
0
  }
306
0
  else {
307
0
      printf("TPM_OrdinalAuditStatus_GetAuditStatus: Error (fatal) "
308
0
       "ordinal %08x out of range\n", ordinal);
309
0
      rc = TPM_FAIL; /* should never occur, always called with ordinal processing */
310
0
  }
311
0
    }
312
    /* trace the ordinals with auditing enabled */
313
0
    if ((rc == 0) && *auditStatus) {
314
0
  printf("  TPM_OrdinalAuditStatus_GetAuditStatus: ordinal %08x status %02x\n",
315
0
         ordinal, *auditStatus);
316
0
    }
317
0
    return rc;
318
0
}
319
320
/* TPM_OrdinalAuditStatus_SetAuditStatus() sets the TPM_PERMANENT_DATA -> ordinalAuditStatus for the
321
   ordinal
322
323
   The flags are stored as a bit map to conserve NVRAM.
324
325
   The array is not written back to NVRAM.  On error, TPM_PERMANENT_DATA is not changed.
326
327
   altered is TRUE if the bit was changed, 
328
*/
329
330
TPM_RESULT TPM_OrdinalAuditStatus_SetAuditStatus(TPM_BOOL *altered,
331
             TPM_PERMANENT_DATA *tpm_permanent_data,
332
             TPM_BOOL auditStatus,
333
             TPM_COMMAND_CODE ordinal)
334
0
{
335
0
    TPM_RESULT    rc = 0;
336
0
    TPM_BOOL    auditable;  /* TRUE if the ordinal is auditable by this TPM
337
             implementation */
338
0
    size_t    index;    /* index of ordinal in array */
339
0
    unsigned int  offset;   /* bit position of ordinal in array */
340
0
    unsigned char bit;
341
342
0
    *altered = FALSE;     /* default, returned on error */
343
#if 0
344
    printf(" TPM_OrdinalAuditStatus_SetAuditStatus: ordinal %08x status %02x\n",
345
     ordinal, auditStatus);
346
#endif
347
    /* If trying to set, screen against the 'never audit' ordinal table */
348
0
    if ((rc == 0) && auditStatus) {
349
0
  TPM_OrdinalTable_GetAuditable(&auditable, ordinal);
350
  /* if it is a 'never audit' ordinal, it can not be set */
351
0
  if (!auditable) {
352
0
      printf("TPM_OrdinalAuditStatus_SetAuditStatus: "
353
0
       "Error, cannot audit ordinal %08x\n", ordinal);
354
0
      rc = TPM_BAD_PARAMETER;
355
0
  }
356
0
    }
357
0
    if (rc == 0) {
358
  /* handle the TPM ordinals */
359
0
  if (ordinal < TPM_ORDINALS_MAX) {
360
0
      index = ordinal/CHAR_BIT;
361
0
      offset = ordinal % CHAR_BIT;
362
0
      bit = 0x01 << offset;
363
      /* determine if the bit is to be altered */
364
0
      if (((tpm_permanent_data->ordinalAuditStatus[index] & bit) && !auditStatus) ||
365
0
    (!(tpm_permanent_data->ordinalAuditStatus[index] & bit) && auditStatus)) {
366
367
0
    *altered = TRUE;
368
0
      }
369
0
      if (auditStatus) {
370
    /* set the bit */
371
0
    tpm_permanent_data->ordinalAuditStatus[index] |= bit;
372
0
      }
373
0
      else {
374
    /* clear the bit */
375
0
    tpm_permanent_data->ordinalAuditStatus[index] &= ~bit;
376
0
      }
377
0
  }
378
  /* handle the TSC ordinals */
379
0
  else if (ordinal == TSC_ORD_PhysicalPresence) {
380
      /* determine if the bit is to be altered */
381
0
      if (((tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT)
382
0
     && !auditStatus) ||
383
0
    (!(tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT)
384
0
     && auditStatus)) {
385
386
0
    *altered = TRUE;
387
0
      }
388
0
      if (auditStatus) {
389
0
    tpm_permanent_data->tscOrdinalAuditStatus |= TSC_PHYS_PRES_AUDIT;
390
0
      }
391
0
      else {
392
0
    tpm_permanent_data->tscOrdinalAuditStatus &= ~TSC_PHYS_PRES_AUDIT;
393
0
      }
394
0
  }
395
0
  else if (ordinal == TSC_ORD_ResetEstablishmentBit) {
396
0
      if (auditStatus) {
397
    /* determine if the bit is to be altered */
398
0
    if (((tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT)
399
0
         && !auditStatus) ||
400
0
        (!(tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT)
401
0
         && auditStatus)) {
402
403
0
        *altered = TRUE;
404
0
    }
405
0
    tpm_permanent_data->tscOrdinalAuditStatus |= TSC_RESET_ESTAB_AUDIT;
406
0
      }
407
0
      else {
408
0
    tpm_permanent_data->tscOrdinalAuditStatus &= ~TSC_RESET_ESTAB_AUDIT;
409
0
      }
410
0
  }
411
0
  else {
412
0
      printf("TPM_OrdinalAuditStatus_SetAuditStatus: Error ordinal %08x out of range\n",
413
0
       ordinal);
414
0
      rc = TPM_BADINDEX;
415
0
  }
416
0
    }
417
0
    return rc;
418
0
}
419
420
/*
421
  Common Processing Functions
422
*/
423
424
/* 8.1 Audit Generation rev 109
425
426
   TPM_AuditDigest_ExtendIn() extends the audit digest with a digest of input parameters
427
*/
428
429
TPM_RESULT TPM_AuditDigest_ExtendIn(tpm_state_t *tpm_state,
430
            TPM_DIGEST inParamDigest)
431
0
{
432
0
    TPM_RESULT    rc = 0;
433
0
    TPM_AUDIT_EVENT_IN  tpm_audit_event_in;
434
0
    TPM_STORE_BUFFER  eventIn_sbuffer;
435
0
    const unsigned char *eventIn_buffer;  /* serialized buffer */
436
0
    uint32_t    eventIn_length;   /* serialization length */
437
    
438
0
    printf(" TPM_AuditDigest_ExtendIn:\n");
439
0
    TPM_AuditEventIn_Init(&tpm_audit_event_in);   /* freed @1 */
440
0
    TPM_Sbuffer_Init(&eventIn_sbuffer);     /* freed @2 */
441
442
0
    if (rc == 0) {
443
  /* b. Create A1 a TPM_AUDIT_EVENT_IN structure */
444
  /* NOTE Done by TPM_AuditEventIn_Init() */
445
  /* i. Set A1 -> inputParms to the digest of the input parameters from the command */
446
  /* (1) Digest value according to the HMAC digest rules of the "above the line" parameters
447
     (i.e. the first HMAC digest calculation). */
448
0
  TPM_Digest_Copy(tpm_audit_event_in.inputParms, inParamDigest);
449
  /* ii. Set A1 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */
450
0
  TPM_CounterValue_CopyPublic(&(tpm_audit_event_in.auditCount),
451
0
            &(tpm_state->tpm_permanent_data.auditMonotonicCounter));
452
  /* serialize the A1 TPM_AUDIT_EVENT_IN object */
453
0
  rc = TPM_AuditEventIn_Store(&eventIn_sbuffer, &tpm_audit_event_in);
454
455
0
    }
456
0
    if (rc == 0) {
457
  /* get the serialization results */
458
0
  TPM_Sbuffer_Get(&eventIn_sbuffer, &eventIn_buffer, &eventIn_length);
459
  /* c. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A1) */
460
0
  TPM_PrintFour("  TPM_AuditDigest_ExtendIn: Previous digest",
461
0
          tpm_state->tpm_stclear_data.auditDigest);
462
0
  TPM_PrintAll("  TPM_AuditDigest_ExtendIn: TPM_AUDIT_EVENT_IN", eventIn_buffer, eventIn_length);
463
0
  rc = TPM_SHA1(tpm_state->tpm_stclear_data.auditDigest,
464
0
          TPM_DIGEST_SIZE, tpm_state->tpm_stclear_data.auditDigest,
465
0
          eventIn_length, eventIn_buffer,
466
0
          0, NULL);
467
0
  TPM_PrintFour("  TPM_AuditDigest_ExtendIn: Current digest (in)",
468
0
          tpm_state->tpm_stclear_data.auditDigest);
469
0
    }
470
0
    TPM_AuditEventIn_Delete(&tpm_audit_event_in); /* @1 */
471
0
    TPM_Sbuffer_Delete(&eventIn_sbuffer);   /* @2 */
472
0
    return rc;
473
0
}
474
475
/* 8.1 Audit Generation rev 109
476
477
   TPM_AuditDigest_ExtendOut() extends the audit digest with a digest of output parameters
478
*/
479
480
TPM_RESULT TPM_AuditDigest_ExtendOut(tpm_state_t *tpm_state,
481
             TPM_DIGEST outParamDigest)
482
0
{
483
0
    TPM_RESULT    rc = 0;
484
0
    TPM_AUDIT_EVENT_OUT tpm_audit_event_out;
485
0
    TPM_STORE_BUFFER  eventOut_sbuffer;
486
0
    const unsigned char *eventOut_buffer; /* serialized buffer */
487
0
    uint32_t    eventOut_length;  /* serialization length */
488
    
489
0
    printf(" TPM_AuditDigest_ExtendOut:\n");
490
0
    TPM_AuditEventOut_Init(&tpm_audit_event_out); /* freed @1 */
491
0
    TPM_Sbuffer_Init(&eventOut_sbuffer);    /* freed @2 */
492
493
0
    if (rc == 0) {
494
  /* d. Create A2 a TPM_AUDIT_EVENT_OUT structure */
495
  /* NOTE Done by TPM_AuditEventOut_Init() */
496
  /* i. Set A2 -> outputParms to the digest of the output parameters from the command */
497
  /* (1). Digest value according to the HMAC digest rules of the "above the line" parameters
498
     (i.e. the first HMAC digest calculation). */
499
0
  TPM_Digest_Copy(tpm_audit_event_out.outputParms, outParamDigest);
500
  /* ii. Set A2 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */
501
0
  TPM_CounterValue_CopyPublic(&(tpm_audit_event_out.auditCount),
502
0
            &(tpm_state->tpm_permanent_data.auditMonotonicCounter));
503
  /* serialize the A2 TPM_AUDIT_EVENT_OUT object */
504
0
  rc = TPM_AuditEventOut_Store(&eventOut_sbuffer, &tpm_audit_event_out);
505
0
    }
506
0
    if (rc == 0) {
507
  /* get the serialization results */
508
0
  TPM_Sbuffer_Get(&eventOut_sbuffer, &eventOut_buffer, &eventOut_length);
509
  /* e. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A2) */
510
0
  TPM_PrintFour("  TPM_AuditDigest_ExtendOut: Previous digest",
511
0
          tpm_state->tpm_stclear_data.auditDigest);
512
0
  TPM_PrintAll("  TPM_AuditDigest_ExtendOut: TPM_AUDIT_EVENT_OUT", eventOut_buffer, eventOut_length);
513
0
  rc = TPM_SHA1(tpm_state->tpm_stclear_data.auditDigest,
514
0
          TPM_DIGEST_SIZE, tpm_state->tpm_stclear_data.auditDigest,
515
0
          eventOut_length, eventOut_buffer,
516
0
          0, NULL);
517
0
  TPM_PrintFour("  TPM_AuditDigest_ExtendOut: Current digest (out)",
518
0
          tpm_state->tpm_stclear_data.auditDigest);
519
0
    }
520
0
    TPM_AuditEventOut_Delete(&tpm_audit_event_out); /* @1 */
521
0
    TPM_Sbuffer_Delete(&eventOut_sbuffer);    /* @2 */
522
0
    return rc;
523
0
}
524
525
/*
526
  Processing Functions
527
*/
528
529
/* The TPM generates an audit event in response to the TPM executing a command that has the audit
530
   flag set to TRUE for that command.
531
532
   The TPM maintains an extended value for all audited operations.
533
*/
534
535
/* 8.3 TPM_GetAuditDigest rev 87
536
537
   This returns the current audit digest. The external audit log has the responsibility to track the
538
   parameters that constitute the audit digest.
539
540
   This value may be unique to an individual TPM.  The value however will be changing at a rate set
541
   by the TPM Owner. Those attempting to use this value may find it changing without their
542
   knowledge.  This value represents a very poor source of tracking uniqueness.
543
*/
544
545
TPM_RESULT TPM_Process_GetAuditDigest(tpm_state_t *tpm_state,
546
              TPM_STORE_BUFFER *response,
547
              TPM_TAG tag,
548
              uint32_t paramSize,
549
              TPM_COMMAND_CODE ordinal,
550
              unsigned char *command,
551
              TPM_TRANSPORT_INTERNAL *transportInternal)
552
0
{
553
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
554
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
555
556
    /* input parameters */
557
0
    uint32_t  startOrdinal; /* The starting ordinal for the list of audited ordinals */
558
559
    /* processing parameters */
560
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
561
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
562
0
    TPM_DIGEST      inParamDigest;
563
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
564
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
565
566
    /* output parameters */
567
0
    uint32_t    outParamStart;  /* starting point of outParam's */
568
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
569
0
    TPM_DIGEST    outParamDigest;
570
0
    TPM_DIGEST    auditDigest;  /* Log of all audited events */
571
0
    TPM_BOOL    more;   /* TRUE if the output does not contain a full list of
572
             audited ordinals */
573
0
    TPM_SIZED_BUFFER  ordList;  /* List of ordinals that are audited. */
574
575
0
    printf("TPM_Process_GetAuditDigest: Ordinal Entry\n");
576
0
    TPM_SizedBuffer_Init(&ordList); /* freed @1 */
577
    /*
578
      get inputs
579
    */
580
    /* save the starting point of inParam's for authorization and auditing */
581
0
    inParamStart = command;
582
    /* get startOrdinal parameter */
583
0
    if (returnCode == TPM_SUCCESS) {
584
0
  returnCode = TPM_Load32(&startOrdinal, &command, &paramSize);
585
0
    }
586
0
    if (returnCode == TPM_SUCCESS) {
587
0
  printf("TPM_Process_GetAuditDigest: startOrdinal %08x\n", startOrdinal);
588
0
    }
589
    /* save the ending point of inParam's for authorization and auditing */
590
0
    inParamEnd = command;
591
    /* digest the input parameters */
592
0
    if (returnCode == TPM_SUCCESS) {
593
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
594
0
            &auditStatus,   /* output */
595
0
            &transportEncrypt,  /* output */
596
0
            tpm_state,
597
0
            tag,
598
0
            ordinal,
599
0
            inParamStart,
600
0
            inParamEnd,
601
0
            transportInternal);
602
0
    }
603
    /* check state */
604
0
    if (returnCode == TPM_SUCCESS) {
605
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
606
0
    }
607
    /* check tag */
608
0
    if (returnCode == TPM_SUCCESS) {
609
0
  returnCode = TPM_CheckRequestTag0(tag);
610
0
    }
611
0
    if (returnCode == TPM_SUCCESS) {
612
0
  if (paramSize != 0) {
613
0
      printf("TPM_Process_GetAuditDigest: Error, command has %u extra bytes\n",
614
0
       paramSize);
615
0
      returnCode = TPM_BAD_PARAM_SIZE;
616
0
  }
617
0
    }
618
    /*
619
      Processing
620
    */
621
0
    if (returnCode == TPM_SUCCESS) {
622
  /* 1. The TPM sets auditDigest to TPM_STANY_DATA -> auditDigest */
623
0
  TPM_Digest_Copy(auditDigest, tpm_state->tpm_stclear_data.auditDigest);
624
  /* 2. The TPM sets counterValue to TPM_PERMANENT_DATA -> auditMonotonicCounter */
625
  /* NOTE Since there is only one, use it directly on the output */
626
0
  printf("TPM_Process_GetAuditDigest: Counter value %08x\n",
627
0
         tpm_state->tpm_permanent_data.auditMonotonicCounter.counter);
628
  /* 3. The TPM creates an ordered list of audited ordinals. The list starts at startOrdinal
629
     listing each ordinal that is audited. */
630
  /* a. If startOrdinal is 0 then the first ordinal that could be audited would be TPM_OIAP
631
     (ordinal 0x0000000A) */
632
  /* b. The next ordinal would be TPM_OSAP (ordinal 0x0000000B) */
633
0
  returnCode = TPM_OrdinalAuditStatus_Store(&ordList,
634
0
              &(tpm_state->tpm_permanent_data),
635
0
              startOrdinal);
636
0
    }
637
0
    if (returnCode == TPM_SUCCESS) {
638
0
  printf("TPM_Process_GetAuditDigest: ordSize %u\n", ordList.size);
639
  /* 4. If the ordered list does not fit in the output buffer the TPM sets more to TRUE */
640
0
  more = FALSE;
641
0
    }
642
    /*
643
      response
644
    */
645
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
646
0
    if (rcf == 0) {
647
0
  printf("TPM_Process_GetAuditDigest: Ordinal returnCode %08x %u\n",
648
0
         returnCode, returnCode);
649
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
650
0
    }
651
    /* success response, append the rest of the parameters.  */
652
0
    if (rcf == 0) {
653
  /* append counterValue */
654
0
  if (returnCode == TPM_SUCCESS) {
655
      /* checkpoint the beginning of the outParam's */
656
0
      outParamStart = response->buffer_current - response->buffer;
657
      /* append counterValue */
658
0
      returnCode = TPM_CounterValue_StorePublic
659
0
       (response,
660
0
        &(tpm_state->tpm_permanent_data.auditMonotonicCounter));
661
0
  }
662
  /* 5. Return TPM_STANY_DATA -> auditDigest as auditDigest */
663
0
  if (returnCode == TPM_SUCCESS) {
664
0
      returnCode = TPM_Digest_Store(response, auditDigest);
665
0
  }
666
  /* append more */
667
0
  if (returnCode == TPM_SUCCESS) {
668
0
      returnCode = TPM_Sbuffer_Append(response, &more, sizeof(TPM_BOOL));
669
0
  }
670
  /* append ordList */
671
0
  if (returnCode == TPM_SUCCESS) {
672
0
      returnCode = TPM_SizedBuffer_Store(response, &ordList);
673
      /* checkpoint the end of the outParam's */
674
0
      outParamEnd = response->buffer_current - response->buffer;
675
0
  }
676
  /* digest the above the line output parameters */
677
0
  if (returnCode == TPM_SUCCESS) {
678
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
679
0
                 auditStatus, /* input audit status */
680
0
                 transportEncrypt,
681
0
                 tag,     
682
0
                 returnCode,
683
0
                 ordinal,   /* command ordinal */
684
0
                 response->buffer + outParamStart,  /* start */
685
0
                 outParamEnd - outParamStart);  /* length */
686
0
  }
687
  /* audit if required */
688
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
689
0
      returnCode = TPM_ProcessAudit(tpm_state,
690
0
            transportEncrypt,
691
0
            inParamDigest,
692
0
            outParamDigest,
693
0
            ordinal);
694
0
  }
695
  /* adjust the initial response */
696
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
697
0
    }
698
    /*
699
      cleanup
700
    */
701
0
    TPM_SizedBuffer_Delete(&ordList); /* @1 */
702
0
    return rcf;
703
0
}
704
705
/* 8.4  TPM_GetAuditDigestSigned rev 101
706
707
   The signing of the audit log returns the entire digest value and the list of currently audited
708
   commands.
709
710
   The inclusion of the list of audited commands as an atomic operation is to tie the current digest
711
   value with the list of commands that are being audited.
712
713
   Note to future architects
714
715
   When auditing functionality is active in a TPM, it may seem logical to remove this ordinal from
716
   the active set of ordinals as the signing functionality of this command could be handled in a
717
   signed transport session. While true this command has a secondary affect also, resetting the
718
   audit log digest. As the reset requires TPM Owner authentication there must be some way in this
719
   command to reflect the TPM Owner wishes. By requiring that a TPM Identity key be the only key
720
   that can sign and reset the TPM Owners authentication is implicit in the execution of the command
721
   (TPM Identity Keys are created and controlled by the TPM Owner only). Hence while one might want
722
   to remove an ordinal this is not one that can be removed if auditing is functional.
723
*/
724
725
TPM_RESULT TPM_Process_GetAuditDigestSigned(tpm_state_t *tpm_state,
726
              TPM_STORE_BUFFER *response,
727
              TPM_TAG tag,
728
              uint32_t paramSize,
729
              TPM_COMMAND_CODE ordinal,
730
              unsigned char *command,
731
              TPM_TRANSPORT_INTERNAL *transportInternal)
732
0
{
733
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
734
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
735
736
    /* input parameters */
737
0
    TPM_KEY_HANDLE  keyHandle;  /* The handle of a loaded key that can perform digital
738
             signatures. */
739
0
    TPM_BOOL    closeAudit; /* Indication if audit session should be closed */
740
0
    TPM_NONCE   antiReplay; /* A nonce to prevent replay attacks */
741
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle used for key
742
             authentication. */
743
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
744
0
    TPM_BOOL  continueAuthSession;  /* The continue use flag for the authorization session
745
             handle */
746
0
    TPM_AUTHDATA  keyAuth;  /* Authorization. HMAC key: key.usageAuth. */
747
748
    /* processing parameters */
749
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
750
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
751
0
    TPM_DIGEST      inParamDigest;
752
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
753
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
754
0
    TPM_BOOL      authHandleValid = FALSE;
755
0
    TPM_SECRET      *hmacKey;
756
0
    TPM_KEY     *sigKey = NULL;     /* the key specified by keyHandle */
757
0
    TPM_SECRET      *keyUsageAuth;
758
0
    TPM_BOOL      parentPCRStatus;
759
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
760
0
    TPM_SIGN_INFO   d1SignInfo;
761
0
    TPM_SIZED_BUFFER    d3SizedBuffer;  /* List of ordinals that are audited. */
762
0
    TPM_STORE_BUFFER    d2Sbuffer;  /* data to be signed */
763
0
    TPM_DIGEST      h1;
764
    
765
    /* output parameters */
766
0
    uint32_t      outParamStart;  /* starting point of outParam's */
767
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
768
0
    TPM_DIGEST      outParamDigest;
769
0
    TPM_DIGEST      ordinalDigest;  /* Digest of all audited ordinals */
770
0
    TPM_SIZED_BUFFER    sig;    /* The signature of the area */
771
772
0
    printf("TPM_Process_GetAuditDigestSigned: Ordinal Entry\n");
773
0
    TPM_SignInfo_Init(&d1SignInfo);   /* freed @1 */
774
0
    TPM_SizedBuffer_Init(&d3SizedBuffer); /* freed @2 */
775
0
    TPM_Sbuffer_Init(&d2Sbuffer);   /* freed @3 */
776
0
    TPM_SizedBuffer_Init(&sig);     /* freed @4 */
777
    /*
778
      get inputs
779
    */
780
    /* get keyHandle parameter */
781
0
    if (returnCode == TPM_SUCCESS) {
782
0
  returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
783
0
    }
784
    /* save the starting point of inParam's for authorization and auditing */
785
0
    inParamStart = command;
786
    /* get closeAudit parameter */
787
0
    if (returnCode == TPM_SUCCESS) {
788
0
  printf("TPM_Process_GetAuditDigestSigned: keyHandle %08x\n", keyHandle);
789
0
  returnCode = TPM_LoadBool(&closeAudit, &command, &paramSize);
790
0
    }
791
    /* get antiReplay parameter */
792
0
    if (returnCode == TPM_SUCCESS) {
793
0
  returnCode = TPM_Digest_Load(antiReplay, &command, &paramSize);
794
0
    }
795
    /* save the ending point of inParam's for authorization and auditing */
796
0
    inParamEnd = command;
797
    /* digest the input parameters */
798
0
    if (returnCode == TPM_SUCCESS) {
799
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
800
0
            &auditStatus,   /* output */
801
0
            &transportEncrypt,  /* output */
802
0
            tpm_state,
803
0
            tag,
804
0
            ordinal,
805
0
            inParamStart,
806
0
            inParamEnd,
807
0
            transportInternal);
808
0
    }
809
    /* check state */
810
0
    if (returnCode == TPM_SUCCESS) {
811
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
812
0
    }
813
    /* check tag */
814
0
    if (returnCode == TPM_SUCCESS) {
815
0
  returnCode = TPM_CheckRequestTag10(tag);
816
0
    }
817
    /* get the optional 'below the line' authorization parameters */
818
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
819
0
  returnCode = TPM_AuthParams_Get(&authHandle,
820
0
          &authHandleValid,
821
0
          nonceOdd,
822
0
          &continueAuthSession,
823
0
          keyAuth,
824
0
          &command, &paramSize);
825
0
    }
826
0
    if (returnCode == TPM_SUCCESS) {
827
0
  if (paramSize != 0) {
828
0
      printf("TPM_Process_GetAuditDigestSigned: Error, command has %u extra bytes\n",
829
0
       paramSize);
830
0
      returnCode = TPM_BAD_PARAM_SIZE;
831
0
  }
832
0
    }
833
    /* do not terminate sessions if the command did not parse correctly */
834
0
    if (returnCode != TPM_SUCCESS) {
835
0
  authHandleValid = FALSE;
836
0
    }
837
    /*
838
      Processing
839
    */
840
    /* 1. Validate the AuthData and parameters using keyAuth, return TPM_AUTHFAIL on error */
841
    /* get the key corresponding to the keyHandle parameter */
842
0
    if (returnCode == TPM_SUCCESS) {
843
0
  returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle,
844
0
             FALSE,   /* not read-only */
845
0
             FALSE,   /* do not ignore PCRs */
846
0
             FALSE);  /* cannot use EK */
847
0
    }
848
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){
849
0
  if (sigKey->authDataUsage != TPM_AUTH_NEVER) {
850
0
      printf("TPM_Process_GetAuditDigestSigned: Error, authorization required\n");
851
0
      returnCode = TPM_AUTHFAIL;
852
0
  }
853
0
    }
854
    /* get keyHandle -> usageAuth */
855
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
856
0
  returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey);
857
0
    }   
858
    /* get the session data */
859
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
860
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
861
0
                &hmacKey,
862
0
                tpm_state,
863
0
                authHandle,
864
0
                TPM_PID_NONE,
865
0
                TPM_ET_KEYHANDLE,
866
0
                ordinal,
867
0
                sigKey,
868
0
                keyUsageAuth,   /* OIAP */
869
0
                sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
870
0
    }
871
    /* validate the authorization to use the key pointed to by keyHandle */
872
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
873
0
  returnCode = TPM_Authdata_Check(tpm_state,
874
0
          *hmacKey,   /* HMAC key */
875
0
          inParamDigest,
876
0
          auth_session_data,  /* authorization session */
877
0
          nonceOdd,   /* Nonce generated by system
878
                   associated with authHandle */
879
0
          continueAuthSession,
880
0
          keyAuth);   /* Authorization digest for input */
881
0
    }
882
    /* 2.Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY,
883
   if not return TPM_INVALID_KEYUSAGE */
884
0
    if (returnCode == TPM_SUCCESS) {
885
0
  if ((sigKey->keyUsage != TPM_KEY_SIGNING) &&
886
0
      (sigKey->keyUsage != TPM_KEY_IDENTITY) &&
887
0
      (sigKey->keyUsage != TPM_KEY_LEGACY)) {
888
0
      printf("TPM_Process_GetAuditDigestSigned: Error, keyUsage %04hx is invalid\n",
889
0
       sigKey->keyUsage);
890
0
      returnCode = TPM_INVALID_KEYUSAGE;
891
0
  }
892
0
    }
893
    /* 3. The TPM validates that the key pointed to by keyHandle has a signature scheme of
894
       TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO, return TPM_INVALID_KEYUSAGE on
895
       error */
896
0
    if (returnCode == TPM_SUCCESS) {
897
0
  if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) &&
898
0
      (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) {
899
0
      printf("TPM_Process_GetAuditDigestSigned: Error, invalid sigScheme %04hx\n",
900
0
       sigKey->algorithmParms.sigScheme);
901
0
      returnCode = TPM_INVALID_KEYUSAGE;
902
0
  }
903
0
    }
904
0
    if (returnCode == TPM_SUCCESS) {
905
  /* 4. Create D1 a TPM_SIGN_INFO structure and set the structure defaults */
906
  /* NOTE Done by TPM_SignInfo_Init() */
907
  /* a. Set D1 -> fixed to "ADIG" */
908
0
  memcpy(d1SignInfo.fixed, "ADIG", TPM_SIGN_INFO_FIXED_SIZE);
909
  /* b. Set D1 -> replay to antiReplay */
910
0
  TPM_Nonce_Copy(d1SignInfo.replay, antiReplay);
911
  /* c. Create D3 a list of all audited ordinals as defined in the TPM_GetAuditDigest
912
     uint32_t[] ordList outgoing parameter */
913
0
  returnCode = TPM_OrdinalAuditStatus_Store(&d3SizedBuffer,
914
0
              &(tpm_state->tpm_permanent_data),
915
0
              0);
916
0
    }
917
    /* d. Create D4 (ordinalDigest outgoing parameter) the SHA-1 of D3 */
918
0
    if (returnCode == TPM_SUCCESS) {
919
0
  returnCode = TPM_SHA1(ordinalDigest,
920
0
            d3SizedBuffer.size, d3SizedBuffer.buffer, 
921
0
            0, NULL);
922
0
    }
923
0
    if (returnCode == TPM_SUCCESS) {
924
  /* e. Set auditDigest to TPM_STANY_DATA -> auditDigest */
925
  /* NOTE: Use it directly on the output */
926
  /* f. Set counterValue to TPM_PERMANENT_DATA -> auditMonotonicCounter */
927
  /* NOTE Since there is only one, use it directly on the output */
928
  /* g. Create D2 the concatenation of auditDigest || counterValue || D4 */
929
0
  returnCode = TPM_Sbuffer_Append(&d2Sbuffer,
930
0
          tpm_state->tpm_stclear_data.auditDigest, TPM_DIGEST_SIZE);
931
0
    }
932
0
    if (returnCode == TPM_SUCCESS) {
933
0
  returnCode =
934
0
      TPM_CounterValue_StorePublic(&d2Sbuffer,
935
0
           &(tpm_state->tpm_permanent_data.auditMonotonicCounter));
936
0
    }
937
0
    if (returnCode == TPM_SUCCESS) {
938
0
  returnCode = TPM_Sbuffer_Append(&d2Sbuffer,
939
0
          ordinalDigest, TPM_DIGEST_SIZE);
940
0
    }
941
    /* h. Set D1 -> data to D2 */
942
0
    if (returnCode == TPM_SUCCESS) {
943
0
  returnCode = TPM_SizedBuffer_SetFromStore(&(d1SignInfo.data), &d2Sbuffer);
944
0
    }
945
    /* i. Create a digital signature of the SHA-1 of D1 by using the signature scheme for keyHandle
946
     */
947
0
    if (returnCode == TPM_SUCCESS) {
948
0
  returnCode = TPM_SHA1_GenerateStructure(h1, &d1SignInfo,
949
0
            (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store);
950
0
    }
951
0
    if (returnCode == TPM_SUCCESS) {
952
0
  returnCode = TPM_RSASignToSizedBuffer(&sig,   /* signature */
953
0
                h1,   /* message */
954
0
                TPM_DIGEST_SIZE, /* message size */
955
0
                sigKey);    /* input, signing key */
956
0
    }
957
0
    if (returnCode == TPM_SUCCESS) {
958
0
  TPM_PrintFour("TPM_Process_GetAuditDigestSigned: auditDigest",
959
0
          tpm_state->tpm_stclear_data.auditDigest); 
960
0
  TPM_PrintFour("TPM_Process_GetAuditDigestSigned: ordinalDigest",
961
0
          ordinalDigest); 
962
0
    }
963
    /* j. Set ordinalDigest to D4 */
964
    /* NOTE Created directly in ordinalDigest */
965
    /* 5. If closeAudit == TRUE */
966
0
    if ((returnCode == TPM_SUCCESS) && closeAudit) {
967
  /* a. If keyHandle->keyUsage is TPM_KEY_IDENTITY */
968
0
  if (sigKey->keyUsage == TPM_KEY_IDENTITY) {
969
      /* i. TPM_STANY_DATA -> auditDigest MUST be set to all zeros. */
970
0
      TPM_Digest_Init(tpm_state->tpm_stclear_data.auditDigest);
971
0
  }
972
  /* b. Else */
973
0
  else {
974
      /* i. Return TPM_INVALID_KEYUSAGE */
975
0
      printf("TPM_Process_GetAuditDigestSigned: Error, "
976
0
       "cannot closeAudit with keyUsage %04hx\n", sigKey->keyUsage);
977
0
      returnCode = TPM_INVALID_KEYUSAGE;
978
0
  }
979
0
    }
980
    /*
981
      response
982
    */
983
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
984
0
    if (rcf == 0) {
985
0
  printf("TPM_Process_GetAuditDigestSigned: Ordinal returnCode %08x %u\n",
986
0
         returnCode, returnCode);
987
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
988
0
    }
989
    /* success response, append the rest of the parameters.  */
990
0
    if (rcf == 0) {
991
0
  if (returnCode == TPM_SUCCESS) {
992
      /* checkpoint the beginning of the outParam's */
993
0
      outParamStart = response->buffer_current - response->buffer;
994
      /* return counterValue */
995
0
      returnCode = TPM_CounterValue_StorePublic
996
0
       (response,
997
0
        &(tpm_state->tpm_permanent_data.auditMonotonicCounter));
998
0
  }
999
  /* return auditDigest */
1000
0
  if (returnCode == TPM_SUCCESS) {
1001
0
      returnCode = TPM_Digest_Store(response,  tpm_state->tpm_stclear_data.auditDigest);
1002
0
  }
1003
  /* return ordinalDigest */
1004
0
  if (returnCode == TPM_SUCCESS) {
1005
0
      returnCode = TPM_Digest_Store(response, ordinalDigest);
1006
0
  }
1007
  /* return sig */
1008
0
  if (returnCode == TPM_SUCCESS) {
1009
0
      returnCode = TPM_SizedBuffer_Store(response, &sig);
1010
      /* checkpoint the end of the outParam's */
1011
0
      outParamEnd = response->buffer_current - response->buffer;
1012
0
  }
1013
  /* digest the above the line output parameters */
1014
0
  if (returnCode == TPM_SUCCESS) {
1015
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1016
0
                 auditStatus, /* input audit status */
1017
0
                 transportEncrypt,
1018
0
                 tag,     
1019
0
                 returnCode,
1020
0
                 ordinal,   /* command ordinal */
1021
0
                 response->buffer + outParamStart,  /* start */
1022
0
                 outParamEnd - outParamStart);  /* length */
1023
0
  }
1024
  /* calculate and set the below the line parameters */
1025
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1026
0
      returnCode = TPM_AuthParams_Set(response,
1027
0
              *hmacKey, /* owner HMAC key */
1028
0
              auth_session_data,
1029
0
              outParamDigest,
1030
0
              nonceOdd,
1031
0
              continueAuthSession);
1032
0
  }
1033
  /* audit if required */
1034
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1035
0
      returnCode = TPM_ProcessAudit(tpm_state,
1036
0
            transportEncrypt,
1037
0
            inParamDigest,
1038
0
            outParamDigest,
1039
0
            ordinal);
1040
0
  }
1041
  /* adjust the initial response */
1042
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1043
0
    }
1044
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1045
0
    if (((rcf != 0) ||
1046
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1047
0
   !continueAuthSession) &&
1048
0
  authHandleValid) {
1049
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1050
0
    }
1051
    /*
1052
      cleanup
1053
    */
1054
0
    TPM_SignInfo_Delete(&d1SignInfo);   /* @1 */
1055
0
    TPM_SizedBuffer_Delete(&d3SizedBuffer); /* @2 */
1056
0
    TPM_Sbuffer_Delete(&d2Sbuffer);   /* @3 */
1057
0
    TPM_SizedBuffer_Delete(&sig);   /* @4 */
1058
0
    return rcf;
1059
0
}
1060
1061
/* 8.5 TPM_SetOrdinalAuditStatus rev 109
1062
1063
   Set the audit flag for a given ordinal. This command requires the authentication of the TPM
1064
   Owner.
1065
*/
1066
1067
TPM_RESULT TPM_Process_SetOrdinalAuditStatus(tpm_state_t *tpm_state,
1068
               TPM_STORE_BUFFER *response,
1069
               TPM_TAG tag,
1070
               uint32_t paramSize,
1071
               TPM_COMMAND_CODE ordinal,
1072
               unsigned char *command,
1073
               TPM_TRANSPORT_INTERNAL *transportInternal)
1074
0
{
1075
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1076
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1077
1078
    /* input parameters */
1079
0
    TPM_COMMAND_CODE  ordinalToAudit; /* The ordinal whose audit flag is to be set */
1080
0
    TPM_BOOL    auditState; /* Value for audit flag */
1081
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle used for owner
1082
             authentication. */
1083
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
1084
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization
1085
               session handle */
1086
0
    TPM_AUTHDATA  ownerAuth;  /* The authorization session digest for inputs and owner
1087
             authentication.  HMAC key: ownerAuth. */
1088
  
1089
    /* processing parameters */
1090
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
1091
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
1092
0
    TPM_DIGEST      inParamDigest;
1093
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1094
0
    TPM_BOOL      altered;    /* status is changing */
1095
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1096
0
    TPM_BOOL      authHandleValid = FALSE;
1097
0
    TPM_SECRET      *hmacKey;
1098
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for authHandle */
1099
    
1100
    /* output parameters */
1101
0
    uint32_t      outParamStart;  /* starting point of outParam's */
1102
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
1103
0
    TPM_DIGEST      outParamDigest;
1104
1105
0
    printf("TPM_Process_SetOrdinalAuditStatus: Ordinal Entry\n");
1106
    /*
1107
      get inputs
1108
    */
1109
    /* save the starting point of inParam's for authorization and auditing */
1110
0
    inParamStart = command;
1111
    /* get ordinalToAudit parameter */
1112
0
    if (returnCode == TPM_SUCCESS) {
1113
0
  returnCode = TPM_Load32(&ordinalToAudit, &command, &paramSize);
1114
0
    }
1115
    /* get auditState parameter */
1116
0
    if (returnCode == TPM_SUCCESS) {
1117
0
  returnCode = TPM_LoadBool(&auditState, &command, &paramSize);
1118
0
    }
1119
0
    if (returnCode == TPM_SUCCESS) {
1120
0
  printf("TPM_Process_SetOrdinalAuditStatus: ordinalToAudit %08x auditState %02x\n",
1121
0
         ordinalToAudit, auditState);
1122
0
    }
1123
    /* save the ending point of inParam's for authorization and auditing */
1124
0
    inParamEnd = command;
1125
    /* digest the input parameters */
1126
0
    if (returnCode == TPM_SUCCESS) {
1127
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1128
0
            &auditStatus,   /* output */
1129
0
            &transportEncrypt,  /* output */
1130
0
            tpm_state,
1131
0
            tag,
1132
0
            ordinal,
1133
0
            inParamStart,
1134
0
            inParamEnd,
1135
0
            transportInternal);
1136
0
    }
1137
    /* check state */
1138
0
    if (returnCode == TPM_SUCCESS) {
1139
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
1140
0
    }
1141
    /* check tag */
1142
0
    if (returnCode == TPM_SUCCESS) {
1143
0
  returnCode = TPM_CheckRequestTag1(tag);
1144
0
    }
1145
    /* get the 'below the line' authorization parameters */
1146
0
    if (returnCode == TPM_SUCCESS) {
1147
0
  returnCode = TPM_AuthParams_Get(&authHandle,
1148
0
          &authHandleValid,
1149
0
          nonceOdd,
1150
0
          &continueAuthSession,
1151
0
          ownerAuth,
1152
0
          &command, &paramSize);
1153
0
    }
1154
0
    if (returnCode == TPM_SUCCESS) {
1155
0
  if (paramSize != 0) {
1156
0
      printf("TPM_Process_SetOrdinalAuditStatus: Error, command has %u extra bytes\n",
1157
0
       paramSize);
1158
0
      returnCode = TPM_BAD_PARAM_SIZE;
1159
0
  }
1160
0
    }
1161
    /* do not terminate sessions if the command did not parse correctly */
1162
0
    if (returnCode != TPM_SUCCESS) {
1163
0
  authHandleValid = FALSE;
1164
0
    }
1165
    /*
1166
      Processing
1167
    */
1168
    /* 1. Validate the AuthData to execute the command and the parameters */
1169
0
    if (returnCode == TPM_SUCCESS) {
1170
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
1171
0
                &hmacKey,
1172
0
                tpm_state,
1173
0
                authHandle,
1174
0
                TPM_PID_NONE,
1175
0
                TPM_ET_OWNER,
1176
0
                ordinal,
1177
0
                NULL,
1178
0
                &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
1179
0
                tpm_state->tpm_permanent_data.ownerAuth);   /* OSAP */
1180
0
    }
1181
    /* calculate and set the below the line parameters */
1182
0
    if (returnCode == TPM_SUCCESS) {
1183
0
  returnCode = TPM_Authdata_Check(tpm_state,
1184
0
          *hmacKey,   /* HMAC key */
1185
0
          inParamDigest,
1186
0
          auth_session_data,  /* authorization session */
1187
0
          nonceOdd,   /* Nonce generated by system
1188
                   associated with authHandle */
1189
0
          continueAuthSession,
1190
0
          ownerAuth);   /* Authorization digest for input */
1191
0
    }
1192
    /* 2. Validate that the ordinal points to a valid TPM ordinal, return TPM_BADINDEX on error */
1193
    /* a. Valid TPM ordinal means an ordinal that the TPM implementation supports */
1194
    /* Done by TPM_OrdinalAuditStatus_SetAuditState() */
1195
    /* 3. Set the non-volatile flag associated with ordinalToAudit to the value in auditState */
1196
    /* NOTE: On error, TPM_PERMANENT_DATA is not changed */
1197
0
    if (returnCode == TPM_SUCCESS) {
1198
0
  returnCode =
1199
0
      TPM_OrdinalAuditStatus_SetAuditStatus(&altered,
1200
0
              &(tpm_state->tpm_permanent_data),
1201
0
              auditState,   /* uninitialized */
1202
0
              ordinalToAudit);
1203
  /* It's not really uninitialized, but beam doesn't understand that TPM_GetInParamDigest()
1204
     can't turn a FALSE into a TRUE */
1205
0
    }
1206
    /* Store the permanent data back to NVRAM */
1207
0
    if (returnCode == TPM_SUCCESS) {
1208
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
1209
0
                altered,
1210
0
                returnCode);
1211
0
    }
1212
    /* Audit Generation 3.b. Corner Cases: TPM_SetOrdinalAuditStatus: In the case where the
1213
       ordinalToAudit is TPM_ORD_SetOrdinalAuditStatus, audit is based on the initial state, not the
1214
       final state. */
1215
    /*
1216
      response
1217
    */
1218
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1219
0
    if (rcf == 0) {
1220
0
  printf("TPM_Process_SetOrdinalAuditStatus: Ordinal returnCode %08x %u\n",
1221
0
         returnCode, returnCode);
1222
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1223
0
    }
1224
    /* success response, append the rest of the parameters.  */
1225
0
    if (rcf == 0) {
1226
0
  if (returnCode == TPM_SUCCESS) {
1227
      /* checkpoint the beginning of the outParam's */
1228
0
      outParamStart = response->buffer_current - response->buffer;
1229
      /* checkpoint the end of the outParam's */
1230
0
      outParamEnd = response->buffer_current - response->buffer;
1231
0
  }
1232
  /* digest the above the line output parameters */
1233
0
  if (returnCode == TPM_SUCCESS) {
1234
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1235
0
                 auditStatus, /* input audit status */
1236
0
                 transportEncrypt,
1237
0
                 tag,     
1238
0
                 returnCode,
1239
0
                 ordinal,   /* command ordinal */
1240
0
                 response->buffer + outParamStart,  /* start */
1241
0
                 outParamEnd - outParamStart);  /* length */
1242
0
  }
1243
  /* calculate and set the below the line parameters */
1244
0
  if (returnCode == TPM_SUCCESS) {
1245
0
      returnCode = TPM_AuthParams_Set(response,
1246
0
              *hmacKey,   /* owner HMAC key */
1247
0
              auth_session_data,
1248
0
              outParamDigest,
1249
0
              nonceOdd,
1250
0
              continueAuthSession);
1251
0
  }
1252
  /* audit if required */
1253
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1254
0
      returnCode = TPM_ProcessAudit(tpm_state,
1255
0
            transportEncrypt,
1256
0
            inParamDigest,
1257
0
            outParamDigest,
1258
0
            ordinal);
1259
0
  }
1260
  /* adjust the initial response */
1261
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1262
0
    }
1263
    /* if there was an error, terminate the session.  */
1264
0
    if (((rcf != 0) ||
1265
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1266
0
   !continueAuthSession) &&
1267
0
  authHandleValid) {
1268
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1269
0
    }
1270
0
    return rcf;
1271
0
}