Coverage Report

Created: 2026-02-11 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtpms/src/tpm12/tpm_admin.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*          TPM Admin Test and Opt-in       */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*        $Id: tpm_admin.c 4505 2011-03-20 17:43:27Z 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
42
#include "tpm_auth.h"
43
#include "tpm_cryptoh.h"
44
#include "tpm_digest.h"
45
#include "tpm_debug.h"
46
#include "tpm_error.h"
47
#include "tpm_key.h"
48
#include "tpm_nonce.h"
49
#include "tpm_permanent.h"
50
#include "tpm_process.h"
51
#include "tpm_secret.h"
52
#include "tpm_ticks.h"
53
#include "tpm_time.h"
54
55
#include "tpm_admin.h"
56
57
/* The Software TPM Self Test works as follows:
58
59
   TPM_LimitedSelfTestCommon(void) - self tests which affect all TPM's
60
   TPM_LimitedSelfTestTPM(tpm_state) - self test per virtual TPM
61
62
   TPM_ContinueSelfTestCmd(tpm_state) - currently does nothing
63
       on failure, sets tpm_state->testState to failure for the virtual TPM
64
65
   TPM_SelfTestFullCmd(tpm_state) calls
66
       TPM_LimitedSelfTestTPM()
67
       TPM_ContinueSelfTestCmd(tpm_state)
68
       on failure, sets tpm_state->testState to failure for the virtual TPM
69
70
   TPM_MainInit(void) calls
71
       TPM_LimitedSelfTestCommon(void)
72
       TPM_LimitedSelfTestTPM(tpm_state)
73
74
   TPM_Process_ContinueSelfTest(tpm_state) calls either (depending on FIPS mode)
75
       TPM_SelfTestFullCmd(tpm_state)
76
       TPM_ContinueSelfTestCmd(tpm_state)
77
78
   TPM_Process_SelfTestFull(tpm_state) calls  
79
       TPM_SelfTestFullCmd(tpm_state)
80
81
   The Software TPM assumes that the coprocessor has run self tests before the application code even
82
   begins.  So this code doesn't do any real testing of the underlying hardware.  This simplifies
83
   the state machine, since TPM_Process_ContinueSelfTest doesn't require a separate thread.
84
*/
85
86
/* TPM_LimitedSelfTestCommon() provides the assurance that a selected subset of TPM commands will
87
   perform properly. The limited nature of the self-test allows the TPM to be functional in as short
88
   of time as possible. all the TPM tests.
89
90
   The caller is responsible for setting the shutdown state on error.
91
*/
92
93
TPM_RESULT TPM_LimitedSelfTestCommon(void)
94
0
{
95
0
    TPM_RESULT  rc = 0;
96
0
    uint32_t  tv_sec;
97
0
    uint32_t  tv_usec;
98
99
0
    printf(" TPM_LimitedSelfTestCommon:\n");
100
#if 0
101
    if (rc == 0) {
102
  rc = TPM_Sbuffer_Test();
103
    }
104
#endif
105
0
    if (rc == 0) {
106
0
  rc = TPM_Uint64_Test();
107
0
    }
108
0
    if (rc == 0) {
109
0
  rc = TPM_CryptoTest();
110
0
    }
111
    /* test time of day clock */
112
0
    if (rc == 0) {
113
0
  rc = TPM_GetTimeOfDay(&tv_sec, &tv_usec);
114
0
    }
115
0
    if (rc != 0) {
116
0
  rc = TPM_FAILEDSELFTEST;
117
0
    }
118
0
    return rc;
119
0
}
120
121
TPM_RESULT TPM_LimitedSelfTestTPM(tpm_state_t *tpm_state)
122
0
{
123
0
    TPM_RESULT    rc = 0;
124
0
    TPM_NONCE   clrData;
125
0
    TPM_SIZED_BUFFER  encData;
126
0
    TPM_NONCE   decData;
127
0
    uint32_t    decLength;
128
    
129
    
130
0
    printf(" TPM_LimitedSelfTestTPM:\n");
131
0
    TPM_SizedBuffer_Init(&encData);   /* freed @1 */
132
133
    /* 8. The TPM MUST check the following: */  
134
    /* a. RNG functionality */
135
    /* NOTE Tested by coprocessor boot */
136
    /* b. Reading and extending the integrity registers. The self-test for the integrity registers
137
       will leave the integrity registers in a known state. */
138
    /* NOTE Since there is nothing special about the PCR's, the common TPM_CryptoTest() is
139
       sufficient */
140
    /* c. Testing the EK integrity, if it exists */
141
    /* i. This requirement specifies that the TPM will verify that the endorsement key pair can
142
       encrypt and decrypt a known value.  This tests the RSA engine. If the EK has not yet been
143
       generated the TPM action is manufacturer specific. */
144
0
    if ((rc == 0) &&
145
0
  (tpm_state->tpm_permanent_data.endorsementKey.keyUsage != TPM_KEY_UNINITIALIZED)) {
146
  /* check the key integrity */
147
0
  if (rc == 0) {
148
0
      rc = TPM_Key_CheckPubDataDigest(&(tpm_state->tpm_permanent_data.endorsementKey));
149
0
  }
150
  /* encrypt */
151
0
  if (rc == 0) {
152
0
      TPM_Nonce_Generate(clrData);
153
0
      rc = TPM_RSAPublicEncrypt_Key(&encData,   /* output */
154
0
            clrData,    /* input */
155
0
            TPM_NONCE_SIZE, /* input */
156
0
            &(tpm_state->tpm_permanent_data.endorsementKey));
157
0
  } 
158
  /* decrypt */
159
0
  if (rc == 0) {
160
0
      rc = TPM_RSAPrivateDecryptH(decData,  /* decrypted data */
161
0
          &decLength, /* length of data put into decrypt_data */
162
0
          TPM_NONCE_SIZE, /* size of decrypt_data buffer */
163
0
          encData.buffer,
164
0
          encData.size,
165
0
          &(tpm_state->tpm_permanent_data.endorsementKey));
166
0
  }
167
  /* verify */
168
0
  if (rc == 0) {
169
0
      if (decLength != TPM_NONCE_SIZE) {
170
0
    printf("TPM_LimitedSelfTestTPM: Error, decrypt length %u should be %u\n",
171
0
           decLength, TPM_NONCE_SIZE);
172
0
    rc = TPM_FAILEDSELFTEST;
173
0
      }
174
0
  }
175
0
  if (rc == 0) {
176
0
      rc = TPM_Nonce_Compare(clrData, decData);
177
0
  }
178
0
    }
179
    /* d. The integrity of the protected capabilities of the TPM */
180
    /* i. This means that the TPM must ensure that its "microcode" has not changed, and not that a
181
       test must be run on each function. */
182
    /* e. Any tamper-resistance markers */
183
    /* i. The tests on the tamper-resistance or tamper-evident markers are under programmable
184
       control.  */
185
    /* There is no requirement to check tamper-evident tape or the status of epoxy surrounding the
186
       case. */
187
    /* NOTE: Done by coprocessor POST */
188
    /* 9. The TPM SHOULD check the following: */
189
    /* a. The hash functionality */
190
    /* i. This check will hash a known value and compare it to an expected result. There is no
191
       requirement to accept external data to perform the check.  */
192
    /* ii. The TPM MAY support a test using external data. */
193
    /* NOTE: Done by TPM_CryptoTest() */
194
    /* b. Any symmetric algorithms */
195
    /* i. This check will use known data with a random key to encrypt and decrypt the data */
196
    /* NOTE: Done by TPM_CryptoTest() */
197
    /* c. Any additional asymmetric algorithms */
198
    /* i. This check will use known data to encrypt and decrypt. */
199
    /* NOTE: So far only RSA is supported */
200
    /* d. The key-wrapping mechanism */
201
    /* i. The TPM should wrap and unwrap a key. The TPM MUST NOT use the endorsement key pair for
202
       this test. */
203
    /* NOTE: There is nothing special about serializing a TPM_STORE_ASYMKEY */
204
    /* e. Any other internal mechanisms */
205
0
    TPM_SizedBuffer_Delete(&encData);   /* @1 */
206
0
    if (rc != 0) {
207
0
  rc = TPM_FAILEDSELFTEST;
208
0
    }
209
    /* set the TPM test state */
210
0
    if ((rc == 0) && (tpm_state->testState != TPM_TEST_STATE_FAILURE)) {
211
0
  printf("  TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_LIMITED);
212
0
  tpm_state->testState = TPM_TEST_STATE_LIMITED;
213
0
    }
214
0
    else {
215
0
  printf("  TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
216
0
  tpm_state->testState = TPM_TEST_STATE_FAILURE;
217
0
    }
218
0
    return rc;
219
0
}
220
221
/* TPM_ContinueSelfTestCmd() runs the continue self test actions
222
223
*/
224
225
TPM_RESULT TPM_ContinueSelfTestCmd(tpm_state_t *tpm_state)
226
0
{
227
0
    TPM_RESULT  rc = 0;
228
229
    /* NOTE all done by limited self test */
230
0
    printf(" TPM_ContinueSelfTestCmd:\n");
231
0
    if (rc != 0) {
232
0
  rc = TPM_FAILEDSELFTEST;
233
0
    }
234
    /* set the TPM test state */
235
0
    if (rc == 0) {
236
0
  printf("  TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FULL);
237
0
  tpm_state->testState = TPM_TEST_STATE_FULL;
238
0
    }
239
0
    else {
240
0
  printf("  TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FAILURE);
241
0
  tpm_state->testState = TPM_TEST_STATE_FAILURE;
242
0
    }
243
0
    return rc;
244
0
}
245
246
/* TPM_SelfTestFullCmd is a request to have the TPM perform another complete self-test.  This test
247
   will take some time but provides an accurate assessment of the TPM's ability to perform all
248
   operations.
249
250
   Runs the actions of self test full.
251
*/
252
253
TPM_RESULT TPM_SelfTestFullCmd(tpm_state_t *tpm_state)
254
0
{
255
0
    TPM_RESULT  rc = 0;
256
257
0
    printf(" TPM_SelfTestFullCmd\n");
258
0
    if (rc == 0) {
259
0
  rc = TPM_LimitedSelfTestTPM(tpm_state);
260
0
    }
261
0
    if (rc == 0) {
262
0
  rc = TPM_ContinueSelfTestCmd(tpm_state);
263
0
    }
264
0
    return rc;
265
0
}
266
267
/* 4.1 TPM_SelfTestFull rev 88
268
269
   SelfTestFull tests all of the TPM capabilities.
270
271
   Unlike TPM_ContinueSelfTest, which may optionally return immediately and then perform the tests,
272
   TPM_SelfTestFull always performs the tests and then returns success or failure.
273
*/
274
275
TPM_RESULT TPM_Process_SelfTestFull(tpm_state_t *tpm_state,
276
            TPM_STORE_BUFFER *response,
277
            TPM_TAG tag,
278
            uint32_t paramSize,
279
            TPM_COMMAND_CODE ordinal,
280
            unsigned char *command,
281
            TPM_TRANSPORT_INTERNAL *transportInternal)
282
0
{
283
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
284
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
285
286
    /* processing parameters */
287
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
288
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
289
0
    TPM_DIGEST      inParamDigest;
290
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
291
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
292
293
    /* output parameters */
294
0
    uint32_t    outParamStart;  /* starting point of outParam's */
295
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
296
0
    TPM_DIGEST    outParamDigest;
297
298
0
    printf("TPM_Process_SelfTestFull: Ordinal Entry\n");
299
    /*
300
      get inputs
301
    */
302
    /* save the starting point of inParam's for authorization and auditing */
303
0
    inParamStart = command;
304
    /* save the ending point of inParam's for authorization and auditing */
305
0
    inParamEnd = command;
306
    /* digest the input parameters */
307
0
    if (returnCode == TPM_SUCCESS) {
308
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
309
0
            &auditStatus,   /* output */
310
0
            &transportEncrypt,  /* output */
311
0
            tpm_state,
312
0
            tag,
313
0
            ordinal,
314
0
            inParamStart,
315
0
            inParamEnd,
316
0
            transportInternal);
317
0
    }
318
    /* check state */
319
0
    if (returnCode == TPM_SUCCESS) {
320
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
321
0
                 TPM_CHECK_NO_LOCKOUT));
322
0
    }
323
    /* check tag */
324
0
    if (returnCode == TPM_SUCCESS) {
325
0
  returnCode = TPM_CheckRequestTag0(tag);
326
0
    }
327
0
    if (returnCode == TPM_SUCCESS) {
328
0
  if (paramSize != 0) {
329
0
      printf("TPM_Process_SelfTestFull: Error, command has %u extra bytes\n", paramSize);
330
0
      returnCode = TPM_BAD_PARAM_SIZE;
331
0
  }
332
0
    }
333
    /*
334
      Processing
335
    */
336
    /* 1. TPM_SelfTestFull SHALL cause a TPM to perform self-test of each TPM internal function. */
337
    /* a. If the self-test succeeds, return TPM_SUCCESS. */
338
    /* b. If the self-test fails, return TPM_FAILEDSELFTEST. */
339
    /* 2. Failure of any test results in overall failure, and the TPM goes into failure mode. */
340
    /* 3. If the TPM has not executed the action of TPM_ContinueSelfTest, the TPM */
341
    /* a. MAY perform the full self-test. */
342
    /* b. MAY return TPM_NEEDS_SELFTEST. */
343
0
    if (returnCode == TPM_SUCCESS) {
344
0
  returnCode = TPM_SelfTestFullCmd(tpm_state);
345
0
    }
346
    /*
347
      response
348
    */
349
0
    if (rcf == 0) {
350
0
  printf("TPM_Process_SelfTestFull: Ordinal returnCode %08x %u\n",
351
0
         returnCode, returnCode);
352
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
353
0
    }
354
    /* success response, append the rest of the parameters.  */
355
0
    if (rcf == 0) {
356
0
  if (returnCode == TPM_SUCCESS) {
357
      /* checkpoint the beginning of the outParam's */
358
0
      outParamStart = response->buffer_current - response->buffer;
359
      /* checkpoint the end of the outParam's */
360
0
      outParamEnd = response->buffer_current - response->buffer;
361
0
  }
362
  /* digest the above the line output parameters */
363
0
  if (returnCode == TPM_SUCCESS) {
364
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
365
0
                 auditStatus, /* input audit status */
366
0
                 transportEncrypt,
367
0
                 tag,     
368
0
                 returnCode,
369
0
                 ordinal,   /* command ordinal */
370
0
                 response->buffer + outParamStart, /* start */
371
0
                 outParamEnd - outParamStart);  /* length */
372
0
  }
373
  /* audit if required */
374
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
375
0
      returnCode = TPM_ProcessAudit(tpm_state,
376
0
            transportEncrypt,
377
0
            inParamDigest,
378
0
            outParamDigest,
379
0
            ordinal);
380
0
  }
381
  /* adjust the initial response */
382
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
383
0
    }
384
0
    return rcf;
385
0
}
386
387
/* 4.2 TPM_ContinueSelfTest rev 88
388
389
   TPM_Process_ContinueSelfTest informs the TPM that it may complete the self test of all TPM
390
   functions.
391
392
   The TPM may return success immediately and then perform the self-test, or it may perform the
393
   self-test and then return success or failure.
394
395
   1. Prior to executing the actions of TPM_ContinueSelfTest, if the TPM receives a command C1 that
396
   uses an untested TPM function, the TPM MUST take one of these actions:
397
398
   a. The TPM MAY return TPM_NEEDS_SELFTEST
399
400
   i. This indicates that the TPM has not tested the internal resources required to execute C1.
401
402
   ii. The TPM does not execute C1.
403
404
   iii. The caller MUST issue TPM_ContinueSelfTest before re-issuing the command C1.
405
406
   (1) If the TPM permits TPM_SelfTestFull prior to completing the actions of TPM_ContinueSelfTest,
407
   the caller MAY issue TPM_SelfTestFull rather than TPM_ContinueSelfTest.
408
409
   b. The TPM MAY return TPM_DOING_SELFTEST
410
411
   i. This indicates that the TPM is doing the actions of TPM_ContinueSelfTest implicitly, as if the
412
   TPM_ContinueSelfTest command had been issued.
413
414
   ii. The TPM does not execute C1.
415
416
   iii. The caller MUST wait for the actions of TPM_ContinueSelfTest to complete before reissuing
417
   the command C1.
418
419
   c. The TPM MAY return TPM_SUCCESS or an error code associated with C1.
420
421
   i. This indicates that the TPM has completed the actions of TPM_ContinueSelfTest and has
422
   completed the command C1.
423
424
   ii. The error code MAY be TPM_FAILEDSELFTEST.
425
*/
426
427
TPM_RESULT TPM_Process_ContinueSelfTest(tpm_state_t *tpm_state,
428
          TPM_STORE_BUFFER *response,
429
          TPM_TAG tag,
430
          uint32_t paramSize,
431
          TPM_COMMAND_CODE ordinal,
432
          unsigned char *command,
433
          TPM_TRANSPORT_INTERNAL *transportInternal)
434
0
{
435
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
436
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
437
438
    /* processing parameters */
439
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
440
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
441
0
    TPM_DIGEST      inParamDigest;
442
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
443
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
444
445
    /* output parameters */
446
0
    uint32_t    outParamStart;  /* starting point of outParam's */
447
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
448
0
    TPM_DIGEST    outParamDigest;
449
450
0
    printf("TPM_Process_ContinueSelfTest: Ordinal Entry\n");
451
    /*
452
      get inputs
453
    */
454
    /* save the starting point of inParam's for authorization and auditing */
455
0
    inParamStart = command;
456
    /* save the ending point of inParam's for authorization and auditing */
457
0
    inParamEnd = command;
458
    /* digest the input parameters */
459
0
    if (returnCode == TPM_SUCCESS) {
460
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
461
0
            &auditStatus,   /* output */
462
0
            &transportEncrypt,  /* output */
463
0
            tpm_state,
464
0
            tag,
465
0
            ordinal,
466
0
            inParamStart,
467
0
            inParamEnd,
468
0
            transportInternal);
469
0
    }
470
    /* check state */
471
0
    if (returnCode == TPM_SUCCESS) {
472
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
473
0
                 TPM_CHECK_NO_LOCKOUT));
474
0
    }
475
    /* check tag */
476
0
    if (returnCode == TPM_SUCCESS) {
477
0
  returnCode = TPM_CheckRequestTag0(tag);
478
0
    }
479
0
    if (returnCode == TPM_SUCCESS) {
480
0
  if (paramSize != 0) {
481
0
      printf("TPM_Process_ContinueSelfTest: Error, command has %u extra bytes\n", paramSize);
482
0
      returnCode = TPM_BAD_PARAM_SIZE;
483
0
  }
484
0
    }
485
    /*
486
      Processing
487
    */
488
0
    if (returnCode == TPM_SUCCESS) {
489
  /* 1. If TPM_PERMANENT_FLAGS -> FIPS is TRUE or TPM_PERMANENT_FLAGS -> TPMpost is TRUE */
490
0
  if ((tpm_state->tpm_permanent_flags.FIPS) ||
491
0
      (tpm_state->tpm_permanent_flags.TPMpost)) {
492
      /* a. The TPM MUST run ALL self-tests */
493
0
      returnCode = TPM_SelfTestFullCmd(tpm_state);
494
0
  }
495
  /* 2. Else */
496
0
  else {
497
      /* a. The TPM MUST complete all self-tests that are outstanding */
498
      /* i. Instead of completing all outstanding self-tests the TPM MAY run all self-tests */
499
0
      returnCode = TPM_ContinueSelfTestCmd(tpm_state);
500
0
  }
501
0
    }
502
    /* 3. The TPM either
503
       a. MAY immediately return TPM_SUCCESS
504
       i. When TPM_ContinueSelfTest finishes execution, it MUST NOT respond to the caller with a
505
       return code.
506
       b. MAY complete the self-test and then return TPM_SUCCESS or TPM_FAILEDSELFTEST.
507
       NOTE Option 3.b. implemented
508
    */
509
    /*
510
      response
511
    */
512
0
    if (rcf == 0) {
513
0
  printf("TPM_Process_ContinueSelfTest: Ordinal returnCode %08x %u\n",
514
0
         returnCode, returnCode);
515
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
516
0
    }
517
    /* success response, append the rest of the parameters.  */
518
0
    if (rcf == 0) {
519
0
  if (returnCode == TPM_SUCCESS) {
520
      /* checkpoint the beginning of the outParam's */
521
0
      outParamStart = response->buffer_current - response->buffer;
522
      /* checkpoint the end of the outParam's */
523
0
      outParamEnd = response->buffer_current - response->buffer;
524
0
  }
525
  /* digest the above the line output parameters */
526
0
  if (returnCode == TPM_SUCCESS) {
527
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
528
0
                 auditStatus, /* input audit status */
529
0
                 transportEncrypt,
530
0
                 tag,     
531
0
                 returnCode,
532
0
                 ordinal,   /* command ordinal */
533
0
                 response->buffer + outParamStart,  /* start */
534
0
                 outParamEnd - outParamStart);  /* length */
535
0
  }
536
  /* audit if required */
537
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
538
0
      returnCode = TPM_ProcessAudit(tpm_state,
539
0
            transportEncrypt,
540
0
            inParamDigest,
541
0
            outParamDigest,
542
0
            ordinal);
543
0
  }
544
  /* adjust the initial response */
545
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
546
0
    }
547
0
    return rcf;
548
0
}
549
550
/* 4.3 TPM_GetTestResult rev 96
551
552
   TPM_GetTestResult provides manufacturer specific information regarding the results of the self
553
   test. This command will work when the TPM is in self test failure mode. The reason for allowing
554
   this command to operate in the failure mode is to allow TPM manufacturers to obtain diagnostic
555
   information.
556
*/
557
558
TPM_RESULT TPM_Process_GetTestResult(tpm_state_t *tpm_state,
559
             TPM_STORE_BUFFER *response,
560
             TPM_TAG tag,
561
             uint32_t paramSize,
562
             TPM_COMMAND_CODE ordinal,
563
             unsigned char *command,
564
             TPM_TRANSPORT_INTERNAL *transportInternal)
565
0
{
566
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
567
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
568
569
    /* processing parameters */
570
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
571
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
572
0
    TPM_DIGEST      inParamDigest;
573
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
574
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
575
576
    /* output parameters */
577
0
    uint32_t    outParamStart;  /* starting point of outParam's */
578
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
579
0
    TPM_DIGEST    outParamDigest;
580
0
    TPM_SIZED_BUFFER  outData;  /* The outData this is manufacturer specific */
581
    
582
0
    printf("TPM_Process_GetTestResult: Ordinal Entry\n");
583
0
    TPM_SizedBuffer_Init(&outData); /* freed @1 */
584
    /*
585
      get inputs
586
    */
587
    /* save the starting point of inParam's for authorization and auditing */
588
0
    inParamStart = command;
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
    /* This command will work when the TPM is in self test failure or limited operation mode. */
605
0
    if (returnCode == TPM_SUCCESS) {
606
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_NO_LOCKOUT);
607
0
    }
608
    /* check tag */
609
0
    if (returnCode == TPM_SUCCESS) {
610
0
  returnCode = TPM_CheckRequestTag0(tag);
611
0
    }
612
0
    if (returnCode == TPM_SUCCESS) {
613
0
  if (paramSize != 0) {
614
0
      printf("TPM_Process_GetTestResult: Error, command has %u extra bytes\n", paramSize);
615
0
      returnCode = TPM_BAD_PARAM_SIZE;
616
0
  }
617
0
    }
618
    /*
619
      Processing
620
    */
621
    /* 1. The TPM SHALL respond to this command with a manufacturer specific block of information
622
       that describes the result of the latest self test. */
623
    /* 2. The information MUST NOT contain any data that uniquely identifies an individual TPM. */
624
    /* allocate some reasonable area */
625
0
    if (returnCode == TPM_SUCCESS) {
626
0
  returnCode = TPM_SizedBuffer_Allocate(&outData, 128);
627
0
    }
628
    /* for now, just return the state of shutdown as a printable string */
629
0
    if (returnCode == TPM_SUCCESS) {
630
0
  size_t len = outData.size;
631
  /* cast because TPM_SIZED_BUFFER is typically unsigned (binary) but snprintf expects char */
632
0
  outData.size = snprintf((char *)(outData.buffer), len,
633
0
                          "Shutdown %08x\n", tpm_state->testState);
634
0
  if (outData.size >= len) {
635
0
      printf("TPM_Process_GetTestResult: Error (fatal), buffer too small\n");
636
0
      returnCode = TPM_FAIL;
637
0
  }
638
0
    }
639
    /*
640
      response
641
    */
642
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
643
0
    if (rcf == 0) {
644
0
  printf("TPM_Process_GetTestResult: Ordinal returnCode %08x %u\n",
645
0
         returnCode, returnCode);
646
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
647
0
    }
648
    /* success response, append the rest of the parameters.  */
649
0
    if (rcf == 0) {
650
0
  if (returnCode == TPM_SUCCESS) {
651
      /* checkpoint the beginning of the outParam's */
652
0
      outParamStart = response->buffer_current - response->buffer;
653
      /* return outData */
654
0
      returnCode = TPM_SizedBuffer_Store(response, &outData);
655
      /* checkpoint the end of the outParam's */
656
0
      outParamEnd = response->buffer_current - response->buffer;
657
0
  }
658
  /* digest the above the line output parameters */
659
0
  if (returnCode == TPM_SUCCESS) {
660
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
661
0
                 auditStatus, /* input audit status */
662
0
                 transportEncrypt,
663
0
                 tag,     
664
0
                 returnCode,
665
0
                 ordinal,   /* command ordinal */
666
0
                 response->buffer + outParamStart,  /* start */
667
0
                 outParamEnd - outParamStart);  /* length */
668
0
  }
669
  /* audit if required */
670
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
671
0
      returnCode = TPM_ProcessAudit(tpm_state,
672
0
            transportEncrypt,
673
0
            inParamDigest,
674
0
            outParamDigest,
675
0
            ordinal);
676
0
  }
677
  /* adjust the initial response */
678
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
679
0
    }
680
    /*
681
      cleanup
682
    */
683
0
    TPM_SizedBuffer_Delete(&outData);   /* @1 */
684
0
    return rcf;
685
0
}
686
687
/* 5.1 TPM_SetOwnerInstall rev 100
688
689
    When enabled but without an owner this command sets the PERMANENT flag that allows or disallows
690
    the ability to insert an owner.
691
 */
692
693
TPM_RESULT TPM_Process_SetOwnerInstall(tpm_state_t *tpm_state,
694
               TPM_STORE_BUFFER *response,
695
               TPM_TAG tag,
696
               uint32_t paramSize,
697
               TPM_COMMAND_CODE ordinal,
698
               unsigned char *command,
699
               TPM_TRANSPORT_INTERNAL *transportInternal)
700
0
{
701
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
702
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
703
704
    /* input parameters */
705
0
    TPM_BOOL        state;  /* State to which ownership flag is to be set. */
706
707
    /* processing parameters */
708
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
709
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
710
0
    TPM_DIGEST      inParamDigest;
711
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
712
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
713
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back NV */
714
0
    TPM_BOOL      physicalPresence;
715
716
    /* output parameters */
717
0
    uint32_t    outParamStart;  /* starting point of outParam's */
718
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
719
0
    TPM_DIGEST    outParamDigest;
720
721
0
    printf("TPM_Process_SetOwnerInstall: Ordinal Entry\n");
722
    /*
723
      get inputs
724
    */
725
    /* save the starting point of inParam's for authorization and auditing */
726
0
    inParamStart = command;
727
    /* get state */
728
0
    if (returnCode == TPM_SUCCESS) {
729
0
  returnCode = TPM_LoadBool(&state, &command, &paramSize);
730
0
    }
731
    /* save the ending point of inParam's for authorization */
732
0
    inParamEnd = command;
733
    /* digest the input parameters */
734
0
    if (returnCode == TPM_SUCCESS) {
735
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
736
0
            &auditStatus,   /* output */
737
0
            &transportEncrypt,  /* output */
738
0
            tpm_state,
739
0
            tag,
740
0
            ordinal,
741
0
            inParamStart,
742
0
            inParamEnd,
743
0
            transportInternal);
744
0
    }
745
    /* check state */
746
0
    if (returnCode == TPM_SUCCESS) {
747
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
748
0
    }
749
    /* check tag */
750
0
    if (returnCode == TPM_SUCCESS) {
751
0
  returnCode = TPM_CheckRequestTag0(tag);
752
0
    }
753
0
    if (returnCode == TPM_SUCCESS) {
754
0
  if (paramSize != 0) {
755
0
      printf("TPM_Process_SetOwnerInstall: Error, command has %u extra bytes\n", paramSize);
756
0
      returnCode = TPM_BAD_PARAM_SIZE;
757
0
  }
758
0
    }
759
    /*
760
      Processing
761
    */
762
0
    if (returnCode == TPM_SUCCESS) {
763
  /* 1. If the TPM has a current owner, this command immediately returns with TPM_SUCCESS. */
764
0
  if (tpm_state->tpm_permanent_data.ownerInstalled) {
765
0
      printf("TPM_Process_SetOwnerInstall: Already current owner\n");
766
0
  }
767
  /* If the TPM does not have a current owner */
768
0
  else {
769
0
      if (returnCode == TPM_SUCCESS) {
770
0
    printf("TPM_Process_SetOwnerInstall: No current owner\n");
771
    /* 2.  The TPM validates the assertion of physical presence. The TPM then sets the
772
       value of TPM_PERMANENT_FLAGS -> ownership to the value in state.
773
    */
774
0
    returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
775
0
      }
776
0
      if (returnCode == TPM_SUCCESS) {
777
0
    if (!physicalPresence) {
778
0
        printf("TPM_Process_SetOwnerInstall: Error, physicalPresence is FALSE\n");
779
0
        returnCode = TPM_BAD_PRESENCE;
780
0
    }
781
0
      }
782
0
      if (returnCode == TPM_SUCCESS) {
783
0
    printf("TPM_Process_SetOwnerInstall: Setting ownership to %02x\n", state);
784
0
    TPM_SetCapability_Flag(&writeAllNV,       /* altered */
785
0
               &(tpm_state->tpm_permanent_flags.ownership), /* flag */
786
0
               state);            /* value */
787
    /* Store the permanent flags back to NVRAM */
788
0
    returnCode = TPM_PermanentAll_NVStore(tpm_state,
789
0
                  writeAllNV,
790
0
                  returnCode);
791
0
      }
792
0
  }
793
0
    }
794
    /*
795
      response
796
    */
797
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
798
0
    if (rcf == 0) {
799
0
  printf("TPM_Process_SetOwnerInstall: Ordinal returnCode %08x %u\n",
800
0
         returnCode, returnCode);
801
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
802
0
    }
803
    /* success response, append the rest of the parameters.  */
804
0
    if (rcf == 0) {
805
0
  if (returnCode == TPM_SUCCESS) {
806
      /* checkpoint the beginning of the outParam's */
807
0
      outParamStart = response->buffer_current - response->buffer;
808
      /* checkpoint the end of the outParam's */
809
0
      outParamEnd = response->buffer_current - response->buffer;
810
0
  }
811
  /* digest the above the line output parameters */
812
0
  if (returnCode == TPM_SUCCESS) {
813
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
814
0
                 auditStatus, /* input audit status */
815
0
                 transportEncrypt,
816
0
                 tag,     
817
0
                 returnCode,
818
0
                 ordinal,   /* command ordinal */
819
0
                 response->buffer + outParamStart,  /* start */
820
0
                 outParamEnd - outParamStart);  /* length */
821
0
  }
822
  /* audit if required */
823
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
824
0
      returnCode = TPM_ProcessAudit(tpm_state,
825
0
            transportEncrypt,
826
0
            inParamDigest,
827
0
            outParamDigest,
828
0
            ordinal);
829
0
  }
830
  /* adjust the initial response */
831
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
832
0
    }
833
0
    return rcf;
834
0
}
835
836
/* 5.2 TPM_OwnerSetDisable rev 107
837
838
   The TPM owner sets the PERMANENT disable flag to TRUE or FALSE.
839
*/
840
841
TPM_RESULT TPM_Process_OwnerSetDisable(tpm_state_t *tpm_state,
842
               TPM_STORE_BUFFER *response,
843
               TPM_TAG tag,
844
               uint32_t paramSize,
845
               TPM_COMMAND_CODE ordinal,
846
               unsigned char *command,
847
               TPM_TRANSPORT_INTERNAL *transportInternal)
848
0
{
849
0
    TPM_RESULT    rcf = 0;      /* fatal error precluding response */
850
0
    TPM_RESULT    returnCode = TPM_SUCCESS; /* command return code */
851
852
    /* input parameters */
853
0
    TPM_BOOL    disableState; /* Value for disable state */
854
0
    TPM_AUTHHANDLE  authHandle; /* The authorization handle used for owner authorization. */
855
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
856
0
    TPM_BOOL    continueAuthSession = TRUE; /* The continue use flag for the
857
                 authorization handle */
858
0
    TPM_AUTHDATA  ownerAuth;  /* The authorization digest for inputs and owner
859
             authorization. HMAC key: ownerAuth. */
860
    
861
    /* processing parameters */
862
0
    unsigned char * inParamStart; /* starting point of inParam's */
863
0
    unsigned char * inParamEnd; /* ending point of inParam's */
864
0
    TPM_DIGEST    inParamDigest;
865
0
    TPM_BOOL    auditStatus;    /* audit the ordinal */
866
0
    TPM_BOOL    transportEncrypt; /* wrapped in encrypted transport session */
867
0
    TPM_BOOL    authHandleValid = FALSE;
868
0
    TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */
869
0
    TPM_SECRET    *hmacKey;
870
0
    TPM_BOOL    writeAllNV = FALSE; /* flag to write back NV */
871
872
    /* output parameters */
873
0
    uint32_t    outParamStart;  /* starting point of outParam's */
874
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
875
0
    TPM_DIGEST    outParamDigest;
876
877
0
    printf("TPM_Process_OwnerSetDisable: Ordinal Entry\n");
878
    /*
879
      get inputs
880
    */
881
    /* save the starting point of inParam's for authorization and auditing */
882
0
    inParamStart = command;
883
    /* get disableState parameter */
884
0
    if (returnCode == TPM_SUCCESS) {
885
0
  returnCode = TPM_LoadBool(&disableState, &command, &paramSize);
886
0
    }
887
    /* save the ending point of inParam's for authorization and auditing */
888
0
    inParamEnd = command;
889
    /* digest the input parameters */
890
0
    if (returnCode == TPM_SUCCESS) {
891
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
892
0
            &auditStatus,   /* output */
893
0
            &transportEncrypt,  /* output */
894
0
            tpm_state,
895
0
            tag,
896
0
            ordinal,
897
0
            inParamStart,
898
0
            inParamEnd,
899
0
            transportInternal);
900
0
    }
901
    /* check state */
902
0
    if (returnCode == TPM_SUCCESS) {
903
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
904
0
                 TPM_CHECK_OWNER |
905
0
                 TPM_CHECK_NO_LOCKOUT));
906
0
    }
907
    /* check tag */
908
0
    if (returnCode == TPM_SUCCESS) {
909
0
  returnCode = TPM_CheckRequestTag1(tag);
910
0
    }
911
    /* get the 'below the line' authorization parameters */
912
0
    if (returnCode == TPM_SUCCESS) {
913
0
  returnCode = TPM_AuthParams_Get(&authHandle,
914
0
          &authHandleValid,
915
0
          nonceOdd,
916
0
          &continueAuthSession,
917
0
          ownerAuth,
918
0
          &command, &paramSize);
919
0
    }
920
0
    if (returnCode == TPM_SUCCESS) {
921
0
  if (paramSize != 0) {
922
0
      printf("TPM_Process_OwnerSetDisable: Error, command has %u extra bytes\n", paramSize);
923
0
      returnCode = TPM_BAD_PARAM_SIZE;
924
0
  }
925
0
    }
926
    /* do not terminate sessions if the command did not parse correctly */
927
0
    if (returnCode != TPM_SUCCESS) {
928
0
  authHandleValid = FALSE;
929
0
    }
930
    /*
931
      Processing
932
    */
933
    /* 1. The TPM SHALL authenticate the command as coming from the TPM Owner. If unsuccessful, the
934
       TPM SHALL return TPM_AUTHFAIL. */
935
0
    if (returnCode == TPM_SUCCESS) {
936
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
937
0
                &hmacKey,
938
0
                tpm_state,
939
0
                authHandle,
940
0
                TPM_PID_NONE,
941
0
                TPM_ET_OWNER,
942
0
                ordinal,
943
0
                NULL,
944
0
                &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
945
0
                tpm_state->tpm_permanent_data.ownerAuth);   /* OSAP */
946
0
    }
947
0
    if (returnCode == TPM_SUCCESS) {
948
0
  returnCode = TPM_Authdata_Check(tpm_state,
949
0
          *hmacKey,   /* owner HMAC key */
950
0
          inParamDigest,  
951
0
          auth_session_data,  /* authorization session */
952
0
          nonceOdd,   /* Nonce generated by system
953
                   associated with authHandle */
954
0
          continueAuthSession,
955
0
          ownerAuth);   /* Authorization digest for input */
956
0
    }
957
    /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS -> disable flag to the value in the
958
       disableState parameter. */
959
0
    if (returnCode == TPM_SUCCESS) {
960
0
  printf("TPM_Process_OwnerSetDisable: Setting disable to %u\n", disableState);
961
0
  TPM_SetCapability_Flag(&writeAllNV,         /* altered */
962
0
             &(tpm_state->tpm_permanent_flags.disable), /* flag */
963
0
             disableState);         /* value */
964
  /* Store the permanent flags back to NVRAM */
965
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
966
0
                writeAllNV,
967
0
                returnCode);
968
0
    }
969
    /*
970
      response
971
    */
972
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
973
0
    if (rcf == 0) {
974
0
  printf("TPM_Process_OwnerSetDisable: Ordinal returnCode %08x %u\n",
975
0
         returnCode, returnCode);
976
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
977
0
    }
978
    /* success response, append the rest of the parameters.  */
979
0
    if (rcf == 0) {
980
0
  if (returnCode == TPM_SUCCESS) {
981
      /* checkpoint the beginning of the outParam's */
982
0
      outParamStart = response->buffer_current - response->buffer;
983
      /* checkpoint the end of the outParam's */
984
0
      outParamEnd = response->buffer_current - response->buffer;
985
0
  }
986
  /* digest the above the line output parameters */
987
0
  if (returnCode == TPM_SUCCESS) {
988
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
989
0
                 auditStatus, /* input audit status */
990
0
                 transportEncrypt,
991
0
                 tag,     
992
0
                 returnCode,
993
0
                 ordinal,   /* command ordinal */
994
0
                 response->buffer + outParamStart,  /* start */
995
0
                 outParamEnd - outParamStart);  /* length */
996
0
  }
997
  /* calculate and set the below the line parameters */
998
0
  if (returnCode == TPM_SUCCESS) {
999
0
      returnCode = TPM_AuthParams_Set(response,
1000
0
              *hmacKey,   /* owner HMAC key */
1001
0
              auth_session_data,
1002
0
              outParamDigest,
1003
0
              nonceOdd,
1004
0
              continueAuthSession);
1005
0
  }
1006
  /* audit if required */
1007
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1008
0
      returnCode = TPM_ProcessAudit(tpm_state,
1009
0
            transportEncrypt,
1010
0
            inParamDigest,
1011
0
            outParamDigest,
1012
0
            ordinal);
1013
0
  }
1014
  /* adjust the initial response */
1015
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1016
0
    }
1017
    /* if there was an error, terminate the session. */
1018
0
    if (((rcf != 0) ||
1019
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1020
0
   !continueAuthSession) &&
1021
0
  authHandleValid) {
1022
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1023
0
    }
1024
0
    return rcf;
1025
0
}
1026
1027
/* 5.3 TPM_PhysicalEnable rev 87
1028
1029
   Sets the PERMANENT disable flag to FALSE using physical presence as authorization.
1030
*/
1031
1032
TPM_RESULT TPM_Process_PhysicalEnable(tpm_state_t *tpm_state,
1033
              TPM_STORE_BUFFER *response,
1034
              TPM_TAG tag,
1035
              uint32_t paramSize,
1036
              TPM_COMMAND_CODE ordinal,
1037
              unsigned char *command,
1038
              TPM_TRANSPORT_INTERNAL *transportInternal)
1039
0
{
1040
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1041
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1042
1043
    /* processing parameters */
1044
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
1045
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
1046
0
    TPM_DIGEST      inParamDigest;
1047
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1048
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1049
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back NV */
1050
0
    TPM_BOOL      physicalPresence;
1051
1052
    /* output parameters */
1053
0
    uint32_t    outParamStart;  /* starting point of outParam's */
1054
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
1055
0
    TPM_DIGEST    outParamDigest;
1056
1057
0
    printf("TPM_Process_PhysicalEnable: Ordinal Entry\n");
1058
    /*
1059
      get inputs
1060
    */
1061
    /* save the starting point of inParam's for authorization and auditing */
1062
0
    inParamStart = command;
1063
    /* save the ending point of inParam's for authorization and auditing */
1064
0
    inParamEnd = command;
1065
    /* digest the input parameters */
1066
0
    if (returnCode == TPM_SUCCESS) {
1067
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1068
0
            &auditStatus,   /* output */
1069
0
            &transportEncrypt,  /* output */
1070
0
            tpm_state,
1071
0
            tag,
1072
0
            ordinal,
1073
0
            inParamStart,
1074
0
            inParamEnd,
1075
0
            transportInternal);
1076
0
    }
1077
    /* check state */
1078
0
    if (returnCode == TPM_SUCCESS) {
1079
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
1080
0
                 TPM_CHECK_NO_LOCKOUT));
1081
0
    }
1082
    /* check tag */
1083
0
    if (returnCode == TPM_SUCCESS) {
1084
0
  returnCode = TPM_CheckRequestTag0(tag);
1085
0
    }
1086
0
    if (returnCode == TPM_SUCCESS) {
1087
0
  if (paramSize != 0) {
1088
0
      printf("TPM_Process_PhysicalEnable: Error, command has %u extra bytes\n", paramSize);
1089
0
      returnCode = TPM_BAD_PARAM_SIZE;
1090
0
  }
1091
0
    }
1092
    /*
1093
      Processing
1094
    */
1095
    /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */
1096
0
    if (returnCode == TPM_SUCCESS) {
1097
0
  returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
1098
0
    }
1099
0
    if (returnCode == TPM_SUCCESS) {
1100
0
  if (!physicalPresence) {
1101
0
      printf("TPM_Process_PhysicalEnable: Error, physicalPresence is FALSE\n");
1102
0
      returnCode = TPM_BAD_PRESENCE;
1103
0
  }
1104
0
    }
1105
    /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to FALSE. */
1106
0
    if (returnCode == TPM_SUCCESS) {
1107
0
  printf("TPM_Process_PhysicalEnable: Setting disable to FALSE\n");
1108
0
  TPM_SetCapability_Flag(&writeAllNV,         /* altered */
1109
0
             &(tpm_state->tpm_permanent_flags.disable), /* flag */
1110
0
             FALSE);            /* value */
1111
  /* Store the permanent flags back to NVRAM */
1112
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
1113
0
                writeAllNV,
1114
0
                returnCode);
1115
0
    }
1116
    /*
1117
      response
1118
    */
1119
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1120
0
    if (rcf == 0) {
1121
0
  printf("TPM_Process_PhysicalEnable: Ordinal returnCode %08x %u\n",
1122
0
         returnCode, returnCode);
1123
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1124
0
    }
1125
    /* success response, append the rest of the parameters.  */
1126
0
    if (rcf == 0) {
1127
0
  if (returnCode == TPM_SUCCESS) {
1128
      /* checkpoint the beginning of the outParam's */
1129
0
      outParamStart = response->buffer_current - response->buffer;
1130
      /* checkpoint the end of the outParam's */
1131
0
      outParamEnd = response->buffer_current - response->buffer;
1132
0
  }
1133
  /* digest the above the line output parameters */
1134
0
  if (returnCode == TPM_SUCCESS) {
1135
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1136
0
                 auditStatus, /* input audit status */
1137
0
                 transportEncrypt,
1138
0
                 tag,     
1139
0
                 returnCode,
1140
0
                 ordinal,   /* command ordinal */
1141
0
                 response->buffer + outParamStart,  /* start */
1142
0
                 outParamEnd - outParamStart);  /* length */
1143
0
  }
1144
  /* audit if required */
1145
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1146
0
      returnCode = TPM_ProcessAudit(tpm_state,
1147
0
            transportEncrypt,
1148
0
            inParamDigest,
1149
0
            outParamDigest,
1150
0
            ordinal);
1151
0
  }
1152
  /* adjust the initial response */
1153
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1154
0
    }
1155
0
    return rcf;
1156
0
}
1157
1158
/* 5.4 TPM_PhysicalDisable rev 87
1159
1160
   Sets the PERMANENT disable flag to TRUE using physical presence as authorization
1161
*/
1162
      
1163
TPM_RESULT TPM_Process_PhysicalDisable(tpm_state_t *tpm_state,
1164
               TPM_STORE_BUFFER *response,
1165
               TPM_TAG tag,
1166
               uint32_t paramSize,
1167
               TPM_COMMAND_CODE ordinal,
1168
               unsigned char *command,
1169
               TPM_TRANSPORT_INTERNAL *transportInternal)
1170
0
{
1171
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1172
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1173
1174
    /* processing parameters */
1175
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
1176
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
1177
0
    TPM_DIGEST      inParamDigest;
1178
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1179
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1180
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back NV */
1181
0
    TPM_BOOL      physicalPresence;
1182
1183
    /* output parameters */
1184
0
    uint32_t    outParamStart;  /* starting point of outParam's */
1185
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
1186
0
    TPM_DIGEST    outParamDigest;
1187
1188
0
    printf("TPM_Process_PhysicalDisable: Ordinal Entry\n");
1189
    /*
1190
      get inputs
1191
    */
1192
    /* save the starting point of inParam's for authorization and auditing */
1193
0
    inParamStart = command;
1194
    /* save the ending point of inParam's for authorization and auditing */
1195
0
    inParamEnd = command;
1196
    /* digest the input parameters */
1197
0
    if (returnCode == TPM_SUCCESS) {
1198
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1199
0
            &auditStatus,   /* output */
1200
0
            &transportEncrypt,  /* output */
1201
0
            tpm_state,
1202
0
            tag,
1203
0
            ordinal,
1204
0
            inParamStart,
1205
0
            inParamEnd,
1206
0
            transportInternal);
1207
0
    }
1208
    /* check state */
1209
0
    if (returnCode == TPM_SUCCESS) {
1210
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
1211
0
                 TPM_CHECK_ENABLED |
1212
0
                 TPM_CHECK_NO_LOCKOUT));
1213
0
    }
1214
    /* check tag */
1215
0
    if (returnCode == TPM_SUCCESS) {
1216
0
  returnCode = TPM_CheckRequestTag0(tag);
1217
0
    }
1218
0
    if (returnCode == TPM_SUCCESS) {
1219
0
  if (paramSize != 0) {
1220
0
      printf("TPM_Process_PhysicalDisable: Error, command has %u extra bytes\n", paramSize);
1221
0
      returnCode = TPM_BAD_PARAM_SIZE;
1222
0
  }
1223
0
    }
1224
    /*
1225
      Processing
1226
    */
1227
    /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */
1228
0
    if (returnCode == TPM_SUCCESS) {
1229
0
  returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
1230
0
    }
1231
0
    if (returnCode == TPM_SUCCESS) {
1232
0
  if (!physicalPresence) {
1233
0
      printf("TPM_Process_PhysicalDisable: Error, physicalPresence is FALSE\n");
1234
0
      returnCode = TPM_BAD_PRESENCE;
1235
0
  }
1236
0
    }
1237
    /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to TRUE. */
1238
0
    if (returnCode == TPM_SUCCESS) {
1239
0
  printf("TPM_Process_PhysicalDisable: Setting disable to TRUE\n");
1240
0
  TPM_SetCapability_Flag(&writeAllNV,         /* altered */
1241
0
             &(tpm_state->tpm_permanent_flags.disable ),  /* flag */
1242
0
             TRUE);            /* value */
1243
  /* Store the permanent flags back to NVRAM */
1244
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
1245
0
                writeAllNV,
1246
0
                returnCode);
1247
0
    }
1248
    /*
1249
      response
1250
    */
1251
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1252
0
    if (rcf == 0) {
1253
0
  printf("TPM_Process_PhysicalDisable: Ordinal returnCode %08x %u\n",
1254
0
         returnCode, returnCode);
1255
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1256
0
    }
1257
    /* success response, append the rest of the parameters.  */
1258
0
    if (rcf == 0) {
1259
0
  if (returnCode == TPM_SUCCESS) {
1260
      /* checkpoint the beginning of the outParam's */
1261
0
      outParamStart = response->buffer_current - response->buffer;
1262
      /* checkpoint the end of the outParam's */
1263
0
      outParamEnd = response->buffer_current - response->buffer;
1264
0
  }
1265
  /* digest the above the line output parameters */
1266
0
  if (returnCode == TPM_SUCCESS) {
1267
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1268
0
                 auditStatus, /* input audit status */
1269
0
                 transportEncrypt,
1270
0
                 tag,     
1271
0
                 returnCode,
1272
0
                 ordinal,   /* command ordinal */
1273
0
                 response->buffer + outParamStart,  /* start */
1274
0
                 outParamEnd - outParamStart);  /* length */
1275
0
  }
1276
  /* audit if required */
1277
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1278
0
      returnCode = TPM_ProcessAudit(tpm_state,
1279
0
            transportEncrypt,
1280
0
            inParamDigest,
1281
0
            outParamDigest,
1282
0
            ordinal);
1283
0
  }
1284
  /* adjust the initial response */
1285
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1286
0
    }
1287
0
    return rcf;
1288
0
}
1289
1290
/* 5.5 TPM_PhysicalSetDeactivated rev 105
1291
1292
   Changes the TPM persistent deactivated flag using physical presence as authorization.
1293
*/
1294
1295
TPM_RESULT TPM_Process_PhysicalSetDeactivated(tpm_state_t *tpm_state,
1296
                TPM_STORE_BUFFER *response,
1297
                TPM_TAG tag,
1298
                uint32_t paramSize,
1299
                TPM_COMMAND_CODE ordinal,
1300
                unsigned char *command,
1301
                TPM_TRANSPORT_INTERNAL *transportInternal)
1302
0
{
1303
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1304
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1305
1306
    /* input parameters */
1307
0
    TPM_BOOL  state;    /* State to which deactivated flag is to be set. */
1308
1309
    /* processing parameters */
1310
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
1311
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
1312
0
    TPM_DIGEST      inParamDigest;
1313
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1314
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1315
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back NV */
1316
0
    TPM_BOOL      physicalPresence;
1317
1318
    /* output parameters */
1319
0
    uint32_t    outParamStart;  /* starting point of outParam's */
1320
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
1321
0
    TPM_DIGEST    outParamDigest;
1322
1323
0
    printf("TPM_Process_PhysicalSetDeactivated: Ordinal Entry\n");
1324
    /*
1325
      get inputs
1326
    */
1327
    /* save the starting point of inParam's for authorization and auditing */
1328
0
    inParamStart = command;
1329
    /* get state parameter */
1330
0
    if (returnCode == TPM_SUCCESS) {
1331
0
  returnCode = TPM_LoadBool(&state, &command, &paramSize);
1332
0
    }
1333
0
    if (returnCode == TPM_SUCCESS) {
1334
0
  printf("TPM_Process_PhysicalSetDeactivated: state %02x\n", state);
1335
0
    }
1336
    /* save the ending point of inParam's for authorization and auditing */
1337
0
    inParamEnd = command;
1338
    /* digest the input parameters */
1339
0
    if (returnCode == TPM_SUCCESS) {
1340
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1341
0
            &auditStatus,   /* output */
1342
0
            &transportEncrypt,  /* output */
1343
0
            tpm_state,
1344
0
            tag,
1345
0
            ordinal,
1346
0
            inParamStart,
1347
0
            inParamEnd,
1348
0
            transportInternal);
1349
0
    }
1350
    /* check state */
1351
0
    if (returnCode == TPM_SUCCESS) {
1352
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
1353
0
                 TPM_CHECK_ENABLED |
1354
0
                 TPM_CHECK_NO_LOCKOUT));
1355
0
    }
1356
    /* check tag */
1357
0
    if (returnCode == TPM_SUCCESS) {
1358
0
  returnCode = TPM_CheckRequestTag0(tag);
1359
0
    }
1360
0
    if (returnCode == TPM_SUCCESS) {
1361
0
  if (paramSize != 0) {
1362
0
      printf("TPM_Process_PhysicalSetDeactivated: Error, command has %u extra bytes\n",
1363
0
       paramSize);
1364
0
      returnCode = TPM_BAD_PARAM_SIZE;
1365
0
  }
1366
0
    }
1367
    /*
1368
      Processing
1369
    */
1370
    /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */
1371
0
    if (returnCode == TPM_SUCCESS) {
1372
0
  returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
1373
0
    }
1374
0
    if (returnCode == TPM_SUCCESS) {
1375
0
  if (!physicalPresence) {
1376
0
      printf("TPM_Process_PhysicalSetDeactivated: Error, physicalPresence is FALSE\n");
1377
0
      returnCode = TPM_BAD_PRESENCE;
1378
0
  }
1379
0
    }
1380
    /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.deactivated flag to the value in the state
1381
       parameter. */
1382
0
    if (returnCode == TPM_SUCCESS) {
1383
0
  printf("TPM_Process_PhysicalSetDeactivated: Setting deactivated to %u\n", state);
1384
0
  TPM_SetCapability_Flag(&writeAllNV,         /* altered */
1385
0
             &(tpm_state->tpm_permanent_flags.deactivated), /* flag */
1386
0
             state);            /* value */
1387
  /* Store the permanent flags back to NVRAM */
1388
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
1389
0
                writeAllNV,
1390
0
                returnCode);
1391
0
    }
1392
    /*
1393
      response
1394
    */
1395
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1396
0
    if (rcf == 0) {
1397
0
  printf("TPM_Process_PhysicalSetDeactivated: Ordinal returnCode %08x %u\n",
1398
0
         returnCode, returnCode);
1399
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1400
0
    }
1401
    /* success response, append the rest of the parameters.  */
1402
0
    if (rcf == 0) {
1403
0
  if (returnCode == TPM_SUCCESS) {
1404
      /* checkpoint the beginning of the outParam's */
1405
0
      outParamStart = response->buffer_current - response->buffer;
1406
      /* checkpoint the end of the outParam's */
1407
0
      outParamEnd = response->buffer_current - response->buffer;
1408
0
  }
1409
  /* digest the above the line output parameters */
1410
0
  if (returnCode == TPM_SUCCESS) {
1411
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1412
0
                 auditStatus, /* input audit status */
1413
0
                 transportEncrypt,
1414
0
                 tag,     
1415
0
                 returnCode,
1416
0
                 ordinal,   /* command ordinal */
1417
0
                 response->buffer + outParamStart,  /* start */
1418
0
                 outParamEnd - outParamStart);  /* length */
1419
0
  }
1420
  /* audit if required */
1421
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1422
0
      returnCode = TPM_ProcessAudit(tpm_state,
1423
0
            transportEncrypt,
1424
0
            inParamDigest,
1425
0
            outParamDigest,
1426
0
            ordinal);
1427
0
  }
1428
  /* adjust the initial response */
1429
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1430
0
    }
1431
0
    return rcf;
1432
0
}
1433
1434
/* 5.6 TPM_SetTempDeactivated rev 87
1435
1436
   This command allows the operator of the platform to deactivate the TPM until the next boot of the
1437
   platform.
1438
1439
   This command requires operator authorization. The operator can provide the authorization by
1440
   either the assertion of physical presence or presenting the operation authorization value.
1441
*/
1442
1443
TPM_RESULT TPM_Process_SetTempDeactivated(tpm_state_t *tpm_state,
1444
            TPM_STORE_BUFFER *response,
1445
            TPM_TAG tag,
1446
            uint32_t paramSize,
1447
            TPM_COMMAND_CODE ordinal,
1448
            unsigned char *command,
1449
            TPM_TRANSPORT_INTERNAL *transportInternal)
1450
0
{
1451
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1452
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1453
1454
    /* input parameters */
1455
0
    TPM_AUTHHANDLE  authHandle; /* auth handle for operation validation.  Session type must
1456
             be OIAP. */
1457
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
1458
0
    TPM_BOOL    continueAuthSession = TRUE; /* The continue use flag for the
1459
                 authorization handle */
1460
0
    TPM_AUTHDATA  operatorAuth; /* HMAC key: operatorAuth */
1461
    
1462
    /* processing parameters */
1463
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
1464
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
1465
0
    TPM_DIGEST      inParamDigest;
1466
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1467
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1468
0
    TPM_BOOL      authHandleValid = FALSE;
1469
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
1470
0
    TPM_SECRET      *hmacKey;
1471
0
#if TPM_V12
1472
0
    TPM_BOOL      physicalPresence;
1473
0
#endif
1474
    
1475
    /* output parameters */
1476
0
    uint32_t    outParamStart;  /* starting point of outParam's */
1477
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
1478
0
    TPM_DIGEST    outParamDigest;
1479
   
1480
0
    printf("TPM_Process_SetTempDeactivated: Ordinal Entry\n");
1481
    /*
1482
      get inputs
1483
    */
1484
    /* save the starting point of inParam's for authorization and auditing */
1485
0
    inParamStart = command;
1486
    /* save the ending point of inParam's for authorization and auditing */
1487
0
    inParamEnd = command;
1488
    /* digest the input parameters */
1489
0
    if (returnCode == TPM_SUCCESS) {
1490
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1491
0
            &auditStatus,   /* output */
1492
0
            &transportEncrypt,  /* output */
1493
0
            tpm_state,
1494
0
            tag,
1495
0
            ordinal,
1496
0
            inParamStart,
1497
0
            inParamEnd,
1498
0
            transportInternal);
1499
0
    }
1500
    /* check state */
1501
0
    if (returnCode == TPM_SUCCESS) {
1502
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
1503
0
                 TPM_CHECK_ACTIVATED |
1504
0
                 TPM_CHECK_NO_LOCKOUT));
1505
0
    }
1506
    /* check tag */
1507
0
    if (returnCode == TPM_SUCCESS) {
1508
0
#if TPM_V12
1509
0
  returnCode = TPM_CheckRequestTag10(tag);
1510
#else /* v1.1 is always auth0.  This check implicitly bypasses the operatorAuth Actions below. */
1511
  returnCode = TPM_CheckRequestTag0(tag);
1512
#endif
1513
0
    }
1514
    /* get the optional 'below the line' authorization parameters */
1515
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1516
0
  returnCode = TPM_AuthParams_Get(&authHandle,
1517
0
          &authHandleValid,
1518
0
          nonceOdd,
1519
0
          &continueAuthSession,
1520
0
          operatorAuth,
1521
0
          &command, &paramSize);
1522
0
    }
1523
0
    if (returnCode == TPM_SUCCESS) {
1524
0
  if (paramSize != 0) {
1525
0
      printf("TPM_Process_SetTempDeactivated: Error, command has %u extra bytes\n",
1526
0
       paramSize);
1527
0
      returnCode = TPM_BAD_PARAM_SIZE;
1528
0
  }
1529
0
    }
1530
    /* do not terminate sessions if the command did not parse correctly */
1531
0
    if (returnCode != TPM_SUCCESS) {
1532
0
  authHandleValid = FALSE;
1533
0
    }
1534
    /*
1535
      Processing
1536
    */
1537
    /* 1. If tag = TPM_TAG_REQ_AUTH1_COMMAND */
1538
    /* a. If TPM_PERMANENT_FLAGS -> operator is FALSE return TPM_NOOPERATOR */
1539
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1540
0
  if (!tpm_state->tpm_permanent_flags.tpmOperator) {
1541
0
      printf("TPM_Process_SetTempDeactivated: Error, no operator\n");
1542
0
      returnCode = TPM_NOOPERATOR;
1543
0
  }
1544
0
    }
1545
    /* b. Validate command and parameters using operatorAuth, on error return TPM_AUTHFAIL */
1546
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1547
0
  printf(" TPM_Process_SetTempDeactivated: authHandle %08x\n", authHandle);
1548
  /* get the session data */
1549
0
  returnCode =
1550
0
      TPM_AuthSessions_GetData(&auth_session_data,
1551
0
             &hmacKey,
1552
0
             tpm_state,
1553
0
             authHandle,
1554
0
             TPM_PID_OIAP,
1555
0
             0, /* OSAP entity type */
1556
0
             ordinal,
1557
0
             NULL,
1558
0
             &(tpm_state->tpm_permanent_data.operatorAuth), /* OIAP */
1559
0
             NULL);            /* OSAP */
1560
0
    }
1561
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1562
0
  returnCode = TPM_Authdata_Check(tpm_state,
1563
0
          *hmacKey,   /* operator HMAC key */
1564
0
          inParamDigest,
1565
0
          auth_session_data,  /* authorization session */
1566
0
          nonceOdd,   /* Nonce generated by system
1567
                   associated with authHandle */
1568
0
          continueAuthSession,
1569
0
          operatorAuth);    /* Authorization digest for input */
1570
  
1571
0
    }
1572
#if TPM_V12 /* v1.1 does not require physical presence */
1573
    /* 2. Else */
1574
    /* a. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */
1575
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
1576
0
  returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
1577
0
    }
1578
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
1579
0
  if (!physicalPresence) {
1580
0
      printf("TPM_Process_SetTempDeactivated: Error, physicalPresence is FALSE\n");
1581
0
      returnCode = TPM_BAD_PRESENCE;
1582
0
  }
1583
0
    }
1584
0
#endif
1585
    /* 3. The TPM SHALL set the TPM_STCLEAR_FLAGS.deactivated flag to the value TRUE. */
1586
0
    if (returnCode == TPM_SUCCESS) {
1587
0
  printf("TPM_Process_SetTempDeactivated: Setting deactivated to TRUE\n");
1588
0
  tpm_state->tpm_stclear_flags.deactivated = TRUE;
1589
0
    }
1590
    /*
1591
      response
1592
    */
1593
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1594
0
    if (rcf == 0) {
1595
0
  printf("TPM_Process_SetTempDeactivated: Ordinal returnCode %08x %u\n",
1596
0
         returnCode, returnCode);
1597
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1598
0
    }
1599
    /* success response, append the rest of the parameters.  */
1600
0
    if (rcf == 0) {
1601
0
  if (returnCode == TPM_SUCCESS) {
1602
      /* checkpoint the beginning of the outParam's */
1603
0
      outParamStart = response->buffer_current - response->buffer;
1604
      /* checkpoint the end of the outParam's */
1605
0
      outParamEnd = response->buffer_current - response->buffer;
1606
0
  }
1607
  /* digest the above the line output parameters */
1608
0
  if (returnCode == TPM_SUCCESS) {
1609
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1610
0
                 auditStatus, /* input audit status */
1611
0
                 transportEncrypt,
1612
0
                 tag,     
1613
0
                 returnCode,
1614
0
                 ordinal,   /* command ordinal */
1615
0
                 response->buffer + outParamStart,  /* start */
1616
0
                 outParamEnd - outParamStart);  /* length */
1617
0
  }
1618
  /* calculate and set the below the line parameters */
1619
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
1620
0
      returnCode = TPM_AuthParams_Set(response,
1621
0
              *hmacKey, /* operator HMAC key */
1622
0
              auth_session_data,
1623
0
              outParamDigest,
1624
0
              nonceOdd,
1625
0
              continueAuthSession);
1626
0
  }
1627
  /* audit if required */
1628
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1629
0
      returnCode = TPM_ProcessAudit(tpm_state,
1630
0
            transportEncrypt,
1631
0
            inParamDigest,
1632
0
            outParamDigest,
1633
0
            ordinal);
1634
0
  }
1635
  /* adjust the initial response */
1636
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1637
0
    }
1638
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1639
0
    if (((rcf != 0) ||
1640
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1641
0
   !continueAuthSession) &&
1642
0
  authHandleValid) {
1643
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1644
0
    }
1645
    /*
1646
      cleanup
1647
    */
1648
0
    return rcf;
1649
0
}
1650
1651
/* 5.7 TPM_SetOperatorAuth rev 87
1652
1653
   This command allows the setting of the operator authorization value. 
1654
1655
   There is no confidentiality applied to the operator authorization as the value is sent under the
1656
   assumption of being local to the platform. If there is a concern regarding the path between the
1657
   TPM and the keyboard then unless the keyboard is using encryption and a secure channel an
1658
   attacker can read the values.
1659
*/
1660
1661
TPM_RESULT TPM_Process_SetOperatorAuth(tpm_state_t *tpm_state,
1662
               TPM_STORE_BUFFER *response,
1663
               TPM_TAG tag,
1664
               uint32_t paramSize,
1665
               TPM_COMMAND_CODE ordinal,
1666
               unsigned char *command,
1667
               TPM_TRANSPORT_INTERNAL *transportInternal)
1668
0
{
1669
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1670
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1671
1672
    /* input parameters */
1673
0
    TPM_SECRET operatorAuth;  /* The operator authorization */
1674
1675
    /* processing parameters */
1676
0
    unsigned char *   inParamStart;   /* starting point of inParam's */
1677
0
    unsigned char *   inParamEnd;   /* ending point of inParam's */
1678
0
    TPM_DIGEST      inParamDigest;
1679
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1680
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1681
0
    TPM_BOOL      writeAllNV = FALSE; /* flag to write back NV */
1682
0
    TPM_BOOL      physicalPresence;
1683
1684
    /* output parameters */
1685
0
    uint32_t    outParamStart;  /* starting point of outParam's */
1686
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
1687
0
    TPM_DIGEST    outParamDigest;
1688
1689
0
    printf("TPM_Process_SetOperatorAuth: Ordinal Entry\n");
1690
    /*
1691
      get inputs
1692
    */
1693
    /* save the starting point of inParam's for authorization and auditing */
1694
0
    inParamStart = command;
1695
    /* get operatorAuth parameter */
1696
0
    if (returnCode == TPM_SUCCESS) {
1697
0
  returnCode = TPM_Secret_Load(operatorAuth, &command, &paramSize);
1698
0
    }
1699
    /* save the ending point of inParam's for authorization and auditing */
1700
0
    inParamEnd = command;
1701
    /* digest the input parameters */
1702
0
    if (returnCode == TPM_SUCCESS) {
1703
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1704
0
            &auditStatus,   /* output */
1705
0
            &transportEncrypt,  /* output */
1706
0
            tpm_state,
1707
0
            tag,
1708
0
            ordinal,
1709
0
            inParamStart,
1710
0
            inParamEnd,
1711
0
            transportInternal);
1712
0
    }
1713
    /* check state */
1714
0
    if (returnCode == TPM_SUCCESS) {
1715
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER);
1716
0
    }
1717
    /* check tag */
1718
0
    if (returnCode == TPM_SUCCESS) {
1719
0
  returnCode = TPM_CheckRequestTag0(tag);
1720
0
    }
1721
0
    if (returnCode == TPM_SUCCESS) {
1722
0
  if (paramSize != 0) {
1723
0
      printf("TPM_Process_SetOperatorAuth: Error, command has %u extra bytes\n",
1724
0
       paramSize);
1725
0
      returnCode = TPM_BAD_PARAM_SIZE;
1726
0
  }
1727
0
    }
1728
    /*
1729
      Processing
1730
    */
1731
    /* 1. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */
1732
0
    if (returnCode == TPM_SUCCESS) {
1733
0
  returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state);
1734
0
    }
1735
0
    if (returnCode == TPM_SUCCESS) {
1736
0
  if (!physicalPresence) {
1737
0
      printf("TPM_Process_SetOperatorAuth: Error, physicalPresence is FALSE\n");
1738
0
      returnCode = TPM_BAD_PRESENCE;
1739
0
  }
1740
0
    }
1741
0
    if (returnCode == TPM_SUCCESS) {
1742
  /* 2. The TPM SHALL set the TPM_PERSISTENT_DATA -> operatorAuth */
1743
0
  TPM_Digest_Copy(tpm_state->tpm_permanent_data.operatorAuth, operatorAuth);
1744
  /* 3. The TPM SHALL set TPM_PERMANENT_FLAGS -> operator to TRUE */
1745
0
  printf("TPM_Process_SetOperatorAuth: Setting operator to TRUE\n");
1746
0
  TPM_SetCapability_Flag(&writeAllNV,         /* altered */
1747
0
             &(tpm_state->tpm_permanent_flags.tpmOperator), /* flag */
1748
0
             TRUE);            /* value */
1749
  /* Store the permanent data and flags back to NVRAM */
1750
0
  returnCode = TPM_PermanentAll_NVStore(tpm_state,
1751
0
                TRUE,
1752
0
                returnCode);
1753
0
    }
1754
    /*
1755
      response
1756
    */
1757
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1758
0
    if (rcf == 0) {
1759
0
  printf("TPM_Process_SetOperatorAuth: Ordinal returnCode %08x %u\n",
1760
0
         returnCode, returnCode);
1761
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1762
0
    }
1763
    /* success response, append the rest of the parameters.  */
1764
0
    if (rcf == 0) {
1765
0
  if (returnCode == TPM_SUCCESS) {
1766
      /* checkpoint the beginning of the outParam's */
1767
0
      outParamStart = response->buffer_current - response->buffer;
1768
      /* checkpoint the end of the outParam's */
1769
0
      outParamEnd = response->buffer_current - response->buffer;
1770
0
  }
1771
  /* digest the above the line output parameters */
1772
0
  if (returnCode == TPM_SUCCESS) {
1773
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1774
0
                 auditStatus, /* input audit status */
1775
0
                 transportEncrypt,
1776
0
                 tag,     
1777
0
                 returnCode,
1778
0
                 ordinal,   /* command ordinal */
1779
0
                 response->buffer + outParamStart,  /* start */
1780
0
                 outParamEnd - outParamStart);  /* length */
1781
0
  }
1782
  /* audit if required */
1783
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1784
0
      returnCode = TPM_ProcessAudit(tpm_state,
1785
0
            transportEncrypt,
1786
0
            inParamDigest,
1787
0
            outParamDigest,
1788
0
            ordinal);
1789
0
  }
1790
  /* adjust the initial response */
1791
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1792
0
    }
1793
0
    return rcf;
1794
0
}
1795
1796
/* 9.3 TPM_ResetLockValue rev 96
1797
1798
   Command that resets the TPM dictionary attack mitigation values
1799
1800
   This allows the TPM owner to cancel the effect of a number of successive authorization failures.
1801
1802
   If this command itself has an authorization failure, it is blocked for the remainder of the lock
1803
   out period.  This prevents a dictionary attack on the owner authorization using this command.
1804
1805
   It is understood that this command allows the TPM owner to perform a dictionary attack on other
1806
   authorization values by alternating a trial and this command.  Similarly, delegating this command
1807
   allows the owner's delegate to perform a dictionary attack.
1808
*/
1809
1810
TPM_RESULT TPM_Process_ResetLockValue(tpm_state_t *tpm_state,
1811
              TPM_STORE_BUFFER *response,
1812
              TPM_TAG tag,
1813
              uint32_t paramSize,
1814
              TPM_COMMAND_CODE ordinal,
1815
              unsigned char *command,
1816
              TPM_TRANSPORT_INTERNAL *transportInternal)
1817
0
{
1818
0
    TPM_RESULT    rcf = 0;      /* fatal error precluding response */
1819
0
    TPM_RESULT    returnCode = TPM_SUCCESS; /* command return code */
1820
1821
    /* input parameters */
1822
0
    TPM_AUTHHANDLE  authHandle; /* The authorization session handle used for TPM Owner
1823
             authorization */
1824
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
1825
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization
1826
               session handle */
1827
0
    TPM_AUTHDATA  ownerAuth;  /* HMAC key TPM Owner auth */
1828
1829
    /* processing parameters */
1830
0
    unsigned char * inParamStart; /* starting point of inParam's */
1831
0
    unsigned char * inParamEnd; /* ending point of inParam's */
1832
0
    TPM_DIGEST    inParamDigest;
1833
0
    TPM_BOOL    auditStatus;    /* audit the ordinal */
1834
0
    TPM_BOOL    transportEncrypt; /* wrapped in encrypted transport session */
1835
0
    TPM_BOOL    authHandleValid = FALSE;
1836
0
    TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */
1837
0
    TPM_SECRET    *hmacKey;
1838
1839
    /* output parameters */
1840
0
    uint32_t    outParamStart;  /* starting point of outParam's */
1841
0
    uint32_t    outParamEnd;  /* ending point of outParam's */
1842
0
    TPM_DIGEST    outParamDigest;
1843
1844
0
    printf("TPM_Process_ResetLockValue: Ordinal Entry\n");
1845
    /*
1846
      get inputs
1847
    */
1848
    /* save the starting point of inParam's for authorization and auditing */
1849
0
    inParamStart = command;
1850
    /* save the ending point of inParam's for authorization and auditing */
1851
0
    inParamEnd = command;
1852
    /* digest the input parameters */
1853
0
    if (returnCode == TPM_SUCCESS) {
1854
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1855
0
            &auditStatus,   /* output */
1856
0
            &transportEncrypt,  /* output */
1857
0
            tpm_state,
1858
0
            tag,
1859
0
            ordinal,
1860
0
            inParamStart,
1861
0
            inParamEnd,
1862
0
            transportInternal);
1863
0
    }
1864
    /* check state */
1865
0
    if (returnCode == TPM_SUCCESS) {
1866
  /* Update disableResetLock.  Ignore the return code since this command is not locked out */
1867
0
  TPM_Authdata_CheckState(tpm_state);
1868
  /* NOTE No TPM_CHECK_NO_LOCKOUT, since this command proceeds anyway */
1869
0
  returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN |
1870
0
                 TPM_CHECK_ENABLED |
1871
0
                 TPM_CHECK_ACTIVATED |
1872
0
                 TPM_CHECK_OWNER));
1873
0
    }
1874
    /* check tag */
1875
0
    if (returnCode == TPM_SUCCESS) {
1876
0
  returnCode = TPM_CheckRequestTag1(tag);
1877
0
    }
1878
    /* get the 'below the line' authorization parameters */
1879
0
    if (returnCode == TPM_SUCCESS) {
1880
0
  returnCode = TPM_AuthParams_Get(&authHandle,
1881
0
          &authHandleValid,
1882
0
          nonceOdd,
1883
0
          &continueAuthSession,
1884
0
          ownerAuth,
1885
0
          &command, &paramSize);
1886
0
    }
1887
0
    if (returnCode == TPM_SUCCESS) {
1888
0
  if (paramSize != 0) {
1889
0
      printf("TPM_Process_ResetLockValue: Error, command has %u extra bytes\n", paramSize);
1890
0
      returnCode = TPM_BAD_PARAM_SIZE;
1891
0
  }
1892
0
    }
1893
    /* do not terminate sessions if the command did not parse correctly */
1894
0
    if (returnCode != TPM_SUCCESS) {
1895
0
  authHandleValid = FALSE;
1896
0
    }
1897
    /*
1898
      Processing
1899
    */
1900
    /* 1. If TPM_STCLEAR_DATA -> disableResetLock is TRUE return TPM_AUTHFAIL */
1901
0
    if (returnCode == TPM_SUCCESS) {
1902
0
  if (tpm_state->tpm_stclear_data.disableResetLock) {
1903
0
      printf("TPM_Process_ResetLockValue: Error, command locked out\n");
1904
0
      returnCode = TPM_AUTHFAIL;
1905
0
  }
1906
0
    }  
1907
    /* a. The internal dictionary attack mechanism will set TPM_STCLEAR_DATA -> disableResetLock to
1908
       FALSE when the timeout period expires */
1909
    /* NOTE Done by TPM_Authdata_CheckState() */
1910
    /* Validate the parameters and owner authorization for this command */
1911
0
    if (returnCode == TPM_SUCCESS) {
1912
0
  if (returnCode == TPM_SUCCESS) {
1913
0
      returnCode =
1914
0
    TPM_AuthSessions_GetData(&auth_session_data,
1915
0
           &hmacKey,
1916
0
           tpm_state,
1917
0
           authHandle,
1918
0
           TPM_PID_NONE,
1919
0
           TPM_ET_OWNER,
1920
0
           ordinal,
1921
0
           NULL,
1922
0
           &(tpm_state->tpm_permanent_data.ownerAuth),  /* OIAP */
1923
0
           tpm_state->tpm_permanent_data.ownerAuth);  /* OSAP */
1924
0
  }
1925
0
  if (returnCode == TPM_SUCCESS) {
1926
0
      returnCode = TPM_Authdata_Check(tpm_state,
1927
0
              *hmacKey,   /* owner HMAC key */
1928
0
              inParamDigest,  
1929
0
              auth_session_data,  /* authorization session */
1930
0
              nonceOdd,   /* Nonce generated by system
1931
                   associated with authHandle */
1932
0
              continueAuthSession,
1933
0
              ownerAuth);   /* Authorization digest for input */
1934
0
  }
1935
  /* 2. If the the command and parameters validation using ownerAuth fails */
1936
0
  if (returnCode != TPM_SUCCESS) {
1937
0
      printf("TPM_Process_ResetLockValue: Error, disabling ordinal\n");
1938
      /* a. Set TPM_STCLEAR_DATA -> disableResetLock to TRUE */
1939
0
      tpm_state->tpm_stclear_data.disableResetLock = TRUE;
1940
      /* b. Restart the TPM dictionary attack lock out period */
1941
      /* A failure restarts it anyway with double the period.*/
1942
      /* c. Return TPM_AUTHFAIL */
1943
0
  }
1944
0
    }
1945
    /* 3. Reset the internal TPM dictionary attack mitigation mechanism */
1946
    /* a. The mechanism is vendor specific and can include time outs, reboots, and other mitigation
1947
       strategies */
1948
0
    if (returnCode == TPM_SUCCESS) {
1949
0
  printf("TPM_Process_ResetLockValue: Resetting the failure counter\n");
1950
  /* clear the authorization failure counter */
1951
0
  tpm_state->tpm_stclear_data.authFailCount = 0;
1952
0
    }
1953
    /*
1954
      response
1955
    */
1956
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1957
0
    if (rcf == 0) {
1958
0
  printf("TPM_Process_ResetLockValue: Ordinal returnCode %08x %u\n",
1959
0
         returnCode, returnCode);
1960
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1961
0
    }
1962
    /* success response, append the rest of the parameters.  */
1963
0
    if (rcf == 0) {
1964
0
  if (returnCode == TPM_SUCCESS) {
1965
      /* checkpoint the beginning of the outParam's */
1966
0
      outParamStart = response->buffer_current - response->buffer;
1967
      /* checkpoint the end of the outParam's */
1968
0
      outParamEnd = response->buffer_current - response->buffer;
1969
0
  }
1970
  /* digest the above the line output parameters */
1971
0
  if (returnCode == TPM_SUCCESS) {
1972
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1973
0
                 auditStatus, /* input audit status */
1974
0
                 transportEncrypt,
1975
0
                 tag,     
1976
0
                 returnCode,
1977
0
                 ordinal,   /* command ordinal */
1978
0
                 response->buffer + outParamStart,  /* start */
1979
0
                 outParamEnd - outParamStart);  /* length */
1980
0
  }
1981
  /* calculate and set the below the line parameters */
1982
0
  if (returnCode == TPM_SUCCESS) {
1983
0
      returnCode = TPM_AuthParams_Set(response,
1984
0
              *hmacKey,   /* owner HMAC key */
1985
0
              auth_session_data,
1986
0
              outParamDigest,
1987
0
              nonceOdd,
1988
0
              continueAuthSession);
1989
0
  }
1990
  /* audit if required */
1991
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1992
0
      returnCode = TPM_ProcessAudit(tpm_state,
1993
0
            transportEncrypt,
1994
0
            inParamDigest,
1995
0
            outParamDigest,
1996
0
            ordinal);
1997
0
  }
1998
  /* adjust the initial response */
1999
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2000
0
    }
2001
    /* if there was an error, terminate the session. */
2002
0
    if (((rcf != 0) ||
2003
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2004
0
   !continueAuthSession) &&
2005
0
  authHandleValid) {
2006
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2007
0
    }
2008
0
    return rcf;
2009
0
}
2010