VirtualBox

source: vbox/trunk/src/libs/libtpms-0.10.0/src/tpm12/tpm_identity.c@ 108932

Last change on this file since 108932 was 108932, checked in by vboxsync, 12 days ago

libtpms-0.10.0: Applied and adjusted our libtpms changes to 0.9.6. jiraref:VBP-1320

File size: 49.5 KB
Line 
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
70void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob)
71{
72 printf(" TPM_EKBlob_Init:\n");
73 tpm_ek_blob->ekType = 0;
74 TPM_SizedBuffer_Init(&(tpm_ek_blob->blob));
75 return;
76}
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
88TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob,
89 unsigned char **stream,
90 uint32_t *stream_size)
91{
92 TPM_RESULT rc = 0;
93
94 printf(" TPM_EKBlob_Load:\n");
95 /* check the tag */
96 if (rc == 0) {
97 rc = TPM_CheckTag(TPM_TAG_EK_BLOB, stream, stream_size);
98 }
99 /* load ekType */
100 if (rc == 0) {
101 rc = TPM_Load16(&(tpm_ek_blob->ekType), stream, stream_size);
102 }
103 /* load blob */
104 if (rc == 0) {
105 rc = TPM_SizedBuffer_Load(&(tpm_ek_blob->blob), stream, stream_size);
106 }
107 return rc;
108}
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
117TPM_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
145void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob)
146{
147 printf(" TPM_EKBlob_Delete:\n");
148 if (tpm_ek_blob != NULL) {
149 TPM_SizedBuffer_Delete(&(tpm_ek_blob->blob));
150 TPM_EKBlob_Init(tpm_ek_blob);
151 }
152 return;
153}
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
166void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
167{
168 printf(" TPM_EKBlobActivate_Init:\n");
169 TPM_SymmetricKey_Init(&(tpm_ek_blob_activate->sessionKey));
170 TPM_Digest_Init(tpm_ek_blob_activate->idDigest);
171 TPM_PCRInfoShort_Init(&(tpm_ek_blob_activate->pcrInfo));
172 return;
173}
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
185TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate,
186 unsigned char **stream,
187 uint32_t *stream_size)
188{
189 TPM_RESULT rc = 0;
190
191 printf(" TPM_EKBlobActivate_Load:\n");
192 /* check tag */
193 if (rc == 0) {
194 rc = TPM_CheckTag(TPM_TAG_EK_BLOB_ACTIVATE, stream, stream_size);
195 }
196 /* load sessionKey */
197 if (rc == 0) {
198 rc = TPM_SymmetricKey_Load(&(tpm_ek_blob_activate->sessionKey), stream, stream_size);
199 }
200 /* load idDigest */
201 if (rc == 0) {
202 rc = TPM_Digest_Load(tpm_ek_blob_activate->idDigest, stream, stream_size);
203 }
204 /* load pcrInfo */
205 if (rc == 0) {
206 rc = TPM_PCRInfoShort_Load(&(tpm_ek_blob_activate->pcrInfo), stream, stream_size, FALSE);
207 }
208 return rc;
209}
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
218TPM_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
253void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
254{
255 printf(" TPM_EKBlobActivate_Delete:\n");
256 if (tpm_ek_blob_activate != NULL) {
257 TPM_SymmetricKey_Delete(&(tpm_ek_blob_activate->sessionKey));
258 TPM_PCRInfoShort_Delete(&(tpm_ek_blob_activate->pcrInfo));
259 TPM_EKBlobActivate_Init(tpm_ek_blob_activate);
260 }
261 return;
262}
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
276void 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
293TPM_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
317TPM_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
341void 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
362void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents)
363{
364 printf(" TPM_IdentityContents_Init:\n");
365 TPM_StructVer_Init(&(tpm_identity_contents->ver));
366 tpm_identity_contents->ordinal = TPM_ORD_MakeIdentity;
367 TPM_Digest_Init(tpm_identity_contents->labelPrivCADigest);
368 TPM_Pubkey_Init(&(tpm_identity_contents->identityPubKey));
369 return;
370}
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
384TPM_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
421TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer,
422 TPM_IDENTITY_CONTENTS *tpm_identity_contents)
423{
424 TPM_RESULT rc = 0;
425
426 printf(" TPM_IdentityContents_Store:\n");
427 /* store ver */
428 if (rc == 0) {
429 rc = TPM_StructVer_Store(sbuffer, &(tpm_identity_contents->ver));
430 }
431 /* store ordinal */
432 if (rc == 0) {
433 rc = TPM_Sbuffer_Append32(sbuffer, tpm_identity_contents->ordinal);
434 }
435 /* store labelPrivCADigest */
436 if (rc == 0) {
437 rc = TPM_Digest_Store(sbuffer, tpm_identity_contents->labelPrivCADigest);
438 }
439 /* store identityPubKey */
440 if (rc == 0) {
441 rc = TPM_Pubkey_Store(sbuffer, &(tpm_identity_contents->identityPubKey));
442 }
443 return rc;
444}
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
455void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents)
456{
457 printf(" TPM_IdentityContents_Delete:\n");
458 if (tpm_identity_contents != NULL) {
459 TPM_Pubkey_Delete(&(tpm_identity_contents->identityPubKey));
460 TPM_IdentityContents_Init(tpm_identity_contents);
461 }
462 return;
463}
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
476void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
477{
478 printf(" TPM_AsymCaContents_Init:\n");
479 TPM_SymmetricKey_Init(&(tpm_asym_ca_contents->sessionKey));
480 TPM_Digest_Init(tpm_asym_ca_contents->idDigest);
481 return;
482}
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
494TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents,
495 unsigned char **stream,
496 uint32_t *stream_size)
497{
498 TPM_RESULT rc = 0;
499
500 printf(" TPM_AsymCaContents_Load:\n");
501 if (rc == 0) {
502 rc = TPM_SymmetricKey_Load(&(tpm_asym_ca_contents->sessionKey), stream, stream_size);
503 }
504 if (rc == 0) {
505 rc = TPM_Digest_Load(tpm_asym_ca_contents->idDigest, stream, stream_size);
506 }
507 return rc;
508}
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
517TPM_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
542void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
543{
544 printf(" TPM_AsymCaContents_Delete:\n");
545 if (tpm_asym_ca_contents != NULL) {
546 TPM_SymmetricKey_Delete(&(tpm_asym_ca_contents->sessionKey));
547 TPM_AsymCaContents_Init(tpm_asym_ca_contents);
548 }
549 return;
550}
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
588TPM_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{
596 TPM_RESULT rcf = 0; /* fatal error precluding response */
597 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
598
599 /* input parameters */
600 TPM_ENCAUTH identityAuth; /* Encrypted usage authorization data for the new identity
601 */
602 TPM_CHOSENID_HASH labelPrivCADigest; /* The digest of the identity label and privacy CA
603 chosen for the new TPM identity. */
604 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 TPM_AUTHHANDLE srkAuthHandle; /* The authorization handle used for SRK authorization. */
608 TPM_NONCE srknonceOdd; /* Nonce generated by system associated with srkAuthHandle
609 */
610 TPM_BOOL continueSrkSession = TRUE; /* Ignored */
611 TPM_AUTHDATA srkAuth; /* The authorization digest for the inputs and the SRK. HMAC
612 key: srk.usageAuth. */
613 TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner
614 authorization. Session type MUST be OSAP. */
615 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
616 TPM_BOOL continueAuthSession = TRUE; /* Ignored */
617 TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner. HMAC key:
618 ownerAuth. */
619 /* processing parameters */
620 unsigned char * inParamStart; /* starting point of inParam's */
621 unsigned char * inParamEnd; /* ending point of inParam's */
622 TPM_DIGEST inParamDigest;
623 TPM_BOOL auditStatus; /* audit the ordinal */
624 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
625 TPM_BOOL srkAuthHandleValid = FALSE;
626 TPM_BOOL authHandleValid = FALSE;
627 TPM_AUTH_SESSION_DATA *srk_auth_session_data = NULL; /* session data for authHandle */
628 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */
629 TPM_SECRET *srkHmacKey;
630 TPM_SECRET *hmacKey;
631 TPM_SECRET a1Auth;
632 TPM_STORE_ASYMKEY *idKeyStoreAsymkey;
633 TPM_IDENTITY_CONTENTS idContents;
634 TPM_DIGEST h1Digest; /* digest of TPM_IDENTITY_CONTENTS structure */
635 int ver;
636
637 /* output parameters */
638 uint32_t outParamStart; /* starting point of outParam's */
639 uint32_t outParamEnd; /* ending point of outParam's */
640 TPM_DIGEST outParamDigest;
641 TPM_KEY idKey; /* The newly created identity key. MAY be TPM_KEY12
642 */
643 TPM_SIZED_BUFFER identityBinding; /* Signature of TPM_IDENTITY_CONTENTS using
644 idKey.private. */
645 printf("TPM_Process_MakeIdentity: Ordinal Entry\n");
646 TPM_Key_Init(&idKeyParams); /* freed @1 */
647 TPM_Key_Init(&idKey); /* freed @2 */
648 TPM_SizedBuffer_Init(&identityBinding); /* freed @3 */
649 TPM_IdentityContents_Init(&idContents); /* freed @4 */
650 /*
651 get inputs
652 */
653 /* save the starting point of inParam's for authorization and auditing */
654 inParamStart = command;
655 /* get identityAuth parameter */
656 if (returnCode == TPM_SUCCESS) {
657 returnCode = TPM_Authdata_Load(identityAuth, &command, &paramSize);
658 }
659 /* get labelPrivCADigest parameter */
660 if (returnCode == TPM_SUCCESS) {
661 returnCode = TPM_Digest_Load(labelPrivCADigest, &command, &paramSize);
662 }
663 /* get idKeyParams parameter */
664 if (returnCode == TPM_SUCCESS) {
665 returnCode = TPM_Key_Load(&idKeyParams, &command, &paramSize);
666 }
667 /* save the ending point of inParam's for authorization and auditing */
668 inParamEnd = command;
669 /* digest the input parameters */
670 if (returnCode == TPM_SUCCESS) {
671 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
672 &auditStatus, /* output */
673 &transportEncrypt, /* output */
674 tpm_state,
675 tag,
676 ordinal,
677 inParamStart,
678 inParamEnd,
679 transportInternal);
680 }
681 /* check state */
682 if (returnCode == TPM_SUCCESS) {
683 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
684 }
685 /* check tag */
686 if (returnCode == TPM_SUCCESS) {
687 returnCode = TPM_CheckRequestTag21(tag);
688 }
689 /* get the optional 'below the line' authorization parameters */
690 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
691 returnCode = TPM_AuthParams_Get(&srkAuthHandle,
692 &srkAuthHandleValid,
693 srknonceOdd,
694 &continueSrkSession,
695 srkAuth,
696 &command, &paramSize);
697 printf("TPM_Process_MakeIdentity: srkAuthHandle %08x\n", srkAuthHandle);
698 }
699 /* get the 'below the line' authorization parameters */
700 if (returnCode == TPM_SUCCESS) {
701 returnCode = TPM_AuthParams_Get(&authHandle,
702 &authHandleValid,
703 nonceOdd,
704 &continueAuthSession,
705 ownerAuth,
706 &command, &paramSize);
707 }
708 if (returnCode == TPM_SUCCESS) {
709 printf("TPM_Process_MakeIdentity: authHandle %08x\n", authHandle);
710 }
711 if (returnCode == TPM_SUCCESS) {
712 if (paramSize != 0) {
713 printf("TPM_Process_MakeIdentity: Error, command has %u extra bytes\n",
714 paramSize);
715 returnCode = TPM_BAD_PARAM_SIZE;
716 }
717 }
718 /* do not terminate sessions if the command did not parse correctly */
719 if (returnCode != TPM_SUCCESS) {
720 srkAuthHandleValid = FALSE;
721 authHandleValid = FALSE;
722 }
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 if (returnCode == TPM_SUCCESS) {
736 returnCode = TPM_Key_CheckProperties(&ver, &idKeyParams, 2048,
737 tpm_state->tpm_permanent_flags.FIPS);
738 printf("TPM_Process_MakeIdentity: key parameters v = %d\n", ver);
739 }
740 /* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity input
741 parameters. */
742 /* get the session data */
743 if (returnCode == TPM_SUCCESS) {
744 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
745 &hmacKey,
746 tpm_state,
747 authHandle,
748 TPM_PID_OSAP,
749 TPM_ET_OWNER,
750 ordinal,
751 NULL,
752 NULL,
753 tpm_state->tpm_permanent_data.ownerAuth);
754 }
755 /* Validate the authorization to use the key pointed to by keyHandle */
756 if (returnCode == TPM_SUCCESS) {
757 returnCode = TPM_Auth2data_Check(tpm_state,
758 *hmacKey, /* HMAC key */
759 inParamDigest,
760 auth_session_data, /* authorization session */
761 nonceOdd, /* Nonce generated by system
762 associated with authHandle */
763 continueAuthSession,
764 ownerAuth); /* Authorization digest for input */
765 }
766 /* 3. Use srkAuthHandle to verify that the SRK owner authorized all TPM_MakeIdentity input
767 parameters. */
768 /* get the session data */
769 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
770 returnCode = TPM_AuthSessions_GetData
771 (&srk_auth_session_data,
772 &srkHmacKey,
773 tpm_state,
774 srkAuthHandle,
775 TPM_PID_NONE,
776 TPM_ET_KEYHANDLE,
777 ordinal,
778 &(tpm_state->tpm_permanent_data.srk),
779 /* OIAP */
780 &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth),
781 /* OSAP */
782 tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest);
783 }
784 /* Validate the authorization to use the key pointed to by keyHandle */
785 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
786 returnCode = TPM_Authdata_Check(tpm_state,
787 *srkHmacKey, /* HMAC key */
788 inParamDigest,
789 srk_auth_session_data, /* authorization session */
790 srknonceOdd, /* Nonce generated by system
791 associated with authHandle */
792 continueSrkSession,
793 srkAuth); /* Authorization digest for input */
794 }
795 /* if there is no SRK authorization, check that the SRK authDataUsage is TPM_AUTH_NEVER */
796 if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
797 if (tpm_state->tpm_permanent_data.srk.authDataUsage != TPM_AUTH_NEVER) {
798 printf("TPM_Process_MakeIdentity: Error, SRK authorization required\n");
799 returnCode = TPM_AUTHFAIL;
800 }
801 }
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 if (returnCode == TPM_SUCCESS) {
806 printf("TPM_Process_MakeIdentity: Checking key parameters\n");
807 if (idKeyParams.keyUsage != TPM_KEY_IDENTITY) {
808 printf("TPM_Process_MakeIdentity: Error, "
809 "idKeyParams keyUsage %08x should be TPM_KEY_IDENTITY\n",
810 idKeyParams.keyUsage);
811 returnCode = TPM_INVALID_KEYUSAGE;
812 }
813 }
814 /* 5. Verify that idKeyParams -> keyFlags -> migratable is FALSE. If it is not, return
815 TPM_INVALID_KEYUSAGE */
816 if (returnCode == TPM_SUCCESS) {
817 if (idKeyParams.keyFlags & TPM_MIGRATABLE) {
818 printf("TPM_Process_MakeIdentity: Error, "
819 "idKeyParams keyFlags %08x cannot be migratable\n",
820 idKeyParams.keyFlags);
821 returnCode = TPM_INVALID_KEYUSAGE;
822 }
823 }
824 /* 6. Create a1 by decrypting identityAuth according to the ADIP indicated by authHandle. */
825 if (returnCode == TPM_SUCCESS) {
826 returnCode = TPM_AuthSessionData_Decrypt(a1Auth,
827 NULL,
828 identityAuth,
829 auth_session_data,
830 NULL,
831 NULL,
832 FALSE); /* even and odd */
833 }
834 /* 7. Set continueAuthSession and continueSRKSession to FALSE. */
835 if (returnCode == TPM_SUCCESS) {
836 continueAuthSession = FALSE;
837 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 }
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 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 printf("TPM_Process_MakeIdentity: Generating key\n");
862 returnCode = TPM_Key_GenerateRSA(&idKey,
863 tpm_state,
864 &(tpm_state->tpm_permanent_data.srk), /* parent key */
865 tpm_state->tpm_stclear_data.PCRS, /* PCR array */
866 ver,
867 idKeyParams.keyUsage,
868 idKeyParams.keyFlags,
869 idKeyParams.authDataUsage, /* TPM_AUTH_DATA_USAGE */
870 &(idKeyParams.algorithmParms), /* TPM_KEY_PARMS */
871 idKeyParams.tpm_pcr_info, /* TPM_PCR_INFO */
872 idKeyParams.tpm_pcr_info_long);/* TPM_PCR_INFO_LONG */
873
874 }
875 /* 11. Ensure that the authorization information in A1 is properly stored in the idKey as
876 usageAuth. */
877 if (returnCode == TPM_SUCCESS) {
878 returnCode = TPM_Key_GetStoreAsymkey(&idKeyStoreAsymkey,
879 &idKey);
880 }
881 if (returnCode == TPM_SUCCESS) {
882 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 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 }
890 /* 15. Encrypt the private portion of idKey using the SRK as the parent key */
891 if (returnCode == TPM_SUCCESS) {
892 printf("TPM_Process_MakeIdentity: Encrypting key private part with SRK\n");
893 returnCode = TPM_Key_GenerateEncData(&idKey, &(tpm_state->tpm_permanent_data.srk));
894 }
895 /* 16. Create a TPM_IDENTITY_CONTENTS structure named idContents using labelPrivCADigest and the
896 information from idKey */
897 if (returnCode == TPM_SUCCESS) {
898 TPM_Digest_Copy(idContents.labelPrivCADigest, labelPrivCADigest);
899 returnCode = TPM_Pubkey_Set(&(idContents.identityPubKey), &idKey);
900 }
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 if (returnCode == TPM_SUCCESS) {
906 returnCode = TPM_SHA1_GenerateStructure(h1Digest,
907 &idContents,
908 (TPM_STORE_FUNCTION_T)TPM_IdentityContents_Store);
909 }
910 /* sign the digest */
911 if (returnCode == TPM_SUCCESS) {
912 printf("TPM_Process_MakeIdentity: Signing digest of TPM_IDENTITY_CONTENTS\n");
913 returnCode = TPM_RSASignToSizedBuffer(&identityBinding, h1Digest, TPM_DIGEST_SIZE, &idKey);
914 }
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 if (rcf == 0) {
949 printf("TPM_Process_MakeIdentity: Ordinal returnCode %08x %u\n",
950 returnCode, returnCode);
951 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
952 }
953 /* success response, append the rest of the parameters. */
954 if (rcf == 0) {
955 if (returnCode == TPM_SUCCESS) {
956 /* checkpoint the beginning of the outParam's */
957 outParamStart = response->buffer_current - response->buffer;
958 /* return idKey */
959 returnCode = TPM_Key_Store(response, &idKey);
960 }
961 if (returnCode == TPM_SUCCESS) {
962 /* return identityBinding */
963 returnCode = TPM_SizedBuffer_Store(response, &identityBinding);
964 /* checkpoint the end of the outParam's */
965 outParamEnd = response->buffer_current - response->buffer;
966 }
967 /* digest the above the line output parameters */
968 if (returnCode == TPM_SUCCESS) {
969 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
970 auditStatus, /* input audit status */
971 transportEncrypt,
972 tag,
973 returnCode,
974 ordinal, /* command ordinal */
975 response->buffer + outParamStart, /* start */
976 outParamEnd - outParamStart); /* length */
977 }
978 /* calculate and set the below the line parameters */
979 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
980 returnCode = TPM_AuthParams_Set(response,
981 *srkHmacKey, /* owner HMAC key */
982 srk_auth_session_data,
983 outParamDigest,
984 srknonceOdd,
985 continueSrkSession);
986 }
987 /* calculate and set the below the line parameters */
988 if (returnCode == TPM_SUCCESS) {
989 returnCode = TPM_AuthParams_Set(response,
990 *hmacKey, /* owner HMAC key */
991 auth_session_data,
992 outParamDigest,
993 nonceOdd,
994 continueAuthSession);
995 }
996 /* audit if required */
997 if ((returnCode == TPM_SUCCESS) && auditStatus) {
998 returnCode = TPM_ProcessAudit(tpm_state,
999 transportEncrypt,
1000 inParamDigest,
1001 outParamDigest,
1002 ordinal);
1003 }
1004 /* adjust the initial response */
1005 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1006 }
1007 /* if there was an error, or continueSrkSession is FALSE, terminate the session */
1008 if (((rcf != 0) ||
1009 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1010 !continueSrkSession) &&
1011 srkAuthHandleValid) {
1012 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, srkAuthHandle);
1013 }
1014 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1015 if (((rcf != 0) ||
1016 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1017 !continueAuthSession) &&
1018 authHandleValid) {
1019 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1020 }
1021 /*
1022 cleanup
1023 */
1024 TPM_Key_Delete(&idKeyParams); /* freed @1 */
1025 TPM_Key_Delete(&idKey); /* freed @2 */
1026 TPM_SizedBuffer_Delete(&identityBinding); /* freed @3 */
1027 TPM_IdentityContents_Delete(&idContents); /* freed @4 */
1028 return rcf;
1029}
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
1047TPM_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{
1055 TPM_RESULT rcf = 0; /* fatal error precluding response */
1056 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
1057
1058 /* input parameters */
1059 TPM_KEY_HANDLE idKeyHandle; /* handle of identity key to be activated */
1060 TPM_SIZED_BUFFER blob; /* The encrypted ASYM_CA_CONTENTS or TPM_EK_BLOB */
1061 TPM_AUTHHANDLE idKeyAuthHandle; /* The authorization handle used for ID key
1062 authorization. */
1063 TPM_NONCE idKeynonceOdd; /* Nonce generated by system associated with idKeyAuthHandle
1064 */
1065 TPM_BOOL continueIdKeySession = TRUE; /* Continue usage flag for idKeyAuthHandle. */
1066 TPM_AUTHDATA idKeyAuth; /* The authorization digest for the inputs and ID key. HMAC
1067 key: idKey.usageAuth. */
1068 TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */
1069 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
1070 TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization
1071 handle */
1072 TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and
1073 owner. HMAC key: ownerAuth. */
1074
1075 /* processing parameters */
1076 unsigned char * inParamStart; /* starting point of inParam's */
1077 unsigned char * inParamEnd; /* ending point of inParam's */
1078 TPM_DIGEST inParamDigest;
1079 TPM_BOOL auditStatus; /* audit the ordinal */
1080 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
1081 TPM_BOOL idKeyAuthHandleValid = FALSE;
1082 TPM_BOOL authHandleValid = FALSE;
1083 TPM_AUTH_SESSION_DATA *id_key_auth_session_data = NULL; /* session data for authHandle */
1084 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */
1085 TPM_SECRET *idKeyHmacKey;
1086 TPM_SECRET *hmacKey;
1087 TPM_KEY *idKey; /* Identity key to be activated */
1088 TPM_SECRET *idKeyUsageAuth;
1089 TPM_BOOL idPCRStatus;
1090 TPM_DIGEST h1Digest; /* digest of public key in idKey */
1091 unsigned char *b1Blob = NULL; /* decrypted blob */
1092 uint32_t b1BlobLength = 0; /* actual valid data */
1093 TPM_STRUCTURE_TAG hTag; /* b1 tag in host byte order */
1094 int vers = 0; /* version of blob */
1095 unsigned char *stream;
1096 uint32_t stream_size;
1097 TPM_EK_BLOB b1EkBlob;
1098 TPM_ASYM_CA_CONTENTS b1AsymCaContents;
1099 TPM_SYMMETRIC_KEY *k1 = NULL;
1100 TPM_EK_BLOB_ACTIVATE a1;
1101
1102 /* output parameters */
1103 uint32_t outParamStart; /* starting point of outParam's */
1104 uint32_t outParamEnd; /* ending point of outParam's */
1105 TPM_DIGEST outParamDigest;
1106 TPM_SYMMETRIC_KEY symmetricKey; /* The decrypted symmetric key. */
1107
1108 printf("TPM_Process_ActivateIdentity: Ordinal Entry\n");
1109 TPM_SizedBuffer_Init(&blob); /* freed @1 */
1110 TPM_SymmetricKey_Init(&symmetricKey); /* freed @2 */
1111 TPM_AsymCaContents_Init(&b1AsymCaContents); /* freed @4 */
1112 TPM_EKBlob_Init(&b1EkBlob); /* freed @5 */
1113 TPM_EKBlobActivate_Init(&a1); /* freed @6 */
1114 /*
1115 get inputs
1116 */
1117 /* get idKey parameter */
1118 if (returnCode == TPM_SUCCESS) {
1119 returnCode = TPM_Load32(&idKeyHandle, &command, &paramSize);
1120 }
1121 /* save the starting point of inParam's for authorization and auditing */
1122 inParamStart = command;
1123 /* get blob parameter */
1124 if (returnCode == TPM_SUCCESS) {
1125 returnCode = TPM_SizedBuffer_Load(&blob, &command, &paramSize);
1126 }
1127 /* save the ending point of inParam's for authorization and auditing */
1128 inParamEnd = command;
1129 /* digest the input parameters */
1130 if (returnCode == TPM_SUCCESS) {
1131 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
1132 &auditStatus, /* output */
1133 &transportEncrypt, /* output */
1134 tpm_state,
1135 tag,
1136 ordinal,
1137 inParamStart,
1138 inParamEnd,
1139 transportInternal);
1140 }
1141 /* check state */
1142 if (returnCode == TPM_SUCCESS) {
1143 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
1144 }
1145 /* check tag */
1146 if (returnCode == TPM_SUCCESS) {
1147 returnCode = TPM_CheckRequestTag21(tag);
1148 }
1149 /* get the optional 'below the line' authorization parameters */
1150 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1151 returnCode = TPM_AuthParams_Get(&idKeyAuthHandle,
1152 &idKeyAuthHandleValid,
1153 idKeynonceOdd,
1154 &continueIdKeySession,
1155 idKeyAuth,
1156 &command, &paramSize);
1157 printf("TPM_Process_ActivateIdentity: idKeyAuthHandle %08x\n", idKeyAuthHandle);
1158 }
1159 /* get the 'below the line' authorization parameters */
1160 if (returnCode == TPM_SUCCESS) {
1161 returnCode = TPM_AuthParams_Get(&authHandle,
1162 &authHandleValid,
1163 nonceOdd,
1164 &continueAuthSession,
1165 ownerAuth,
1166 &command, &paramSize);
1167 }
1168 if (returnCode == TPM_SUCCESS) {
1169 printf("TPM_Process_ActivateIdentity: authHandle %08x\n", authHandle);
1170 }
1171 if (returnCode == TPM_SUCCESS) {
1172 if (paramSize != 0) {
1173 printf("TPM_Process_ActivateIdentity: Error, command has %u extra bytes\n",
1174 paramSize);
1175 returnCode = TPM_BAD_PARAM_SIZE;
1176 }
1177 }
1178 /* do not terminate sessions if the command did not parse correctly */
1179 if (returnCode != TPM_SUCCESS) {
1180 idKeyAuthHandleValid = FALSE;
1181 authHandleValid = FALSE;
1182 }
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 if (returnCode == TPM_SUCCESS) {
1190 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
1191 &hmacKey,
1192 tpm_state,
1193 authHandle,
1194 TPM_PID_NONE,
1195 TPM_ET_OWNER,
1196 ordinal,
1197 NULL,
1198 &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
1199 tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */
1200 }
1201 /* Validate the authorization to use the key pointed to by keyHandle */
1202 if (returnCode == TPM_SUCCESS) {
1203 returnCode = TPM_Authdata_Check(tpm_state,
1204 *hmacKey, /* HMAC key */
1205 inParamDigest,
1206 auth_session_data, /* authorization session */
1207 nonceOdd, /* Nonce generated by system
1208 associated with authHandle */
1209 continueAuthSession,
1210 ownerAuth); /* Authorization digest for input */
1211 }
1212 /* 2. Using the idKeyAuthHandle, validate the authorization to execute command and all of the
1213 incoming parameters */
1214 /* get the idKey */
1215 if (returnCode == TPM_SUCCESS) {
1216 returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idKeyHandle,
1217 FALSE, /* not r/o, using to authenticate */
1218 FALSE, /* do not ignore PCRs */
1219 FALSE); /* cannot use EK */
1220 }
1221 /* get keyHandle -> usageAuth */
1222 if (returnCode == TPM_SUCCESS) {
1223 returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey);
1224 }
1225 /* get the session data */
1226 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1227 returnCode = TPM_AuthSessions_GetData(&id_key_auth_session_data,
1228 &idKeyHmacKey,
1229 tpm_state,
1230 idKeyAuthHandle,
1231 TPM_PID_NONE,
1232 TPM_ET_KEYHANDLE,
1233 ordinal,
1234 idKey,
1235 idKeyUsageAuth, /* OIAP */
1236 idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
1237 }
1238 /* Validate the authorization to use the key pointed to by keyHandle */
1239 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1240 returnCode = TPM_Auth2data_Check(tpm_state,
1241 *idKeyHmacKey, /* HMAC key */
1242 inParamDigest,
1243 id_key_auth_session_data, /* authorization session */
1244 idKeynonceOdd, /* Nonce generated by system
1245 associated with authHandle */
1246 continueIdKeySession,
1247 idKeyAuth); /* Authorization digest for input */
1248 }
1249 /* if there is no idKey authorization, check that the idKey -> authDataUsage is TPM_AUTH_NEVER
1250 */
1251 if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
1252 if (idKey->authDataUsage != TPM_AUTH_NEVER) {
1253 printf("TPM_Process_ActivateIdentity: Error, ID key authorization required\n");
1254 returnCode = TPM_AUTHFAIL;
1255 }
1256 }
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 if (returnCode == TPM_SUCCESS) {
1260 printf("TPM_Process_ActivateIdentity: Checking for identity key\n");
1261 if (idKey->keyUsage != TPM_KEY_IDENTITY) {
1262 printf("TPM_Process_ActivateIdentity: Error, keyUsage %04hx must be TPM_KEY_IDENTITY\n",
1263 idKey->keyUsage);
1264 returnCode = TPM_BAD_PARAMETER;
1265 }
1266 }
1267 /* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */
1268 if (returnCode == TPM_SUCCESS) {
1269 returnCode = TPM_Key_GeneratePubkeyDigest(h1Digest, idKey);
1270 }
1271 /* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */
1272 if (returnCode == TPM_SUCCESS) {
1273 printf("TPM_Process_ActivateIdentity: Decrypting blob with EK\n");
1274 returnCode = TPM_RSAPrivateDecryptMalloc(&b1Blob, /* decrypted data */
1275 &b1BlobLength, /* actual size of b1 data */
1276 blob.buffer,
1277 blob.size,
1278 &(tpm_state->tpm_permanent_data.endorsementKey));
1279 }
1280 /* 6. Determine the type and version of B1 */
1281 if (returnCode == TPM_SUCCESS) {
1282 stream = b1Blob; /* b1 must be preserved for the free */
1283 stream_size = b1BlobLength;
1284 /* convert possible tag to uint16_t */
1285 hTag = ntohs(*(TPM_STRUCTURE_TAG *)b1Blob);
1286 /* a. If B1 -> tag is TPM_TAG_EK_BLOB then */
1287 if (hTag == TPM_TAG_EK_BLOB) {
1288 /* i. B1 is a TPM_EK_BLOB */
1289 printf("TPM_Process_ActivateIdentity: b1 is TPM_EK_BLOB\n");
1290 vers = 2;
1291 returnCode = TPM_EKBlob_Load(&b1EkBlob, &stream, &stream_size);
1292 }
1293 /* b. Else */
1294 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 printf("TPM_Process_ActivateIdentity: b1 is TPM_ASYM_CA_CONTENTS\n");
1299 vers = 1;
1300 returnCode = TPM_AsymCaContents_Load(&b1AsymCaContents, &stream, &stream_size);
1301 }
1302 }
1303 /* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */
1304 if ((returnCode == TPM_SUCCESS) && (vers == 1)) {
1305 /* a. Compare H1 to B1 -> idDigest on mismatch return TPM_BAD_PARAMETER */
1306 if (returnCode == TPM_SUCCESS) {
1307 returnCode = TPM_Digest_Compare(h1Digest, b1AsymCaContents.idDigest);
1308 if (returnCode != 0) {
1309 printf("TPM_Process_ActivateIdentity: Error "
1310 "comparing TPM_ASYM_CA_CONTENTS idDigest\n");
1311 returnCode = TPM_BAD_PARAMETER;
1312 }
1313 }
1314 /* b. Set K1 to B1 -> sessionKey */
1315 if (returnCode == TPM_SUCCESS) {
1316 k1 = &(b1AsymCaContents.sessionKey);
1317 }
1318 }
1319 /* 8. If B1 is a TPM_EK_BLOB then */
1320 if ((returnCode == TPM_SUCCESS) && (vers == 2)) {
1321 /* a. Validate that B1 -> ekType is TPM_EK_TYPE_ACTIVATE, return TPM_BAD_TYPE if not. */
1322 if (returnCode == TPM_SUCCESS) {
1323 if (b1EkBlob.ekType != TPM_EK_TYPE_ACTIVATE) {
1324 printf("TPM_Process_ActivateIdentity: Error, "
1325 "TPM_EK_BLOB not ekType TPM_EK_TYPE_ACTIVATE\n");
1326 returnCode = TPM_BAD_TYPE;
1327 }
1328 }
1329 /* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1 -> blob */
1330 if (returnCode == TPM_SUCCESS) {
1331 stream = b1EkBlob.blob.buffer;
1332 stream_size = b1EkBlob.blob.size;
1333 returnCode = TPM_EKBlobActivate_Load(&a1, &stream, &stream_size);
1334 }
1335 /* c. Compare H1 to A1 -> idDigest on mismatch return TPM_BAD_PARAMETER */
1336 if (returnCode == TPM_SUCCESS) {
1337 returnCode = TPM_Digest_Compare(h1Digest, a1.idDigest);
1338 if (returnCode != 0) {
1339 printf("TPM_Process_ActivateIdentity: Error "
1340 "comparing TPM_EK_TYPE_ACTIVATE idDigest\n");
1341 returnCode = TPM_BAD_PARAMETER;
1342 }
1343 }
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 if (returnCode == TPM_SUCCESS) {
1351 if (returnCode == TPM_SUCCESS) {
1352 returnCode =
1353 TPM_PCRInfoShort_CheckDigest(&(a1.pcrInfo),
1354 tpm_state->tpm_stclear_data.PCRS, /* PCR array */
1355 tpm_state->tpm_stany_flags.localityModifier);
1356 }
1357 }
1358 /* f. Set K1 to A1 -> symmetricKey */
1359 if (returnCode == TPM_SUCCESS) {
1360 k1 = &(a1.sessionKey);
1361 }
1362 }
1363 /*
1364 response
1365 */
1366 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
1367 if (rcf == 0) {
1368 printf("TPM_Process_ActivateIdentity: Ordinal returnCode %08x %u\n",
1369 returnCode, returnCode);
1370 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1371 }
1372 /* success response, append the rest of the parameters. */
1373 if (rcf == 0) {
1374 if (returnCode == TPM_SUCCESS) {
1375 /* checkpoint the beginning of the outParam's */
1376 outParamStart = response->buffer_current - response->buffer;
1377 /* 9. Return K1 */
1378 returnCode = TPM_SymmetricKey_Store(response, k1);
1379 /* checkpoint the end of the outParam's */
1380 outParamEnd = response->buffer_current - response->buffer;
1381 }
1382 /* digest the above the line output parameters */
1383 if (returnCode == TPM_SUCCESS) {
1384 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
1385 auditStatus, /* input audit status */
1386 transportEncrypt,
1387 tag,
1388 returnCode,
1389 ordinal, /* command ordinal */
1390 response->buffer + outParamStart, /* start */
1391 outParamEnd - outParamStart); /* length */
1392 }
1393 /* calculate and set the below the line parameters */
1394 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1395 returnCode = TPM_AuthParams_Set(response,
1396 *idKeyHmacKey, /* owner HMAC key */
1397 id_key_auth_session_data,
1398 outParamDigest,
1399 idKeynonceOdd,
1400 continueIdKeySession);
1401 }
1402 /* calculate and set the below the line parameters */
1403 if (returnCode == TPM_SUCCESS) {
1404 returnCode = TPM_AuthParams_Set(response,
1405 *hmacKey, /* owner HMAC key */
1406 auth_session_data,
1407 outParamDigest,
1408 nonceOdd,
1409 continueAuthSession);
1410 }
1411 /* audit if required */
1412 if ((returnCode == TPM_SUCCESS) && auditStatus) {
1413 returnCode = TPM_ProcessAudit(tpm_state,
1414 transportEncrypt,
1415 inParamDigest,
1416 outParamDigest,
1417 ordinal);
1418 }
1419 /* adjust the initial response */
1420 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1421 }
1422 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1423 if (((rcf != 0) ||
1424 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1425 !continueIdKeySession) &&
1426 idKeyAuthHandleValid) {
1427 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, idKeyAuthHandle);
1428 }
1429 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1430 if (((rcf != 0) ||
1431 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1432 !continueAuthSession) &&
1433 authHandleValid) {
1434 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1435 }
1436
1437
1438 /*
1439 cleanup
1440 */
1441 TPM_SizedBuffer_Delete(&blob); /* @1 */
1442 TPM_SymmetricKey_Delete(&symmetricKey); /* @2 */
1443 free(b1Blob); /* @3 */
1444 TPM_AsymCaContents_Delete(&b1AsymCaContents); /* @4 */
1445 TPM_EKBlob_Delete(&b1EkBlob); /* @5 */
1446 TPM_EKBlobActivate_Delete(&a1); /* @6 */
1447 return rcf;
1448}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette