VirtualBox

source: vbox/trunk/src/libs/libtpms-0.9.0/src/tpm12/tpm_storage.c@ 91612

最後變更 在這個檔案從91612是 91612,由 vboxsync 提交於 3 年 前

src/libs: Export libtpms-0.9.0, bugref:10078

檔案大小: 133.9 KB
 
1/********************************************************************************/
2/* */
3/* Storage Functions */
4/* Written by Ken Goldman */
5/* IBM Thomas J. Watson Research Center */
6/* $Id: tpm_storage.c 4442 2011-02-14 20:20:01Z 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#include <string.h>
43
44#include "tpm_auth.h"
45#include "tpm_cryptoh.h"
46#include "tpm_crypto.h"
47#include "tpm_debug.h"
48#include "tpm_digest.h"
49#include "tpm_error.h"
50#include "tpm_io.h"
51#include "tpm_key.h"
52#include "tpm_memory.h"
53#include "tpm_nonce.h"
54#include "tpm_pcr.h"
55#include "tpm_process.h"
56#include "tpm_secret.h"
57#include "tpm_structures.h"
58#include "tpm_ver.h"
59
60#include "tpm_storage.h"
61
62/* local function prototypes */
63
64static TPM_RESULT TPM_SealCryptCommon(BYTE **o1,
65 TPM_ADIP_ENC_SCHEME adipEncScheme,
66 TPM_SIZED_BUFFER *inData,
67 TPM_AUTH_SESSION_DATA *auth_session_data,
68 TPM_NONCE nonceOdd);
69
70static TPM_RESULT TPM_LoadKeyCommon(TPM_KEY_HANDLE *inKeyHandle,
71 TPM_BOOL *key_added,
72 TPM_SECRET **hmacKey,
73 TPM_AUTH_SESSION_DATA **auth_session_data,
74 tpm_state_t *tpm_state,
75 TPM_TAG tag,
76 TPM_COMMAND_CODE ordinal,
77 TPM_KEY_HANDLE parentHandle,
78 TPM_KEY *inKey,
79 TPM_DIGEST inParamDigest,
80 TPM_AUTHHANDLE authHandle,
81 TPM_NONCE nonceOdd,
82 TPM_BOOL continueAuthSession,
83 TPM_AUTHDATA parentAuth);
84
85/*
86 TPM_BOUND_DATA
87*/
88
89/* TPM_BoundData_Init()
90
91 sets members to default values
92 sets all pointers to NULL and sizes to 0
93 always succeeds - no return code
94*/
95
96void TPM_BoundData_Init(TPM_BOUND_DATA *tpm_bound_data)
97{
98 printf(" TPM_BoundData_Init:\n");
99 TPM_StructVer_Init(&(tpm_bound_data->ver));
100 tpm_bound_data->payload = TPM_PT_BIND;
101 tpm_bound_data->payloadDataSize = 0;
102 tpm_bound_data->payloadData = NULL;
103 return;
104}
105
106/* TPM_BoundData_Load()
107
108 deserialize the structure from a 'stream'
109 'stream_size' is checked for sufficient data
110 returns 0 or error codes
111
112 Before use, call TPM_BoundData_Init()
113 After use, call TPM_BoundData_Delete() to free memory
114*/
115
116TPM_RESULT TPM_BoundData_Load(TPM_BOUND_DATA *tpm_bound_data,
117 unsigned char **stream,
118 uint32_t *stream_size)
119{
120 TPM_RESULT rc = 0;
121
122 printf(" TPM_BoundData_Load:\n");
123 if (rc == 0) {
124 rc = TPM_StructVer_Load(&(tpm_bound_data->ver), stream, stream_size);
125 }
126 /* check ver immediately to ease debugging */
127 if (rc == 0) {
128 rc = TPM_StructVer_CheckVer(&(tpm_bound_data->ver));
129 }
130 if (rc == 0) {
131 rc = TPM_Load8(&(tpm_bound_data->payload), stream, stream_size);
132 }
133 if ((rc == 0) && (*stream_size > 0)){
134 /* There is no payloadData size in the serialized data. Assume it consumes the rest of the
135 stream */
136 tpm_bound_data->payloadDataSize = *stream_size;
137 rc = TPM_Malloc(&(tpm_bound_data->payloadData), tpm_bound_data->payloadDataSize);
138 }
139 if ((rc == 0) && (*stream_size > 0)){
140 memcpy(tpm_bound_data->payloadData, *stream, tpm_bound_data->payloadDataSize);
141 *stream += tpm_bound_data->payloadDataSize;
142 *stream_size -= tpm_bound_data->payloadDataSize;
143 }
144 return rc;
145}
146
147#if 0
148/* TPM_BoundData_Store()
149
150 serialize the structure to a stream contained in 'sbuffer'
151 returns 0 or error codes
152
153 This structure serialization assumes that the payloadDataSize member indicates the size of
154 payloadData.
155*/
156
157TPM_RESULT TPM_BoundData_Store(TPM_STORE_BUFFER *sbuffer,
158 const TPM_BOUND_DATA *tpm_bound_data)
159{
160 TPM_RESULT rc = 0;
161
162 printf(" TPM_BoundData_Store:\n");
163 if (rc == 0) {
164 rc = TPM_StructVer_Store(sbuffer, &(tpm_bound_data->ver));
165 }
166 if (rc == 0) {
167 rc = TPM_Sbuffer_Append(sbuffer, &(tpm_bound_data->payload), sizeof(TPM_PAYLOAD_TYPE));
168 }
169 if (rc == 0) {
170 rc = TPM_Sbuffer_Append(sbuffer, tpm_bound_data->payloadData,
171 tpm_bound_data->payloadDataSize);
172 }
173 return rc;
174}
175#endif
176
177/* TPM_BoundData_Delete()
178
179 No-OP if the parameter is NULL, else:
180 frees memory allocated for the bound_data
181 sets pointers to NULL
182 calls TPM_BoundData_Init to set members back to default values
183 The bound_data itself is not freed
184*/
185
186void TPM_BoundData_Delete(TPM_BOUND_DATA *tpm_bound_data)
187{
188 printf(" TPM_BoundData_Delete:\n");
189 if (tpm_bound_data != NULL) {
190 free(tpm_bound_data->payloadData);
191 TPM_BoundData_Init(tpm_bound_data);
192 }
193 return;
194}
195
196/*
197 TPM_SEALED_DATA
198*/
199
200/* TPM_SealedData_Init()
201
202 sets members to default values
203 sets all pointers to NULL and sizes to 0
204 always succeeds - no return code
205*/
206
207void TPM_SealedData_Init(TPM_SEALED_DATA *tpm_sealed_data)
208{
209 printf(" TPM_SealedData_Init:\n");
210 tpm_sealed_data->payload = TPM_PT_SEAL;
211 TPM_Secret_Init(tpm_sealed_data->authData);
212 TPM_Secret_Init(tpm_sealed_data->tpmProof);
213 TPM_Digest_Init(tpm_sealed_data->storedDigest);
214 TPM_SizedBuffer_Init(&(tpm_sealed_data->data));
215 return;
216}
217
218/* TPM_SealedData_Load()
219
220 deserialize the structure from a 'stream'
221 'stream_size' is checked for sufficient data
222 returns 0 or error codes
223
224 Before use, call TPM_SealedData_Init()
225 After use, call TPM_SealedData_Delete() to free memory
226*/
227
228TPM_RESULT TPM_SealedData_Load(TPM_SEALED_DATA *tpm_sealed_data,
229 unsigned char **stream,
230 uint32_t *stream_size)
231{
232 TPM_RESULT rc = 0;
233
234 printf(" TPM_SealedData_Load:\n");
235 /* load payload */
236 if (rc == 0) {
237 rc = TPM_Load8(&(tpm_sealed_data->payload), stream, stream_size);
238 }
239 /* load authData */
240 if (rc == 0) {
241 rc = TPM_Secret_Load(tpm_sealed_data->authData, stream, stream_size);
242 }
243 /* load tpmProof */
244 if (rc == 0) {
245 rc = TPM_Secret_Load(tpm_sealed_data->tpmProof, stream, stream_size);
246 }
247 /* load storedDigest */
248 if (rc == 0) {
249 rc = TPM_Digest_Load(tpm_sealed_data->storedDigest, stream, stream_size);
250 }
251 /* load dataSize and data */
252 if (rc == 0) {
253 rc = TPM_SizedBuffer_Load(&(tpm_sealed_data->data), stream, stream_size);
254 }
255 return rc;
256}
257
258/* TPM_SealedData_Store()
259
260 serialize the structure to a stream contained in 'sbuffer'
261 returns 0 or error codes
262*/
263
264TPM_RESULT TPM_SealedData_Store(TPM_STORE_BUFFER *sbuffer,
265 const TPM_SEALED_DATA *tpm_sealed_data)
266{
267 TPM_RESULT rc = 0;
268 printf(" TPM_SealedData_Store:\n");
269 /* store payload */
270 if (rc == 0) {
271 rc = TPM_Sbuffer_Append(sbuffer, &(tpm_sealed_data->payload), sizeof(TPM_PAYLOAD_TYPE));
272 }
273 /* store authData */
274 if (rc == 0) {
275 rc = TPM_Secret_Store(sbuffer, tpm_sealed_data->authData);
276 }
277 /* store tpmProof */
278 if (rc == 0) {
279 rc = TPM_Secret_Store(sbuffer, tpm_sealed_data->tpmProof);
280 }
281 /* store storedDigest */
282 if (rc == 0) {
283 rc = TPM_Digest_Store(sbuffer, tpm_sealed_data->storedDigest);
284 }
285 /* store dataSize and data */
286 if (rc == 0) {
287 rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sealed_data->data));
288 }
289 return rc;
290}
291
292/* TPM_SealedData_Delete()
293
294 No-OP if the parameter is NULL, else:
295 frees memory allocated for the object
296 sets pointers to NULL
297 calls TPM_SealedData_Init to set members back to default values
298 The object itself is not freed
299*/
300
301void TPM_SealedData_Delete(TPM_SEALED_DATA *tpm_sealed_data)
302{
303 printf(" TPM_SealedData_Delete:\n");
304 if (tpm_sealed_data != NULL) {
305 TPM_SizedBuffer_Delete(&(tpm_sealed_data->data));
306 TPM_SealedData_Init(tpm_sealed_data);
307 }
308 return;
309}
310
311/* TPM_SealedData_GenerateEncData() generates an enc_data structure by serializing the
312 TPM_SEALED_DATA structure and encrypting the result using the public key.
313*/
314
315TPM_RESULT TPM_SealedData_GenerateEncData(TPM_SIZED_BUFFER *enc_data,
316 const TPM_SEALED_DATA *tpm_sealed_data,
317 TPM_KEY *tpm_key)
318{
319 TPM_RESULT rc = 0;
320 TPM_STORE_BUFFER sbuffer; /* TPM_SEALED_DATA serialization */
321
322 printf(" TPM_SealedData_GenerateEncData\n");
323 TPM_Sbuffer_Init(&sbuffer); /* freed @1 */
324 /* serialize the TPM_SEALED_DATA */
325 if (rc == 0) {
326 rc = TPM_SealedData_Store(&sbuffer, tpm_sealed_data);
327 }
328 /* encrypt the TPM_SEALED_DATA serialization buffer with the public key, and place
329 the result in the encData members */
330 if (rc == 0) {
331 rc = TPM_RSAPublicEncryptSbuffer_Key(enc_data, &sbuffer, tpm_key);
332 }
333 TPM_Sbuffer_Delete(&sbuffer); /* @1 */
334 return rc;
335}
336
337/* TPM_SealedData_DecryptEncData() decrypts the enc_data using the private key. The
338 result is deserialized and stored in the TPM_SEALED_DATA structure.
339
340*/
341
342TPM_RESULT TPM_SealedData_DecryptEncData(TPM_SEALED_DATA *tpm_sealed_data, /* result */
343 TPM_SIZED_BUFFER *enc_data, /* encrypted input */
344 TPM_KEY *tpm_key) /* key for decrypting */
345{
346 TPM_RESULT rc = 0;
347 unsigned char *decryptData = NULL; /* freed @1 */
348 uint32_t decryptDataLength = 0; /* actual valid data */
349 unsigned char *stream;
350 uint32_t stream_size;
351
352 printf(" TPM_SealedData_DecryptEncData:\n");
353 /* allocate space for the decrypted data */
354 if (rc == 0) {
355 rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */
356 &decryptDataLength, /* actual size of decrypted data */
357 enc_data->buffer, /* encrypted data */
358 enc_data->size, /* encrypted data size */
359 tpm_key);
360 }
361 /* load the TPM_SEALED_DATA structure from the decrypted data stream */
362 if (rc == 0) {
363 /* use temporary variables, because TPM_SealedData_Load() moves the stream */
364 stream = decryptData;
365 stream_size = decryptDataLength;
366 rc = TPM_SealedData_Load(tpm_sealed_data, &stream, &stream_size);
367 }
368 free(decryptData); /* @1 */
369 return rc;
370}
371
372
373/*
374 TPM_STORED_DATA
375*/
376
377/* TPM_StoredData_Init()
378
379 sets members to default values
380 sets all pointers to NULL and sizes to 0
381 always succeeds - no return code
382*/
383
384void TPM_StoredData_Init(TPM_STORED_DATA *tpm_stored_data,
385 unsigned int version)
386{
387 printf(" TPM_StoredData_Init: v%u\n", version);
388 if (version == 1) {
389 TPM_StructVer_Init(&(tpm_stored_data->ver));
390 }
391 else {
392 ((TPM_STORED_DATA12 *)tpm_stored_data)->tag = TPM_TAG_STORED_DATA12;
393 ((TPM_STORED_DATA12 *)tpm_stored_data)->et = 0x0000;
394 }
395 TPM_SizedBuffer_Init(&(tpm_stored_data->sealInfo));
396 TPM_SizedBuffer_Init(&(tpm_stored_data->encData));
397 tpm_stored_data->tpm_seal_info = NULL;
398 return;
399}
400
401/* TPM_StoredData_Load()
402
403 deserialize the structure from a 'stream'
404 'stream_size' is checked for sufficient data
405 returns 0 or error codes
406
407 Before use, call TPM_StoredData_Init()
408 After use, call TPM_StoredData_Delete() to free memory
409
410 This function handles both TPM_STORED_DATA and TPM_STORED_DATA12 and returns the 'version'.
411*/
412
413TPM_RESULT TPM_StoredData_Load(TPM_STORED_DATA *tpm_stored_data,
414 unsigned int *version,
415 unsigned char **stream,
416 uint32_t *stream_size)
417{
418 TPM_RESULT rc = 0;
419
420 /* Peek at the first byte to guess the version number. The data is verified later.
421 TPM_STORED_DATA is 01,01,00,00 TPM_STORED_DATA12 is 00,16,00,00 */
422 if ((rc == 0) && (*stream_size > 0)) {
423 if (**stream == 0x01) {
424 *version = 1;
425 }
426 else {
427 *version = 2;
428 }
429 printf(" TPM_StoredData_Load: v%u\n", *version);
430 }
431 /* 1.1 load ver */
432 if ((rc == 0) && (*version == 1)) {
433 rc = TPM_StructVer_Load(&(tpm_stored_data->ver), stream, stream_size);
434 }
435 /* 1.2 load tag */
436 if ((rc == 0) && (*version != 1)) {
437 rc = TPM_Load16(&(((TPM_STORED_DATA12 *)tpm_stored_data)->tag), stream, stream_size);
438 }
439 /* 1.2 load et */
440 if ((rc == 0) && (*version != 1)) {
441 rc = TPM_Load16(&(((TPM_STORED_DATA12 *)tpm_stored_data)->et), stream, stream_size);
442 }
443 /* check the TPM_STORED_DATA structure version */
444 if ((rc == 0) && (*version == 1)) {
445 rc = TPM_StructVer_CheckVer(&(tpm_stored_data->ver));
446 }
447 /* check the TPM_STORED_DATA12 structure tag */
448 if ((rc == 0) && (*version != 1)) {
449 rc = TPM_StoredData_CheckTag((TPM_STORED_DATA12 *)tpm_stored_data);
450 }
451 /* load sealInfoSize and sealInfo */
452 if (rc == 0) {
453 rc = TPM_SizedBuffer_Load(&(tpm_stored_data->sealInfo), stream, stream_size);
454 }
455 /* load the TPM_PCR_INFO or TPM_PCR_INFO_LONG cache */
456 if (rc == 0) {
457 if (*version == 1) {
458 rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_stored_data->tpm_seal_info),
459 &(tpm_stored_data->sealInfo));
460 }
461 else {
462 rc = TPM_PCRInfoLong_CreateFromBuffer
463 (&(((TPM_STORED_DATA12 *)tpm_stored_data)->tpm_seal_info_long),
464 &(tpm_stored_data->sealInfo));
465 }
466 }
467 /* load encDataSize and encData */
468 if (rc == 0) {
469 rc = TPM_SizedBuffer_Load(&(tpm_stored_data->encData), stream, stream_size);
470 }
471 return rc;
472}
473
474/* TPM_StoredData_StoreClearData() serializes a TPM_STORED_DATA structure, excluding encData,
475 appending results to 'sbuffer'.
476
477 Before serializing, it serializes tpm_seal_info to sealInfoSize and sealInfo.
478
479 This function handles both TPM_STORED_DATA and TPM_STORED_DATA12.
480
481 serialize the structure to a stream contained in 'sbuffer'
482 returns 0 or error codes
483*/
484
485TPM_RESULT TPM_StoredData_StoreClearData(TPM_STORE_BUFFER *sbuffer,
486 TPM_STORED_DATA *tpm_stored_data,
487 unsigned int version)
488{
489 TPM_RESULT rc = 0;
490
491 printf(" TPM_StoredData_StoreClearData: v%u\n", version);
492 /* 1.1 store ver */
493 if ((rc == 0) && (version == 1)) {
494 rc = TPM_StructVer_Store(sbuffer, &(tpm_stored_data->ver));
495 }
496 /* 1.2 store tag */
497 if ((rc == 0) && (version != 1)) {
498 rc = TPM_Sbuffer_Append16(sbuffer, ((TPM_STORED_DATA12 *)tpm_stored_data)->tag);
499 }
500 /* 1.2 store et */
501 if ((rc == 0) && (version != 1)) {
502 rc = TPM_Sbuffer_Append16(sbuffer, ((TPM_STORED_DATA12 *)tpm_stored_data)->et);
503 }
504 /* store sealInfoSize and sealInfo */
505 if (rc == 0) {
506 /* copy cache to sealInfoSize and sealInfo */
507 if (version == 1) {
508 rc = TPM_SizedBuffer_SetStructure(&(tpm_stored_data->sealInfo),
509 tpm_stored_data->tpm_seal_info,
510 (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store);
511 }
512 else {
513 rc = TPM_SizedBuffer_SetStructure(&(tpm_stored_data->sealInfo),
514 tpm_stored_data->tpm_seal_info,
515 (TPM_STORE_FUNCTION_T)TPM_PCRInfoLong_Store);
516 }
517 }
518 /* copy sealInfoSize and sealInfo to sbuffer */
519 if (rc == 0) {
520 rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_stored_data->sealInfo));
521 }
522 return rc;
523}
524
525/* TPM_StoredData_Store()
526
527 Before serializing, it serializes tpm_seal_info to sealInfoSize and sealInfo.
528
529 serialize the structure to a stream contained in 'sbuffer'
530 returns 0 or error codes
531*/
532
533TPM_RESULT TPM_StoredData_Store(TPM_STORE_BUFFER *sbuffer,
534 TPM_STORED_DATA *tpm_stored_data,
535 unsigned int version)
536{
537 TPM_RESULT rc = 0;
538
539 printf(" TPM_StoredData_Store: v%u\n", version);
540 if (rc == 0) {
541 rc = TPM_StoredData_StoreClearData(sbuffer, tpm_stored_data, version);
542 }
543 /* store encDataSize and encData */
544 if (rc == 0) {
545 rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_stored_data->encData));
546 }
547 return rc;
548}
549
550/* TPM_StoredData_Delete()
551
552 No-OP if the parameter is NULL, else:
553 frees memory allocated for the object
554 sets pointers to NULL
555 calls TPM_StoredData_Init to set members back to default values
556 The object itself is not freed
557*/
558
559void TPM_StoredData_Delete(TPM_STORED_DATA *tpm_stored_data,
560 unsigned int version)
561{
562 printf(" TPM_StoredData_Delete: v%u\n", version);
563 if (tpm_stored_data != NULL) {
564 TPM_SizedBuffer_Delete(&(tpm_stored_data->sealInfo));
565 TPM_SizedBuffer_Delete(&(tpm_stored_data->encData));
566 if (version == 1) {
567 TPM_PCRInfo_Delete(tpm_stored_data->tpm_seal_info);
568 free(tpm_stored_data->tpm_seal_info);
569 }
570 else {
571 TPM_PCRInfoLong_Delete((TPM_PCR_INFO_LONG *)tpm_stored_data->tpm_seal_info);
572 free(tpm_stored_data->tpm_seal_info);
573 }
574 TPM_StoredData_Init(tpm_stored_data, version);
575 }
576 return;
577}
578
579/* TPM_StoredData_CheckTag() verifies the tag and et members of a TPM_STORED_DATA12 structure
580
581 */
582
583TPM_RESULT TPM_StoredData_CheckTag(TPM_STORED_DATA12 *tpm_stored_data12)
584{
585 TPM_RESULT rc = 0;
586
587 printf(" TPM_StoredData_CheckTag:\n");
588 if (rc == 0) {
589 if (tpm_stored_data12->tag != TPM_TAG_STORED_DATA12) {
590 printf("TPM_StoredData_CheckTag: Error, tag expected %04x found %04hx\n",
591 TPM_TAG_STORED_DATA12, tpm_stored_data12->tag);
592 rc = TPM_BAD_VERSION;
593 }
594 }
595 return rc;
596}
597
598/* TPM_StoredData_GenerateDigest() generates a TPM_DIGEST over the TPM_STORED_DATA structure
599 excluding the encDataSize and encData members.
600*/
601
602TPM_RESULT TPM_StoredData_GenerateDigest(TPM_DIGEST tpm_digest,
603 TPM_STORED_DATA *tpm_stored_data,
604 unsigned int version)
605{
606 TPM_RESULT rc = 0;
607 TPM_STORE_BUFFER sbuffer; /* TPM_STORED_DATA serialization */
608
609 printf(" TPM_StoredData_GenerateDigest:\n");
610 TPM_Sbuffer_Init(&sbuffer); /* freed @1 */
611 /* serialize the TPM_STORED_DATA excluding the encData fields */
612 if (rc == 0) {
613 rc = TPM_StoredData_StoreClearData(&sbuffer, tpm_stored_data, version);
614 }
615 if (rc == 0) {
616 rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer);
617 }
618 TPM_Sbuffer_Delete(&sbuffer); /* @1 */
619 return rc;
620}
621
622/*
623 Processing Functions
624*/
625
626/* TPM_SealCryptCommon() rev 98
627
628 Handles the encrypt/decrypt actions common to TPM_Sealx and TPM_Unseal
629
630 'encrypt TRUE for encryption, FALSE for decryption
631
632 The output o1 must be freed by the caller.
633*/
634
635static TPM_RESULT TPM_SealCryptCommon(BYTE **o1, /* freed by caller */
636 TPM_ADIP_ENC_SCHEME adipEncScheme,
637 TPM_SIZED_BUFFER *inData,
638 TPM_AUTH_SESSION_DATA *auth_session_data,
639 TPM_NONCE nonceOdd)
640{
641 TPM_RESULT rc = 0;
642 BYTE *x1; /* XOR string, MGF1 output */
643 TPM_DIGEST ctr; /* symmetric key algorithm CTR */
644
645 printf(" TPM_SealCryptCommon:\n");
646 x1 = NULL; /* freed @1 */
647
648 /* allocate for the output o1 */
649 if (rc == TPM_SUCCESS) {
650 rc = TPM_Malloc(o1, inData->size); /* freed by caller */
651 }
652 if (rc == TPM_SUCCESS) {
653 TPM_PrintFourLimit(" TPM_SealCryptCommon: input data", inData->buffer, inData->size);
654 }
655 switch (adipEncScheme) {
656 case TPM_ET_XOR:
657 printf(" TPM_SealCryptCommon: TPM_ET_XOR\n");
658 if (rc == TPM_SUCCESS) {
659 /* i. Use MGF1 to create string X1 of length sealedDataSize. The inputs to MGF1 are;
660 authLastnonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four
661 concatenated values form the Z value that is the seed for MFG1. */
662 rc = TPM_MGF1_GenerateArray(&x1, /* MGF1 array */
663 inData->size, /* MGF1 array length */
664
665 TPM_NONCE_SIZE +
666 TPM_NONCE_SIZE +
667 sizeof("XOR") -1 +
668 TPM_DIGEST_SIZE, /* seed length */
669
670 TPM_NONCE_SIZE, auth_session_data->nonceEven,
671 TPM_NONCE_SIZE, nonceOdd,
672 sizeof("XOR") -1, "XOR",
673 TPM_DIGEST_SIZE, auth_session_data->sharedSecret,
674 0, NULL);
675 }
676 /* ii. Create o1 by XOR of d1 -> data and X1 */
677 if (rc == TPM_SUCCESS) {
678 TPM_PrintFour(" TPM_SealCryptCommon: XOR key", x1);
679 TPM_XOR(*o1, inData->buffer, x1, inData->size);
680 }
681 break;
682 case TPM_ET_AES128_CTR:
683 printf(" TPM_SealCryptCommon: TPM_ET_AES128_CTR\n");
684 /* i. Create o1 by encrypting d1 -> data using the algorithm indicated by inData ->
685 et */
686 /* ii. Key is from authHandle -> sharedSecret */
687 /* iii. IV is SHA-1 of (authLastNonceEven || nonceOdd) */
688 if (rc == TPM_SUCCESS) {
689 rc = TPM_SHA1(ctr,
690 TPM_NONCE_SIZE, auth_session_data->nonceEven,
691 TPM_NONCE_SIZE, nonceOdd,
692 0, NULL);
693 }
694 if (rc == TPM_SUCCESS) {
695 TPM_PrintFour(" TPM_SealCryptCommon: AES key", auth_session_data->sharedSecret);
696 TPM_PrintFour(" TPM_SealCryptCommon: CTR", ctr);
697 rc = TPM_SymmetricKeyData_CtrCrypt(*o1, /* output data */
698 inData->buffer, /* input data */
699 inData->size, /* data size */
700 auth_session_data->sharedSecret, /* key */
701 TPM_SECRET_SIZE, /* key size */
702 ctr, /* CTR */
703 TPM_DIGEST_SIZE); /* CTR size */
704 }
705 break;
706 default:
707 printf("TPM_SealCryptCommon: Error, unsupported adipEncScheme %02x\n", adipEncScheme);
708 rc = TPM_INAPPROPRIATE_ENC;
709 break;
710 }
711 if (rc == 0) {
712 TPM_PrintFour(" TPM_SealCryptCommon: output data", *o1);
713
714 }
715 free(x1); /* @1 */
716 return rc;
717}
718
719/* 10.1 TPM_Seal rev 110
720
721 The SEAL operation allows software to explicitly state the future "trusted" configuration that
722 the platform must be in for the secret to be revealed. The SEAL operation also implicitly
723 includes the relevant platform configuration (PCR-values) when the SEAL operation was
724 performed. The SEAL operation uses the tpmProof value to BIND the blob to an individual TPM.
725
726 TPM_Seal is used to encrypt private objects that can only be decrypted using TPM_Unseal.
727*/
728
729TPM_RESULT TPM_Process_Seal(tpm_state_t *tpm_state,
730 TPM_STORE_BUFFER *response,
731 TPM_TAG tag,
732 uint32_t paramSize,
733 TPM_COMMAND_CODE ordinal,
734 unsigned char *command,
735 TPM_TRANSPORT_INTERNAL *transportInternal)
736{
737 TPM_RESULT rcf = 0; /* fatal error precluding response */
738 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
739
740 /* input parameters */
741 TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that can perform seal
742 operations. */
743 TPM_ENCAUTH encAuth; /* The encrypted authorization data for the sealed data. */
744 TPM_SIZED_BUFFER pcrInfo; /* The PCR selection information. The caller MAY use
745 TPM_PCR_INFO_LONG. */
746 TPM_SIZED_BUFFER inData; /* The data to be sealed to the platform and any specified
747 PCRs */
748 TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle
749 authorization. Must be an OS_AP session for this
750 command. */
751 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
752 TPM_BOOL continueAuthSession = TRUE; /* Ignored */
753 TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and keyHandle. HMAC
754 key: key.usageAuth. */
755
756 /* processing */
757 unsigned char * inParamStart; /* starting point of inParam's */
758 unsigned char * inParamEnd; /* ending point of inParam's */
759 TPM_DIGEST inParamDigest;
760 TPM_BOOL auditStatus; /* audit the ordinal */
761 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
762 TPM_BOOL authHandleValid = FALSE;
763 TPM_SECRET *hmacKey;
764 TPM_KEY *key = NULL; /* the key specified by keyHandle */
765 TPM_SECRET *keyUsageAuth;
766 TPM_BOOL parentPCRStatus;
767 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
768 unsigned int v1PcrVersion = 1; /* pcrInfo version */
769 TPM_STORED_DATA12 *s1_12;
770 TPM_PCR_INFO tpm_pcr_info; /* deserialized pcrInfo v1 */
771 TPM_PCR_INFO_LONG tpm_pcr_info_long; /* deserialized pcrInfo v2 */
772 unsigned char *stream;
773 uint32_t stream_size;
774 TPM_DIGEST a1Auth;
775 TPM_SEALED_DATA s2SealedData;
776
777 /* output parameters */
778 uint32_t outParamStart; /* starting point of outParam's */
779 uint32_t outParamEnd; /* ending point of outParam's */
780 TPM_DIGEST outParamDigest;
781 TPM_STORED_DATA s1StoredData; /* Encrypted, integrity-protected data object that is the
782 result of the TPM_Seal operation. Returned as
783 SealedData */
784
785 printf("TPM_Process_Seal: Ordinal Entry\n");
786 TPM_SizedBuffer_Init(&pcrInfo); /* freed @1 */
787 TPM_SizedBuffer_Init(&inData); /* freed @2 */
788 TPM_StoredData_Init(&s1StoredData, v1PcrVersion); /* freed @3, default is v1 */
789 TPM_PCRInfo_Init(&tpm_pcr_info); /* freed @4 */
790 TPM_PCRInfoLong_Init(&tpm_pcr_info_long); /* freed @5 */
791 TPM_SealedData_Init(&s2SealedData); /* freed @6 */
792 s1_12 = (TPM_STORED_DATA12 *)&s1StoredData; /* to avoid casts */
793 /*
794 get inputs
795 */
796 /* get keyHandle parameter */
797 if (returnCode == TPM_SUCCESS) {
798 returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
799 }
800 /* save the starting point of inParam's for authorization and auditing */
801 inParamStart = command;
802 /* get encAuth parameter */
803 if (returnCode == TPM_SUCCESS) {
804 printf("TPM_Process_Seal: keyHandle %08x\n", keyHandle);
805 returnCode = TPM_Authdata_Load(encAuth, &command, &paramSize);
806 }
807 /* get pcrInfo parameter */
808 if (returnCode == TPM_SUCCESS) {
809 returnCode = TPM_SizedBuffer_Load(&pcrInfo, &command, &paramSize);
810 }
811 /* get inData parameter */
812 if (returnCode == TPM_SUCCESS) {
813 returnCode = TPM_SizedBuffer_Load(&inData, &command, &paramSize);
814 }
815 if (returnCode == TPM_SUCCESS) {
816 printf("TPM_Process_Seal: Sealing %u bytes\n", inData.size);
817 }
818 /* save the ending point of inParam's for authorization and auditing */
819 inParamEnd = command;
820 /* digest the input parameters */
821 if (returnCode == TPM_SUCCESS) {
822 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
823 &auditStatus, /* output */
824 &transportEncrypt, /* output */
825 tpm_state,
826 tag,
827 ordinal,
828 inParamStart,
829 inParamEnd,
830 transportInternal);
831 }
832 /* check state */
833 if (returnCode == TPM_SUCCESS) {
834 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
835 }
836 /* check tag */
837 if (returnCode == TPM_SUCCESS) {
838 returnCode = TPM_CheckRequestTag1(tag);
839 }
840 /* get the 'below the line' authorization parameters */
841 if (returnCode == TPM_SUCCESS) {
842 returnCode = TPM_AuthParams_Get(&authHandle,
843 &authHandleValid,
844 nonceOdd,
845 &continueAuthSession,
846 pubAuth,
847 &command, &paramSize);
848 }
849 if (returnCode == TPM_SUCCESS) {
850 if (paramSize != 0) {
851 printf("TPM_Process_Seal: Error, command has %u extra bytes\n",
852 paramSize);
853 returnCode = TPM_BAD_PARAM_SIZE;
854 }
855 }
856 /* do not terminate sessions if the command did not parse correctly */
857 if (returnCode != TPM_SUCCESS) {
858 authHandleValid = FALSE;
859 }
860 /*
861 Processing
862 */
863 /* get the key corresponding to the keyHandle parameter */
864 if (returnCode == TPM_SUCCESS) {
865 returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle,
866 FALSE, /* not r/o, using to encrypt */
867 FALSE, /* do not ignore PCRs */
868 FALSE); /* cannot use EK */
869 }
870 /* get keyHandle -> usageAuth */
871 if (returnCode == TPM_SUCCESS) {
872 returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key);
873 }
874 /* get the session data */
875 if (returnCode == TPM_SUCCESS) {
876 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
877 &hmacKey,
878 tpm_state,
879 authHandle,
880 TPM_PID_OSAP,
881 TPM_ET_KEYHANDLE,
882 ordinal,
883 key,
884 NULL, /* OIAP */
885 key->tpm_store_asymkey->pubDataDigest); /* OSAP */
886 }
887 /* 1. Validate the authorization to use the key pointed to by keyHandle */
888 if (returnCode == TPM_SUCCESS) {
889 returnCode = TPM_Authdata_Check(tpm_state,
890 *hmacKey, /* HMAC key */
891 inParamDigest,
892 auth_session_data, /* authorization session */
893 nonceOdd, /* Nonce generated by system
894 associated with authHandle */
895 continueAuthSession,
896 pubAuth); /* Authorization digest for input */
897 }
898 /* 2. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */
899 if (returnCode == TPM_SUCCESS) {
900 if (inData.size == 0) {
901 printf("TPM_Process_Seal: Error, inDataSize is 0\n");
902 returnCode = TPM_BAD_PARAMETER;
903 }
904 }
905 /* 3. If the keyUsage field of the key indicated by keyHandle does not have the value
906 TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE. */
907 if (returnCode == TPM_SUCCESS) {
908 if (key->keyUsage != TPM_KEY_STORAGE) {
909 printf("TPM_Process_Seal: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n",
910 key->keyUsage);
911 returnCode = TPM_INVALID_KEYUSAGE;
912 }
913 }
914 /* 4. If the keyHandle points to a migratable key then the TPM MUST return the error code
915 TPM_INVALID_KEY_USAGE. */
916 if (returnCode == TPM_SUCCESS) {
917 if (key->keyFlags & TPM_MIGRATABLE) {
918 printf("TPM_Process_Seal: Error, key keyFlags %08x indicates migratable\n",
919 key->keyFlags);
920 returnCode = TPM_INVALID_KEYUSAGE;
921 }
922 }
923 /* 5. Determine the version of pcrInfo */
924 if (returnCode == TPM_SUCCESS) {
925 /* a. If pcrInfoSize is 0 */
926 if (pcrInfo.size == 0) {
927 v1PcrVersion = 1; /* i. set V1 to 1 */
928 }
929 else { /* b. Else */
930 /* i. Point X1 as TPM_PCR_INFO_LONG structure to pcrInfo */
931 /* ii. If X1 -> tag is TPM_TAG_PCR_INFO_LONG */
932 if (htons(*(uint16_t *)(pcrInfo.buffer)) == TPM_TAG_PCR_INFO_LONG) {
933 v1PcrVersion = 2; /* (1) Set V1 to 2 */
934 }
935 else { /* iii. Else */
936 v1PcrVersion = 1; /* (1) Set V1 to 1 */
937 }
938 }
939 /* 6. If V1 is 1 then */
940 /* a. Create S1 a TPM_STORED_DATA structure */
941 /* 7. else */
942 /* a. Create S1 a TPM_STORED_DATA12 structure */
943 /* b. Set S1 -> et to 0 */
944 /* 8. Set S1 -> encDataSize to 0 */
945 /* 9. Set S1 -> encData to all zeros */
946 printf("TPM_Process_Seal: V%u\n", v1PcrVersion);
947 TPM_StoredData_Init(&s1StoredData, v1PcrVersion);
948 /* 10. Set S1 -> sealInfoSize to pcrInfoSize */
949 /* NOTE This step is unnecessary. If pcrInfoSize is 0, sealInfoSize is already initialized
950 to 0. If pcrInfoSize is non-zero, sealInfoSize is the result of serialization of the
951 tpm_seal_info member, which is either a TPM_PCR_INFO or a TPM_PCR_INFO_LONG */
952 }
953 /* 11. If pcrInfoSize is not 0 then */
954 if ((returnCode == TPM_SUCCESS) && (pcrInfo.size != 0)) {
955 printf("TPM_Process_Seal: Creating PCR digest\n");
956 /* assign the stream, so pcrInfo is not altered */
957 stream = pcrInfo.buffer;
958 stream_size = pcrInfo.size;
959 /* a. if V1 is 1 then */
960 if (v1PcrVersion == 1) {
961 /* i. Validate pcrInfo as a valid TPM_PCR_INFO structure, return TPM_BADINDEX on
962 error */
963 if (returnCode == TPM_SUCCESS) {
964 returnCode = TPM_PCRInfo_Load(&tpm_pcr_info, &stream, &stream_size);
965 if (returnCode != 0) {
966 returnCode = TPM_BADINDEX;
967 }
968 }
969 /* build the TPM_STORED_DATA S1 structure */
970 if (returnCode == TPM_SUCCESS) {
971 /* ii. Set S1 -> sealInfo -> pcrSelection to pcrInfo -> pcrSelection */
972 returnCode = TPM_PCRInfo_CreateFromBuffer(&(s1StoredData.tpm_seal_info), &pcrInfo);
973 }
974 /* iii. Create h1 the composite hash of the PCR selected by pcrInfo -> pcrSelection */
975 /* iv. Set S1 -> sealInfo -> digestAtCreation to h1 */
976 /* NOTE hash directly to destination. */
977 if (returnCode == TPM_SUCCESS) {
978 returnCode =
979 TPM_PCRSelection_GenerateDigest(s1StoredData.tpm_seal_info->digestAtCreation,
980 &(tpm_pcr_info.pcrSelection),
981 tpm_state->tpm_stclear_data.PCRS);
982 }
983 /* v. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */
984 /* NOTE digestAtRelease copied during TPM_PCRInfo_CreateFromBuffer() */
985 }
986 /* b. else (v1 is 2) */
987 else {
988 /* i. Validate pcrInfo as a valid TPM_PCR_INFO_LONG structure, return TPM_BADINDEX
989 on error */
990 if (returnCode == TPM_SUCCESS) {
991 returnCode = TPM_PCRInfoLong_Load(&tpm_pcr_info_long, &stream, &stream_size);
992 if (returnCode != 0) {
993 returnCode = TPM_BADINDEX;
994 }
995 }
996 /* build the TPM_STORED_DATA S1 structure */
997 if (returnCode == TPM_SUCCESS) {
998 /* ii. Set S1 -> sealInfo -> creationPCRSelection to pcrInfo -> creationPCRSelection
999 */
1000 /* iii. Set S1 -> sealInfo -> releasePCRSelection to pcrInfo -> releasePCRSelection
1001 */
1002 /* iv. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */
1003 /* v. Set S1 -> sealInfo -> localityAtRelease to pcrInfo -> localityAtRelease */
1004 /* NOTE copied during TPM_PCRInfoLong_CreateFromBuffer() */
1005 returnCode = TPM_PCRInfoLong_CreateFromBuffer(&(s1_12->tpm_seal_info_long),
1006 &pcrInfo);
1007 }
1008 if (returnCode == TPM_SUCCESS) {
1009 /* vi. Create h2 the composite hash of the PCR selected by pcrInfo ->
1010 creationPCRSelection */
1011 /* vii. Set S1 -> sealInfo -> digestAtCreation to h2 */
1012 /* NOTE hash directly to destination. */
1013 returnCode =
1014 TPM_PCRSelection_GenerateDigest(s1_12->tpm_seal_info_long->digestAtCreation,
1015 &(tpm_pcr_info_long.creationPCRSelection),
1016 tpm_state->tpm_stclear_data.PCRS);
1017 }
1018 /* viii. Set S1 -> sealInfo -> localityAtCreation to TPM_STANY_FLAGS ->
1019 localityModifier */
1020 if (returnCode == TPM_SUCCESS) {
1021 returnCode = TPM_Locality_Set(&(s1_12->tpm_seal_info_long->localityAtCreation),
1022 tpm_state->tpm_stany_flags.localityModifier);
1023 }
1024 }
1025 }
1026 /* 12. Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */
1027 if (returnCode == TPM_SUCCESS) {
1028 returnCode = TPM_AuthSessionData_Decrypt(a1Auth,
1029 NULL,
1030 encAuth,
1031 auth_session_data,
1032 NULL,
1033 NULL,
1034 FALSE); /* even and odd */
1035 }
1036 /* 13. The TPM provides NO validation of a1. Well-known values (like all zeros) are valid and
1037 possible. */
1038 /* 14. Create S2 a TPM_SEALED_DATA structure */
1039 if (returnCode == TPM_SUCCESS) {
1040 /* a. Set S2 -> payload to TPM_PT_SEAL */
1041 /* NOTE: Done at TPM_SealedData_Init() */
1042 /* b. Set S2 -> tpmProof to TPM_PERMANENT_DATA -> tpmProof */
1043 TPM_Secret_Copy(s2SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof);
1044 /* c. Create h3 the SHA-1 of S1 */
1045 /* d. Set S2 -> storedDigest to h3 */
1046 returnCode = TPM_StoredData_GenerateDigest(s2SealedData.storedDigest,
1047 &s1StoredData, v1PcrVersion);
1048 }
1049 if (returnCode == TPM_SUCCESS) {
1050 /* e. Set S2 -> authData to a1 */
1051 TPM_Secret_Copy(s2SealedData.authData, a1Auth);
1052 /* f. Set S2 -> dataSize to inDataSize */
1053 /* g. Set S2 -> data to inData */
1054 returnCode = TPM_SizedBuffer_Copy(&(s2SealedData.data), &inData);
1055 }
1056 /* 15. Validate that the size of S2 can be encrypted by the key pointed to by keyHandle, return
1057 TPM_BAD_DATASIZE on error */
1058 /* 16. Create s3 the encryption of S2 using the key pointed to by keyHandle */
1059 /* 17. Set continueAuthSession to FALSE */
1060 if (returnCode == TPM_SUCCESS) {
1061 continueAuthSession = FALSE;
1062 }
1063 /* 18. Set S1 -> encDataSize to the size of s3 */
1064 /* 19. Set S1 -> encData to s3 */
1065 if (returnCode == TPM_SUCCESS) {
1066 returnCode = TPM_SealedData_GenerateEncData(&(s1StoredData.encData), &s2SealedData, key);
1067 }
1068 /*
1069 response
1070 */
1071 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
1072 if (rcf == 0) {
1073 printf("TPM_Process_Seal: Ordinal returnCode %08x %u\n",
1074 returnCode, returnCode);
1075 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1076 }
1077 /* success response, append the rest of the parameters. */
1078 if (rcf == 0) {
1079 if (returnCode == TPM_SUCCESS) {
1080 /* checkpoint the beginning of the outParam's */
1081 outParamStart = response->buffer_current - response->buffer;
1082 /* 20. Return S1 as sealedData */
1083 returnCode = TPM_StoredData_Store(response, &s1StoredData, v1PcrVersion);
1084 /* checkpoint the end of the outParam's */
1085 outParamEnd = response->buffer_current - response->buffer;
1086 }
1087 /* digest the above the line output parameters */
1088 if (returnCode == TPM_SUCCESS) {
1089 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
1090 auditStatus, /* input audit status */
1091 transportEncrypt,
1092 tag,
1093 returnCode,
1094 ordinal, /* command ordinal */
1095 response->buffer + outParamStart, /* start */
1096 outParamEnd - outParamStart); /* length */
1097 }
1098 /* calculate and set the below the line parameters */
1099 if (returnCode == TPM_SUCCESS) {
1100 returnCode = TPM_AuthParams_Set(response,
1101 *hmacKey, /* owner HMAC key */
1102 auth_session_data,
1103 outParamDigest,
1104 nonceOdd,
1105 continueAuthSession);
1106 }
1107 /* audit if required */
1108 if ((returnCode == TPM_SUCCESS) && auditStatus) {
1109 returnCode = TPM_ProcessAudit(tpm_state,
1110 transportEncrypt,
1111 inParamDigest,
1112 outParamDigest,
1113 ordinal);
1114 }
1115 /* adjust the initial response */
1116 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1117 }
1118 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1119 if (((rcf != 0) ||
1120 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1121 !continueAuthSession) &&
1122 authHandleValid) {
1123 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1124 }
1125 /*
1126 cleanup
1127 */
1128 TPM_SizedBuffer_Delete(&pcrInfo); /* @1 */
1129 TPM_SizedBuffer_Delete(&inData); /* @2 */
1130 TPM_StoredData_Delete(&s1StoredData, v1PcrVersion); /* @3 */
1131 TPM_PCRInfo_Delete(&tpm_pcr_info); /* @4 */
1132 TPM_PCRInfoLong_Delete(&tpm_pcr_info_long); /* @5 */
1133 TPM_SealedData_Delete(&s2SealedData); /* @6 */
1134 return rcf;
1135}
1136
1137/* 10.7 TPM_Sealx rev 110
1138
1139 The TPM_Sealx command works exactly like the TPM_Seal command with the additional requirement of
1140 encryption for the inData parameter. This command also places in the sealed blob the information
1141 that the TPM_Unseal also requires encryption.
1142
1143 TPM_Sealx requires the use of 1.2 data structures. The actions are the same as TPM_Seal without
1144 the checks for 1.1 data structure usage.
1145*/
1146
1147TPM_RESULT TPM_Process_Sealx(tpm_state_t *tpm_state,
1148 TPM_STORE_BUFFER *response,
1149 TPM_TAG tag,
1150 uint32_t paramSize,
1151 TPM_COMMAND_CODE ordinal,
1152 unsigned char *command,
1153 TPM_TRANSPORT_INTERNAL *transportInternal)
1154{
1155 TPM_RESULT rcf = 0; /* fatal error precluding response */
1156 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
1157
1158 /* input parameters */
1159 TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that can perform seal
1160 operations. */
1161 TPM_ENCAUTH encAuth; /* The encrypted authorization data for the sealed data */
1162 TPM_SIZED_BUFFER pcrInfo; /* If 0 there are no PCR registers in use. pcrInfo MUST use
1163 TPM_PCR_INFO_LONG */
1164 TPM_SIZED_BUFFER inData; /* The data to be sealed to the platform and any specified
1165 PCRs */
1166
1167 TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle
1168 authorization. Must be an OSAP session for this command.
1169 */
1170 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
1171 TPM_BOOL continueAuthSession = TRUE; /* Ignored */
1172 TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and keyHandle. HMAC
1173 key: key.usageAuth. */
1174
1175 /* processing */
1176 unsigned char * inParamStart; /* starting point of inParam's */
1177 unsigned char * inParamEnd; /* ending point of inParam's */
1178 TPM_DIGEST inParamDigest;
1179 TPM_BOOL auditStatus; /* audit the ordinal */
1180 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
1181 TPM_BOOL authHandleValid = FALSE;
1182 TPM_SECRET *hmacKey;
1183 TPM_KEY *key = NULL; /* the key specified by keyHandle */
1184 TPM_SECRET *keyUsageAuth;
1185 TPM_BOOL parentPCRStatus;
1186 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
1187
1188 /* output parameters */
1189 uint32_t outParamStart; /* starting point of outParam's */
1190 uint32_t outParamEnd; /* ending point of outParam's */
1191 TPM_DIGEST outParamDigest;
1192 TPM_STORED_DATA12 s1StoredData; /* Encrypted, integrity-protected data object that
1193 is the result of the TPM_Seal operation. Returned
1194 as SealedData */
1195 TPM_STORED_DATA *s1_11; /* 1.1 version to avoid casts */
1196 TPM_SEALED_DATA s2SealedData;
1197 TPM_DIGEST a1Auth;
1198 BYTE *o1DecryptedData;
1199
1200 printf("TPM_Process_Sealx: Ordinal Entry\n");
1201 s1_11 = (TPM_STORED_DATA *)&s1StoredData; /* 1.1 version to avoid casts */
1202 TPM_SizedBuffer_Init(&pcrInfo); /* freed @1 */
1203 TPM_SizedBuffer_Init(&inData); /* freed @2 */
1204 TPM_StoredData_Init(s1_11, 2); /* freed @3 */
1205 TPM_SealedData_Init(&s2SealedData); /* freed @4 */
1206 o1DecryptedData = NULL; /* freed @5 */
1207 /*
1208 get inputs
1209 */
1210 /* get keyHandle parameter */
1211 if (returnCode == TPM_SUCCESS) {
1212 returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
1213 }
1214 /* save the starting point of inParam's for authorization and auditing */
1215 inParamStart = command;
1216 /* get encAuth parameter */
1217 if (returnCode == TPM_SUCCESS) {
1218 returnCode = TPM_Authdata_Load(encAuth, &command, &paramSize);
1219 }
1220 /* get pcrInfo parameter */
1221 if (returnCode == TPM_SUCCESS) {
1222 returnCode = TPM_SizedBuffer_Load(&pcrInfo, &command, &paramSize);
1223 }
1224 /* get inData parameter */
1225 if (returnCode == TPM_SUCCESS) {
1226 returnCode = TPM_SizedBuffer_Load(&inData, &command, &paramSize);
1227 }
1228 if (returnCode == TPM_SUCCESS) {
1229 printf("TPM_Process_Sealx: Sealing %u bytes\n", inData.size);
1230 TPM_PrintFourLimit("TPM_Process_Sealx: Sealing data", inData.buffer, inData.size);
1231 }
1232 /* save the ending point of inParam's for authorization and auditing */
1233 inParamEnd = command;
1234 /* digest the input parameters */
1235 if (returnCode == TPM_SUCCESS) {
1236 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
1237 &auditStatus, /* output */
1238 &transportEncrypt, /* output */
1239 tpm_state,
1240 tag,
1241 ordinal,
1242 inParamStart,
1243 inParamEnd,
1244 transportInternal);
1245 }
1246 /* check state */
1247 if (returnCode == TPM_SUCCESS) {
1248 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
1249 }
1250 /* check tag */
1251 if (returnCode == TPM_SUCCESS) {
1252 returnCode = TPM_CheckRequestTag1(tag);
1253 }
1254 /* get the 'below the line' authorization parameters */
1255 if (returnCode == TPM_SUCCESS) {
1256 returnCode = TPM_AuthParams_Get(&authHandle,
1257 &authHandleValid,
1258 nonceOdd,
1259 &continueAuthSession,
1260 pubAuth,
1261 &command, &paramSize);
1262 }
1263 if (returnCode == TPM_SUCCESS) {
1264 if (paramSize != 0) {
1265 printf("TPM_Process_Sealx: Error, command has %u extra bytes\n",
1266 paramSize);
1267 returnCode = TPM_BAD_PARAM_SIZE;
1268 }
1269 }
1270 /* do not terminate sessions if the command did not parse correctly */
1271 if (returnCode != TPM_SUCCESS) {
1272 authHandleValid = FALSE;
1273 }
1274 /*
1275 Processing
1276 */
1277 /* get the key corresponding to the keyHandle parameter */
1278 if (returnCode == TPM_SUCCESS) {
1279 returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle,
1280 FALSE, /* not r/o, using to encrypt */
1281 FALSE, /* do not ignore PCRs */
1282 FALSE); /* cannot use EK */
1283 }
1284 /* get keyHandle -> usageAuth */
1285 if (returnCode == TPM_SUCCESS) {
1286 returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key);
1287 }
1288 /* get the session data */
1289 if (returnCode == TPM_SUCCESS) {
1290 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
1291 &hmacKey,
1292 tpm_state,
1293 authHandle,
1294 TPM_PID_OSAP,
1295 TPM_ET_KEYHANDLE,
1296 ordinal,
1297 key,
1298 NULL, /* OIAP */
1299 key->tpm_store_asymkey->pubDataDigest); /* OSAP */
1300 }
1301 /* 1. Validate the authorization to use the key pointed to by keyHandle */
1302 if (returnCode == TPM_SUCCESS) {
1303 returnCode = TPM_Authdata_Check(tpm_state,
1304 *hmacKey, /* HMAC key */
1305 inParamDigest,
1306 auth_session_data, /* authorization session */
1307 nonceOdd, /* Nonce generated by system
1308 associated with authHandle */
1309 continueAuthSession,
1310 pubAuth); /* Authorization digest for input */
1311 }
1312 /* 2. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */
1313 if (returnCode == TPM_SUCCESS) {
1314 if (inData.size == 0) {
1315 printf("TPM_Process_Sealx: Error, inDataSize is 0\n");
1316 returnCode = TPM_BAD_PARAMETER;
1317 }
1318 }
1319 /* 3. If the keyUsage field of the key indicated by keyHandle does not have the value
1320 TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE. */
1321 if (returnCode == TPM_SUCCESS) {
1322 if (key->keyUsage != TPM_KEY_STORAGE) {
1323 printf("TPM_Process_Sealx: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n",
1324 key->keyUsage);
1325 returnCode = TPM_INVALID_KEYUSAGE;
1326 }
1327 }
1328 /* 4. If the keyHandle points to a migratable key then the TPM MUST return the error code
1329 TPM_INVALID_KEY_USAGE. */
1330 if (returnCode == TPM_SUCCESS) {
1331 if (key->keyFlags & TPM_MIGRATABLE) {
1332 printf("TPM_Process_Sealx: Error, key keyFlags %08x indicates migratable\n",
1333 key->keyFlags);
1334 returnCode = TPM_INVALID_KEYUSAGE;
1335 }
1336 }
1337 /* 5. Create S1 a TPM_STORED_DATA12 structure */
1338 /* 6. Set S1 -> encDataSize to 0 */
1339 /* 7. Set S1 -> encData to all zeros */
1340 /* NOTE: Done by TPM_StoredData_Init() */
1341 /* 8. Set S1 -> sealInfoSize to pcrInfoSize */
1342 /* NOTE This step is unnecessary. If pcrInfoSize is 0, sealInfoSize is already initialized
1343 to 0. If pcrInfoSize is non-zero, sealInfoSize is the result of serialization of the
1344 tpm_seal_info member, which is a TPM_PCR_INFO_LONG */
1345 /* 9. If pcrInfoSize is not 0 then */
1346 if ((returnCode == TPM_SUCCESS) && (pcrInfo.size != 0)) {
1347 printf("TPM_Process_Sealx: Setting sealInfo to pcrInfo\n");
1348 /* initializing the s -> TPM_PCR_INFO_LONG cache to the contents of pcrInfo */
1349 /* a. Validate pcrInfo as a valid TPM_PCR_INFO_LONG structure, return TPM_BADINDEX on
1350 error */
1351 if (returnCode == TPM_SUCCESS) {
1352 returnCode = TPM_PCRInfoLong_CreateFromBuffer(&(s1StoredData.tpm_seal_info_long),
1353 &pcrInfo);
1354 if (returnCode != TPM_SUCCESS) {
1355 returnCode = TPM_BADINDEX;
1356 }
1357 }
1358 /* b. Set S1 -> sealInfo -> creationPCRSelection to pcrInfo -> creationPCRSelection */
1359 /* c. Set S1 -> sealInfo -> releasePCRSelection to pcrInfo -> releasePCRSelection */
1360 /* d. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */
1361 /* e. Set S1 -> sealInfo -> localityAtRelease to pcrInfo -> localityAtRelease */
1362 /* NOTE copied during TPM_PCRInfoLong_CreateFromBuffer() */
1363 /* f. Create h2 the composite hash of the PCR selected by pcrInfo -> creationPCRSelection */
1364 /* g. Set S1 -> sealInfo -> digestAtCreation to h2 */
1365 if (returnCode == TPM_SUCCESS) {
1366 returnCode = TPM_PCRSelection_GenerateDigest
1367 (s1StoredData.tpm_seal_info_long->digestAtCreation,
1368 &(s1StoredData.tpm_seal_info_long->creationPCRSelection),
1369 tpm_state->tpm_stclear_data.PCRS);
1370 }
1371 /* h. Set S1 -> sealInfo -> localityAtCreation to TPM_STANY_DATA -> localityModifier */
1372 if (returnCode == TPM_SUCCESS) {
1373 returnCode = TPM_Locality_Set(&(s1StoredData.tpm_seal_info_long->localityAtCreation),
1374 tpm_state->tpm_stany_flags.localityModifier);
1375 }
1376 }
1377 /* 10. Create S2 a TPM_SEALED_DATA structure */
1378 /* NOTE: Done at TPM_SealedData_Init() */
1379 /* 11.Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */
1380 if (returnCode == TPM_SUCCESS) {
1381 printf("TPM_Process_Sealx: Decrypting encAuth\n");
1382 returnCode = TPM_AuthSessionData_Decrypt(a1Auth, /* a1 even */
1383 NULL, /* a1 odd (2nd encAuth) */
1384 encAuth, /* encAuthEven */
1385 auth_session_data,
1386 NULL, /* nonceOdd */
1387 NULL, /* encAuthOdd */
1388 FALSE); /* even and odd */
1389 }
1390 if (returnCode == TPM_SUCCESS) {
1391 TPM_PrintFour("TPM_Process_Sealx: Decrypted Auth", a1Auth);
1392 /* a. If authHandle indicates XOR encryption for the AuthData secrets */
1393 if (auth_session_data->adipEncScheme == TPM_ET_XOR) {
1394 /* i. Set S1 -> et to TPM_ET_XOR || TPM_ET_KEY */
1395 /* (1) TPM_ET_KEY is added because TPM_Unseal uses zero as a special value indicating no
1396 encryption. */
1397 s1StoredData.et = TPM_ET_XOR | TPM_ET_KEY;
1398 }
1399 /* b. Else */
1400 else {
1401 /* i. Set S1 -> et to algorithm indicated by authHandle */
1402 s1StoredData.et = auth_session_data->adipEncScheme << 8;
1403 }
1404 }
1405 /* 12. The TPM provides NO validation of a1. Well-known values (like all zeros) are valid and
1406 possible. */
1407 /* 13. If authHandle indicates XOR encryption */
1408 /* a. Use MGF1 to create string X2 of length inDataSize. The inputs to MGF1 are;
1409 authLastNonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four concatenated
1410 values form the Z value that is the seed for MFG1. */
1411 /* b. Create o1 by XOR of inData and x2 */
1412 /* 14. Else */
1413 /* a. Create o1 by decrypting inData using the algorithm indicated by authHandle */
1414 /* b. Key is from authHandle -> sharedSecret */
1415 /* c. CTR is SHA-1 of (authLastNonceEven || nonceOdd) */
1416 if (returnCode == TPM_SUCCESS) {
1417 printf("TPM_Process_Sealx: decrypting inData\n");
1418 returnCode = TPM_SealCryptCommon(&o1DecryptedData, /* freed by caller */
1419 auth_session_data->adipEncScheme,
1420 &inData,
1421 auth_session_data,
1422 nonceOdd);
1423
1424 }
1425 /* 15. Create S2 a TPM_SEALED_DATA structure */
1426 if (returnCode == TPM_SUCCESS) {
1427 /* a. Set S2 -> payload to TPM_PT_SEAL */
1428 /* NOTE: Done at TPM_SealedData_Init() */
1429 /* b. Set S2 -> tpmProof to TPM_PERMANENT_DATA -> tpmProof */
1430 TPM_Secret_Copy(s2SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof);
1431 /* c. Create h3 the SHA-1 of S1 */
1432 /* d. Set S2 -> storedDigest to h3 */
1433 returnCode = TPM_StoredData_GenerateDigest(s2SealedData.storedDigest, s1_11, 2);
1434 }
1435 /* e. Set S2 -> authData to a1 */
1436 if (returnCode == TPM_SUCCESS) {
1437 TPM_Secret_Copy(s2SealedData.authData, a1Auth);
1438 /* f. Set S2 -> dataSize to inDataSize */
1439 /* g. Set S2 -> data to o1 */
1440 returnCode = TPM_SizedBuffer_Set(&(s2SealedData.data), inData.size, o1DecryptedData);
1441 }
1442 /* 16. Validate that the size of S2 can be encrypted by the key pointed to by keyHandle, return
1443 */
1444 /* TPM_BAD_DATASIZE on error */
1445 /* 17. Create s3 the encryption of S2 using the key pointed to by keyHandle */
1446 /* 18. Set continueAuthSession to FALSE */
1447 if (returnCode == TPM_SUCCESS) {
1448 continueAuthSession = FALSE;
1449 }
1450 /* 19. Set S1 -> encDataSize to the size of s3 */
1451 /* 20. Set S1 -> encData to s3 */
1452 if (returnCode == TPM_SUCCESS) {
1453 printf("TPM_Process_Sealx: Encrypting sealed data\n");
1454 returnCode = TPM_SealedData_GenerateEncData(&(s1StoredData.encData), &s2SealedData, key);
1455 }
1456 /*
1457 response
1458 */
1459 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
1460 if (rcf == 0) {
1461 printf("TPM_Process_Sealx: Ordinal returnCode %08x %u\n",
1462 returnCode, returnCode);
1463 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1464 }
1465 /* success response, append the rest of the parameters. */
1466 if (rcf == 0) {
1467 if (returnCode == TPM_SUCCESS) {
1468 /* checkpoint the beginning of the outParam's */
1469 outParamStart = response->buffer_current - response->buffer;
1470 /* 21. Return S1 as sealedData */
1471 returnCode = TPM_StoredData_Store(response, s1_11, 2);
1472 /* checkpoint the end of the outParam's */
1473 outParamEnd = response->buffer_current - response->buffer;
1474 }
1475 /* digest the above the line output parameters */
1476 if (returnCode == TPM_SUCCESS) {
1477 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
1478 auditStatus, /* input audit status */
1479 transportEncrypt,
1480 tag,
1481 returnCode,
1482 ordinal, /* command ordinal */
1483 response->buffer + outParamStart, /* start */
1484 outParamEnd - outParamStart); /* length */
1485 }
1486 /* calculate and set the below the line parameters */
1487 if (returnCode == TPM_SUCCESS) {
1488 returnCode = TPM_AuthParams_Set(response,
1489 *hmacKey, /* owner HMAC key */
1490 auth_session_data,
1491 outParamDigest,
1492 nonceOdd,
1493 continueAuthSession);
1494 }
1495 /* audit if required */
1496 if ((returnCode == TPM_SUCCESS) && auditStatus) {
1497 returnCode = TPM_ProcessAudit(tpm_state,
1498 transportEncrypt,
1499 inParamDigest,
1500 outParamDigest,
1501 ordinal);
1502 }
1503 /* adjust the initial response */
1504 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1505 }
1506 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1507 if (((rcf != 0) ||
1508 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1509 !continueAuthSession) &&
1510 authHandleValid) {
1511 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1512 }
1513 /*
1514 cleanup
1515 */
1516 TPM_SizedBuffer_Delete(&pcrInfo); /* @1 */
1517 TPM_SizedBuffer_Delete(&inData); /* @2 */
1518 TPM_StoredData_Delete(s1_11, 2); /* @3 */
1519 TPM_SealedData_Delete(&s2SealedData); /* @4 */
1520 free(o1DecryptedData); /* @5 */
1521 return rcf;
1522}
1523
1524/* 10.2 TPM_Unseal rev 110
1525
1526 The TPM_Unseal operation will reveal TPM_Sealed data only if it was encrypted on this platform
1527 and the current configuration (as defined by the named PCR contents) is the one named as
1528 qualified to decrypt it. Internally, TPM_Unseal accepts a data blob generated by a TPM_Seal
1529 operation. TPM_Unseal decrypts the structure internally, checks the integrity of the resulting
1530 data, and checks that the PCR named has the value named during TPM_Seal. Additionally, the
1531 caller must supply appropriate authorization data for blob and for the key that was used to seal
1532 that data.
1533
1534 If the integrity, platform configuration and authorization checks succeed, the sealed data is
1535 returned to the caller; otherwise, an error is generated.
1536*/
1537
1538TPM_RESULT TPM_Process_Unseal(tpm_state_t *tpm_state,
1539 TPM_STORE_BUFFER *response,
1540 TPM_TAG tag,
1541 uint32_t paramSize,
1542 TPM_COMMAND_CODE ordinal,
1543 unsigned char *command,
1544 TPM_TRANSPORT_INTERNAL *transportInternal)
1545{
1546 TPM_RESULT rcf = 0; /* fatal error precluding response */
1547 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
1548
1549 /* input parameters */
1550 TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can unseal the data. */
1551 TPM_STORED_DATA inData; /* The encrypted data generated by TPM_Seal. */
1552 TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle. */
1553 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
1554 TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization
1555 handle */
1556 TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and
1557 parentHandle. HMAC key: parentKey.usageAuth. */
1558 TPM_AUTHHANDLE dataAuthHandle; /* The authorization handle used to authorize inData. */
1559 TPM_NONCE datanonceOdd; /* Nonce generated by system associated with
1560 entityAuthHandle */
1561 TPM_BOOL continueDataSession = TRUE; /* Continue usage flag for dataAuthHandle. */
1562 TPM_AUTHDATA dataAuth; /* The authorization digest for the encrypted entity. HMAC
1563 key: entity.usageAuth. */
1564
1565 /* processing */
1566 unsigned char * inParamStart; /* starting point of inParam's */
1567 unsigned char * inParamEnd; /* ending point of inParam's */
1568 TPM_DIGEST inParamDigest;
1569 TPM_BOOL auditStatus; /* audit the ordinal */
1570 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
1571 TPM_BOOL authHandleValid = FALSE;
1572 TPM_BOOL dataAuthHandleValid = FALSE;
1573 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
1574 TPM_AUTH_SESSION_DATA *data_auth_session_data = NULL; /* session data for dataAuthHandle
1575 */
1576 TPM_SECRET *hmacKey;
1577 TPM_SECRET *dataHmacKey;
1578 unsigned int v1StoredDataVersion = 1; /* version of TPM_STORED_DATA
1579 inData */
1580 TPM_KEY *parentKey;
1581 TPM_BOOL parentPCRStatus;
1582 TPM_SECRET *parentUsageAuth;
1583 TPM_SEALED_DATA d1SealedData;
1584 TPM_DIGEST h1StoredDataDigest;
1585 TPM_STORED_DATA12 *s2StoredData;
1586 BYTE *o1Encrypted; /* For ADIP encryption */
1587 TPM_ADIP_ENC_SCHEME adipEncScheme;
1588
1589 /* output parameters */
1590 uint32_t outParamStart; /* starting point of outParam's */
1591 uint32_t outParamEnd; /* ending point of outParam's */
1592 TPM_DIGEST outParamDigest;
1593 uint32_t secretSize = 0; /* Decrypted data that had been sealed */
1594 BYTE *secret = NULL;
1595
1596 printf("TPM_Process_Unseal: Ordinal Entry\n");
1597 TPM_StoredData_Init(&inData, v1StoredDataVersion); /* freed @1, default is v1 */
1598 TPM_SealedData_Init(&d1SealedData); /* freed @2 */
1599 o1Encrypted = NULL; /* freed @3 */
1600 s2StoredData = (TPM_STORED_DATA12 *)&inData; /* inData when it's a TPM_STORED_DATA12
1601 structure */
1602 /*
1603 get inputs
1604 */
1605 /* get parentHandle parameter */
1606 if (returnCode == TPM_SUCCESS) {
1607 returnCode = TPM_Load32(&parentHandle, &command, &paramSize);
1608 }
1609 /* save the starting point of inParam's for authorization and auditing */
1610 inParamStart = command;
1611 /* get inData parameter */
1612 if (returnCode == TPM_SUCCESS) {
1613 printf("TPM_Process_Unseal: parentHandle %08x\n", parentHandle);
1614 returnCode = TPM_StoredData_Load(&inData, &v1StoredDataVersion, &command, &paramSize);
1615 }
1616 if (returnCode == TPM_SUCCESS) {
1617 printf("TPM_Process_Unseal: inData is v%u\n", v1StoredDataVersion);
1618 }
1619 /* save the ending point of inParam's for authorization and auditing */
1620 inParamEnd = command;
1621 /* digest the input parameters */
1622 if (returnCode == TPM_SUCCESS) {
1623 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
1624 &auditStatus, /* output */
1625 &transportEncrypt, /* output */
1626 tpm_state,
1627 tag,
1628 ordinal,
1629 inParamStart,
1630 inParamEnd,
1631 transportInternal);
1632 }
1633 /* check state */
1634 if (returnCode == TPM_SUCCESS) {
1635 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
1636 }
1637 /* check tag */
1638 if (returnCode == TPM_SUCCESS) {
1639 returnCode = TPM_CheckRequestTag21(tag);
1640 }
1641 /* get the optional 'below the line' authorization parameters */
1642 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1643 returnCode = TPM_AuthParams_Get(&authHandle,
1644 &authHandleValid,
1645 nonceOdd,
1646 &continueAuthSession,
1647 parentAuth,
1648 &command, &paramSize);
1649 }
1650 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1651 printf("TPM_Process_Unseal: authHandle %08x\n", authHandle);
1652 }
1653 /* get the 'below the line' authorization parameters */
1654 if (returnCode == TPM_SUCCESS) {
1655 returnCode = TPM_AuthParams_Get(&dataAuthHandle,
1656 &dataAuthHandleValid,
1657 datanonceOdd,
1658 &continueDataSession,
1659 dataAuth,
1660 &command, &paramSize);
1661 }
1662 if (returnCode == TPM_SUCCESS) {
1663 printf("TPM_Process_Unseal: dataAuthHandle %08x\n", dataAuthHandle);
1664 }
1665 if (returnCode == TPM_SUCCESS) {
1666 if (paramSize != 0) {
1667 printf("TPM_Process_Unseal: Error, command has %u extra bytes\n",
1668 paramSize);
1669 returnCode = TPM_BAD_PARAM_SIZE;
1670 }
1671 }
1672 /* do not terminate sessions if the command did not parse correctly */
1673 if (returnCode != TPM_SUCCESS) {
1674 authHandleValid = FALSE;
1675 dataAuthHandleValid = FALSE;
1676 }
1677 /*
1678 Processing
1679 */
1680 /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle
1681 */
1682 if (returnCode == TPM_SUCCESS) {
1683 returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus,
1684 tpm_state, parentHandle,
1685 FALSE, /* not r/o, using to decrypt */
1686 FALSE, /* do not ignore PCRs */
1687 FALSE); /* cannot use EK */
1688 }
1689 /* get parentHandle -> usageAuth */
1690 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1691 returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey);
1692 }
1693 /* get the first session data */
1694 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1695 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
1696 &hmacKey,
1697 tpm_state,
1698 authHandle,
1699 TPM_PID_NONE,
1700 TPM_ET_KEYHANDLE,
1701 ordinal,
1702 parentKey,
1703 parentUsageAuth, /* OIAP */
1704 parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/
1705 }
1706 /* 1. The TPM MUST validate that parentAuth authorizes the use of the key in parentHandle, on
1707 error return TPM_AUTHFAIL */
1708 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1709 returnCode = TPM_Authdata_Check(tpm_state,
1710 *hmacKey, /* HMAC key */
1711 inParamDigest,
1712 auth_session_data, /* authorization session */
1713 nonceOdd, /* Nonce generated by system
1714 associated with authHandle */
1715 continueAuthSession,
1716 parentAuth); /* Authorization digest for input */
1717 }
1718 /* if there are no parent auth parameters */
1719 if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
1720 if (parentKey->authDataUsage != TPM_AUTH_NEVER) {
1721 printf("TPM_Process_Unseal: Error, parent key authorization required\n");
1722 returnCode = TPM_AUTHFAIL;
1723 }
1724 }
1725 /* 2. If the keyUsage field of the key indicated by parentHandle does not have the value
1726 TPM_KEY_STORAGE, the TPM MUST return the error code TPM_INVALID_KEYUSAGE. */
1727 if (returnCode == TPM_SUCCESS) {
1728 if (parentKey->keyUsage != TPM_KEY_STORAGE) {
1729 printf("TPM_Process_Unseal: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n",
1730 parentKey->keyUsage);
1731 returnCode = TPM_INVALID_KEYUSAGE;
1732 }
1733 }
1734 /* 3. The TPM MUST check that the TPM_KEY_FLAGS -> Migratable flag has the value FALSE in the
1735 key indicated by parentKeyHandle. If not, the TPM MUST return the error code
1736 TPM_INVALID_KEYUSAGE */
1737 if (returnCode == TPM_SUCCESS) {
1738 if (parentKey->keyFlags & TPM_MIGRATABLE) {
1739 printf("TPM_Process_Unseal: Error, key keyFlags %08x indicates migratable\n",
1740 parentKey->keyFlags);
1741 returnCode = TPM_INVALID_KEYUSAGE;
1742 }
1743 }
1744 /* 4. Determine the version of inData */
1745 /* a. If inData -> tag = TPM_TAG_STORED_DATA12 */
1746 /* i. Set V1 to 2 */
1747 /* ii. Map S2 a TPM_STORED_DATA12 structure to inData */
1748 /* b. Else If inData -> ver = 1.1 */
1749 /* i. Set V1 to 1 */
1750 /* ii. Map S2 a TPM_STORED_DATA structure to inData */
1751 /* c. Else */
1752 /* i. Return TPM_BAD_VERSION */
1753 /* NOTE: Done during TPM_StoredData_Load() */
1754 /* The extra indent of error checking is required because the next steps all return
1755 TPM_NOTSEALED_BLOB on error */
1756 if (returnCode == TPM_SUCCESS) {
1757 /* 5. Create d1 by decrypting S2 -> encData using the key pointed to by parentHandle */
1758 printf("TPM_Process_Unseal: Decrypting encData\n");
1759 if (returnCode == TPM_SUCCESS) {
1760 returnCode = TPM_SealedData_DecryptEncData(&d1SealedData, /* TPM_SEALED_DATA */
1761 &(inData.encData),
1762 parentKey);
1763 }
1764 /* 6. Validate d1 */
1765 /* a. d1 MUST be a TPM_SEALED_DATA structure */
1766 /* NOTE Done during TPM_SealedData_DecryptEncData() */
1767 /* b. d1 -> tpmProof MUST match TPM_PERMANENT_DATA -> tpmProof */
1768 if (returnCode == TPM_SUCCESS) {
1769 printf("TPM_Process_Unseal: Sealed data size %u\n", d1SealedData.data.size);
1770 TPM_PrintFour("TPM_Process_Unseal: Sealed data", d1SealedData.data.buffer);
1771 printf("TPM_Process_Unseal: Checking tpmProof\n");
1772 returnCode = TPM_Secret_Compare(d1SealedData.tpmProof,
1773 tpm_state->tpm_permanent_data.tpmProof);
1774 }
1775 if (returnCode == TPM_SUCCESS) {
1776 /* c. Set S2 -> encDataSize to 0 */
1777 /* d. Set S2 -> encData to all zeros */
1778 /* NOTE: This would be done at cleanup */
1779 TPM_SizedBuffer_Delete(&(inData.encData));
1780 /* e. Create h1 the SHA-1 of S2 */
1781 returnCode = TPM_StoredData_GenerateDigest(h1StoredDataDigest,
1782 &inData, v1StoredDataVersion);
1783 }
1784 /* f. d1 -> storedDigest MUST match h1 */
1785 if (returnCode == TPM_SUCCESS) {
1786 printf("TPM_Process_Unseal: Checking storedDigest\n");
1787 returnCode = TPM_Digest_Compare(d1SealedData.storedDigest, h1StoredDataDigest);
1788 }
1789 /* g. d1 -> payload MUST be TPM_PT_SEAL */
1790 if (returnCode == TPM_SUCCESS) {
1791 if (d1SealedData.payload != TPM_PT_SEAL) {
1792 printf("TPM_Process_Unseal: Error, payload %02x not TPM_PT_SEAL\n",
1793 d1SealedData.payload);
1794 returnCode = TPM_NOTSEALED_BLOB;
1795 }
1796 }
1797 /* h. Any failure MUST return TPM_NOTSEALED_BLOB */
1798 if (returnCode != TPM_SUCCESS) {
1799 returnCode = TPM_NOTSEALED_BLOB;
1800 }
1801 }
1802 /* 7. If S2 -> sealInfo is not 0 then */
1803 /* NOTE: Done by _CheckDigest() */
1804 if (returnCode == TPM_SUCCESS) {
1805 printf("TPM_Process_Unseal: Checking PCR digest\n");
1806 /* a. If V1 is 1 then */
1807 if (v1StoredDataVersion == 1) {
1808 /* i. Validate that S2 -> pcrInfo is a valid TPM_PCR_INFO structure */
1809 /* NOTE: Done during TPM_StoredData_Load() */
1810 /* ii. Create h2 the composite hash of the PCR selected by S2 -> pcrInfo -> pcrSelection
1811 */
1812 /* c. Compare h2 with S2 -> pcrInfo -> digestAtRelease, on mismatch return
1813 TPM_WRONGPCRVALUE */
1814 returnCode = TPM_PCRInfo_CheckDigest(inData.tpm_seal_info,
1815 tpm_state->tpm_stclear_data.PCRS); /* PCR array */
1816 }
1817 /* b. If V1 is 2 then */
1818 else {
1819 /* i. Validate that S2 -> pcrInfo is a valid TPM_PCR_INFO_LONG structure */
1820 /* NOTE: Done during TPM_StoredData_Load() */
1821 /* ii. Create h2 the composite hash of the PCR selected by S2 -> pcrInfo ->
1822 releasePCRSelection */
1823 /* iii. Check that S2 -> pcrInfo -> localityAtRelease for TPM_STANY_DATA ->
1824 localityModifier is TRUE */
1825 /* (1) For example if TPM_STANY_DATA -> localityModifier was 2 then S2 -> pcrInfo ->
1826 localityAtRelease -> TPM_LOC_TWO would have to be TRUE */
1827 /* c. Compare h2 with S2 -> pcrInfo -> digestAtRelease, on mismatch return
1828 TPM_WRONGPCRVALUE */
1829 returnCode =
1830 TPM_PCRInfoLong_CheckDigest(s2StoredData->tpm_seal_info_long,
1831 tpm_state->tpm_stclear_data.PCRS, /* PCR array */
1832 tpm_state->tpm_stany_flags.localityModifier);
1833 }
1834 }
1835 /* 8. The TPM MUST validate authorization to use d1 by checking that the HMAC calculation
1836 using d1 -> authData as the shared secret matches the dataAuth. Return TPM_AUTHFAIL on
1837 mismatch. */
1838 /* get the second session data */
1839 /* NOTE: While OSAP isn't specifically excluded, there is currently no way to set up an OSAP
1840 session using TPM_SEALED_DATA as the entity */
1841 if (returnCode == TPM_SUCCESS) {
1842 returnCode = TPM_AuthSessions_GetData(&data_auth_session_data,
1843 &dataHmacKey,
1844 tpm_state,
1845 dataAuthHandle,
1846 TPM_PID_OIAP, /* currently require OIAP */
1847 0, /* OSAP entity type */
1848 ordinal,
1849 NULL,
1850 &(d1SealedData.authData), /* OIAP */
1851 NULL); /* OSAP */
1852 }
1853 if (returnCode == TPM_SUCCESS) {
1854 returnCode = TPM_Auth2data_Check(tpm_state,
1855 *dataHmacKey, /* HMAC key */
1856 inParamDigest,
1857 data_auth_session_data, /* authorization session */
1858 datanonceOdd, /* Nonce generated by system
1859 associated with authHandle */
1860 continueDataSession,
1861 dataAuth); /* Authorization digest for input */
1862 }
1863 if (returnCode == TPM_SUCCESS) {
1864 /* 9. If V1 is 2 and S2 -> et specifies encryption (i.e. is not all zeros) then */
1865 if ((v1StoredDataVersion == 2) && (s2StoredData->et != 0x0000)) {
1866 /* a. If tag is not TPM_TAG_RQU_AUTH2_COMMAND, return TPM_AUTHFAIL */
1867 if (returnCode == TPM_SUCCESS) {
1868 if (tag != TPM_TAG_RQU_AUTH2_COMMAND) {
1869 printf("TPM_Process_Unseal: Error, sealed with encryption but auth-1\n");
1870 returnCode = TPM_AUTHFAIL;
1871 }
1872 }
1873 /* b. Verify that the authHandle session type is TPM_PID_OSAP or TPM_PID_DSAP, return
1874 TPM_BAD_MODE on error. */
1875 if (returnCode == TPM_SUCCESS) {
1876 if ((auth_session_data->protocolID != TPM_PID_OSAP) &&
1877 (auth_session_data->protocolID != TPM_PID_DSAP)) {
1878 printf("TPM_Process_Unseal: Error, sealed with encryption but OIAP\n");
1879 returnCode = TPM_BAD_MODE;
1880 }
1881 }
1882 /* c. If MSB of S2 -> et is TPM_ET_XOR */
1883 /* i. Use MGF1 to create string X1 of length sealedDataSize. The inputs to MGF1 are;
1884 authLastnonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four
1885 concatenated values form the Z value that is the seed for MFG1. */
1886 /* d. Else */
1887 /* i. Create o1 by encrypting d1 -> data using the algorithm indicated by inData ->
1888 et */
1889 /* ii. Key is from authHandle -> sharedSecret */
1890 /* iii. IV is SHA-1 of (authLastNonceEven || nonceOdd) */
1891 if (returnCode == TPM_SUCCESS) {
1892 /* entity type MSB is ADIP encScheme */
1893 adipEncScheme = (s2StoredData->et >> 8) & 0x00ff;
1894 printf("TPM_Process_Unseal: Encrypting the output, encScheme %02x\n",
1895 adipEncScheme);
1896 returnCode = TPM_SealCryptCommon(&o1Encrypted,
1897 adipEncScheme,
1898 &(d1SealedData.data),
1899 auth_session_data,
1900 nonceOdd);
1901 secretSize = d1SealedData.data.size;
1902 secret = o1Encrypted;
1903 }
1904 /* e. Set continueAuthSession to FALSE */
1905 continueAuthSession = FALSE;
1906 }
1907 /* 10. else */
1908 else {
1909 printf("TPM_Process_Unseal: No output encryption\n");
1910 /* a. Set o1 to d1 -> data */
1911 secretSize = d1SealedData.data.size;
1912 secret = d1SealedData.data.buffer;
1913 }
1914 }
1915 /* 11. Set the return secret as o1 */
1916 /*
1917 response
1918 */
1919 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
1920 if (rcf == 0) {
1921 printf("TPM_Process_Unseal: Ordinal returnCode %08x %u\n",
1922 returnCode, returnCode);
1923 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
1924 }
1925 /* success response, append the rest of the parameters. */
1926 if (rcf == 0) {
1927 if (returnCode == TPM_SUCCESS) {
1928 /* checkpoint the beginning of the outParam's */
1929 outParamStart = response->buffer_current - response->buffer;
1930 /* return secretSize */
1931 returnCode = TPM_Sbuffer_Append32(response, secretSize);
1932 }
1933 if (returnCode == TPM_SUCCESS) {
1934 /* return secret */
1935 returnCode = TPM_Sbuffer_Append(response, secret, secretSize);
1936 /* checkpoint the end of the outParam's */
1937 outParamEnd = response->buffer_current - response->buffer;
1938 }
1939 /* digest the above the line output parameters */
1940 if (returnCode == TPM_SUCCESS) {
1941 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
1942 auditStatus, /* input audit status */
1943 transportEncrypt,
1944 tag,
1945 returnCode,
1946 ordinal, /* command ordinal */
1947 response->buffer + outParamStart, /* start */
1948 outParamEnd - outParamStart); /* length */
1949 }
1950 /* calculate and set the below the line parameters */
1951 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
1952 returnCode = TPM_AuthParams_Set(response,
1953 *hmacKey, /* HMAC key */
1954 auth_session_data,
1955 outParamDigest,
1956 nonceOdd,
1957 continueAuthSession);
1958 }
1959 /* calculate and set the below the line parameters */
1960 if (returnCode == TPM_SUCCESS) {
1961 returnCode = TPM_AuthParams_Set(response,
1962 *dataHmacKey, /* HMAC key */
1963 data_auth_session_data,
1964 outParamDigest,
1965 datanonceOdd,
1966 continueDataSession);
1967 }
1968 /* audit if required */
1969 if ((returnCode == TPM_SUCCESS) && auditStatus) {
1970 returnCode = TPM_ProcessAudit(tpm_state,
1971 transportEncrypt,
1972 inParamDigest,
1973 outParamDigest,
1974 ordinal);
1975 }
1976 /* adjust the initial response */
1977 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
1978 }
1979 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
1980 if (((rcf != 0) ||
1981 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1982 !continueAuthSession) &&
1983 authHandleValid) {
1984 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
1985 }
1986 if (((rcf != 0) ||
1987 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
1988 !continueDataSession) &&
1989 dataAuthHandleValid) {
1990 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, dataAuthHandle);
1991 }
1992 /*
1993 cleanup
1994 */
1995 TPM_StoredData_Delete(&inData, v1StoredDataVersion); /* @1 */
1996 TPM_SealedData_Delete(&d1SealedData); /* @2 */
1997 free(o1Encrypted); /* @3 */
1998 return rcf;
1999}
2000
2001/* 10.3 TPM_UnBind rev 87
2002
2003 TPM_UnBind takes the data blob that is the result of a Tspi_Data_Bind command and decrypts it
2004 for export to the User. The caller must authorize the use of the key that will decrypt the
2005 incoming blob.
2006
2007 UnBind operates on a block-by-block basis, and has no notion of any relation between one block
2008 and another.
2009
2010 UnBind SHALL operate on a single block only.
2011*/
2012
2013TPM_RESULT TPM_Process_UnBind(tpm_state_t *tpm_state,
2014 TPM_STORE_BUFFER *response,
2015 TPM_TAG tag,
2016 uint32_t paramSize,
2017 TPM_COMMAND_CODE ordinal,
2018 unsigned char *command,
2019 TPM_TRANSPORT_INTERNAL *transportInternal)
2020{
2021 TPM_RESULT rcf = 0; /* fatal error precluding response */
2022 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
2023
2024 /* input parameters */
2025 TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform
2026 UnBind operations. */
2027 TPM_SIZED_BUFFER inData; /* Encrypted blob to be decrypted */
2028 TPM_AUTHHANDLE authHandle; /* The handle used for keyHandle authorization */
2029 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
2030 TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization
2031 handle */
2032 TPM_AUTHDATA privAuth; /* The authorization digest that authorizes the inputs and
2033 use of keyHandle. HMAC key: key.usageAuth. */
2034
2035 /* processing parameters */
2036 unsigned char * inParamStart; /* starting point of inParam's */
2037 unsigned char * inParamEnd; /* ending point of inParam's */
2038 TPM_DIGEST inParamDigest;
2039 TPM_BOOL auditStatus; /* audit the ordinal */
2040 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
2041 TPM_BOOL authHandleValid = FALSE;
2042 TPM_SECRET *hmacKey;
2043 TPM_KEY *key = NULL; /* the key specified by keyHandle */
2044 TPM_SECRET *keyUsageAuth;
2045 TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* for key */
2046 TPM_BOOL parentPCRStatus;
2047 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
2048 uint32_t decrypt_data_size; /* resulting decrypted data size */
2049 BYTE *decrypt_data = NULL; /* The resulting decrypted data. */
2050 unsigned char *stream;
2051 uint32_t stream_size;
2052 TPM_BOUND_DATA tpm_bound_data;
2053
2054 /* output parameters */
2055 uint32_t outParamStart; /* starting point of outParam's */
2056 uint32_t outParamEnd; /* ending point of outParam's */
2057 TPM_DIGEST outParamDigest;
2058 size_t outDataSize = 0; /* The length of the returned decrypted data */
2059 BYTE *outData = NULL; /* The resulting decrypted data. */
2060
2061 printf("TPM_Process_UnBind: Ordinal Entry\n");
2062 TPM_SizedBuffer_Init(&inData); /* freed @1 */
2063 TPM_BoundData_Init(&tpm_bound_data); /* freed @3 */
2064 /*
2065 get inputs
2066 */
2067 /* get keyHandle parameter */
2068 if (returnCode == TPM_SUCCESS) {
2069 returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
2070 }
2071 /* save the starting point of inParam's for authorization and auditing */
2072 inParamStart = command;
2073 /* get areaToSignSize and areaToSign parameters */
2074 if (returnCode == TPM_SUCCESS) {
2075 printf("TPM_Process_UnBind: keyHandle %08x\n", keyHandle);
2076 returnCode = TPM_SizedBuffer_Load(&inData, &command, &paramSize);
2077 }
2078 if (returnCode == TPM_SUCCESS) {
2079 printf("TPM_Process_UnBind: UnBinding %u bytes\n", inData.size);
2080 }
2081 /* save the ending point of inParam's for authorization and auditing */
2082 inParamEnd = command;
2083 /* digest the input parameters */
2084 if (returnCode == TPM_SUCCESS) {
2085 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
2086 &auditStatus, /* output */
2087 &transportEncrypt, /* output */
2088 tpm_state,
2089 tag,
2090 ordinal,
2091 inParamStart,
2092 inParamEnd,
2093 transportInternal);
2094 }
2095 /* check state */
2096 if (returnCode == TPM_SUCCESS) {
2097 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
2098 }
2099 /* check tag */
2100 if (returnCode == TPM_SUCCESS) {
2101 returnCode = TPM_CheckRequestTag10(tag);
2102 }
2103 /* get the optional 'below the line' authorization parameters */
2104 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2105 returnCode = TPM_AuthParams_Get(&authHandle,
2106 &authHandleValid,
2107 nonceOdd,
2108 &continueAuthSession,
2109 privAuth,
2110 &command, &paramSize);
2111 }
2112 if (returnCode == TPM_SUCCESS) {
2113 if (paramSize != 0) {
2114 printf("TPM_Process_UnBind: Error, command has %u extra bytes\n",
2115 paramSize);
2116 returnCode = TPM_BAD_PARAM_SIZE;
2117 }
2118 }
2119 /* do not terminate sessions if the command did not parse correctly */
2120 if (returnCode != TPM_SUCCESS) {
2121 authHandleValid = FALSE;
2122 }
2123 /*
2124 Processing
2125 */
2126 /* 1. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */
2127 if (returnCode == TPM_SUCCESS) {
2128 if (inData.size == 0) {
2129 printf("TPM_Process_UnBind: Error, inDataSize is 0\n");
2130 returnCode = TPM_BAD_PARAMETER;
2131 }
2132 }
2133 /* get the key corresponding to the keyHandle parameter */
2134 if (returnCode == TPM_SUCCESS) {
2135 returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle,
2136 FALSE, /* not read-only */
2137 FALSE, /* do not ignore PCRs */
2138 FALSE); /* cannot use EK */
2139 }
2140 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){
2141 if (key->authDataUsage != TPM_AUTH_NEVER) {
2142 printf("TPM_Process_UnBind: Error, authorization required\n");
2143 returnCode = TPM_AUTHFAIL;
2144 }
2145 }
2146 /* get keyHandle -> usageAuth */
2147 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2148 returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key);
2149 }
2150 /* get the session data */
2151 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2152 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
2153 &hmacKey,
2154 tpm_state,
2155 authHandle,
2156 TPM_PID_NONE,
2157 TPM_ET_KEYHANDLE,
2158 ordinal,
2159 key,
2160 keyUsageAuth, /* OIAP */
2161 key->tpm_store_asymkey->pubDataDigest); /* OSAP */
2162 }
2163 /* 2. Validate the authorization to use the key pointed to by keyHandle */
2164 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2165 returnCode = TPM_Authdata_Check(tpm_state,
2166 *hmacKey, /* HMAC key */
2167 inParamDigest,
2168 auth_session_data, /* authorization session */
2169 nonceOdd, /* Nonce generated by system
2170 associated with authHandle */
2171 continueAuthSession,
2172 privAuth); /* Authorization digest for input */
2173 }
2174 /* 3. If the keyUsage field of the key referenced by keyHandle does not have the value
2175 TPM_KEY_BIND or TPM_KEY_LEGACY, the TPM must return the error code TPM_INVALID_KEYUSAGE */
2176 if (returnCode == TPM_SUCCESS) {
2177 if ((key->keyUsage != TPM_KEY_BIND) && (key->keyUsage != TPM_KEY_LEGACY)) {
2178 printf("TPM_Process_UnBind: Error, invalid keyUsage %04hx\n", (key->keyUsage));
2179 returnCode = TPM_INVALID_KEYUSAGE;
2180 }
2181 }
2182 /* Get the TPM_RSA_KEY_PARMS associated with key */
2183 if (returnCode == TPM_SUCCESS) {
2184 returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, &(key->algorithmParms));
2185 }
2186 /* 4. Decrypt the inData using the key pointed to by keyHandle */
2187 if (returnCode == TPM_SUCCESS) {
2188 returnCode =
2189 TPM_RSAPrivateDecryptMalloc(&decrypt_data, /* decrypted data, freed @2 */
2190 &decrypt_data_size, /* actual size of decrypted data
2191 data */
2192 inData.buffer,
2193 inData.size,
2194 key);
2195 }
2196 if (returnCode == TPM_SUCCESS) {
2197 /* 5. if (keyHandle -> encScheme does not equal TPM_ES_RSAESOAEP_SHA1_MGF1) and (keyHandle
2198 -> keyUsage equals TPM_KEY_LEGACY), */
2199 if ((key->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) &&
2200 (key->keyUsage == TPM_KEY_LEGACY)) {
2201 printf("TPM_Process_UnBind: Legacy key\n");
2202 /* a. The payload does not have TPM specific markers to validate, so no consistency
2203 check can be performed. */
2204 /* b. Set the output parameter outData to the value of the decrypted value of
2205 inData. (Padding associated with the encryption wrapping of inData SHALL NOT be
2206 returned.) */
2207 outData = decrypt_data;
2208 /* c. Set the output parameter outDataSize to the size of outData, as deduced from the
2209 decryption process. */
2210 outDataSize = decrypt_data_size;
2211 }
2212 /* 6. else */
2213 else {
2214 printf("TPM_Process_UnBind: Payload is TPM_BOUND_DATA structure\n");
2215 /* a. Interpret the decrypted data under the assumption that it is a TPM_BOUND_DATA
2216 structure, and validate that the payload type is TPM_PT_BIND */
2217 if (returnCode == TPM_SUCCESS) {
2218 stream = decrypt_data;
2219 stream_size = decrypt_data_size;
2220 returnCode = TPM_BoundData_Load(&tpm_bound_data,
2221 &stream,
2222 &stream_size);
2223 }
2224 if (returnCode == TPM_SUCCESS) {
2225 if (tpm_bound_data.payload != TPM_PT_BIND) {
2226 printf("TPM_Process_UnBind: Error, "
2227 "TPM_BOUND_DATA->payload %02x not TPM_PT_BIND\n",
2228 tpm_bound_data.payload);
2229 returnCode = TPM_INVALID_STRUCTURE;
2230 }
2231 }
2232 /* b. Set the output parameter outData to the value of TPM_BOUND_DATA ->
2233 payloadData. (Other parameters of TPM_BOUND_DATA SHALL NOT be returned. Padding
2234 associated with the encryption wrapping of inData SHALL NOT be returned.) */
2235 if (returnCode == TPM_SUCCESS) {
2236 outData = tpm_bound_data.payloadData;
2237 /* c. Set the output parameter outDataSize to the size of outData, as deduced from
2238 the decryption process and the interpretation of TPM_BOUND_DATA. */
2239 outDataSize = tpm_bound_data.payloadDataSize;
2240 }
2241 }
2242 }
2243 /*
2244 response
2245 */
2246 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
2247 if (rcf == 0) {
2248 printf("TPM_Process_UnBind: Ordinal returnCode %08x %u\n",
2249 returnCode, returnCode);
2250 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
2251 }
2252 /* success response, append the rest of the parameters. */
2253 if (rcf == 0) {
2254 if (returnCode == TPM_SUCCESS) {
2255 /* checkpoint the beginning of the outParam's */
2256 outParamStart = response->buffer_current - response->buffer;
2257 /* 10. Return the computed outData */
2258 /* append outDataSize */
2259 returnCode = TPM_Sbuffer_Append32(response, outDataSize);
2260 }
2261 if (returnCode == TPM_SUCCESS) {
2262 /* append outData */
2263 returnCode = TPM_Sbuffer_Append(response, outData, outDataSize);
2264 /* checkpoint the end of the outParam's */
2265 outParamEnd = response->buffer_current - response->buffer;
2266 }
2267 /* digest the above the line output parameters */
2268 if (returnCode == TPM_SUCCESS) {
2269 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
2270 auditStatus, /* input audit status */
2271 transportEncrypt,
2272 tag,
2273 returnCode,
2274 ordinal, /* command ordinal */
2275 response->buffer + outParamStart, /* start */
2276 outParamEnd - outParamStart); /* length */
2277 }
2278 /* calculate and set the below the line parameters */
2279 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2280 returnCode = TPM_AuthParams_Set(response,
2281 *hmacKey, /* HMAC key */
2282 auth_session_data,
2283 outParamDigest,
2284 nonceOdd,
2285 continueAuthSession);
2286 }
2287 /* audit if required */
2288 if ((returnCode == TPM_SUCCESS) && auditStatus) {
2289 returnCode = TPM_ProcessAudit(tpm_state,
2290 transportEncrypt,
2291 inParamDigest,
2292 outParamDigest,
2293 ordinal);
2294 }
2295 /* adjust the initial response */
2296 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2297 }
2298 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
2299 if (((rcf != 0) ||
2300 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2301 !continueAuthSession) &&
2302 authHandleValid) {
2303 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2304 }
2305 /*
2306 cleanup
2307 */
2308 TPM_SizedBuffer_Delete(&inData); /* @1 */
2309 free(decrypt_data); /* @2 */
2310 TPM_BoundData_Delete(&tpm_bound_data); /* @3 */
2311 return rcf;
2312}
2313
2314/* 10.4 TPM_CreateWrapKey rev 114
2315
2316 The TPM_CreateWrapKey command both generates and creates a secure storage bundle for asymmetric
2317 keys.
2318
2319 The newly created key can be locked to a specific PCR value by specifying a set of PCR registers.
2320*/
2321
2322TPM_RESULT TPM_Process_CreateWrapKey(tpm_state_t *tpm_state,
2323 TPM_STORE_BUFFER *response,
2324 TPM_TAG tag,
2325 uint32_t paramSize,
2326 TPM_COMMAND_CODE ordinal,
2327 unsigned char *command,
2328 TPM_TRANSPORT_INTERNAL *transportInternal)
2329{
2330 TPM_RESULT rcf = 0; /* fatal error precluding response */
2331 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
2332
2333 /* input parameters */
2334 TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can perform key wrapping. */
2335 TPM_ENCAUTH dataUsageAuth; /* Encrypted usage authorization data for the key. */
2336 TPM_ENCAUTH dataMigrationAuth; /* Encrypted migration authorization data for the
2337 key.*/
2338 TPM_KEY keyInfo; /* Information about key to be created, pubkey.keyLength and
2339 keyInfo.encData elements are 0. MAY be TPM_KEY12 */
2340 TPM_AUTHHANDLE authHandle; /* The authorization handle used for parent key
2341 authorization. Must be an OSAP session. */
2342 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
2343 TPM_BOOL continueAuthSession = TRUE; /* Ignored */
2344 TPM_AUTHDATA pubAuth; /* The authorization digest that authorizes the use of the
2345 public key in parentHandle. HMAC key:
2346 parentKey.usageAuth. */
2347
2348 /* processing parameters */
2349 unsigned char * inParamStart; /* starting point of inParam's */
2350 unsigned char * inParamEnd; /* ending point of inParam's */
2351 TPM_DIGEST inParamDigest;
2352 TPM_BOOL auditStatus; /* audit the ordinal */
2353 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
2354 TPM_BOOL authHandleValid = FALSE;
2355 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
2356 TPM_SECRET *hmacKey;
2357 TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */
2358 TPM_BOOL parentPCRStatus;
2359 TPM_RSA_KEY_PARMS *keyInfoRSAParms = NULL; /* substructure of keyInfo */
2360 TPM_SECRET du1UsageAuth;
2361 TPM_SECRET dm1MigrationAuth;
2362 TPM_STORE_ASYMKEY *wrappedStoreAsymkey; /* substructure of wrappedKey */
2363 TPM_PCR_INFO wrappedPCRInfo;
2364 int ver; /* TPM_KEY or TPM_KEY12 */
2365
2366 /* output parameters */
2367 TPM_KEY wrappedKey; /* The TPM_KEY structure which includes the public and
2368 encrypted private key. MAY be TPM_KEY12 */
2369 uint32_t outParamStart; /* starting point of outParam's */
2370 uint32_t outParamEnd; /* ending point of outParam's */
2371 TPM_DIGEST outParamDigest;
2372
2373 printf("TPM_Process_CreateWrapKey: Ordinal Entry\n");
2374 TPM_Key_Init(&keyInfo);
2375 TPM_Key_Init(&wrappedKey);
2376 TPM_PCRInfo_Init(&wrappedPCRInfo);
2377 /*
2378 get inputs
2379 */
2380 /* get parentHandle parameter */
2381 if (returnCode == TPM_SUCCESS) {
2382 returnCode = TPM_Load32(&parentHandle, &command, &paramSize);
2383 }
2384 /* save the starting point of inParam's for authorization and auditing */
2385 inParamStart = command;
2386 /* get dataUsageAuth parameter */
2387 if (returnCode == TPM_SUCCESS) {
2388 printf("TPM_Process_CreateWrapKey: parentHandle %08x\n", parentHandle);
2389 returnCode = TPM_Authdata_Load(dataUsageAuth, &command, &paramSize);
2390 }
2391 /* get dataMigrationAuth parameter */
2392 if (returnCode == TPM_SUCCESS) {
2393 returnCode = TPM_Authdata_Load(dataMigrationAuth, &command, &paramSize);
2394 }
2395 /* get keyInfo parameter */
2396 if (returnCode == TPM_SUCCESS) {
2397 returnCode = TPM_Key_Load(&keyInfo, &command, &paramSize); /* freed @1 */
2398 }
2399 /* save the ending point of inParam's for authorization and auditing */
2400 inParamEnd = command;
2401 /* digest the input parameters */
2402 if (returnCode == TPM_SUCCESS) {
2403 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
2404 &auditStatus, /* output */
2405 &transportEncrypt, /* output */
2406 tpm_state,
2407 tag,
2408 ordinal,
2409 inParamStart,
2410 inParamEnd,
2411 transportInternal);
2412 }
2413 /* check state */
2414 if (returnCode == TPM_SUCCESS) {
2415 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
2416 }
2417 /* check tag */
2418 if (returnCode == TPM_SUCCESS) {
2419 returnCode = TPM_CheckRequestTag1(tag);
2420 }
2421 /* get the 'below the line' authorization parameters */
2422 if (returnCode == TPM_SUCCESS) {
2423 returnCode = TPM_AuthParams_Get(&authHandle,
2424 &authHandleValid,
2425 nonceOdd,
2426 &continueAuthSession,
2427 pubAuth,
2428 &command, &paramSize);
2429 }
2430 if (returnCode == TPM_SUCCESS) {
2431 if (paramSize != 0) {
2432 printf("TPM_Process_CreateWrapKey: Error, command has %u extra bytes\n",
2433 paramSize);
2434 returnCode = TPM_BAD_PARAM_SIZE;
2435 }
2436 }
2437 /* do not terminate sessions if the command did not parse correctly */
2438 if (returnCode != TPM_SUCCESS) {
2439 authHandleValid = FALSE;
2440 }
2441 /*
2442 Processing
2443 */
2444 /* get the key corresponding to the parentHandle parameter */
2445 if (returnCode == TPM_SUCCESS) {
2446 returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state,
2447 parentHandle,
2448 FALSE, /* not r/o, using to encrypt w/public key */
2449 FALSE, /* do not ignore PCRs */
2450 FALSE); /* cannot use EK */
2451 }
2452 /* get the session data */
2453 if (returnCode == TPM_SUCCESS) {
2454 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
2455 &hmacKey,
2456 tpm_state,
2457 authHandle,
2458 TPM_PID_OSAP,
2459 TPM_ET_KEYHANDLE,
2460 ordinal,
2461 parentKey,
2462 NULL, /* OIAP */
2463 parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/
2464 }
2465 /* 1. Validate the authorization to use the key pointed to by parentHandle. Return TPM_AUTHFAIL
2466 on any error. */
2467 /* 2. Validate the session type for parentHandle is OSAP. */
2468 if (returnCode == TPM_SUCCESS) {
2469 TPM_PrintFour("TPM_Process_CreateWrapKey: sharedSecret", auth_session_data->sharedSecret);
2470 returnCode = TPM_Authdata_Check(tpm_state,
2471 *hmacKey, /* HMAC key */
2472 inParamDigest,
2473 auth_session_data, /* authorization session */
2474 nonceOdd, /* Nonce generated by system
2475 associated with authHandle
2476 */
2477 continueAuthSession,
2478 pubAuth); /* Authorization digest for input */
2479 }
2480 /* 3. If the TPM is not designed to create a key of the type requested in keyInfo, return the
2481 error code TPM_BAD_KEY_PROPERTY */
2482 if (returnCode == TPM_SUCCESS) {
2483 printf("TPM_Process_CreateWrapKey: Checking key properties\n");
2484 returnCode = TPM_Key_CheckProperties(&ver, &keyInfo, 0,
2485 tpm_state->tpm_permanent_flags.FIPS);
2486 }
2487 /* Get the TPM_RSA_KEY_PARMS associated with keyInfo */
2488 if (returnCode == TPM_SUCCESS) {
2489 printf("TPM_Process_CreateWrapKey: key parameters v = %d\n", ver);
2490 returnCode = TPM_KeyParms_GetRSAKeyParms(&keyInfoRSAParms, &(keyInfo.algorithmParms));
2491 }
2492 /* 4. Verify that parentHandle->keyUsage equals TPM_KEY_STORAGE */
2493 if (returnCode == TPM_SUCCESS) {
2494 if (parentKey->keyUsage != TPM_KEY_STORAGE) {
2495 printf("TPM_Process_CreateWrapKey: Error, parent keyUsage not TPM_KEY_STORAGE\n");
2496 returnCode = TPM_INVALID_KEYUSAGE;
2497 }
2498 }
2499 /* 5. If parentHandle -> keyFlags -> migratable is TRUE and keyInfo -> keyFlags -> migratable is
2500 FALSE then return TPM_INVALID_KEYUSAGE */
2501 if (returnCode == TPM_SUCCESS) {
2502 if ((parentKey->keyFlags & TPM_MIGRATABLE) && !(keyInfo.keyFlags & TPM_MIGRATABLE)) {
2503 printf("TPM_Process_CreateWrapKey: Error, parent not migratable\n");
2504 returnCode = TPM_INVALID_KEYUSAGE;
2505 }
2506 }
2507 /* 6. Validate key parameters */
2508 /* a. keyInfo -> keyUsage MUST NOT be TPM_KEY_IDENTITY or TPM_KEY_AUTHCHANGE. If it is, return
2509 TPM_INVALID_KEYUSAGE */
2510 if (returnCode == TPM_SUCCESS) {
2511 if ((keyInfo.keyUsage == TPM_KEY_IDENTITY) ||
2512 (keyInfo.keyUsage == TPM_KEY_AUTHCHANGE)) {
2513 printf("TPM_Process_CreateWrapKey: Error, Invalid key usage %04x\n",
2514 keyInfo.keyUsage);
2515 returnCode = TPM_INVALID_KEYUSAGE;
2516 }
2517 }
2518 /* b. If keyInfo -> keyFlags -> migrateAuthority is TRUE then return TPM_INVALID_KEYUSAGE */
2519 if (returnCode == TPM_SUCCESS) {
2520 if (keyInfo.keyFlags & TPM_MIGRATEAUTHORITY) {
2521 printf("TPM_Process_CreateWrapKey: Error, Invalid key flags %08x\n",
2522 keyInfo.keyFlags);
2523 returnCode = TPM_INVALID_KEYUSAGE;
2524 }
2525 }
2526 /* 7. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then
2527 a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS
2528 b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS
2529 c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS
2530 NOTE Done in step 3 TPM_Key_CheckProperties()
2531 */
2532 /* 8. If keyInfo -> keyUsage equals TPM_KEY_STORAGE or TPM_KEY_MIGRATE
2533 i. algorithmID MUST be TPM_ALG_RSA
2534 ii. encScheme MUST be TPM_ES_RSAESOAEP_SHA1_MGF1
2535 iii. sigScheme MUST be TPM_SS_NONE
2536 iv. key size MUST be 2048
2537 v. exponentSize MUST be 0
2538 NOTE Done in step 3 TPM_Key_CheckProperties()
2539 */
2540 /* 9. Determine the version of key
2541 a.If keyInfo -> ver is 1.1
2542 i. Set V1 to 1
2543 ii. Map wrappedKey to a TPM_KEY structure
2544 iii. Validate all remaining TPM_KEY structures
2545 b. Else if keyInfo -> tag is TPM_TAG_KEY12
2546 i. Set V1 to 2
2547 ii. Map wrappedKey to a TPM_KEY12 structure
2548 iii. Validate all remaining TPM_KEY12 structures
2549 NOTE Check done by TPM_Key_CheckProperties()
2550 NOTE Map done by TPM_Key_GenerateRSA()
2551 */
2552 /* 10..Create DU1 by decrypting dataUsageAuth according to the ADIP indicated by authHandle */
2553 /* 11. Create DM1 by decrypting dataMigrationAuth according to the ADIP indicated by
2554 authHandle */
2555 if (returnCode == TPM_SUCCESS) {
2556 TPM_AuthSessionData_Decrypt(du1UsageAuth,
2557 dm1MigrationAuth,
2558 dataUsageAuth, /* even encAuth */
2559 auth_session_data,
2560 nonceOdd,
2561 dataMigrationAuth, /* odd encAuth */
2562 TRUE);
2563 }
2564 /* 12. Set continueAuthSession to FALSE */
2565 if (returnCode == TPM_SUCCESS) {
2566 continueAuthSession = FALSE;
2567 }
2568 /* 13. Generate asymmetric key according to algorithm information in keyInfo */
2569 /* 14. Fill in the wrappedKey structure with information from the newly generated key. */
2570 if (returnCode == TPM_SUCCESS) {
2571 printf("TPM_Process_CreateWrapKey: Generating key\n");
2572 returnCode = TPM_Key_GenerateRSA(&wrappedKey,
2573 tpm_state,
2574 parentKey,
2575 tpm_state->tpm_stclear_data.PCRS, /* PCR array */
2576 ver,
2577 keyInfo.keyUsage,
2578 keyInfo.keyFlags,
2579 keyInfo.authDataUsage, /* TPM_AUTH_DATA_USAGE */
2580 &(keyInfo.algorithmParms), /* TPM_KEY_PARMS */
2581 keyInfo.tpm_pcr_info, /* TPM_PCR_INFO */
2582 keyInfo.tpm_pcr_info_long); /* TPM_PCR_INFO_LONG */
2583 }
2584 if (returnCode == TPM_SUCCESS) {
2585 returnCode = TPM_Key_GetStoreAsymkey(&wrappedStoreAsymkey,
2586 &wrappedKey);
2587 }
2588 if (returnCode == TPM_SUCCESS) {
2589 /* a. Set wrappedKey -> encData -> usageAuth to DU1 */
2590 TPM_Secret_Copy(wrappedStoreAsymkey->usageAuth, du1UsageAuth);
2591 /* b. If the KeyFlags -> migratable bit is set to 1, the wrappedKey -> encData ->
2592 migrationAuth SHALL contain the decrypted value from dataMigrationAuth. */
2593 if (wrappedKey.keyFlags & TPM_MIGRATABLE) {
2594 TPM_Secret_Copy(wrappedStoreAsymkey->migrationAuth, dm1MigrationAuth);
2595 }
2596 /* c. If the KeyFlags -> migratable bit is set to 0, the wrappedKey -> encData ->
2597 migrationAuth SHALL be set to the value tpmProof */
2598 else {
2599 TPM_Secret_Copy(wrappedStoreAsymkey->migrationAuth,
2600 tpm_state->tpm_permanent_data.tpmProof);
2601 }
2602 printf("TPM_Process_CreateWrapKey: wrappedKey.PCRInfoSize %d\n", wrappedKey.pcrInfo.size);
2603 }
2604 /* 15. If keyInfo->PCRInfoSize is non-zero. */
2605 /* a. If V1 is 1 */
2606 /* i. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO structure using the pcrSelection to
2607 indicate the PCR's in use */
2608 /* b. Else */
2609 /* i. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO_LONG structure */
2610 /* c. Set wrappedKey -> pcrInfo to keyInfo -> pcrInfo */
2611 /* d. Set wrappedKey -> digestAtCreation to the TPM_COMPOSITE_HASH indicated by
2612 creationPCRSelection */
2613 /* e. If V1 is 2 set wrappedKey -> localityAtCreation to TPM_STANY_DATA -> locality */
2614 /* NOTE Done by TPM_Key_GenerateRSA() */
2615 /* 16. Encrypt the private portions of the wrappedKey structure using the key in parentHandle */
2616 if (returnCode == TPM_SUCCESS) {
2617 returnCode = TPM_Key_GenerateEncData(&wrappedKey, parentKey);
2618 }
2619 /*
2620 response
2621 */
2622 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
2623 if (rcf == 0) {
2624 printf("TPM_Process_CreateWrapKey: Ordinal returnCode %08x %u\n",
2625 returnCode, returnCode);
2626 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
2627 }
2628 /* success response, append the rest of the parameters. */
2629 if (rcf == 0) {
2630 if (returnCode == TPM_SUCCESS) {
2631 /* checkpoint the beginning of the outParam's */
2632 outParamStart = response->buffer_current - response->buffer;
2633 /* 17. Return the newly generated key in the wrappedKey parameter */
2634 returnCode = TPM_Key_Store(response, &wrappedKey);
2635 /* checkpoint the end of the outParam's */
2636 outParamEnd = response->buffer_current - response->buffer;
2637 }
2638 /* digest the above the line output parameters */
2639 if (returnCode == TPM_SUCCESS) {
2640 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
2641 auditStatus, /* input audit status */
2642 transportEncrypt,
2643 tag,
2644 returnCode,
2645 ordinal, /* command ordinal */
2646 response->buffer + outParamStart, /* start */
2647 outParamEnd - outParamStart); /* length */
2648 }
2649 /* calculate and set the below the line parameters */
2650 if (returnCode == TPM_SUCCESS) {
2651 returnCode = TPM_AuthParams_Set(response,
2652 *hmacKey, /* HMAC key */
2653 auth_session_data,
2654 outParamDigest,
2655 nonceOdd,
2656 continueAuthSession);
2657 }
2658 /* audit if required */
2659 if ((returnCode == TPM_SUCCESS) && auditStatus) {
2660 returnCode = TPM_ProcessAudit(tpm_state,
2661 transportEncrypt,
2662 inParamDigest,
2663 outParamDigest,
2664 ordinal);
2665 }
2666 /* adjust the initial response */
2667 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2668 }
2669 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
2670 if (((rcf != 0) ||
2671 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2672 !continueAuthSession) &&
2673 authHandleValid) {
2674 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2675 }
2676 /* cleanup */
2677 TPM_Key_Delete(&keyInfo); /* @1 */
2678 TPM_Key_Delete(&wrappedKey); /* @2 */
2679 TPM_PCRInfo_Delete(&wrappedPCRInfo); /* @3 */
2680 return rcf;
2681}
2682
2683/* 27.8 TPM_LoadKey rev 114
2684
2685 Version 1.2 deprecates LoadKey due to the HMAC of the new keyhandle on return. The wrapping makes
2686 use of the handle difficult in an environment where the TSS, or other management entity, is
2687 changing the TPM handle to a virtual handle.
2688
2689 Software using loadKey on a 1.2 TPM can have a collision with the returned handle as the 1.2 TPM
2690 uses random values in the lower three bytes of the handle. All new software must use LoadKey2 to
2691 allow management software the ability to manage the key handle.
2692
2693 Before the TPM can use a key to either wrap, unwrap, bind, unbind, seal, unseal, sign or perform
2694 any other action, it needs to be present in the TPM. The TPM_LoadKey function loads the key into
2695 the TPM for further use.
2696*/
2697
2698TPM_RESULT TPM_Process_LoadKey(tpm_state_t *tpm_state,
2699 TPM_STORE_BUFFER *response,
2700 TPM_TAG tag,
2701 uint32_t paramSize,
2702 TPM_COMMAND_CODE ordinal,
2703 unsigned char *command,
2704 TPM_TRANSPORT_INTERNAL *transportInternal)
2705{
2706 TPM_RESULT rcf = 0; /* fatal error precluding response */
2707 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
2708
2709 /* input parameters */
2710 TPM_KEY_HANDLE parentHandle; /* TPM handle of parent key. */
2711 TPM_KEY *inKey; /* Incoming key structure, both encrypted private and clear
2712 public portions. MAY be TPM_KEY12 */
2713 TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle
2714 authorization. */
2715 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
2716 TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization
2717 handle */
2718 TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and
2719 parentHandle. HMAC key: parentKey.usageAuth. */
2720 /* processing parameters */
2721 unsigned char * inParamStart; /* starting point of inParam's */
2722 unsigned char * inParamEnd; /* ending point of inParam's */
2723 TPM_DIGEST inParamDigest;
2724 TPM_BOOL auditStatus; /* audit the ordinal */
2725 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
2726 TPM_BOOL authHandleValid = FALSE;
2727 TPM_SECRET *hmacKey;
2728 TPM_BOOL key_added = FALSE; /* key has been added to handle list */
2729 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
2730
2731 /* output parameters */
2732 uint32_t outParamStart; /* starting point of outParam's */
2733 uint32_t outParamEnd; /* ending point of outParam's */
2734 TPM_DIGEST outParamDigest;
2735 TPM_KEY_HANDLE inKeyHandle; /* Internal TPM handle where decrypted key was loaded. */
2736
2737 printf("TPM_Process_LoadKey: Ordinal Entry\n");
2738 inKey = NULL; /* freed @1 */
2739 /*
2740 get inputs
2741 */
2742 /* get parentHandle parameter */
2743 if (returnCode == TPM_SUCCESS) {
2744 returnCode = TPM_Load32(&parentHandle, &command, &paramSize);
2745 }
2746 /* save the starting point of inParam's for authorization and auditing */
2747 inParamStart = command;
2748 /* Allocate space for inKey. The key cannot be a local variable, since it persists in key
2749 storage after the command completes. */
2750 if (returnCode == TPM_SUCCESS) {
2751 printf("TPM_Process_LoadKey: parentHandle %08x\n", parentHandle);
2752 returnCode = TPM_Malloc((unsigned char **)&inKey, sizeof(TPM_KEY)); /* freed @1 */
2753 }
2754 /* get inKey parameter */
2755 if (returnCode == TPM_SUCCESS) {
2756 TPM_Key_Init(inKey); /* freed @2 */
2757 returnCode = TPM_Key_Load(inKey, &command, &paramSize); /* freed @2 */
2758 }
2759 if (returnCode == TPM_SUCCESS) {
2760 TPM_PrintFour("TPM_Process_LoadKey: inKey n", inKey->pubKey.buffer);
2761 }
2762 /* save the ending point of inParam's for authorization and auditing */
2763 inParamEnd = command;
2764 /* digest the input parameters */
2765 if (returnCode == TPM_SUCCESS) {
2766 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
2767 &auditStatus, /* output */
2768 &transportEncrypt, /* output */
2769 tpm_state,
2770 tag,
2771 ordinal,
2772 inParamStart,
2773 inParamEnd,
2774 transportInternal);
2775 }
2776 /* check state */
2777 if (returnCode == TPM_SUCCESS) {
2778 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
2779 }
2780 /* check tag */
2781 if (returnCode == TPM_SUCCESS) {
2782 returnCode = TPM_CheckRequestTag10(tag);
2783 }
2784 /* get the optional 'below the line' authorization parameters */
2785 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2786 returnCode = TPM_AuthParams_Get(&authHandle,
2787 &authHandleValid,
2788 nonceOdd,
2789 &continueAuthSession,
2790 parentAuth,
2791 &command, &paramSize);
2792 }
2793 if (returnCode == TPM_SUCCESS) {
2794 if (paramSize != 0) {
2795 printf("TPM_Process_LoadKey: Error, command has %u extra bytes\n",
2796 paramSize);
2797 returnCode = TPM_BAD_PARAM_SIZE;
2798 }
2799 }
2800 /* do not terminate sessions if the command did not parse correctly */
2801 if (returnCode != TPM_SUCCESS) {
2802 authHandleValid = FALSE;
2803 }
2804 /*
2805 Processing
2806 */
2807 if (returnCode == TPM_SUCCESS) {
2808 returnCode = TPM_LoadKeyCommon(&inKeyHandle, /* output */
2809 &key_added, /* output */
2810 &hmacKey, /* output */
2811 &auth_session_data, /* output */
2812 tpm_state,
2813 tag,
2814 ordinal,
2815 parentHandle,
2816 inKey,
2817 inParamDigest,
2818 authHandle, /*uninitialized*/
2819 nonceOdd,
2820 continueAuthSession,
2821 parentAuth);
2822 }
2823 /*
2824 response
2825 */
2826 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
2827 if (rcf == 0) {
2828 printf("TPM_Process_LoadKey: Ordinal returnCode %08x %u\n",
2829 returnCode, returnCode);
2830 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
2831 }
2832 /* success response, append the rest of the parameters. */
2833 if (rcf == 0) {
2834 if (returnCode == TPM_SUCCESS) {
2835 /* checkpoint the beginning of the outParam's */
2836 outParamStart = response->buffer_current - response->buffer;
2837 /* return the key handle */
2838 returnCode = TPM_Sbuffer_Append32(response, inKeyHandle);
2839 /* checkpoint the end of the outParam's */
2840 outParamEnd = response->buffer_current - response->buffer;
2841 }
2842 /* digest the above the line output parameters */
2843 if (returnCode == TPM_SUCCESS) {
2844 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
2845 auditStatus, /* input audit status */
2846 transportEncrypt,
2847 tag,
2848 returnCode,
2849 ordinal, /* command ordinal */
2850 response->buffer + outParamStart, /* start */
2851 outParamEnd - outParamStart); /* length */
2852 }
2853 /* calculate and set the below the line parameters */
2854 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
2855 returnCode = TPM_AuthParams_Set(response,
2856 *hmacKey, /* HMAC key */
2857 auth_session_data,
2858 outParamDigest,
2859 nonceOdd,
2860 continueAuthSession);
2861 }
2862 /* audit if required */
2863 if ((returnCode == TPM_SUCCESS) && auditStatus) {
2864 returnCode = TPM_ProcessAudit(tpm_state,
2865 transportEncrypt,
2866 inParamDigest,
2867 outParamDigest,
2868 ordinal);
2869 }
2870 /* adjust the initial response */
2871 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
2872 }
2873 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
2874 if (((rcf != 0) ||
2875 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
2876 !continueAuthSession) &&
2877 authHandleValid) {
2878 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
2879 }
2880 /*
2881 cleanup
2882 */
2883 /* if there was a failure, delete inKey */
2884 if ((rcf != 0) || (returnCode != TPM_SUCCESS)) {
2885 TPM_Key_Delete(inKey); /* @2 */
2886 free(inKey); /* @1 */
2887 if (key_added) {
2888 /* if there was a failure and inKey was stored in the handle list, free the handle.
2889 Ignore errors, since only one error code can be returned. */
2890 TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, inKeyHandle);
2891 }
2892 }
2893 return rcf;
2894}
2895
2896/* 10.5 TPM_LoadKey2 rev 107
2897
2898 Before the TPM can use a key to either wrap, unwrap, unbind, seal, unseal, sign or perform any
2899 other action, it needs to be present in the TPM. The TPM_LoadKey2 function loads the key into
2900 the TPM for further use.
2901
2902 The TPM assigns the key handle. The TPM always locates a loaded key by use of the handle. The
2903 assumption is that the handle may change due to key management operations. It is the
2904 responsibility of upper level software to maintain the mapping between handle and any label used
2905 by external software.
2906
2907 This command has the responsibility of enforcing restrictions on the use of keys. For example,
2908 when attempting to load a STORAGE key it will be checked for the restrictions on a storage key
2909 (2048 size etc.).
2910
2911 The load command must maintain a record of whether any previous key in the key hierarchy was
2912 bound to a PCR using parentPCRStatus.
2913
2914 The flag parentPCRStatus enables the possibility of checking that a platform passed through some
2915 particular state or states before finishing in the current state. A grandparent key could be
2916 linked to state-1, a parent key could linked to state-2, and a child key could be linked to
2917 state-3, for example. The use of the child key then indicates that the platform passed through
2918 states 1 and 2 and is currently in state 3, in this example. TPM_Startup with stType ==
2919 TPM_ST_CLEAR indicates that the platform has been reset, so the platform has not passed through
2920 the previous states. Hence keys with parentPCRStatus==TRUE must be unloaded if TPM_Startup is
2921 issued with stType == TPM_ST_CLEAR.
2922
2923 If a TPM_KEY structure has been decrypted AND the integrity test using "pubDataDigest" has passed
2924 AND the key is non-migratory, the key must have been created by the TPM. So there is every reason
2925 to believe that the key poses no security threat to the TPM. While there is no known attack from
2926 a rogue migratory key, there is a desire to verify that a loaded migratory key is a real key,
2927 arising from a general sense of unease about execution of arbitrary data as a key. Ideally a
2928 consistency check would consist of an encrypt/decrypt cycle, but this may be expensive. For RSA
2929 keys, it is therefore suggested that the consistency test consists of dividing the supposed RSA
2930 product by the supposed RSA prime, and checking that there is no remainder.
2931*/
2932
2933TPM_RESULT TPM_Process_LoadKey2(tpm_state_t *tpm_state,
2934 TPM_STORE_BUFFER *response,
2935 TPM_TAG tag,
2936 uint32_t paramSize,
2937 TPM_COMMAND_CODE ordinal,
2938 unsigned char *command,
2939 TPM_TRANSPORT_INTERNAL *transportInternal)
2940{
2941 TPM_RESULT rcf = 0; /* fatal error precluding response */
2942 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
2943
2944 /* input parameters */
2945 TPM_KEY_HANDLE parentHandle; /* TPM handle of parent key. */
2946 TPM_KEY *inKey; /* Incoming key structure, both encrypted private and clear
2947 public portions. MAY be TPM_KEY12 */
2948 TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle
2949 authorization. */
2950 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
2951 TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization
2952 handle */
2953 TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and
2954 parentHandle. HMAC key: parentKey.usageAuth. */
2955 /* processing parameters */
2956 unsigned char * inParamStart; /* starting point of inParam's */
2957 unsigned char * inParamEnd; /* ending point of inParam's */
2958 TPM_DIGEST inParamDigest;
2959 TPM_BOOL auditStatus; /* audit the ordinal */
2960 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
2961 TPM_BOOL authHandleValid = FALSE;
2962 TPM_SECRET *hmacKey;
2963 TPM_BOOL key_added = FALSE; /* key has been added to handle list */
2964 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
2965
2966 /* output parameters */
2967 uint32_t outParamStart; /* starting point of outParam's */
2968 uint32_t outParamEnd; /* ending point of outParam's */
2969 TPM_DIGEST outParamDigest;
2970 TPM_KEY_HANDLE inKeyHandle; /* Internal TPM handle where decrypted key was loaded. */
2971
2972 printf("TPM_Process_LoadKey2: Ordinal Entry\n");
2973 inKey = NULL; /* freed @1 */
2974 /*
2975 get inputs
2976 */
2977 /* get parentHandle parameter */
2978 if (returnCode == TPM_SUCCESS) {
2979 returnCode = TPM_Load32(&parentHandle, &command, &paramSize);
2980 }
2981 /* save the starting point of inParam's for authorization and auditing */
2982 inParamStart = command;
2983 /* Allocate space for inKey. The key cannot be a local variable, since it persists in key
2984 storage after the command completes. */
2985 if (returnCode == TPM_SUCCESS) {
2986 printf("TPM_Process_LoadKey2: parentHandle %08x\n", parentHandle);
2987 returnCode = TPM_Malloc((unsigned char **)&inKey, sizeof(TPM_KEY)); /* freed @1 */
2988 }
2989 /* get inKey parameter */
2990 if (returnCode == TPM_SUCCESS) {
2991 TPM_Key_Init(inKey); /* freed @2 */
2992 returnCode = TPM_Key_Load(inKey, &command, &paramSize); /* freed @2 */
2993 }
2994 if (returnCode == TPM_SUCCESS) {
2995 TPM_PrintFour("TPM_Process_LoadKey2: inKey n", inKey->pubKey.buffer);
2996 }
2997 /* save the ending point of inParam's for authorization and auditing */
2998 inParamEnd = command;
2999 /* digest the input parameters */
3000 if (returnCode == TPM_SUCCESS) {
3001 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
3002 &auditStatus, /* output */
3003 &transportEncrypt, /* output */
3004 tpm_state,
3005 tag,
3006 ordinal,
3007 inParamStart,
3008 inParamEnd,
3009 transportInternal);
3010 }
3011 /* check state */
3012 if (returnCode == TPM_SUCCESS) {
3013 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
3014 }
3015 /* check tag */
3016 if (returnCode == TPM_SUCCESS) {
3017 returnCode = TPM_CheckRequestTag10(tag);
3018 }
3019 /* get the optional 'below the line' authorization parameters */
3020 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3021 returnCode = TPM_AuthParams_Get(&authHandle,
3022 &authHandleValid,
3023 nonceOdd,
3024 &continueAuthSession,
3025 parentAuth,
3026 &command, &paramSize);
3027 }
3028 if (returnCode == TPM_SUCCESS) {
3029 if (paramSize != 0) {
3030 printf("TPM_Process_LoadKey2: Error, command has %u extra bytes\n",
3031 paramSize);
3032 returnCode = TPM_BAD_PARAM_SIZE;
3033 }
3034 }
3035 /* do not terminate sessions if the command did not parse correctly */
3036 if (returnCode != TPM_SUCCESS) {
3037 authHandleValid = FALSE;
3038 }
3039 /*
3040 Processing
3041 */
3042 if (returnCode == TPM_SUCCESS) {
3043 returnCode = TPM_LoadKeyCommon(&inKeyHandle, /* output */
3044 &key_added, /* output */
3045 &hmacKey, /* output */
3046 &auth_session_data, /* output */
3047 tpm_state,
3048 tag,
3049 ordinal,
3050 parentHandle,
3051 inKey,
3052 inParamDigest,
3053 authHandle, /* uninitialized */
3054 nonceOdd,
3055 continueAuthSession,
3056 parentAuth);
3057 }
3058 /*
3059 response
3060 */
3061 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
3062 if (rcf == 0) {
3063 printf("TPM_Process_LoadKey2: Ordinal returnCode %08x %u\n",
3064 returnCode, returnCode);
3065 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3066 }
3067 /* success response, append the rest of the parameters. */
3068 if (rcf == 0) {
3069 if (returnCode == TPM_SUCCESS) {
3070 /* checkpoint the beginning of the outParam's */
3071 outParamStart = response->buffer_current - response->buffer;
3072 /* checkpoint the end of the outParam's */
3073 outParamEnd = response->buffer_current - response->buffer;
3074 /* In TPM_LoadKey2, the inKeyHandle is not part of the output HMAC */
3075 /* return the key handle */
3076 returnCode = TPM_Sbuffer_Append32(response, inKeyHandle);
3077 }
3078 /* digest the above the line output parameters */
3079 if (returnCode == TPM_SUCCESS) {
3080 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
3081 auditStatus, /* input audit status */
3082 transportEncrypt,
3083 tag,
3084 returnCode,
3085 ordinal, /* command ordinal */
3086 response->buffer + outParamStart, /* start */
3087 outParamEnd - outParamStart); /* length */
3088 }
3089 /* calculate and set the below the line parameters */
3090 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3091 returnCode = TPM_AuthParams_Set(response,
3092 *hmacKey, /* HMAC key */
3093 auth_session_data,
3094 outParamDigest,
3095 nonceOdd,
3096 continueAuthSession);
3097 }
3098 /* audit if required */
3099 if ((returnCode == TPM_SUCCESS) && auditStatus) {
3100 returnCode = TPM_ProcessAudit(tpm_state,
3101 transportEncrypt,
3102 inParamDigest,
3103 outParamDigest,
3104 ordinal);
3105 }
3106 /* adjust the initial response */
3107 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3108 }
3109 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
3110 if (((rcf != 0) ||
3111 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
3112 !continueAuthSession) &&
3113 authHandleValid) {
3114 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
3115 }
3116 /*
3117 cleanup
3118 */
3119 /* if there was a failure, delete inKey */
3120 if ((rcf != 0) || (returnCode != TPM_SUCCESS)) {
3121 TPM_Key_Delete(inKey); /* @2 */
3122 free(inKey); /* @1 */
3123 if (key_added) {
3124 /* if there was a failure and inKey was stored in the handle list, free the handle.
3125 Ignore errors, since only one error code can be returned. */
3126 TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, inKeyHandle);
3127 }
3128 }
3129 return rcf;
3130}
3131
3132/* TPM_LoadKeyCommon rev 114
3133
3134 Code common to TPM_LoadKey and TPM_LoadKey2. They differ only in whether the key handle is
3135 included in the response HMAC calculation.
3136*/
3137
3138static TPM_RESULT TPM_LoadKeyCommon(TPM_KEY_HANDLE *inKeyHandle, /* output */
3139 TPM_BOOL *key_added, /* output */
3140 TPM_SECRET **hmacKey, /* output */
3141 TPM_AUTH_SESSION_DATA **auth_session_data, /* output */
3142 tpm_state_t *tpm_state,
3143 TPM_TAG tag,
3144 TPM_COMMAND_CODE ordinal,
3145 TPM_KEY_HANDLE parentHandle,
3146 TPM_KEY *inKey,
3147 TPM_DIGEST inParamDigest,
3148 TPM_AUTHHANDLE authHandle,
3149 TPM_NONCE nonceOdd,
3150 TPM_BOOL continueAuthSession,
3151 TPM_AUTHDATA parentAuth)
3152{
3153 TPM_RESULT rc = 0;
3154 TPM_KEY *parentKey; /* the key specified by parentHandle */
3155 TPM_SECRET *parentUsageAuth;
3156 TPM_BOOL parentPCRStatus;
3157 TPM_BOOL parentPCRUsage;
3158 int ver;
3159
3160 printf("TPM_LoadKeyCommon:\n");
3161 *key_added = FALSE; /* key has been added to handle list */
3162 /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle
3163 */
3164 if (rc == TPM_SUCCESS) {
3165 rc = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus,
3166 tpm_state, parentHandle,
3167 FALSE, /* not r/o, using to decrypt */
3168 FALSE, /* do not ignore PCRs */
3169 FALSE); /* cannot use EK */
3170 }
3171 /* check TPM_AUTH_DATA_USAGE authDataUsage */
3172 if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) {
3173 if (parentKey->authDataUsage != TPM_AUTH_NEVER) {
3174 printf("TPM_LoadKeyCommon: Error, authorization required\n");
3175 rc = TPM_AUTHFAIL;
3176 }
3177 }
3178 /* get parentHandle -> usageAuth */
3179 if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3180 rc = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey);
3181 }
3182 /* get the session data */
3183 if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3184 rc = TPM_AuthSessions_GetData(auth_session_data,
3185 hmacKey,
3186 tpm_state,
3187 authHandle,
3188 TPM_PID_NONE,
3189 TPM_ET_KEYHANDLE,
3190 ordinal,
3191 parentKey,
3192 parentUsageAuth, /* OIAP */
3193 parentKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
3194 }
3195 /* 1. Validate the command and the parameters using parentAuth and parentHandle -> usageAuth */
3196 if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3197 rc = TPM_Authdata_Check(tpm_state,
3198 **hmacKey, /* HMAC key */
3199 inParamDigest,
3200 *auth_session_data, /* authorization session */
3201 nonceOdd, /* Nonce generated by system
3202 associated with authHandle */
3203 continueAuthSession,
3204 parentAuth); /* Authorization digest for input */
3205 }
3206 /* 2. If parentHandle -> keyUsage is NOT TPM_KEY_STORAGE return TPM_INVALID_KEYUSAGE */
3207 if (rc == TPM_SUCCESS) {
3208 if (parentKey->keyUsage != TPM_KEY_STORAGE) {
3209 printf("TPM_LoadKeyCommon: Error, "
3210 "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n",
3211 parentKey->keyUsage);
3212 rc = TPM_INVALID_KEYUSAGE;
3213 }
3214 }
3215 /* 3. If the TPM is not designed to operate on a key of the type specified by inKey, return the
3216 error code TPM_BAD_KEY_PROPERTY. */
3217 if (rc == TPM_SUCCESS) {
3218 rc = TPM_Key_CheckProperties(&ver, inKey, 0, tpm_state->tpm_permanent_flags.FIPS);
3219 printf("TPM_LoadKeyCommon: key parameters v = %d\n", ver);
3220 }
3221 /* 4. The TPM MUST handle both TPM_KEY and TPM_KEY12 structures.
3222 This step is done at TPM_Key_Load()
3223 */
3224 /* 5. Decrypt the inKey -> privkey to obtain TPM_STORE_ASYMKEY structure using the key in
3225 parentHandle.
3226 */
3227 if (rc == TPM_SUCCESS) {
3228 rc = TPM_Key_DecryptEncData(inKey, parentKey);
3229 }
3230 /* 6. Validate the integrity of inKey and decrypted TPM_STORE_ASYMKEY
3231 a. Reproduce inKey -> TPM_STORE_ASYMKEY -> pubDataDigest using the fields of inKey, and check
3232 that the reproduced value is the same as pubDataDigest
3233 */
3234 if (rc == TPM_SUCCESS) {
3235 rc = TPM_Key_CheckPubDataDigest(inKey);
3236 }
3237 /* 7. Validate the consistency of the key and it's key usage. */
3238 /* a. If inKey -> keyFlags -> migratable is TRUE, the TPM SHALL verify consistency of the public
3239 and private components of the asymmetric key pair. If inKey -> keyFlags -> migratable is
3240 FALSE, the TPM MAY verify consistency of the public and private components of the asymmetric
3241 key pair. The consistency of an RSA key pair MAY be verified by dividing the supposed (P*Q)
3242 product by a supposed prime and checking that there is no remainder.
3243
3244 This step is done at TPM_Key_Load()
3245 */
3246 /* b. If inKey -> keyUsage is TPM_KEY_IDENTITY, verify that inKey->keyFlags->migratable is
3247 FALSE. If it is not, return TPM_INVALID_KEYUSAGE
3248 */
3249 if (rc == TPM_SUCCESS) {
3250 if ((inKey->keyUsage == TPM_KEY_IDENTITY) &&
3251 (inKey->keyFlags & TPM_MIGRATABLE)) {
3252 printf("TPM_LoadKeyCommon: Error, identity key is migratable\n");
3253 rc = TPM_INVALID_KEYUSAGE;
3254 }
3255 }
3256 /* c. If inKey -> keyUsage is TPM_KEY_AUTHCHANGE, return TPM_INVALID_KEYUSAGE */
3257 if (rc == TPM_SUCCESS) {
3258 if (inKey->keyUsage == TPM_KEY_AUTHCHANGE) {
3259 printf("TPM_LoadKeyCommon: Error, keyUsage is TPM_KEY_AUTHCHANGE\n");
3260 rc = TPM_INVALID_KEYUSAGE;
3261 }
3262 }
3263 /* d. If inKey -> keyFlags -> migratable equals 0 then verify that TPM_STORE_ASYMKEY ->
3264 migrationAuth equals TPM_PERMANENT_DATA -> tpmProof */
3265 if (rc == TPM_SUCCESS) {
3266 if (!(inKey->keyFlags & TPM_MIGRATABLE)) {
3267 rc = TPM_Secret_Compare(tpm_state->tpm_permanent_data.tpmProof,
3268 inKey->tpm_store_asymkey->migrationAuth);
3269 if (rc != 0) {
3270 printf("TPM_LoadKeyCommon: Error, tpmProof mismatch\n");
3271 rc = TPM_INVALID_KEYUSAGE;
3272 }
3273 }
3274 }
3275 /* e. Validate the mix of encryption and signature schemes
3276 f. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then
3277 i. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS
3278 ii. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return
3279 TPM_NOTFIPS
3280 iii. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return
3281 TPM_NOTFIPS
3282 g. If inKey -> keyUsage is TPM_KEY_STORAGE or TPM_KEY_MIGRATE
3283 i. algorithmID MUST be TPM_ALG_RSA
3284 ii. Key size MUST be 2048
3285 iii. exponentSize MUST be 0
3286 iv. sigScheme MUST be TPM_SS_NONE
3287 h. If inKey -> keyUsage is TPM_KEY_IDENTITY
3288 i. algorithmID MUST be TPM_ALG_RSA
3289 ii. Key size MUST be 2048
3290 iv. exponentSize MUST be 0
3291 iii. encScheme MUST be TPM_ES_NONE
3292 NOTE Done in step 3.
3293 */
3294 if (rc == TPM_SUCCESS) {
3295 /* i. If the decrypted inKey -> pcrInfo is NULL, */
3296 /* i. The TPM MUST set the internal indicator to indicate that the key is not using any PCR
3297 registers. */
3298 /* j. Else */
3299 /* i. The TPM MUST store pcrInfo in a manner that allows the TPM to calculate a composite
3300 hash whenever the key will be in use */
3301 /* ii. The TPM MUST handle both version 1.1 TPM_PCR_INFO and 1.2 TPM_PCR_INFO_LONG
3302 structures according to the type of TPM_KEY structure */
3303 /* (1) The TPM MUST validate the TPM_PCR_INFO or TPM_PCR_INFO_LONG structures for legal
3304 values. However, the digestAtRelease and localityAtRelease are not validated for
3305 authorization until use time.*/
3306 /* NOTE TPM_Key_Load() loads the TPM_PCR_INFO or TPM_PCR_INFO_LONG cache */
3307 }
3308 /* 8. Perform any processing necessary to make TPM_STORE_ASYMKEY key available for
3309 operations. */
3310 /* NOTE Done at TPM_Key_Load() */
3311 /* 9. Load key and key information into internal memory of the TPM. If insufficient memory
3312 exists return error TPM_NOSPACE. */
3313 /* 10. Assign inKeyHandle according to internal TPM rules. */
3314 /* 11. Set InKeyHandle -> parentPCRStatus to parentHandle -> parentPCRStatus. */
3315 if (rc == TPM_SUCCESS) {
3316 *inKeyHandle = 0; /* no preferred value */
3317 rc = TPM_KeyHandleEntries_AddKeyEntry(inKeyHandle, /* output */
3318 tpm_state->tpm_key_handle_entries, /* input */
3319 inKey, /* input */
3320 parentPCRStatus,
3321 0); /* keyControl */
3322 }
3323 if (rc == TPM_SUCCESS) {
3324 printf(" TPM_LoadKeyCommon: Loaded key handle %08x\n", *inKeyHandle);
3325 /* remember that the handle has been added to handle list, so it can be deleted on error */
3326 *key_added = TRUE;
3327
3328 }
3329 /* 12. If parentHandle indicates it is using PCR registers then set inKeyHandle ->
3330 parentPCRStatus to TRUE. */
3331 if (rc == TPM_SUCCESS) {
3332 rc = TPM_Key_GetPCRUsage(&parentPCRUsage, parentKey, 0);
3333 }
3334 if (rc == TPM_SUCCESS) {
3335 if (parentPCRUsage) {
3336 rc = TPM_KeyHandleEntries_SetParentPCRStatus(tpm_state->tpm_key_handle_entries,
3337 *inKeyHandle, TRUE);
3338 }
3339 }
3340 return rc;
3341}
3342
3343/* 10.6 TPM_GetPubKey rev 102
3344
3345 The owner of a key may wish to obtain the public key value from a loaded key. This information
3346 may have privacy concerns so the command must have authorization from the key owner.
3347*/
3348
3349TPM_RESULT TPM_Process_GetPubKey(tpm_state_t *tpm_state,
3350 TPM_STORE_BUFFER *response,
3351 TPM_TAG tag,
3352 uint32_t paramSize,
3353 TPM_COMMAND_CODE ordinal,
3354 unsigned char *command,
3355 TPM_TRANSPORT_INTERNAL *transportInternal)
3356{
3357 TPM_RESULT rcf = 0; /* fatal error precluding response */
3358 TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
3359
3360 /* input parameters */
3361 TPM_KEY_HANDLE keyHandle; /* TPM handle of key. */
3362 TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle
3363 authorization. */
3364 TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
3365 TPM_BOOL continueAuthSession = TRUE; /*The continue use flag for the authorization
3366 handle */
3367 TPM_AUTHDATA keyAuth; /* Authorization HMAC key: key.usageAuth. */
3368
3369 /* processing parameters */
3370 unsigned char * inParamStart; /* starting point of inParam's */
3371 unsigned char * inParamEnd; /* ending point of inParam's */
3372 TPM_DIGEST inParamDigest;
3373 TPM_BOOL auditStatus; /* audit the ordinal */
3374 TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
3375 TPM_BOOL authHandleValid = FALSE;
3376 TPM_SECRET *hmacKey;
3377 TPM_KEY *key = NULL; /* the key specified by keyHandle */
3378 TPM_BOOL parentPCRStatus;
3379 TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */
3380 TPM_SECRET *keyUsageAuth;
3381 TPM_STORE_BUFFER pubkeyStream;
3382
3383 /* output parameters */
3384 uint32_t outParamStart; /* starting point of outParam's */
3385 uint32_t outParamEnd; /* ending point of outParam's */
3386 TPM_DIGEST outParamDigest;
3387 const unsigned char *pubkeyStreamBuffer; /* output */
3388 uint32_t pubkeyStreamLength;
3389
3390 printf("TPM_Process_GetPubKey: Ordinal Entry\n");
3391 TPM_Sbuffer_Init(&pubkeyStream); /* freed @1 */
3392 /*
3393 get inputs
3394 */
3395 /* get keyHandle parameter */
3396 if (returnCode == TPM_SUCCESS) {
3397 returnCode = TPM_Load32(&keyHandle, &command, &paramSize);
3398 }
3399 /* save the starting point of inParam's for authorization and auditing */
3400 inParamStart = command;
3401 if (returnCode == TPM_SUCCESS) {
3402 printf("TPM_Process_GetPubKey: keyHandle %08x\n", keyHandle);
3403 }
3404 /* save the ending point of inParam's for authorization and auditing */
3405 inParamEnd = command;
3406 /* digest the input parameters */
3407 if (returnCode == TPM_SUCCESS) {
3408 returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
3409 &auditStatus, /* output */
3410 &transportEncrypt, /* output */
3411 tpm_state,
3412 tag,
3413 ordinal,
3414 inParamStart,
3415 inParamEnd,
3416 transportInternal);
3417 }
3418 /* check state */
3419 if (returnCode == TPM_SUCCESS) {
3420 returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
3421 }
3422 /* check tag */
3423 if (returnCode == TPM_SUCCESS) {
3424 returnCode = TPM_CheckRequestTag10(tag);
3425 }
3426 /* get the optional 'below the line' authorization parameters */
3427 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3428 returnCode = TPM_AuthParams_Get(&authHandle,
3429 &authHandleValid,
3430 nonceOdd,
3431 &continueAuthSession,
3432 keyAuth,
3433 &command, &paramSize);
3434 }
3435 if (returnCode == TPM_SUCCESS) {
3436 if (paramSize != 0) {
3437 printf("TPM_Process_GetPubKey: Error, command has %u extra bytes\n",
3438 paramSize);
3439 returnCode = TPM_BAD_PARAM_SIZE;
3440 }
3441 }
3442 /* do not terminate sessions if the command did not parse correctly */
3443 if (returnCode != TPM_SUCCESS) {
3444 authHandleValid = FALSE;
3445 }
3446 /*
3447 Processing
3448 */
3449 /* get the key corresponding to the keyHandle parameter */
3450 if (returnCode == TPM_SUCCESS) {
3451 printf("TPM_Process_GetPubKey: Key handle %08x\n", keyHandle);
3452 returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle,
3453 TRUE, /* read-only */
3454 FALSE, /* do not ignore PCRs */
3455 FALSE); /* cannot use EK */
3456 }
3457 /* 1. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */
3458 /* get keyHandle -> usageAuth */
3459 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3460 returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key);
3461 }
3462 /* get the session data */
3463 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3464 returnCode = TPM_AuthSessions_GetData(&auth_session_data,
3465 &hmacKey,
3466 tpm_state,
3467 authHandle,
3468 TPM_PID_NONE,
3469 TPM_ET_KEYHANDLE,
3470 ordinal,
3471 key,
3472 keyUsageAuth, /* OIAP */
3473 key->tpm_store_asymkey->pubDataDigest); /* OSAP */
3474 }
3475
3476
3477 /* a. Validate the command parameters using keyHandle -> usageAuth, on error return
3478 TPM_AUTHFAIL */
3479 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3480 returnCode = TPM_Authdata_Check(tpm_state,
3481 *hmacKey, /* HMAC key */
3482 inParamDigest,
3483 auth_session_data, /* authorization session */
3484 nonceOdd, /* Nonce generated by system
3485 associated with authHandle */
3486 continueAuthSession,
3487 keyAuth); /* Authorization digest for input */
3488 }
3489 /* 2. Else */
3490 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){
3491 /* a. Verify that keyHandle -> authDataUsage is TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER,
3492 on error return TPM_AUTHFAIL */
3493#ifdef TPM_V12
3494 if ((key->authDataUsage != TPM_NO_READ_PUBKEY_AUTH) &&
3495 (key->authDataUsage != TPM_AUTH_NEVER)) {
3496 printf("TPM_Process_GetPubKey: Error, authorization required\n");
3497 returnCode = TPM_AUTHFAIL;
3498 }
3499#else /* TPM 1.1 does not have TPM_NO_READ_PUBKEY_AUTH */
3500 if (key->authDataUsage != TPM_AUTH_NEVER) {
3501 printf("TPM_Process_GetPubKey: Error, authorization required\n");
3502 returnCode = TPM_AUTHFAIL;
3503 }
3504#endif
3505 }
3506#ifdef TPM_V12 /* TPM 1.1 does not have readSRKPub */
3507 if (returnCode == TPM_SUCCESS) {
3508 /* 3. If keyHandle == TPM_KH_SRK then */
3509 if ((keyHandle == TPM_KH_SRK) &&
3510 /* a. If TPM_PERMANENT_FLAGS -> readSRKPub is FALSE then return TPM_INVALID_KEYHANDLE */
3511 !tpm_state->tpm_permanent_flags.readSRKPub) {
3512 printf("TPM_Process_GetPubKey: "
3513 "Error, keyHandle is TPM_KH_SRK and readSRKPub is FALSE\n");
3514 returnCode = TPM_INVALID_KEYHANDLE;
3515 }
3516 }
3517#endif
3518 /* 4. If keyHandle -> pcrInfoSize is not 0 */
3519 /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */
3520 /* i. Create a digestAtRelease according to the specified PCR registers and compare
3521 to keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */
3522 /* ii. If specified validate any locality requests */
3523 /* NOTE: Done at TPM_KeyHandleEntries_GetKey() */
3524 /* 5. Create a TPM_PUBKEY structure and return */
3525 if (returnCode == TPM_SUCCESS) {
3526 returnCode = TPM_Key_StorePubkey(&pubkeyStream, /* output */
3527 &pubkeyStreamBuffer, /* output */
3528 &pubkeyStreamLength, /* output */
3529 key); /* input */
3530 }
3531 /*
3532 response
3533 */
3534 /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
3535 if (rcf == 0) {
3536 printf("TPM_Process_GetPubKey: Ordinal returnCode %08x %u\n",
3537 returnCode, returnCode);
3538 rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
3539 }
3540 /* success response, append the rest of the parameters. */
3541 if (rcf == 0) {
3542 if (returnCode == TPM_SUCCESS) {
3543 /* checkpoint the beginning of the outParam's */
3544 outParamStart = response->buffer_current - response->buffer;
3545 /* TPM_PUBKEY structure */
3546 returnCode = TPM_Sbuffer_Append(response, pubkeyStreamBuffer, pubkeyStreamLength);
3547 /* checkpoint the end of the outParam's */
3548 outParamEnd = response->buffer_current - response->buffer;
3549 }
3550 /* digest the above the line output parameters */
3551 if (returnCode == TPM_SUCCESS) {
3552 returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
3553 auditStatus, /* input audit status */
3554 transportEncrypt,
3555 tag,
3556 returnCode,
3557 ordinal, /* command ordinal */
3558 response->buffer + outParamStart, /* start */
3559 outParamEnd - outParamStart); /* length */
3560 }
3561 /* calculate and set the below the line parameters */
3562 if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) {
3563 returnCode = TPM_AuthParams_Set(response,
3564 *hmacKey, /* owner HMAC key */
3565 auth_session_data,
3566 outParamDigest,
3567 nonceOdd,
3568 continueAuthSession);
3569 }
3570 /* audit if required */
3571 if ((returnCode == TPM_SUCCESS) && auditStatus) {
3572 returnCode = TPM_ProcessAudit(tpm_state,
3573 transportEncrypt,
3574 inParamDigest,
3575 outParamDigest,
3576 ordinal);
3577 }
3578 /* adjust the initial response */
3579 rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
3580 }
3581 /* if there was an error, or continueAuthSession is FALSE, terminate the session */
3582 if (((rcf != 0) ||
3583 ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
3584 !continueAuthSession) &&
3585 authHandleValid) {
3586 TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
3587 }
3588 /*
3589 cleanup
3590 */
3591 TPM_Sbuffer_Delete(&pubkeyStream); /* @1 */
3592 return rcf;
3593}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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