Coverage Report

Created: 2026-08-13 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtpms/src/tpm12/tpm_identity.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*      TPM Identity Handling         */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*        $Id: tpm_identity.c 4526 2011-03-24 21:14:42Z kgoldman $    */
7
/*                    */
8
/* (c) Copyright IBM Corporation 2006, 2010.          */
9
/*                    */
10
/* All rights reserved.               */
11
/*                    */
12
/* Redistribution and use in source and binary forms, with or without   */
13
/* modification, are permitted provided that the following conditions are */
14
/* met:                   */
15
/*                    */
16
/* Redistributions of source code must retain the above copyright notice, */
17
/* this list of conditions and the following disclaimer.      */
18
/*                    */
19
/* Redistributions in binary form must reproduce the above copyright    */
20
/* notice, this list of conditions and the following disclaimer in the    */
21
/* documentation and/or other materials provided with the distribution.   */
22
/*                    */
23
/* Neither the names of the IBM Corporation nor the names of its    */
24
/* contributors may be used to endorse or promote products derived from   */
25
/* this software without specific prior written permission.     */
26
/*                    */
27
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    */
28
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    */
29
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  */
30
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT   */
31
/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT   */
33
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  */
34
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  */
35
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT    */
36
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  */
37
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   */
38
/********************************************************************************/
39
40
#include <stdio.h>
41
#include <stdlib.h>
42
43
#include "tpm_auth.h"
44
#include "tpm_crypto.h"
45
#include "tpm_cryptoh.h"
46
#include "tpm_debug.h"
47
#include "tpm_digest.h"
48
#include "tpm_error.h"
49
#include "tpm_io.h"
50
#include "tpm_key.h"
51
#include "tpm_memory.h"
52
#include "tpm_pcr.h"
53
#include "tpm_process.h"
54
#include "tpm_secret.h"
55
#include "tpm_storage.h"
56
#include "tpm_ver.h"
57
#include "tpm_identity.h"
58
59
/*
60
  TPM_EK_BLOB
61
*/
62
63
/* TPM_EKBlob_Init()
64
65
   sets members to default values
66
   sets all pointers to NULL and sizes to 0
67
   always succeeds - no return code
68
*/
69
70
void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob)
71
0
{
72
0
    printf(" TPM_EKBlob_Init:\n");
73
0
    tpm_ek_blob->ekType = 0;
74
0
    TPM_SizedBuffer_Init(&(tpm_ek_blob->blob));
75
0
    return;
76
0
}
77
78
/* TPM_EKBlob_Load()
79
80
   deserialize the structure from a 'stream'
81
   'stream_size' is checked for sufficient data
82
   returns 0 or error codes
83
   
84
   Before use, call TPM_EKBlob_Init()
85
   After use, call TPM_EKBlob_Delete() to free memory
86
*/
87
88
TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob,
89
         unsigned char **stream,
90
         uint32_t *stream_size)
91
0
{
92
0
    TPM_RESULT    rc = 0;
93
94
0
    printf(" TPM_EKBlob_Load:\n");
95
    /* check the tag */
96
0
    if (rc == 0) {
97
0
  rc = TPM_CheckTag(TPM_TAG_EK_BLOB, stream, stream_size);
98
0
    }
99
    /* load ekType */
100
0
    if (rc == 0) {
101
0
  rc = TPM_Load16(&(tpm_ek_blob->ekType), stream, stream_size);
102
0
    }
103
    /* load blob */
104
0
    if (rc == 0) {
105
0
  rc = TPM_SizedBuffer_Load(&(tpm_ek_blob->blob), stream, stream_size);
106
0
    }
107
0
    return rc;
108
0
}
109
110
#if 0
111
/* TPM_EKBlob_Store()
112
   
113
   serialize the structure to a stream contained in 'sbuffer'
114
   returns 0 or error codes
115
*/
116
117
TPM_RESULT TPM_EKBlob_Store(TPM_STORE_BUFFER *sbuffer,
118
          const TPM_EK_BLOB *tpm_ek_blob)
119
{
120
    TPM_RESULT    rc = 0;
121
122
    printf(" TPM_EKBlob_Store:\n");
123
    if (rc == 0) {
124
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB); 
125
    }
126
    if (rc == 0) {
127
  rc = TPM_Sbuffer_Append16(sbuffer, tpm_ek_blob->ekType); 
128
    }
129
    if (rc == 0) {
130
  rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_ek_blob->blob)); 
131
    }
132
    return rc;
133
}
134
#endif
135
136
/* TPM_EKBlob_Delete()
137
138
   No-OP if the parameter is NULL, else:
139
   frees memory allocated for the object
140
   sets pointers to NULL
141
   calls TPM_EKBlob_Init to set members back to default values
142
   The object itself is not freed
143
*/   
144
145
void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob)
146
0
{
147
0
    printf(" TPM_EKBlob_Delete:\n");
148
0
    if (tpm_ek_blob != NULL) {
149
0
  TPM_SizedBuffer_Delete(&(tpm_ek_blob->blob));
150
0
  TPM_EKBlob_Init(tpm_ek_blob);
151
0
    }
152
0
    return;
153
0
}
154
155
/*
156
  TPM_EK_BLOB_ACTIVATE
157
*/
158
159
/* TPM_EKBlobActivate_Init()
160
161
   sets members to default values
162
   sets all pointers to NULL and sizes to 0
163
   always succeeds - no return code
164
*/
165
166
void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
167
0
{
168
0
    printf(" TPM_EKBlobActivate_Init:\n");
169
0
    TPM_SymmetricKey_Init(&(tpm_ek_blob_activate->sessionKey));
170
0
    TPM_Digest_Init(tpm_ek_blob_activate->idDigest);
171
0
    TPM_PCRInfoShort_Init(&(tpm_ek_blob_activate->pcrInfo));
172
0
    return;
173
0
}
174
175
/* TPM_EKBlobActivate_Load()
176
177
   deserialize the structure from a 'stream'
178
   'stream_size' is checked for sufficient data
179
   returns 0 or error codes
180
   
181
   Before use, call TPM_EKBlobActivate_Init()
182
   After use, call TPM_EKBlobActivate_Delete() to free memory
183
*/
184
185
TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate,
186
           unsigned char **stream,
187
           uint32_t *stream_size)
188
0
{
189
0
    TPM_RESULT    rc = 0;
190
191
0
    printf(" TPM_EKBlobActivate_Load:\n");
192
    /* check tag */
193
0
    if (rc == 0) {
194
0
  rc = TPM_CheckTag(TPM_TAG_EK_BLOB_ACTIVATE, stream, stream_size);
195
0
    }
196
    /* load sessionKey */
197
0
    if (rc == 0) {
198
0
  rc = TPM_SymmetricKey_Load(&(tpm_ek_blob_activate->sessionKey), stream, stream_size);
199
0
    }
200
    /* load idDigest */
201
0
    if (rc == 0) {
202
0
  rc = TPM_Digest_Load(tpm_ek_blob_activate->idDigest, stream, stream_size);
203
0
    }
204
    /* load pcrInfo */
205
0
    if (rc == 0) {
206
0
  rc = TPM_PCRInfoShort_Load(&(tpm_ek_blob_activate->pcrInfo), stream, stream_size, FALSE);
207
0
    }
208
0
    return rc;
209
0
}
210
211
#if 0
212
/* TPM_EKBlobActivate_Store()
213
   
214
   serialize the structure to a stream contained in 'sbuffer'
215
   returns 0 or error codes
216
*/
217
218
TPM_RESULT TPM_EKBlobActivate_Store(TPM_STORE_BUFFER *sbuffer,
219
            const TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
220
{
221
    TPM_RESULT    rc = 0;
222
223
    printf(" TPM_EKBlobActivate_Store:\n");
224
    /* store tag */
225
    if (rc == 0) {
226
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_ACTIVATE); 
227
    }
228
    /* store sessionKey */
229
    if (rc == 0) {
230
  rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_ek_blob_activate->sessionKey));
231
    }
232
    /* store idDigest */
233
    if (rc == 0) {
234
  rc = TPM_Digest_Store(sbuffer, tpm_ek_blob_activate->idDigest);
235
    }
236
    /* store pcrInfo */
237
    if (rc == 0) {
238
  rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_ek_blob_activate->pcrInfo), FALSE);
239
    }
240
    return rc;
241
}
242
#endif
243
244
/* TPM_EKBlobActivate_Delete()
245
246
   No-OP if the parameter is NULL, else:
247
   frees memory allocated for the object
248
   sets pointers to NULL
249
   calls TPM_EKBlobActivate_Init to set members back to default values
250
   The object itself is not freed
251
*/   
252
253
void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
254
0
{
255
0
    printf(" TPM_EKBlobActivate_Delete:\n");
256
0
    if (tpm_ek_blob_activate != NULL) {
257
0
  TPM_SymmetricKey_Delete(&(tpm_ek_blob_activate->sessionKey));
258
0
  TPM_PCRInfoShort_Delete(&(tpm_ek_blob_activate->pcrInfo));
259
0
  TPM_EKBlobActivate_Init(tpm_ek_blob_activate);
260
0
    }
261
0
    return;
262
0
}
263
264
/*
265
  TPM_EK_BLOB_AUTH
266
*/
267
268
#if 0
269
/* TPM_EKBlobAuth_Init()
270
271
   sets members to default values
272
   sets all pointers to NULL and sizes to 0
273
   always succeeds - no return code
274
*/
275
276
void TPM_EKBlobAuth_Init(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth)
277
{
278
    printf(" TPM_EKBlobAuth_Init:\n");
279
    TPM_Secret_Init(tpm_ek_blob_auth->authValue);
280
    return;
281
}
282
283
/* TPM_EKBlobAuth_Load()
284
285
   deserialize the structure from a 'stream'
286
   'stream_size' is checked for sufficient data
287
   returns 0 or error codes
288
   
289
   Before use, call TPM_EKBlobAuth_Init()
290
   After use, call TPM_EKBlobAuth_Delete() to free memory
291
*/
292
293
TPM_RESULT TPM_EKBlobAuth_Load(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth,
294
             unsigned char **stream,
295
             uint32_t *stream_size)
296
{
297
    TPM_RESULT    rc = 0;
298
299
    printf(" TPM_EKBlobAuth_Load:\n");
300
    /* check tag */
301
    if (rc == 0) {
302
  rc = TPM_CheckTag(TPM_TAG_EK_BLOB_AUTH, stream, stream_size);
303
    }
304
    /* load authValue */
305
    if (rc == 0) {
306
  rc = TPM_Secret_Load(tpm_ek_blob_auth->authValue, stream, stream_size);
307
    }
308
    return rc;
309
}
310
311
/* TPM_EKBlobAuth_Store()
312
   
313
   serialize the structure to a stream contained in 'sbuffer'
314
   returns 0 or error codes
315
*/
316
317
TPM_RESULT TPM_EKBlobAuth_Store(TPM_STORE_BUFFER *sbuffer,
318
        const TPM_EK_BLOB_AUTH *tpm_ek_blob_auth)
319
{
320
    TPM_RESULT    rc = 0;
321
322
    printf(" TPM_EKBlobAuth_Store:\n");
323
    if (rc == 0) {
324
  rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_AUTH); 
325
    }
326
    if (rc == 0) {
327
  rc = TPM_Secret_Store(sbuffer, tpm_ek_blob_auth->authValue);
328
    }
329
    return rc;
330
}
331
332
/* TPM_EKBlobAuth_Delete()
333
334
   No-OP if the parameter is NULL, else:
335
   frees memory allocated for the object
336
   sets pointers to NULL
337
   calls TPM_EKBlobAuth_Init to set members back to default values
338
   The object itself is not freed
339
*/   
340
341
void TPM_EKBlobAuth_Delete(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth)
342
{
343
    printf(" TPM_EKBlobAuth_Delete:\n");
344
    if (tpm_ek_blob_auth != NULL) {
345
  TPM_EKBlobAuth_Init(tpm_ek_blob_auth);
346
    }
347
    return;
348
}
349
#endif
350
351
/*
352
  TPM_IDENTITY_CONTENTS
353
*/
354
355
/* TPM_IdentityContents_Init()
356
357
   sets members to default values
358
   sets all pointers to NULL and sizes to 0
359
   always succeeds - no return code
360
*/
361
362
void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents)
363
0
{
364
0
    printf(" TPM_IdentityContents_Init:\n");
365
0
    TPM_StructVer_Init(&(tpm_identity_contents->ver));
366
0
    tpm_identity_contents->ordinal = TPM_ORD_MakeIdentity;
367
0
    TPM_Digest_Init(tpm_identity_contents->labelPrivCADigest);
368
0
    TPM_Pubkey_Init(&(tpm_identity_contents->identityPubKey));
369
0
    return;
370
0
}
371
372
/* TPM_IdentityContents_Load()  
373
374
   deserialize the structure from a 'stream'
375
   'stream_size' is checked for sufficient data
376
   returns 0 or error codes
377
   
378
   Before use, call TPM_IdentityContents_Init()
379
   After use, call TPM_IdentityContents_Delete() to free memory
380
381
   NOTE: Never called.
382
*/
383
#if 0
384
TPM_RESULT TPM_IdentityContents_Load(TPM_IDENTITY_CONTENTS *tpm_identity_contents,
385
             unsigned char **stream,
386
             uint32_t *stream_size)
387
{
388
    TPM_RESULT    rc = 0;
389
390
    printf(" TPM_IdentityContents_Load:\n");
391
    /* load ver */
392
    if (rc == 0) {
393
  rc = TPM_StructVer_Load(&(tpm_identity_contents->ver), stream, stream_size);
394
    }
395
    /* check ver immediately to ease debugging */
396
    if (rc == 0) {
397
  rc = TPM_StructVer_CheckVer(&(tpm_identity_contents->ver));
398
    }
399
    /* load ordinal */
400
    if (rc == 0) {
401
  rc = TPM_Load32(&(tpm_identity_contents->ordinal), stream, stream_size);
402
    }
403
    /* load labelPrivCADigest */
404
    if (rc == 0) {
405
  rc = TPM_Digest_Load(tpm_identity_contents->labelPrivCADigest, stream, stream_size);
406
    }
407
    /* load identityPubKey */
408
    if (rc == 0) {
409
  rc = TPM_Pubkey_Load(&(tpm_identity_contents->identityPubKey), stream, stream_size);
410
    }
411
    return rc;
412
}
413
#endif
414
415
/* TPM_IdentityContents_Store()
416
   
417
   serialize the structure to a stream contained in 'sbuffer'
418
   returns 0 or error codes
419
*/
420
421
TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer,
422
              TPM_IDENTITY_CONTENTS *tpm_identity_contents)
423
0
{
424
0
    TPM_RESULT    rc = 0;
425
426
0
    printf(" TPM_IdentityContents_Store:\n");
427
    /* store ver */
428
0
    if (rc == 0) {
429
0
  rc = TPM_StructVer_Store(sbuffer, &(tpm_identity_contents->ver));
430
0
    }
431
    /* store ordinal */
432
0
    if (rc == 0) {
433
0
  rc = TPM_Sbuffer_Append32(sbuffer, tpm_identity_contents->ordinal);
434
0
    }
435
    /* store labelPrivCADigest */
436
0
    if (rc == 0) {
437
0
  rc = TPM_Digest_Store(sbuffer, tpm_identity_contents->labelPrivCADigest);
438
0
    }
439
    /* store identityPubKey */
440
0
    if (rc == 0) {
441
0
  rc = TPM_Pubkey_Store(sbuffer, &(tpm_identity_contents->identityPubKey));
442
0
    }
443
0
    return rc;
444
0
}
445
446
/* TPM_IdentityContents_Delete()
447
448
   No-OP if the parameter is NULL, else:
449
   frees memory allocated for the object
450
   sets pointers to NULL
451
   calls TPM_IdentityContents_Init to set members back to default values
452
   The object itself is not freed
453
*/   
454
455
void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents)
456
0
{
457
0
    printf(" TPM_IdentityContents_Delete:\n");
458
0
    if (tpm_identity_contents != NULL) {
459
0
  TPM_Pubkey_Delete(&(tpm_identity_contents->identityPubKey));
460
0
  TPM_IdentityContents_Init(tpm_identity_contents);
461
0
    }
462
0
    return;
463
0
}
464
465
/*
466
  TPM_ASYM_CA_CONTENTS
467
*/
468
469
/* TPM_AsymCaContents_Init()
470
471
   sets members to default values
472
   sets all pointers to NULL and sizes to 0
473
   always succeeds - no return code
474
*/
475
476
void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
477
0
{
478
0
    printf(" TPM_AsymCaContents_Init:\n");
479
0
    TPM_SymmetricKey_Init(&(tpm_asym_ca_contents->sessionKey));
480
0
    TPM_Digest_Init(tpm_asym_ca_contents->idDigest);
481
0
    return;
482
0
}
483
484
/* TPM_AsymCaContents_Load()
485
486
   deserialize the structure from a 'stream'
487
   'stream_size' is checked for sufficient data
488
   returns 0 or error codes
489
   
490
   Before use, call TPM_AsymCaContents_Init()
491
   After use, call TPM_AsymCaContents_Delete() to free memory
492
*/
493
494
TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents,
495
           unsigned char **stream,
496
           uint32_t *stream_size)
497
0
{
498
0
    TPM_RESULT    rc = 0;
499
500
0
    printf(" TPM_AsymCaContents_Load:\n");
501
0
    if (rc == 0) {
502
0
  rc = TPM_SymmetricKey_Load(&(tpm_asym_ca_contents->sessionKey), stream, stream_size);
503
0
    }
504
0
    if (rc == 0) {
505
0
  rc = TPM_Digest_Load(tpm_asym_ca_contents->idDigest, stream, stream_size);
506
0
    }
507
0
    return rc;
508
0
}
509
510
#if 0
511
/* TPM_AsymCaContents_Store()
512
   
513
   serialize the structure to a stream contained in 'sbuffer'
514
   returns 0 or error codes
515
*/
516
517
TPM_RESULT TPM_AsymCaContents_Store(TPM_STORE_BUFFER *sbuffer,
518
            const TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
519
{
520
    TPM_RESULT    rc = 0;
521
522
    printf(" TPM_AsymCaContents_Store:\n");
523
    if (rc == 0) {
524
  rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_asym_ca_contents->sessionKey));
525
    }
526
    if (rc == 0) {
527
  rc = TPM_Digest_Store(sbuffer, tpm_asym_ca_contents->idDigest);
528
    }
529
    return rc;
530
}
531
#endif
532
533
/* TPM_AsymCaContents_Delete()
534
535
   No-OP if the parameter is NULL, else:
536
   frees memory allocated for the object
537
   sets pointers to NULL
538
   calls TPM_AsymCaContents_Init to set members back to default values
539
   The object itself is not freed
540
*/   
541
542
void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
543
0
{
544
0
    printf(" TPM_AsymCaContents_Delete:\n");
545
0
    if (tpm_asym_ca_contents != NULL) {
546
0
  TPM_SymmetricKey_Delete(&(tpm_asym_ca_contents->sessionKey));
547
0
  TPM_AsymCaContents_Init(tpm_asym_ca_contents);
548
0
    }
549
0
    return;
550
0
}
551
552
553
554
555
556
557
/*
558
  Processing Functions
559
*/
560
561
/* 15.1 TPM_MakeIdentity rev 114
562
563
   Generate a new Attestation Identity Key (AIK)
564
565
   labelPrivCADigest identifies the privacy CA that the owner expects to be the target CA for the
566
   AIK.  The selection is not enforced by the TPM.  It is advisory only.  It is included because the
567
   TSS cannot be trusted to send the AIK to the correct privacy CA.  The privacy CA can use this
568
   parameter to validate that it is the target privacy CA and label intended by the TPM owner at the
569
   time the key was created.  The label can be used to indicate an application purpose.
570
571
   The public key of the new TPM identity SHALL be identityPubKey. The private key of the new TPM
572
   identity SHALL be tpm_signature_key.
573
574
   Properties of the new identity
575
576
   TPM_PUBKEY identityPubKey This SHALL be the public key of a previously unused asymmetric key
577
   pair.
578
579
   TPM_STORE_ASYMKEY tpm_signature_key This SHALL be the private key that forms a pair with
580
   identityPubKey and SHALL be extant only in a TPM-shielded location.
581
   
582
   This capability also generates a TPM_KEY containing the tpm_signature_key.
583
   
584
   If identityPubKey is stored on a platform it SHALL exist only in storage to which access is
585
   controlled and is available to authorized entities.
586
*/
587
588
TPM_RESULT TPM_Process_MakeIdentity(tpm_state_t *tpm_state,
589
            TPM_STORE_BUFFER *response,
590
            TPM_TAG tag,
591
            uint32_t paramSize,
592
            TPM_COMMAND_CODE ordinal,
593
            unsigned char *command,
594
            TPM_TRANSPORT_INTERNAL *transportInternal)
595
0
{
596
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
597
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
598
599
    /* input parameters */
600
0
    TPM_ENCAUTH   identityAuth; /* Encrypted usage authorization data for the new identity
601
             */
602
0
    TPM_CHOSENID_HASH labelPrivCADigest;  /* The digest of the identity label and privacy CA
603
               chosen for the new TPM identity. */
604
0
    TPM_KEY   idKeyParams;  /* Structure containing all parameters of new identity
605
             key. pubKey.keyLength & idKeyParams.encData are both 0
606
             MAY be TPM_KEY12 */
607
0
    TPM_AUTHHANDLE  srkAuthHandle;  /* The authorization handle used for SRK authorization. */
608
0
    TPM_NONCE   srknonceOdd;  /* Nonce generated by system associated with srkAuthHandle
609
             */
610
0
    TPM_BOOL  continueSrkSession = TRUE; /* Ignored */
611
0
    TPM_AUTHDATA  srkAuth;  /* The authorization digest for the inputs and the SRK. HMAC
612
             key: srk.usageAuth. */
613
0
    TPM_AUTHHANDLE  authHandle; /* The authorization handle used for owner
614
             authorization. Session type MUST be OSAP. */
615
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
616
0
    TPM_BOOL  continueAuthSession = TRUE; /* Ignored */
617
0
    TPM_AUTHDATA  ownerAuth;  /* The authorization digest for inputs and owner. HMAC key:
618
             ownerAuth. */
619
    /* processing parameters */
620
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
621
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
622
0
    TPM_DIGEST      inParamDigest;
623
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
624
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
625
0
    TPM_BOOL      srkAuthHandleValid = FALSE;
626
0
    TPM_BOOL      authHandleValid = FALSE;
627
0
    TPM_AUTH_SESSION_DATA *srk_auth_session_data = NULL; /* session data for authHandle */
628
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL;  /* session data for dataAuthHandle */
629
0
    TPM_SECRET      *srkHmacKey;
630
0
    TPM_SECRET      *hmacKey;
631
0
    TPM_SECRET      a1Auth;
632
0
    TPM_STORE_ASYMKEY   *idKeyStoreAsymkey;
633
0
    TPM_IDENTITY_CONTENTS idContents;
634
0
    TPM_DIGEST      h1Digest; /* digest of TPM_IDENTITY_CONTENTS structure */
635
0
    int       ver;
636
637
    /* output parameters */
638
0
    uint32_t      outParamStart;  /* starting point of outParam's */
639
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
640
0
    TPM_DIGEST      outParamDigest;
641
0
    TPM_KEY     idKey;    /* The newly created identity key. MAY be TPM_KEY12
642
               */
643
0
    TPM_SIZED_BUFFER    identityBinding;  /* Signature of TPM_IDENTITY_CONTENTS using
644
                 idKey.private. */
645
0
    printf("TPM_Process_MakeIdentity: Ordinal Entry\n");
646
0
    TPM_Key_Init(&idKeyParams);     /* freed @1 */
647
0
    TPM_Key_Init(&idKey);     /* freed @2 */
648
0
    TPM_SizedBuffer_Init(&identityBinding); /* freed @3 */
649
0
    TPM_IdentityContents_Init(&idContents); /* freed @4 */
650
    /*
651
      get inputs
652
    */
653
    /* save the starting point of inParam's for authorization and auditing */
654
0
    inParamStart = command;
655
    /* get identityAuth parameter */
656
0
    if (returnCode == TPM_SUCCESS) {
657
0
  returnCode = TPM_Authdata_Load(identityAuth, &command, &paramSize);
658
0
    }
659
    /* get labelPrivCADigest parameter */
660
0
    if (returnCode == TPM_SUCCESS) {
661
0
  returnCode = TPM_Digest_Load(labelPrivCADigest, &command, &paramSize);
662
0
    }
663
    /* get idKeyParams parameter */
664
0
    if (returnCode == TPM_SUCCESS) {
665
0
  returnCode = TPM_Key_Load(&idKeyParams, &command, &paramSize);
666
0
    }
667
    /* save the ending point of inParam's for authorization and auditing */
668
0
    inParamEnd = command;
669
    /* digest the input parameters */
670
0
    if (returnCode == TPM_SUCCESS) {
671
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
672
0
            &auditStatus,   /* output */
673
0
            &transportEncrypt,  /* output */
674
0
            tpm_state,
675
0
            tag,
676
0
            ordinal,
677
0
            inParamStart,
678
0
            inParamEnd,
679
0
            transportInternal);
680
0
    }
681
    /* check state */
682
0
    if (returnCode == TPM_SUCCESS) {
683
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
684
0
    }
685
    /* check tag */
686
0
    if (returnCode == TPM_SUCCESS) {
687
0
  returnCode = TPM_CheckRequestTag21(tag);
688
0
    }
689
    /* get the optional 'below the line' authorization parameters */
690
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
691
0
  returnCode = TPM_AuthParams_Get(&srkAuthHandle,
692
0
          &srkAuthHandleValid,
693
0
          srknonceOdd,
694
0
          &continueSrkSession,
695
0
          srkAuth,
696
0
          &command, &paramSize);
697
0
  printf("TPM_Process_MakeIdentity: srkAuthHandle %08x\n", srkAuthHandle);
698
0
    }
699
    /* get the 'below the line' authorization parameters */
700
0
    if (returnCode == TPM_SUCCESS) {
701
0
  returnCode = TPM_AuthParams_Get(&authHandle,
702
0
          &authHandleValid,
703
0
          nonceOdd,
704
0
          &continueAuthSession,
705
0
          ownerAuth,
706
0
          &command, &paramSize);
707
0
    }
708
0
    if (returnCode == TPM_SUCCESS) {
709
0
  printf("TPM_Process_MakeIdentity: authHandle %08x\n", authHandle); 
710
0
    }
711
0
    if (returnCode == TPM_SUCCESS) {
712
0
  if (paramSize != 0) {
713
0
      printf("TPM_Process_MakeIdentity: Error, command has %u extra bytes\n",
714
0
       paramSize);
715
0
      returnCode = TPM_BAD_PARAM_SIZE;
716
0
  }
717
0
    }
718
    /* do not terminate sessions if the command did not parse correctly */
719
0
    if (returnCode != TPM_SUCCESS) {
720
0
  srkAuthHandleValid = FALSE;
721
0
  authHandleValid = FALSE;
722
0
    }
723
    /*
724
      Processing
725
    */
726
    /* 1. Validate the idKeyParams parameters for the key description */
727
    /* a. If the algorithm type is RSA the key length MUST be a minimum of 2048 and MUST use the
728
       default exponent. For interoperability the key length SHOULD be 2048 */
729
    /* b. If the algorithm type is other than RSA the strength provided by the key MUST be
730
       comparable to RSA 2048 */
731
    /* c. If the TPM is not designed to create a key of the requested type, return the error code
732
       TPM_BAD_KEY_PROPERTY */
733
    /* d. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then */
734
    /* i. If authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */
735
0
    if (returnCode == TPM_SUCCESS) {
736
0
  returnCode = TPM_Key_CheckProperties(&ver, &idKeyParams, 2048,
737
0
               tpm_state->tpm_permanent_flags.FIPS);
738
0
  printf("TPM_Process_MakeIdentity: key parameters v = %d\n", ver);
739
0
    }
740
    /* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity input
741
       parameters. */
742
    /* get the session data */
743
0
    if (returnCode == TPM_SUCCESS) {
744
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
745
0
                &hmacKey,
746
0
                tpm_state,
747
0
                authHandle,
748
0
                TPM_PID_OSAP,
749
0
                TPM_ET_OWNER,
750
0
                ordinal,
751
0
                NULL,
752
0
                NULL,
753
0
                tpm_state->tpm_permanent_data.ownerAuth);
754
0
    }
755
    /* Validate the authorization to use the key pointed to by keyHandle */
756
0
    if (returnCode == TPM_SUCCESS) {
757
0
  returnCode = TPM_Auth2data_Check(tpm_state,
758
0
           *hmacKey,    /* HMAC key */
759
0
           inParamDigest,
760
0
           auth_session_data, /* authorization session */
761
0
           nonceOdd,    /* Nonce generated by system
762
                   associated with authHandle */
763
0
           continueAuthSession,
764
0
           ownerAuth);    /* Authorization digest for input */
765
0
    }
766
    /* 3. Use srkAuthHandle to verify that the SRK owner authorized all TPM_MakeIdentity input
767
       parameters. */
768
    /* get the session data */
769
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
770
0
  returnCode = TPM_AuthSessions_GetData
771
0
         (&srk_auth_session_data,
772
0
          &srkHmacKey,
773
0
          tpm_state,
774
0
          srkAuthHandle,
775
0
          TPM_PID_NONE,
776
0
          TPM_ET_KEYHANDLE,
777
0
          ordinal,
778
0
          &(tpm_state->tpm_permanent_data.srk),
779
          /* OIAP */
780
0
          &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth),
781
          /* OSAP */
782
0
          tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest);
783
0
    }
784
    /* Validate the authorization to use the key pointed to by keyHandle */
785
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
786
0
  returnCode = TPM_Authdata_Check(tpm_state,
787
0
          *srkHmacKey,    /* HMAC key */
788
0
          inParamDigest,
789
0
          srk_auth_session_data, /* authorization session */
790
0
          srknonceOdd,    /* Nonce generated by system
791
                   associated with authHandle */
792
0
          continueSrkSession,
793
0
          srkAuth);   /* Authorization digest for input */
794
0
    }
795
    /* if there is no SRK authorization, check that the SRK authDataUsage is TPM_AUTH_NEVER */
796
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
797
0
  if (tpm_state->tpm_permanent_data.srk.authDataUsage != TPM_AUTH_NEVER) {
798
0
      printf("TPM_Process_MakeIdentity: Error, SRK authorization required\n");
799
0
      returnCode = TPM_AUTHFAIL;
800
0
  }
801
0
    }
802
    /* 4. Verify that idKeyParams -> keyUsage is TPM_KEY_IDENTITY. If it is not, return
803
       TPM_INVALID_KEYUSAGE */
804
    /* NOTE: TPM_KEY_IDENTITY keys must use TPM_SS_RSASSAPKCS1v15_SHA1 */
805
0
    if (returnCode == TPM_SUCCESS) {
806
0
  printf("TPM_Process_MakeIdentity: Checking key parameters\n");
807
0
  if (idKeyParams.keyUsage != TPM_KEY_IDENTITY) {
808
0
      printf("TPM_Process_MakeIdentity: Error, "
809
0
       "idKeyParams keyUsage %08x should be TPM_KEY_IDENTITY\n",
810
0
       idKeyParams.keyUsage);
811
0
      returnCode = TPM_INVALID_KEYUSAGE;
812
0
  }
813
0
    }
814
    /* 5. Verify that idKeyParams -> keyFlags -> migratable is FALSE. If it is not, return
815
       TPM_INVALID_KEYUSAGE */
816
0
    if (returnCode == TPM_SUCCESS) {
817
0
  if (idKeyParams.keyFlags & TPM_MIGRATABLE) {
818
0
      printf("TPM_Process_MakeIdentity: Error, "
819
0
       "idKeyParams keyFlags %08x cannot be migratable\n",
820
0
       idKeyParams.keyFlags);
821
0
      returnCode = TPM_INVALID_KEYUSAGE;
822
0
  }
823
0
    }
824
    /* 6. Create a1 by decrypting identityAuth according to the ADIP indicated by authHandle. */
825
0
    if (returnCode == TPM_SUCCESS) {
826
0
  returnCode = TPM_AuthSessionData_Decrypt(a1Auth,
827
0
             NULL,
828
0
             identityAuth,
829
0
             auth_session_data,
830
0
             NULL,
831
0
             NULL,
832
0
             FALSE);  /* even and odd */
833
0
    }
834
    /* 7. Set continueAuthSession and continueSRKSession to FALSE. */
835
0
    if (returnCode == TPM_SUCCESS) {
836
0
  continueAuthSession = FALSE;
837
0
  continueSrkSession = FALSE;
838
  /* 8. Determine the structure version */
839
  /* a. If idKeyParams -> tag is TPM_TAG_KEY12 */
840
  /* i. Set V1 to 2 */
841
  /* ii. Create idKey a TPM_KEY12 structure using idKeyParams as the default values for the
842
         structure */
843
  /* b. If idKeyParams -> ver is 1.1  */
844
  /* i. Set V1 to 1 */
845
  /* ii. Create idKey a TPM_KEY structure using idKeyParams as the default values for the
846
         structure */
847
  /* NOTE Done by TPM_Key_CheckProperties() */
848
  /* NOTE The creation determination is done by TPM_Key_GenerateRSA() */
849
0
    }
850
    /* 9. Set the digestAtCreation values for pcrInfo */
851
    /* NOTE Done as the key is generated */
852
    /* a. For PCR_INFO_LONG include the locality of the current command */
853
    /* 10. Create an asymmetric key pair (identityPubKey and tpm_signature_key) using a
854
       TPM-protected capability, in accordance with the algorithm specified in idKeyParams */
855
0
    if (returnCode == TPM_SUCCESS) {
856
  /* generate the key pair, create the tpm_store_asymkey cache, copy key parameters, create
857
     tpm_pcr_info cache, copies pcr parameters, sets digestAtCreation, sets pubKey, serializes
858
     pcrInfo
859
     
860
     does not set encData */
861
0
  printf("TPM_Process_MakeIdentity: Generating key\n");
862
0
  returnCode = TPM_Key_GenerateRSA(&idKey,
863
0
           tpm_state,
864
0
           &(tpm_state->tpm_permanent_data.srk),  /* parent key */
865
0
           tpm_state->tpm_stclear_data.PCRS,  /* PCR array */
866
0
           ver,
867
0
           idKeyParams.keyUsage,
868
0
           idKeyParams.keyFlags,
869
0
           idKeyParams.authDataUsage, /* TPM_AUTH_DATA_USAGE */
870
0
           &(idKeyParams.algorithmParms), /* TPM_KEY_PARMS */
871
0
           idKeyParams.tpm_pcr_info,  /* TPM_PCR_INFO */
872
0
           idKeyParams.tpm_pcr_info_long);/* TPM_PCR_INFO_LONG */
873
874
0
    }
875
    /* 11. Ensure that the authorization information in A1 is properly stored in the idKey as
876
       usageAuth. */
877
0
    if (returnCode == TPM_SUCCESS) {
878
0
  returnCode = TPM_Key_GetStoreAsymkey(&idKeyStoreAsymkey,
879
0
               &idKey);
880
0
    }
881
0
    if (returnCode == TPM_SUCCESS) {
882
0
  TPM_Secret_Copy(idKeyStoreAsymkey->usageAuth, a1Auth);
883
  /* 12. Attach identityPubKey and tpm_signature_key to idKey */
884
  /* Note: Done as the key is generated */
885
  /* 13. Set idKey -> migrationAuth to TPM_PERMANENT_DATA -> tpmProof */
886
0
  TPM_Secret_Copy(idKeyStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof);
887
  /* 14. Ensure that all TPM_PAYLOAD_TYPE structures identity this key as TPM_PT_ASYM */
888
  /* NOTE Done as the key is generated */
889
0
    }  
890
    /* 15. Encrypt the private portion of idKey using the SRK as the parent key */
891
0
    if (returnCode == TPM_SUCCESS) {
892
0
  printf("TPM_Process_MakeIdentity: Encrypting key private part with SRK\n");
893
0
  returnCode = TPM_Key_GenerateEncData(&idKey, &(tpm_state->tpm_permanent_data.srk));
894
0
    }
895
    /* 16. Create a TPM_IDENTITY_CONTENTS structure named idContents using labelPrivCADigest and the
896
       information from idKey */
897
0
    if (returnCode == TPM_SUCCESS) {
898
0
  TPM_Digest_Copy(idContents.labelPrivCADigest, labelPrivCADigest);
899
0
  returnCode = TPM_Pubkey_Set(&(idContents.identityPubKey), &idKey);
900
0
    }
901
    /* 17. Sign idContents using tpm_signature_key and TPM_SS_RSASSAPKCS1v15_SHA1. Store the result
902
       in identityBinding. */
903
    /* NOTE: TPM_Key_CheckProperties() verified TPM_SS_RSASSAPKCS1v15_SHA1 */
904
    /* serialize tpm_identity_contents and hash the results*/
905
0
    if (returnCode == TPM_SUCCESS) {
906
0
  returnCode = TPM_SHA1_GenerateStructure(h1Digest,
907
0
            &idContents,
908
0
            (TPM_STORE_FUNCTION_T)TPM_IdentityContents_Store);
909
0
    }
910
    /* sign the digest */
911
0
    if (returnCode == TPM_SUCCESS) {
912
0
  printf("TPM_Process_MakeIdentity: Signing digest of TPM_IDENTITY_CONTENTS\n");
913
0
  returnCode = TPM_RSASignToSizedBuffer(&identityBinding, h1Digest, TPM_DIGEST_SIZE, &idKey);
914
0
    }
915
#if 0 /* NOTE Debug code to reverse the signature */
916
    if (returnCode == TPM_SUCCESS) {
917
  unsigned char   *message = NULL;
918
  unsigned char   *narr = NULL;
919
  uint32_t  nbytes;
920
  unsigned char   *earr = NULL;
921
  uint32_t  ebytes;
922
  if (returnCode == 0) {
923
      returnCode = TPM_Malloc(&message, identityBinding.size); /* freed @10 */
924
  }
925
  if (returnCode == 0) {
926
      returnCode = TPM_Key_GetPublicKey(&nbytes, &narr, &idKey);
927
  }
928
  if (returnCode == 0) {
929
      returnCode = TPM_Key_GetExponent(&ebytes, &earr, &idKey);
930
  }
931
  if (returnCode == 0) {
932
      returnCode = TPM_RSAPublicEncryptRaw(message,     /* output */
933
             identityBinding.size,  
934
             identityBinding.buffer,  /* input */
935
             identityBinding.size,  
936
             narr,      /* public modulus */
937
             nbytes,
938
             earr,      /* public exponent */
939
             ebytes);
940
  }
941
  free(message);  /* @10 */
942
    }
943
#endif
944
    /*
945
      response
946
    */
947
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
948
0
    if (rcf == 0) {
949
0
  printf("TPM_Process_MakeIdentity: Ordinal returnCode %08x %u\n",
950
0
         returnCode, returnCode);
951
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
952
0
    }
953
    /* success response, append the rest of the parameters.  */
954
0
    if (rcf == 0) {
955
0
  if (returnCode == TPM_SUCCESS) {
956
      /* checkpoint the beginning of the outParam's */
957
0
      outParamStart = response->buffer_current - response->buffer;
958
      /* return idKey */
959
0
      returnCode = TPM_Key_Store(response, &idKey);
960
0
  }
961
0
  if (returnCode == TPM_SUCCESS) {
962
      /* return identityBinding */
963
0
      returnCode = TPM_SizedBuffer_Store(response, &identityBinding);
964
      /* checkpoint the end of the outParam's */
965
0
      outParamEnd = response->buffer_current - response->buffer;
966
0
  }
967
  /* digest the above the line output parameters */
968
0
  if (returnCode == TPM_SUCCESS) {
969
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
970
0
                 auditStatus, /* input audit status */
971
0
                 transportEncrypt,
972
0
                 tag,     
973
0
                 returnCode,
974
0
                 ordinal,   /* command ordinal */
975
0
                 response->buffer + outParamStart,  /* start */
976
0
                 outParamEnd - outParamStart);  /* length */
977
0
  }
978
  /* calculate and set the below the line parameters */
979
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
980
0
      returnCode = TPM_AuthParams_Set(response,
981
0
              *srkHmacKey,  /* owner HMAC key */
982
0
              srk_auth_session_data,
983
0
              outParamDigest,
984
0
              srknonceOdd,
985
0
              continueSrkSession);
986
0
  }
987
  /* calculate and set the below the line parameters */
988
0
  if (returnCode == TPM_SUCCESS) {
989
0
      returnCode = TPM_AuthParams_Set(response,
990
0
              *hmacKey, /* owner HMAC key */
991
0
              auth_session_data,
992
0
              outParamDigest,
993
0
              nonceOdd,
994
0
              continueAuthSession);
995
0
  }
996
  /* audit if required */
997
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
998
0
      returnCode = TPM_ProcessAudit(tpm_state,
999
0
            transportEncrypt,
1000
0
            inParamDigest,
1001
0
            outParamDigest,
1002
0
            ordinal);
1003
0
  }
1004
  /* adjust the initial response */
1005
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1006
0
    }
1007
    /* if there was an error, or continueSrkSession is FALSE, terminate the session */
1008
0
    if (((rcf != 0) ||
1009
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1010
0
   !continueSrkSession) &&
1011
0
  srkAuthHandleValid) {
1012
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, srkAuthHandle);
1013
0
    }
1014
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1015
0
    if (((rcf != 0) ||
1016
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1017
0
   !continueAuthSession) &&
1018
0
  authHandleValid) {
1019
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1020
0
    }
1021
    /*
1022
      cleanup
1023
    */
1024
0
    TPM_Key_Delete(&idKeyParams);   /* freed @1 */
1025
0
    TPM_Key_Delete(&idKey);     /* freed @2 */
1026
0
    TPM_SizedBuffer_Delete(&identityBinding); /* freed @3 */
1027
0
    TPM_IdentityContents_Delete(&idContents); /* freed @4 */
1028
0
    return rcf;
1029
0
}
1030
1031
/* 15.2 TPM_ActivateIdentity rev 107
1032
1033
  The purpose of TPM_ActivateIdentity is to twofold. The first purpose is to obtain assurance that
1034
  the credential in the TPM_SYM_CA_ATTESTATION is for this TPM. The second purpose is to obtain the
1035
  session key used to encrypt the TPM_IDENTITY_CREDENTIAL.
1036
1037
  The command TPM_ActivateIdentity activates a TPM identity created using the command
1038
  TPM_MakeIdentity.
1039
  
1040
  The command assumes the availability of the private key associated with the identity. The command
1041
  will verify the association between the keys during the process.
1042
  
1043
  The command will decrypt the input blob and extract the session key and verify the connection
1044
  between the public and private keys. The input blob can be in 1.1 or 1.2 format.
1045
*/
1046
1047
TPM_RESULT TPM_Process_ActivateIdentity(tpm_state_t *tpm_state,
1048
          TPM_STORE_BUFFER *response,
1049
          TPM_TAG tag,
1050
          uint32_t paramSize,
1051
          TPM_COMMAND_CODE ordinal,
1052
          unsigned char *command,
1053
          TPM_TRANSPORT_INTERNAL *transportInternal)
1054
0
{
1055
0
    TPM_RESULT  rcf = 0;      /* fatal error precluding response */
1056
0
    TPM_RESULT  returnCode = TPM_SUCCESS; /* command return code */
1057
1058
    /* input parameters */
1059
0
    TPM_KEY_HANDLE  idKeyHandle;  /* handle of identity key to be activated */
1060
0
    TPM_SIZED_BUFFER  blob;   /* The encrypted ASYM_CA_CONTENTS or TPM_EK_BLOB */
1061
0
    TPM_AUTHHANDLE  idKeyAuthHandle;  /* The authorization handle used for ID key
1062
               authorization. */
1063
0
    TPM_NONCE   idKeynonceOdd;  /* Nonce generated by system associated with idKeyAuthHandle
1064
             */
1065
0
    TPM_BOOL  continueIdKeySession = TRUE; /* Continue usage flag for idKeyAuthHandle. */
1066
0
    TPM_AUTHDATA  idKeyAuth;  /* The authorization digest for the inputs and ID key. HMAC
1067
             key: idKey.usageAuth. */
1068
0
    TPM_AUTHHANDLE  authHandle; /* The authorization handle used for owner authorization. */
1069
0
    TPM_NONCE   nonceOdd; /* Nonce generated by system associated with authHandle */
1070
0
    TPM_BOOL  continueAuthSession = TRUE; /* The continue use flag for the authorization
1071
               handle */
1072
0
    TPM_AUTHDATA    ownerAuth;  /* The authorization digest for inputs and
1073
               owner. HMAC key: ownerAuth. */
1074
1075
    /* processing parameters */
1076
0
    unsigned char *   inParamStart;     /* starting point of inParam's */
1077
0
    unsigned char *   inParamEnd;     /* ending point of inParam's */
1078
0
    TPM_DIGEST      inParamDigest;
1079
0
    TPM_BOOL      auditStatus;    /* audit the ordinal */
1080
0
    TPM_BOOL      transportEncrypt; /* wrapped in encrypted transport session */
1081
0
    TPM_BOOL      idKeyAuthHandleValid = FALSE;
1082
0
    TPM_BOOL      authHandleValid = FALSE;
1083
0
    TPM_AUTH_SESSION_DATA *id_key_auth_session_data = NULL; /* session data for authHandle */
1084
0
    TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */
1085
0
    TPM_SECRET      *idKeyHmacKey;
1086
0
    TPM_SECRET      *hmacKey;
1087
0
    TPM_KEY     *idKey;     /* Identity key to be activated */
1088
0
    TPM_SECRET      *idKeyUsageAuth;
1089
0
    TPM_BOOL      idPCRStatus;
1090
0
    TPM_DIGEST      h1Digest;   /* digest of public key in idKey */
1091
0
    unsigned char   *b1Blob = NULL;   /* decrypted blob */
1092
0
    uint32_t      b1BlobLength = 0; /* actual valid data */
1093
0
    TPM_STRUCTURE_TAG   hTag;     /* b1 tag in host byte order */
1094
0
    int       vers = 0;   /* version of blob */
1095
0
    unsigned char   *stream;
1096
0
    uint32_t      stream_size;
1097
0
    TPM_EK_BLOB     b1EkBlob;
1098
0
    TPM_ASYM_CA_CONTENTS  b1AsymCaContents;
1099
0
    TPM_SYMMETRIC_KEY   *k1 = NULL;
1100
0
    TPM_EK_BLOB_ACTIVATE  a1;
1101
1102
    /* output parameters */
1103
0
    uint32_t      outParamStart;  /* starting point of outParam's */
1104
0
    uint32_t      outParamEnd;  /* ending point of outParam's */
1105
0
    TPM_DIGEST      outParamDigest;
1106
0
    TPM_SYMMETRIC_KEY   symmetricKey; /* The decrypted symmetric key. */
1107
1108
0
    printf("TPM_Process_ActivateIdentity: Ordinal Entry\n");
1109
0
    TPM_SizedBuffer_Init(&blob);    /* freed @1 */
1110
0
    TPM_SymmetricKey_Init(&symmetricKey); /* freed @2 */
1111
0
    TPM_AsymCaContents_Init(&b1AsymCaContents); /* freed @4 */
1112
0
    TPM_EKBlob_Init(&b1EkBlob);     /* freed @5 */
1113
0
    TPM_EKBlobActivate_Init(&a1);   /* freed @6 */
1114
    /*
1115
      get inputs
1116
    */
1117
    /* get idKey parameter */
1118
0
    if (returnCode == TPM_SUCCESS) {
1119
0
  returnCode = TPM_Load32(&idKeyHandle, &command, &paramSize);
1120
0
    }
1121
    /* save the starting point of inParam's for authorization and auditing */
1122
0
    inParamStart = command;
1123
    /* get blob parameter */
1124
0
    if (returnCode == TPM_SUCCESS) {
1125
0
  returnCode = TPM_SizedBuffer_Load(&blob, &command, &paramSize);
1126
0
    }
1127
    /* save the ending point of inParam's for authorization and auditing */
1128
0
    inParamEnd = command;
1129
    /* digest the input parameters */
1130
0
    if (returnCode == TPM_SUCCESS) {
1131
0
  returnCode = TPM_GetInParamDigest(inParamDigest,  /* output */
1132
0
            &auditStatus,   /* output */
1133
0
            &transportEncrypt,  /* output */
1134
0
            tpm_state,
1135
0
            tag,
1136
0
            ordinal,
1137
0
            inParamStart,
1138
0
            inParamEnd,
1139
0
            transportInternal);
1140
0
    }
1141
    /* check state */
1142
0
    if (returnCode == TPM_SUCCESS) {
1143
0
  returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
1144
0
    }
1145
    /* check tag */
1146
0
    if (returnCode == TPM_SUCCESS) {
1147
0
  returnCode = TPM_CheckRequestTag21(tag);
1148
0
    }
1149
    /* get the optional 'below the line' authorization parameters */
1150
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1151
0
  returnCode = TPM_AuthParams_Get(&idKeyAuthHandle,
1152
0
          &idKeyAuthHandleValid,
1153
0
          idKeynonceOdd,
1154
0
          &continueIdKeySession,
1155
0
          idKeyAuth,
1156
0
          &command, &paramSize);
1157
0
  printf("TPM_Process_ActivateIdentity: idKeyAuthHandle %08x\n", idKeyAuthHandle);
1158
0
    }
1159
    /* get the 'below the line' authorization parameters */
1160
0
    if (returnCode == TPM_SUCCESS) {
1161
0
  returnCode = TPM_AuthParams_Get(&authHandle,
1162
0
          &authHandleValid,
1163
0
          nonceOdd,
1164
0
          &continueAuthSession,
1165
0
          ownerAuth,
1166
0
          &command, &paramSize);
1167
0
    }
1168
0
    if (returnCode == TPM_SUCCESS) {
1169
0
  printf("TPM_Process_ActivateIdentity: authHandle %08x\n", authHandle); 
1170
0
    }
1171
0
    if (returnCode == TPM_SUCCESS) {
1172
0
  if (paramSize != 0) {
1173
0
      printf("TPM_Process_ActivateIdentity: Error, command has %u extra bytes\n",
1174
0
       paramSize);
1175
0
      returnCode = TPM_BAD_PARAM_SIZE;
1176
0
  }
1177
0
    }
1178
    /* do not terminate sessions if the command did not parse correctly */
1179
0
    if (returnCode != TPM_SUCCESS) {
1180
0
  idKeyAuthHandleValid = FALSE;
1181
0
  authHandleValid = FALSE;
1182
0
    }
1183
    /*
1184
      Processing
1185
    */
1186
    /* 1. Using the authHandle field, validate the owner's authorization to execute the command and
1187
       all of the incoming parameters. */
1188
    /* get the session data */
1189
0
    if (returnCode == TPM_SUCCESS) {
1190
0
  returnCode = TPM_AuthSessions_GetData(&auth_session_data,
1191
0
                &hmacKey,
1192
0
                tpm_state,
1193
0
                authHandle,
1194
0
                TPM_PID_NONE,
1195
0
                TPM_ET_OWNER,
1196
0
                ordinal,
1197
0
                NULL,
1198
0
                &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
1199
0
                tpm_state->tpm_permanent_data.ownerAuth);   /* OSAP */
1200
0
    }
1201
    /* Validate the authorization to use the key pointed to by keyHandle */
1202
0
    if (returnCode == TPM_SUCCESS) {
1203
0
  returnCode = TPM_Authdata_Check(tpm_state,
1204
0
          *hmacKey,   /* HMAC key */
1205
0
          inParamDigest,
1206
0
          auth_session_data,  /* authorization session */
1207
0
          nonceOdd,   /* Nonce generated by system
1208
                   associated with authHandle */
1209
0
          continueAuthSession,
1210
0
          ownerAuth);   /* Authorization digest for input */
1211
0
    }
1212
    /* 2. Using the idKeyAuthHandle, validate the authorization to execute command and all of the
1213
       incoming parameters */
1214
    /* get the idKey */
1215
0
    if (returnCode == TPM_SUCCESS) {
1216
0
  returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idKeyHandle,
1217
0
             FALSE,   /* not r/o, using to authenticate */
1218
0
             FALSE,   /* do not ignore PCRs */
1219
0
             FALSE);  /* cannot use EK */
1220
0
    }
1221
    /* get keyHandle -> usageAuth */
1222
0
    if (returnCode == TPM_SUCCESS) {
1223
0
  returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey);
1224
0
    }   
1225
    /* get the session data */
1226
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1227
0
  returnCode = TPM_AuthSessions_GetData(&id_key_auth_session_data,
1228
0
                &idKeyHmacKey,
1229
0
                tpm_state,
1230
0
                idKeyAuthHandle,
1231
0
                TPM_PID_NONE,
1232
0
                TPM_ET_KEYHANDLE,
1233
0
                ordinal,
1234
0
                idKey,
1235
0
                idKeyUsageAuth,   /* OIAP */
1236
0
                idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
1237
0
    }
1238
    /* Validate the authorization to use the key pointed to by keyHandle */
1239
0
    if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1240
0
  returnCode = TPM_Auth2data_Check(tpm_state,
1241
0
           *idKeyHmacKey,   /* HMAC key */
1242
0
           inParamDigest,
1243
0
           id_key_auth_session_data,  /* authorization session */
1244
0
           idKeynonceOdd,   /* Nonce generated by system
1245
                   associated with authHandle */
1246
0
           continueIdKeySession,
1247
0
           idKeyAuth);    /* Authorization digest for input */
1248
0
    }
1249
    /* if there is no idKey authorization, check that the idKey -> authDataUsage is TPM_AUTH_NEVER
1250
       */
1251
0
    if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
1252
0
  if (idKey->authDataUsage != TPM_AUTH_NEVER) {
1253
0
      printf("TPM_Process_ActivateIdentity: Error, ID key authorization required\n");
1254
0
      returnCode = TPM_AUTHFAIL;
1255
0
  }
1256
0
    }
1257
    /* 3. Validate that the idKey is the public key of a valid TPM identity by checking that
1258
       idKeyHandle -> keyUsage is TPM_KEY_IDENTITY. Return TPM_BAD_PARAMETER on mismatch */
1259
0
    if (returnCode == TPM_SUCCESS) {
1260
0
  printf("TPM_Process_ActivateIdentity: Checking for identity key\n");
1261
0
  if (idKey->keyUsage != TPM_KEY_IDENTITY) {
1262
0
      printf("TPM_Process_ActivateIdentity: Error, keyUsage %04hx must be TPM_KEY_IDENTITY\n",
1263
0
       idKey->keyUsage);
1264
0
      returnCode = TPM_BAD_PARAMETER;
1265
0
  }
1266
0
    }
1267
    /* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */
1268
0
    if (returnCode == TPM_SUCCESS) {
1269
0
  returnCode = TPM_Key_GeneratePubkeyDigest(h1Digest, idKey);
1270
0
    }
1271
    /* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */
1272
0
    if (returnCode == TPM_SUCCESS) {
1273
0
  printf("TPM_Process_ActivateIdentity: Decrypting blob with EK\n");
1274
0
  returnCode = TPM_RSAPrivateDecryptMalloc(&b1Blob, /* decrypted data */
1275
0
             &b1BlobLength, /* actual size of b1 data */
1276
0
             blob.buffer,
1277
0
             blob.size,
1278
0
             &(tpm_state->tpm_permanent_data.endorsementKey));
1279
0
    }
1280
    /* 6. Determine the type and version of B1 */
1281
0
    if (returnCode == TPM_SUCCESS) {
1282
0
  stream = b1Blob;    /* b1 must be preserved for the free */
1283
0
  stream_size = b1BlobLength;
1284
  /* convert possible tag to uint16_t */
1285
0
  hTag = ntohs(*(TPM_STRUCTURE_TAG *)b1Blob);
1286
  /* a. If B1 -> tag is TPM_TAG_EK_BLOB then */
1287
0
  if (hTag == TPM_TAG_EK_BLOB) {
1288
      /* i. B1 is a TPM_EK_BLOB */
1289
0
      printf("TPM_Process_ActivateIdentity: b1 is TPM_EK_BLOB\n");
1290
0
      vers = 2;
1291
0
      returnCode = TPM_EKBlob_Load(&b1EkBlob, &stream, &stream_size);
1292
0
  }
1293
  /* b. Else */
1294
0
  else {
1295
      /* i. B1 is a TPM_ASYM_CA_CONTENTS. As there is no tag for this structure it is possible
1296
         for the TPM to make a mistake here but other sections of the structure undergo
1297
         validation */
1298
0
      printf("TPM_Process_ActivateIdentity: b1 is TPM_ASYM_CA_CONTENTS\n");
1299
0
      vers = 1;
1300
0
      returnCode = TPM_AsymCaContents_Load(&b1AsymCaContents, &stream, &stream_size);
1301
0
  }
1302
0
    }
1303
    /* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */
1304
0
    if ((returnCode == TPM_SUCCESS) && (vers == 1)) {
1305
  /* a. Compare H1 to B1 -> idDigest on mismatch return TPM_BAD_PARAMETER */
1306
0
  if (returnCode == TPM_SUCCESS) {
1307
0
      returnCode = TPM_Digest_Compare(h1Digest, b1AsymCaContents.idDigest);
1308
0
      if (returnCode != 0) {
1309
0
    printf("TPM_Process_ActivateIdentity: Error "
1310
0
           "comparing TPM_ASYM_CA_CONTENTS idDigest\n");
1311
0
    returnCode = TPM_BAD_PARAMETER;
1312
0
      }
1313
0
  }
1314
  /* b. Set K1 to B1 -> sessionKey */
1315
0
  if (returnCode == TPM_SUCCESS) {
1316
0
      k1 = &(b1AsymCaContents.sessionKey);
1317
0
  }
1318
0
    }
1319
    /* 8. If B1 is a TPM_EK_BLOB then */
1320
0
    if ((returnCode == TPM_SUCCESS) && (vers == 2)) {
1321
  /* a. Validate that B1 -> ekType is TPM_EK_TYPE_ACTIVATE, return TPM_BAD_TYPE if not. */
1322
0
  if (returnCode == TPM_SUCCESS) {
1323
0
      if (b1EkBlob.ekType != TPM_EK_TYPE_ACTIVATE) {
1324
0
    printf("TPM_Process_ActivateIdentity: Error, "
1325
0
           "TPM_EK_BLOB not ekType TPM_EK_TYPE_ACTIVATE\n");
1326
0
    returnCode = TPM_BAD_TYPE;
1327
0
      }
1328
0
  }
1329
  /* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1 -> blob */
1330
0
  if (returnCode == TPM_SUCCESS) {
1331
0
      stream = b1EkBlob.blob.buffer;
1332
0
      stream_size =  b1EkBlob.blob.size;
1333
0
      returnCode = TPM_EKBlobActivate_Load(&a1, &stream, &stream_size);
1334
0
  }
1335
  /* c. Compare H1 to A1 -> idDigest on mismatch return TPM_BAD_PARAMETER */
1336
0
  if (returnCode == TPM_SUCCESS) {
1337
0
      returnCode = TPM_Digest_Compare(h1Digest, a1.idDigest);
1338
0
      if (returnCode != 0) {
1339
0
    printf("TPM_Process_ActivateIdentity: Error "
1340
0
           "comparing TPM_EK_TYPE_ACTIVATE idDigest\n");
1341
0
    returnCode = TPM_BAD_PARAMETER;
1342
0
      }
1343
0
  }
1344
  /* d. If A1 -> pcrSelection is not NULL */
1345
  /* i. Compute a composite hash C1 using the PCR selection A1 -> pcrSelection */
1346
  /* ii. Compare C1 to A1 -> pcrInfo -> digestAtRelease and return TPM_WRONGPCRVAL on a
1347
     mismatch */
1348
  /* e. If A1 -> pcrInfo specifies a locality ensure that the appropriate locality has been
1349
     asserted, return TPM_BAD_LOCALITY on error */
1350
0
  if (returnCode == TPM_SUCCESS) {
1351
0
      if (returnCode == TPM_SUCCESS) {
1352
0
    returnCode =
1353
0
        TPM_PCRInfoShort_CheckDigest(&(a1.pcrInfo),
1354
0
             tpm_state->tpm_stclear_data.PCRS, /* PCR array */
1355
0
             tpm_state->tpm_stany_flags.localityModifier);
1356
0
      }
1357
0
  }
1358
  /* f. Set K1 to A1 -> symmetricKey */
1359
0
  if (returnCode == TPM_SUCCESS) {
1360
0
      k1 = &(a1.sessionKey);
1361
0
  }
1362
0
    }
1363
    /*
1364
      response
1365
    */
1366
    /* standard response: tag, (dummy) paramSize, returnCode.  Failure is fatal. */
1367
0
    if (rcf == 0) {
1368
0
  printf("TPM_Process_ActivateIdentity: Ordinal returnCode %08x %u\n",
1369
0
         returnCode, returnCode);
1370
0
  rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1371
0
    }
1372
    /* success response, append the rest of the parameters.  */
1373
0
    if (rcf == 0) {
1374
0
  if (returnCode == TPM_SUCCESS) {
1375
      /* checkpoint the beginning of the outParam's */
1376
0
      outParamStart = response->buffer_current - response->buffer;
1377
      /* 9. Return K1 */
1378
0
      returnCode = TPM_SymmetricKey_Store(response, k1);
1379
      /* checkpoint the end of the outParam's */
1380
0
      outParamEnd = response->buffer_current - response->buffer;
1381
0
  }
1382
  /* digest the above the line output parameters */
1383
0
  if (returnCode == TPM_SUCCESS) {
1384
0
      returnCode = TPM_GetOutParamDigest(outParamDigest,  /* output */
1385
0
                 auditStatus, /* input audit status */
1386
0
                 transportEncrypt,
1387
0
                 tag,     
1388
0
                 returnCode,
1389
0
                 ordinal,   /* command ordinal */
1390
0
                 response->buffer + outParamStart,  /* start */
1391
0
                 outParamEnd - outParamStart);  /* length */
1392
0
  }
1393
  /* calculate and set the below the line parameters */
1394
0
  if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1395
0
      returnCode = TPM_AuthParams_Set(response,
1396
0
              *idKeyHmacKey,  /* owner HMAC key */
1397
0
              id_key_auth_session_data,
1398
0
              outParamDigest,
1399
0
              idKeynonceOdd,
1400
0
              continueIdKeySession);
1401
0
  }
1402
  /* calculate and set the below the line parameters */
1403
0
  if (returnCode == TPM_SUCCESS) {
1404
0
      returnCode = TPM_AuthParams_Set(response,
1405
0
              *hmacKey, /* owner HMAC key */
1406
0
              auth_session_data,
1407
0
              outParamDigest,
1408
0
              nonceOdd,
1409
0
              continueAuthSession);
1410
0
  }
1411
  /* audit if required */
1412
0
  if ((returnCode == TPM_SUCCESS) && auditStatus) {
1413
0
      returnCode = TPM_ProcessAudit(tpm_state,
1414
0
            transportEncrypt,
1415
0
            inParamDigest,
1416
0
            outParamDigest,
1417
0
            ordinal);
1418
0
  }
1419
  /* adjust the initial response */
1420
0
  rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1421
0
    }
1422
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1423
0
    if (((rcf != 0) ||
1424
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1425
0
   !continueIdKeySession) &&
1426
0
  idKeyAuthHandleValid) {
1427
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, idKeyAuthHandle);
1428
0
    }
1429
    /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1430
0
    if (((rcf != 0) ||
1431
0
   ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1432
0
   !continueAuthSession) &&
1433
0
  authHandleValid) {
1434
0
  TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1435
0
    }
1436
      
1437
1438
    /*
1439
      cleanup
1440
    */
1441
0
    TPM_SizedBuffer_Delete(&blob);      /* @1 */
1442
0
    TPM_SymmetricKey_Delete(&symmetricKey);   /* @2 */
1443
0
    free(b1Blob);         /* @3 */
1444
0
    TPM_AsymCaContents_Delete(&b1AsymCaContents); /* @4 */
1445
0
    TPM_EKBlob_Delete(&b1EkBlob);     /* @5 */
1446
0
    TPM_EKBlobActivate_Delete(&a1);     /* @6 */
1447
0
    return rcf;
1448
0
}