ia64/xen-unstable

view tools/vtpm_manager/manager/vtsp.c @ 8977:f84d5cdd9895

Clean up segment selector fixup and validation.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 23 14:43:45 2006 +0100 (2006-02-23)
parents d186157615d6
children 8589cdd09636
line source
1 // ===================================================================
2 //
3 // Copyright (c) 2005, Intel Corp.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 // * Neither the name of Intel Corporation nor the names of its
17 // contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 // ===================================================================
33 //
34 // vtsp.c
35 //
36 // Higher level interface to TCS for use in service.
37 //
38 // ==================================================================
40 #include <string.h>
41 #include "tcg.h"
42 #include "tcs.h"
43 #include "bsg.h"
44 #include "log.h"
45 #include "crypto.h"
46 #include "vtsp.h"
47 #include "buffer.h"
49 #define RSA_KEY_SIZE 0x0800
51 /***********************************************************************************
52 * GenerateAuth: Generate authorization info to be sent back to application
53 *
54 * Parameters: outParamDigestText The concatenation of output parameters to be SHA1ed
55 * outParamDigestTextSize Size of inParamDigestText
56 * HMACkey Key to be used for HMACing
57 * For OIAP use key.authUsage or PersistStore.ownerAuth
58 * For OSAP use shared secret
59 * pAuth Authorization information from the application
60 *
61 * Return: TPM_SUCCESS Authorization data created
62 * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP
63 *************************************************************************************/
64 TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,
65 /*[IN]*/ UINT32 inParamDigestTextSize,
66 /*[IN]*/ const TPM_SECRET *HMACkey,
67 /*[IN,OUT]*/ TCS_AUTH *auth) {
69 if (inParamDigestText == NULL || auth == NULL)
70 return (TPM_AUTHFAIL);
71 else {
73 //Generate new OddNonce
74 Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));
76 // Create SHA1 inParamDigest
77 TPM_DIGEST inParamDigest;
78 Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *) &inParamDigest);
80 // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
81 BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
83 BSG_PackList( hmacText, 4,
84 BSG_TPM_DIGEST, &inParamDigest,
85 BSG_TPM_NONCE, &(auth->NonceEven),
86 BSG_TPM_NONCE, &(auth->NonceOdd),
87 BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
89 Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));
91 return(TPM_SUCCESS);
93 }
94 }
96 /***********************************************************************************
97 * VerifyAuth: Verify the authdata for a command requiring authorization
98 *
99 * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed
100 * inParamDigestTextSize Size of inParamDigestText
101 * authDataUsage AuthDataUsage for the Entity being used
102 * Key->authDataUsage or TPM_AUTH_OWNER
103 * HMACkey Key to be used for HMACing
104 * For OIAP use key.authUsage or PersistStore.ownerAuth
105 * For OSAP use NULL (It will be aquired from the Auth Session)
106 * If unknown (default), assume OIAP
107 * sessionAuth A TCS_AUTH info for the session
108 * pAuth Authorization information from the application
109 * hContext If specified, on failed Auth, VerifyAuth will
110 * generate a new OIAP session in place of themselves
111 * destroyed session.
112 *
113 * Return: TPM_SUCCESS Authorization Verified
114 * TPM_AUTHFAIL Authorization Failed
115 * TPM_FAIL Failure during SHA1 routines
116 *************************************************************************************/
117 TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,
118 /*[IN]*/ UINT32 outParamDigestTextSize,
119 /*[IN]*/ const TPM_SECRET *HMACkey,
120 /*[IN,OUT]*/ TCS_AUTH *auth,
121 /*[IN]*/ TCS_CONTEXT_HANDLE hContext) {
122 if (outParamDigestText == NULL || auth == NULL)
123 return (TPM_AUTHFAIL);
126 // Create SHA1 inParamDigest
127 TPM_DIGEST outParamDigest;
128 Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *) &outParamDigest);
130 // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
131 TPM_DIGEST hm;
132 BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
134 BSG_PackList( hmacText, 4,
135 BSG_TPM_DIGEST, &outParamDigest,
136 BSG_TPM_NONCE, &(auth->NonceEven),
137 BSG_TPM_NONCE, &(auth->NonceOdd),
138 BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
140 Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),
141 (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);
143 // Compare correct HMAC with provided one.
144 if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates equality
145 return (TPM_SUCCESS);
146 else {
147 // If specified, reconnect the OIAP session.
148 // NOTE: This only works for TCS's that never have a 0 context.
149 if (hContext)
150 VTSP_OIAP( hContext, auth);
151 return (TPM_AUTHFAIL);
152 }
153 }
155 TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,
156 TCS_AUTH *auth) {
158 vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");
159 TPM_RESULT status = TPM_SUCCESS;
160 TPMTRYRETURN( TCSP_OIAP(hContext,
161 &auth->AuthHandle,
162 &auth->NonceEven) );
164 memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
165 auth->fContinueAuthSession = FALSE;
167 goto egress;
169 abort_egress:
171 egress:
173 return status;
174 }
176 TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,
177 const TPM_ENTITY_TYPE entityType,
178 const UINT32 entityValue,
179 const TPM_AUTHDATA *usageAuth,
180 TPM_SECRET *sharedSecret,
181 TCS_AUTH *auth) {
183 vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");
184 TPM_RESULT status = TPM_SUCCESS;
185 TPM_NONCE nonceEvenOSAP, nonceOddOSAP;
187 Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) );
189 TPMTRYRETURN( TCSP_OSAP( hContext,
190 entityType,
191 entityValue,
192 nonceOddOSAP,
193 &auth->AuthHandle,
194 &auth->NonceEven,
195 &nonceEvenOSAP) );
197 // Calculating Session Secret
198 BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];
200 BSG_PackList( sharedSecretText, 2,
201 BSG_TPM_NONCE, &nonceEvenOSAP,
202 BSG_TPM_NONCE, &nonceOddOSAP);
204 Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret);
206 memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
207 auth->fContinueAuthSession = FALSE;
209 goto egress;
211 abort_egress:
213 egress:
215 return status;
216 }
220 TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,
221 CRYPTO_INFO *crypto_info) {
223 TPM_RESULT status;
224 TPM_NONCE antiReplay;
225 TPM_DIGEST checksum;
226 BYTE *pubEKtext;
227 UINT32 pubEKtextsize;
229 vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");
231 // GenerateAuth new nonceOdd
232 Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );
235 TPMTRYRETURN( TCSP_ReadPubek( hContext,
236 antiReplay,
237 &pubEKtextsize,
238 &pubEKtext,
239 &checksum) );
242 // Extract the remaining output parameters
243 TPM_PUBKEY pubEK;
245 BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);
247 // Build CryptoInfo for the bindingKey
248 TPM_RSA_KEY_PARMS rsaKeyParms;
250 BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
251 pubEK.algorithmParms.parms,
252 &rsaKeyParms);
254 Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
255 rsaKeyParms.exponent,
256 pubEK.pubKey.keyLength,
257 pubEK.pubKey.key,
258 crypto_info);
260 // Destroy rsaKeyParms
261 BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
263 // Set encryption scheme
264 crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
265 //crypto_info->encScheme = pubEK.algorithmParms.encScheme;
266 crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;
268 goto egress;
270 abort_egress:
272 egress:
274 return status;
275 }
277 TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
278 const TPM_AUTHDATA *ownerAuth,
279 const TPM_AUTHDATA *srkAuth,
280 CRYPTO_INFO *ek_cryptoInfo,
281 TCS_AUTH *auth) {
283 vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");
285 TPM_RESULT status = TPM_SUCCESS;
286 TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;
287 TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;
288 BYTE *new_srk;
290 BYTE *paramText; // Digest to make Auth.
291 UINT32 paramTextSize;
293 // vars for srkpubkey parameter
294 TPM_KEY srkPub;
295 TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_SS_NONE, 12, 0};
296 BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
297 srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;
299 struct pack_buf_t srkText;
301 //These values are accurate for an enc(AuthData).
302 struct pack_buf_t encOwnerAuth, encSrkAuth;
304 encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
305 encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
307 if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {
308 vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");
309 status = TPM_RESOURCES;
310 goto abort_egress;
311 }
313 Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth, &encOwnerAuth.size, encOwnerAuth.data);
314 Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth, &encSrkAuth.size, encSrkAuth.data);
317 // Build srk public key struct
318 srkPub.ver = TPM_STRUCT_VER_1_1;
319 srkPub.keyUsage = TPM_KEY_STORAGE;
320 srkPub.keyFlags = 0x00;
321 srkPub.authDataUsage = TPM_AUTH_ALWAYS;
322 memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));
323 srkPub.PCRInfoSize = 0;
324 srkPub.PCRInfo = 0;
325 srkPub.pubKey.keyLength= 0;
326 srkPub.encDataSize = 0;
328 srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
329 srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);
331 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
333 paramTextSize = BSG_PackList(paramText, 5,
334 BSG_TPM_COMMAND_CODE,&command,
335 BSG_TPM_PROTOCOL_ID, &proto_id,
336 BSG_TPM_SIZE32_DATA, &encOwnerAuth,
337 BSG_TPM_SIZE32_DATA, &encSrkAuth,
338 BSG_TPM_KEY, &srkPub);
340 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );
342 new_srk = srkText.data;
343 TPMTRYRETURN( TCSP_TakeOwnership ( hContext,
344 proto_id,
345 encOwnerAuth.size,
346 encOwnerAuth.data,
347 encSrkAuth.size,
348 encSrkAuth.data,
349 &srkText.size,
350 &new_srk,
351 auth ) );
354 paramTextSize = BSG_PackList(paramText, 2,
355 BSG_TPM_RESULT, &status,
356 BSG_TPM_COMMAND_CODE, &command);
357 memcpy(paramText + paramTextSize, new_srk, srkText.size);
358 paramTextSize += srkText.size;
361 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
362 ownerAuth, auth,
363 hContext) );
365 goto egress;
367 abort_egress:
369 egress:
371 free(srkText.data);
372 free(encSrkAuth.data);
373 free(encOwnerAuth.data);
374 free(paramText);
376 TCS_FreeMemory(hContext, new_srk);
378 return status;
379 }
381 TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
382 const TPM_AUTHDATA *ownerAuth,
383 TCS_AUTH *auth) {
385 vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");
387 TPM_RESULT status = TPM_SUCCESS;
388 TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;
390 BYTE *paramText; // Digest to make Auth.
391 UINT32 paramTextSize;
393 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
395 paramTextSize = BSG_PackList(paramText, 1,
396 BSG_TPM_COMMAND_CODE, &command);
398 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
399 ownerAuth, auth) );
401 // Call TCS
402 TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in
403 auth) );
405 // Verify Auth
406 paramTextSize = BSG_PackList(paramText, 2,
407 BSG_TPM_RESULT, &status,
408 BSG_TPM_COMMAND_CODE, &command);
410 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
411 ownerAuth, auth,
412 hContext) );
413 goto egress;
415 abort_egress:
416 egress:
417 free(paramText);
418 return status;
419 }
421 TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
422 const TPM_KEY_USAGE usage,
423 const TPM_AUTHDATA *newKeyAuth,
424 const TCS_KEY_HANDLE parentHandle,
425 const TPM_AUTHDATA *osapSharedSecret,
426 buffer_t *pubKeyBuf,
427 TCS_AUTH *auth) {
429 int i;
430 TPM_RESULT status = TPM_SUCCESS;
431 TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;
433 vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);
435 // vars for Calculate encUsageAuth
436 BYTE *paramText;
437 UINT32 paramTextSize;
439 // vars for Calculate encUsageAuth
440 BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
441 TPM_DIGEST XORKey1;
442 UINT32 XORbufferSize;
443 TPM_SECRET encUsageAuth, encMigrationAuth;
445 // vars for Flatten newKey prototype
446 BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
447 UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH;
448 struct pack_buf_t newKeyText;
450 // Fill in newKey
451 TPM_KEY newKey;
453 BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
454 newKey.algorithmParms.algorithmID = TPM_ALG_RSA;
455 newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;
456 newKey.algorithmParms.parmSize = 12;
458 switch (usage) {
459 case TPM_KEY_SIGNING:
460 vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");
461 newKey.keyUsage = TPM_KEY_SIGNING;
462 newKey.algorithmParms.encScheme = TPM_ES_NONE;
463 newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;
464 break;
465 case TPM_KEY_STORAGE:
466 vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");
467 newKey.keyUsage = TPM_KEY_STORAGE;
468 newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
469 newKey.algorithmParms.sigScheme = TPM_SS_NONE;
470 break;
471 case TPM_KEY_BIND:
472 vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");
473 newKey.keyUsage = TPM_KEY_BIND;
474 newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
475 newKey.algorithmParms.sigScheme = TPM_SS_NONE;
476 break;
477 default:
478 vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");
479 status = TPM_BAD_PARAMETER;
480 goto abort_egress;
481 }
484 newKey.ver = TPM_STRUCT_VER_1_1;
486 newKey.keyFlags = 0;
487 newKey.authDataUsage = TPM_AUTH_ALWAYS;
488 newKey.pubKey.keyLength= 0;
489 newKey.encDataSize = 0;
490 newKey.encData = NULL;
492 // FIXME: Support PCR bindings
493 newKey.PCRInfoSize = 0;
494 newKey.PCRInfo = NULL;
496 // Calculate encUsageAuth
497 XORbufferSize = BSG_PackList( XORbuffer, 2,
498 BSG_TPM_SECRET, osapSharedSecret,
499 BSG_TPM_NONCE, &auth->NonceEven);
500 Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);
502 // FIXME: No support for migratable keys.
503 for (i=0; i < TPM_DIGEST_SIZE; i++)
504 ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *) newKeyAuth)[i];
506 // Flatten newKey prototype
507 flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);
508 newKeyText.data = flatKey;
509 newKeyText.size = flatKeySize;
511 // Generate HMAC
512 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
514 paramTextSize = BSG_PackList(paramText, 3,
515 BSG_TPM_COMMAND_CODE, &command,
516 BSG_TPM_AUTHDATA, &encUsageAuth,
517 BSG_TPM_AUTHDATA, &encMigrationAuth);
518 memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
519 paramTextSize += newKeyText.size;
522 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
523 osapSharedSecret, auth) );
525 // Call TCS
526 TPMTRYRETURN( TCSP_CreateWrapKey( hContext,
527 parentHandle,
528 encUsageAuth,
529 encMigrationAuth,
530 &newKeyText.size,
531 &newKeyText.data,
532 auth) );
534 // Verify Auth
535 paramTextSize = BSG_PackList(paramText, 2,
536 BSG_TPM_RESULT, &status,
537 BSG_TPM_COMMAND_CODE, &command);
538 memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
539 paramTextSize += newKeyText.size;
541 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
542 osapSharedSecret, auth, 0) );
544 // Unpack/return key structure
545 TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );
546 TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data) );
548 goto egress;
550 abort_egress:
552 egress:
554 free(flatKey);
555 free(paramText);
556 TCS_FreeMemory(hContext, newKeyText.data);
558 return status;
559 }
561 TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
562 const TCS_KEY_HANDLE hUnwrappingKey,
563 const buffer_t *rgbWrappedKeyBlob,
564 const TPM_AUTHDATA *parentAuth,
565 TPM_HANDLE *newKeyHandle,
566 TCS_AUTH *auth,
567 CRYPTO_INFO *cryptoinfo,
568 const BOOL skipTPMLoad) {
571 vtpmloginfo(VTPM_LOG_VTSP, "Loading Key %s.\n", (!skipTPMLoad ? "into TPM" : "only into memory"));
573 TPM_RESULT status = TPM_SUCCESS;
574 TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
576 BYTE *paramText=NULL; // Digest to make Auth.
577 UINT32 paramTextSize;
579 // SkipTPMLoad stops key from being loaded into TPM, but still generates CRYPTO_INFO for it
580 if (! skipTPMLoad) {
582 if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) ||
583 (newKeyHandle==NULL) || (auth==NULL)) {
584 status = TPM_BAD_PARAMETER;
585 goto abort_egress;
586 }
588 // Generate Extra TCS Parameters
589 TPM_HANDLE phKeyHMAC;
591 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
593 paramTextSize = BSG_PackList(paramText, 1,
594 BSG_TPM_COMMAND_CODE, &command);
596 memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));
597 paramTextSize += buffer_len(rgbWrappedKeyBlob);
599 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
600 parentAuth, auth) );
602 // Call TCS
603 TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,
604 hUnwrappingKey,
605 buffer_len(rgbWrappedKeyBlob),
606 rgbWrappedKeyBlob->bytes,
607 auth,
608 newKeyHandle,
609 &phKeyHMAC) );
611 // Verify Auth
612 paramTextSize = BSG_PackList(paramText, 3,
613 BSG_TPM_RESULT, &status,
614 BSG_TPM_COMMAND_CODE, &command,
615 BSG_TPM_HANDLE, newKeyHandle);
617 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
618 parentAuth, auth,
619 hContext) );
620 }
622 // Build cryptoinfo structure for software crypto function.
623 if (cryptoinfo != NULL) {
624 TPM_KEY newKey;
626 // Unpack/return key structure
627 BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
628 TPM_RSA_KEY_PARMS rsaKeyParms;
630 BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
631 newKey.algorithmParms.parms,
632 &rsaKeyParms);
634 Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
635 rsaKeyParms.exponent,
636 newKey.pubKey.keyLength,
637 newKey.pubKey.key,
638 cryptoinfo);
640 // Destroy rsaKeyParms
641 BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
643 // Set encryption scheme
644 cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
645 }
647 goto egress;
649 abort_egress:
651 egress:
653 free(paramText);
654 return status;
655 }
657 TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
658 const TPM_KEY_HANDLE key_handle,
659 const buffer_t *bound_data,
660 const TPM_AUTHDATA *usage_auth,
661 buffer_t *clear_data,
662 TCS_AUTH *auth) {
664 vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n", buffer_len(bound_data));
666 TPM_RESULT status = TPM_SUCCESS;
667 TPM_COMMAND_CODE command = TPM_ORD_UnBind;
669 BYTE *paramText; // Digest to make Auth.
670 UINT32 paramTextSize;
672 // Generate Extra TCS Parameters
673 struct pack_buf_t clear_data32;
674 BYTE *clear_data_text;
675 UINT32 clear_data_size;
677 struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
679 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
681 paramTextSize = BSG_PackList(paramText, 2,
682 BSG_TPM_COMMAND_CODE, &command,
683 BSG_TPM_SIZE32_DATA, &bound_data32);
685 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
686 usage_auth, auth) );
688 // Call TCS
689 TPMTRYRETURN( TCSP_UnBind( hContext,
690 key_handle,
691 buffer_len(bound_data),
692 bound_data->bytes,
693 auth,
694 &clear_data_size,
695 &clear_data_text) );
698 // Verify Auth
699 clear_data32.size = clear_data_size;
700 clear_data32.data = clear_data_text;
701 paramTextSize = BSG_PackList(paramText, 3,
702 BSG_TPM_RESULT, &status,
703 BSG_TPM_COMMAND_CODE, &command,
704 BSG_TPM_SIZE32_DATA, &clear_data32);
706 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
707 usage_auth, auth,
708 hContext) );
710 // Unpack/return key structure
711 TPMTRYRETURN(buffer_init(clear_data, 0, 0));
712 TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, clear_data_text) );
714 goto egress;
716 abort_egress:
718 egress:
720 free(paramText);
721 TCS_FreeMemory(hContext, clear_data_text);
723 return status;
724 }
726 TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
727 const buffer_t *inData,
728 buffer_t *outData)
729 {
730 vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n", buffer_len(inData));
731 TPM_BOUND_DATA boundData;
732 UINT32 i;
734 // Fill boundData's accessory information
735 boundData.ver = TPM_STRUCT_VER_1_1;
736 boundData.payload = TPM_PT_BIND;
737 boundData.payloadData = inData->bytes;
739 // Pack boundData before encryption
740 BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) *
741 (sizeof(TPM_VERSION) +
742 sizeof(TPM_PAYLOAD_TYPE) +
743 buffer_len(inData)));
744 if (flatBoundData == NULL) {
745 return TPM_NOSPACE;
746 }
747 UINT32 flatBoundDataSize = 0;
748 flatBoundDataSize = BSG_PackList( flatBoundData, 2,
749 BSG_TPM_VERSION, &boundData.ver,
750 BSG_TYPE_BYTE, &boundData.payload);
752 memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));
753 flatBoundDataSize += buffer_len(inData);
755 BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is what will come out.
756 UINT32 out_tmp_size;
758 // Encrypt flatBoundData
759 Crypto_RSAEnc( cryptoInfo,
760 flatBoundDataSize,
761 flatBoundData,
762 &out_tmp_size,
763 out_tmp);
765 if (out_tmp_size > RSA_KEY_SIZE/8) {
766 // The result of RSAEnc should be a fixed size based on key size.
767 vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");
768 }
770 buffer_init(outData, 0, NULL);
771 buffer_append_raw(outData, out_tmp_size, out_tmp);
773 vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);
774 for(i = 0 ; i < out_tmp_size ; i++) {
775 vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);
776 }
777 vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
779 // Free flatBoundData
780 free(flatBoundData);
782 return TPM_SUCCESS;
783 }
785 TPM_RESULT VTSP_Seal(const TCS_CONTEXT_HANDLE hContext,
786 const TPM_KEY_HANDLE keyHandle,
787 const TPM_AUTHDATA *sealDataAuth,
788 const TPM_PCR_COMPOSITE *pcrComp,
789 const buffer_t *inData,
790 TPM_STORED_DATA *sealedData,
791 const TPM_SECRET *osapSharedSecret,
792 TCS_AUTH *auth) {
794 TPM_RESULT status = TPM_SUCCESS;
795 TPM_COMMAND_CODE command = TPM_ORD_Seal;
797 BYTE *paramText; // Digest to make Auth.
798 UINT32 paramTextSize;
800 // Generate PCR_Info Struct from Comp
801 TPM_PCR_INFO pcrInfo;
802 UINT32 pcrInfoSize, flatpcrSize;
803 BYTE flatpcr[3 + // PCR_Select = 3 1 byte banks
804 sizeof(UINT16) + // 2 byte UINT16
805 sizeof(UINT32) + // PCR_Comp = 4 byte UINT32
806 24 * sizeof(TPM_PCRVALUE) ]; // up to 24 PCRs
808 if (pcrComp != NULL) {
809 //printf("\n\tBinding to PCRs: ");
810 //for(int i = 0 ; i < pcrComp->select.sizeOfSelect ; i++)
811 //printf("%2.2x", pcrComp->select.pcrSelect[i]);
813 memcpy(&pcrInfo.pcrSelection, &pcrComp->select, sizeof(TPM_PCR_SELECTION));
815 flatpcrSize = BSG_Pack(BSG_TPM_PCR_COMPOSITE, (BYTE *) pcrComp, flatpcr);
816 Crypto_SHA1Full((BYTE *) flatpcr, flatpcrSize, (BYTE *) &(pcrInfo.digestAtRelease));
817 memset(&(pcrInfo.digestAtCreation), 0, sizeof(TPM_DIGEST));
818 pcrInfoSize = BSG_Pack(BSG_TPM_PCR_INFO, (BYTE *) &pcrInfo, flatpcr);
819 } else {
820 //printf("\n\tBinding to no PCRS.");
821 pcrInfoSize = 0;
822 }
824 // Calculate encUsageAuth
825 BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
826 UINT32 XORbufferSize = sizeof(XORbuffer);
827 TPM_DIGEST XORKey;
828 TPM_ENCAUTH encAuth;
830 BSG_PackList( XORbuffer, 2,
831 BSG_TPM_SECRET, osapSharedSecret,
832 BSG_TPM_NONCE, &auth->NonceEven );
834 Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey);
836 int i;
837 for (i=0; i < TPM_DIGEST_SIZE; i++)
838 ((BYTE *) &encAuth)[i] = ((BYTE *) &XORKey)[i] ^ ((BYTE *) sealDataAuth)[i];
840 // Generate Extra TCS Parameters
841 UINT32 inDataSize = buffer_len(inData);
842 struct pack_buf_t inData_pack = {inDataSize, inData->bytes};
843 struct pack_buf_t pcrInfo_pack = {pcrInfoSize, flatpcr};
845 UINT32 sealedDataSize;
846 BYTE *flatSealedData=NULL;
848 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
850 paramTextSize = BSG_PackList(paramText, 4,
851 BSG_TPM_COMMAND_CODE, &command,
852 BSG_TPM_ENCAUTH, &encAuth,
853 BSG_TPM_SIZE32_DATA, &pcrInfo_pack,
854 BSG_TPM_SIZE32_DATA, &inData_pack);
856 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
857 osapSharedSecret, auth) );
859 // Call TCS
860 TPMTRYRETURN( TCSP_Seal( hContext,
861 keyHandle,
862 encAuth,
863 pcrInfoSize,
864 flatpcr,
865 inDataSize,
866 inData->bytes,
867 auth,
868 &sealedDataSize,
869 &flatSealedData) );
871 // Unpack/return key structure
872 BSG_Unpack( BSG_TPM_STORED_DATA, flatSealedData, sealedData );
874 paramTextSize = BSG_PackList(paramText, 3,
875 BSG_TPM_RESULT, &status,
876 BSG_TPM_COMMAND_CODE, &command,
877 BSG_TPM_STORED_DATA, sealedData);
879 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
880 osapSharedSecret, auth,
881 0) );
884 goto egress;
886 abort_egress:
887 egress:
889 if (flatSealedData)
890 TCS_FreeMemory( hContext, flatSealedData);
892 free(paramText);
893 return status;
894 }
897 TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE hContext,
898 const TPM_KEY_HANDLE keyHandle,
899 const TPM_STORED_DATA *sealedData,
900 const TPM_AUTHDATA *key_usage_auth,
901 const TPM_AUTHDATA *data_usage_auth,
902 buffer_t *outData,
903 TCS_AUTH *auth,
904 TCS_AUTH *dataAuth) {
906 TPM_RESULT status = TPM_SUCCESS;
907 TPM_COMMAND_CODE command = TPM_ORD_Unseal;
909 BYTE *paramText; // Digest to make Auth.
910 UINT32 paramTextSize;
912 // Generate Extra TCS Parameters
913 UINT32 sealDataSize, clearDataSize;
914 BYTE *flatSealedData= (BYTE *) malloc(sizeof(TPM_VERSION) +
915 2 * sizeof(UINT32) +
916 sealedData->sealInfoSize +
917 sealedData->encDataSize),
918 *clearData=NULL;
920 sealDataSize = BSG_Pack(BSG_TPM_STORED_DATA, sealedData, flatSealedData );
922 paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
924 paramTextSize = BSG_PackList(paramText, 2,
925 BSG_TPM_COMMAND_CODE, &command,
926 BSG_TPM_STORED_DATA, sealedData);
928 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
929 key_usage_auth, auth) );
931 TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
932 data_usage_auth, dataAuth) );
933 // Call TCS
934 TPMTRYRETURN( TCSP_Unseal( hContext,
935 keyHandle,
936 sealDataSize,
937 flatSealedData,
938 auth,
939 dataAuth,
940 &clearDataSize,
941 &clearData) );
943 // Verify Auth
944 struct pack_buf_t clearData_pack = {clearDataSize, clearData};
946 paramTextSize = BSG_PackList(paramText, 3,
947 BSG_TPM_RESULT, &status,
948 BSG_TPM_COMMAND_CODE, &command,
949 BSG_TPM_SIZE32_DATA, &clearData_pack);
951 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
952 key_usage_auth, auth,
953 hContext) );
955 TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
956 data_usage_auth, dataAuth,
957 hContext) );
959 // Unpack/return key structure
960 TPMTRYRETURN( buffer_init(outData, clearDataSize, clearData) );
962 goto egress;
964 abort_egress:
965 egress:
967 if (flatSealedData)
968 TCS_FreeMemory( hContext, clearData);
970 free(paramText);
971 return status;
972 }
975 // Function Reaches into unsupported TCS command, beware.
976 TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
977 const buffer_t *inbuf,
978 buffer_t *outbuf ) {
980 vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");
981 TPM_RESULT status = TPM_SUCCESS;
983 // Generate Extra TCS Parameters
984 BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
985 UINT32 resultTextSize = TCPA_MAX_BUFFER_LENGTH;
987 // Call TCS
988 TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes,
989 &resultTextSize, resultText) );
991 // Unpack/return key structure
992 TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) );
993 goto egress;
995 abort_egress:
997 egress:
998 TCS_FreeMemory(hContext, resultText);
999 free(resultText);
1000 return status;