From mboxrd@z Thu Jan 1 00:00:00 1970 From: Matthew Fioravante Subject: [PATCH 1/7] vtpm Mini-Os domain: vtpm_managerd Date: Wed, 25 Aug 2010 11:05:23 -0400 Message-ID: <4C753133.70100@jhuapl.edu> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0493889955==" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: "xen-devel@lists.xensource.com" List-Id: xen-devel@lists.xenproject.org This is a cryptographically signed message in MIME format. --===============0493889955== Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="------------ms070301090804070908050306" This is a cryptographically signed message in MIME format. --------------ms070301090804070908050306 Content-Type: multipart/mixed; boundary="------------080201090103050803020605" This is a multi-part message in MIME format. --------------080201090103050803020605 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Signed-off-by: Matthew Fioravante The following is a major patch to the vtpm_manager. I apologize in=20 advance for submitting such a large patch. Let me know if you'd like me=20 to break it up. This patch contains the following: -A new routine to flush all handles from the tpm everytime vtpm_managerd = is started. Previously if the manager would crash it would leave stale=20 keys and auth handles in the tpm. After restarting the manager several=20 times and letting it crash, the tpm would run out of memory and the=20 manager would fail to start with a TPM_NO_SPACE error. -Several memory errors fixed such as uninitialized reads and memory leaks= =2E -Fixed the signal handler to work with blocking IO and threads=20 correctly. Previously the manager would not shutdown correctly when you=20 tried to Ctrl+C close it on 64 bit. -Removal of VTPM_MULTI_VM #defines. These were supposed to be a partial=20 implementation for a way to run vtpms in multiple domains but it was=20 never finished. It doesn't appear there has been any development on this = for several years. Since vtpm-stubdom performs this functionality I=20 removed these #defines and #ifdefs to make the code a little cleaner. -New vTPM ordinals: VTPM_SAVE_KEY and VTPM_LOAD_KEY. The vtpm domains=20 encrypt their persistent state themselves, they only request the manager = to store the key. -#define VTPM_STUBDOM will build the manager in stubdom mode. The=20 manager can only work in either vtpm-stubdom or vtpmd mode. You cannot=20 combine them. Clearing out the manager state will be required. # rm /var/vtpm/VTPM /var/vtpm/vtpm_dm* --------------080201090103050803020605 Content-Type: text/x-patch; name="1-manager.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="1-manager.patch" diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/README --- a/tools/vtpm_manager/README Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/README Tue Jul 20 15:26:31 2010 -0400 @@ -43,9 +43,6 @@ LOGGING_MODULES -> How extensive logging happens see util/log.h for more info =20 -VTPM_MULTI_VM -> Defined: VTPMs run in their own VMs - Not Defined (default): VTPMs are process= es - # Debugging flags that may disappear without notice in the future =20 DUMMY_BACKEND -> vtpm_manager listens on /tmp/in.fifo and= =20 @@ -59,6 +56,10 @@ lost. However this has no protection fro= m malicious app issuing a TPM_OwnerClear to wipe the TPM= =20 =20 +VTPM_STUBDOM -> vtpm_manager runs in vtpm_stubdom mode with + vtpm instances running in mini-os domains + (see: stubdom/vtpm/README for details) + Requirements =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - xen-unstable=20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/Rules.mk --- a/tools/vtpm_manager/Rules.mk Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/Rules.mk Tue Jul 20 15:26:31 2010 -0400 @@ -40,12 +40,12 @@ #CFLAGS +=3D -DLOGGING_MODULES=3D0x0 #CFLAGS +=3D -DLOGGING_MODULES=3D0xff =20 -# Use frontend/backend pairs between manager & DMs? -#CFLAGS +=3D -DVTPM_MULTI_VM - # vtpm_manager listens on fifo's rather than backend #CFLAGS +=3D -DDUMMY_BACKEND =20 +# Build for use with vtpm-stubdom +#CFLAGS +=3D -DVTPM_STUBDOM + # TCS talks to fifo's rather than /dev/tpm. TPM Emulator assumed on fifo= s #CFLAGS +=3D -DDUMMY_TPM =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/crypto/crypto.h --- a/tools/vtpm_manager/crypto/crypto.h Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/crypto/crypto.h Tue Jul 20 15:26:31 2010 -0400 @@ -127,6 +127,8 @@ /*[IN]*/ BYTE *modulus,=20 CRYPTO_INFO* cryptoInfo); =20 +void Crypto_RSACryptoInfoFree(CRYPTO_INFO* cryptoInfo); + // // symmetric pack and unpack operations // diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/crypto/rsa.c --- a/tools/vtpm_manager/crypto/rsa.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/crypto/rsa.c Tue Jul 20 15:26:31 2010 -0400 @@ -149,6 +149,10 @@ =20 } =20 +void Crypto_RSACryptoInfoFree(CRYPTO_INFO* cryptoInfo) { + RSA_free(cryptoInfo->keyInfo); +} + int Crypto_RSAEnc( CRYPTO_INFO *key, UINT32 inDataSize, BYTE *inData, @@ -161,6 +165,7 @@ =20 if (paddedData =3D=3D NULL)=20 return -1; + memset(paddedData, 0, sizeof(BYTE) * paddedDataSize); =20 *outDataSize =3D 0; =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/crypto/sym_crypto= =2Ec --- a/tools/vtpm_manager/crypto/sym_crypto.c Thu Jul 01 14:17:13 2010 -04= 00 +++ b/tools/vtpm_manager/crypto/sym_crypto.c Tue Jul 20 15:26:31 2010 -04= 00 @@ -41,6 +41,7 @@ #include =20 #include "tcg.h" +#include "log.h" #include "sym_crypto.h" =20 typedef enum crypt_op_type_t { @@ -119,11 +120,11 @@ =20 buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV); =20 - buffer_init (o_cipher, - clear->size + - EVP_CIPHER_iv_length(key->cipher) + - EVP_CIPHER_block_size (key->cipher), - 0); + TPMTRYRETURN( buffer_init (o_cipher, + clear->size + + EVP_CIPHER_iv_length(key->cipher) + + EVP_CIPHER_block_size (key->cipher), + 0) ); =20 // copy the IV into the front buffer_copy (o_cipher, &iv); @@ -139,6 +140,7 @@ goto egress; =20 abort_egress: + buffer_free(o_cipher); =20 egress: =20 @@ -170,7 +172,7 @@ =20 // and decrypt TPMTRYRETURN ( ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear, CR= YPT_DECRYPT) ); - =20 + goto egress; =20 abort_egress: diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/dmictl.c --- a/tools/vtpm_manager/manager/dmictl.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/manager/dmictl.c Tue Jul 20 15:26:31 2010 -0400 @@ -116,6 +116,13 @@ =20 return (VTPM_Close_DMI_Extra(dmi_res) ); } + +void free_dmi(VTPM_DMI_RESOURCE *dmi_res) { + if(dmi_res !=3D NULL) { + free(dmi_res->NVMLocation); + } + free(dmi_res); +} =09 TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) { =20 @@ -254,7 +261,7 @@ =20 // Close DMI first TPMTRYRETURN(close_dmi( dmi_res )); - free ( dmi_res ); + free_dmi(dmi_res); =09 status=3DTPM_SUCCESS; =20 goto egress; diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/securesto= rage.c --- a/tools/vtpm_manager/manager/securestorage.c Thu Jul 01 14:17:13 2010= -0400 +++ b/tools/vtpm_manager/manager/securestorage.c Tue Jul 20 15:26:31 2010= -0400 @@ -42,7 +42,6 @@ #include #include #include - #include "tcg.h" #include "vtpm_manager.h" #include "vtpmpriv.h" @@ -86,8 +85,9 @@ =20 data_cipher32.size =3D buffer_len(&data_cipher); data_cipher32.data =3D data_cipher.bytes; - =20 + TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) + symkey_cip= her32.size + data_cipher32.size, NULL)); + memset(sealed_data->bytes, 0, sealed_data->size); =20 BSG_PackList(sealed_data->bytes, 2, BSG_TPM_SIZE32_DATA, &symkey_cipher32, @@ -114,6 +114,32 @@ return status; } =20 +TPM_RESULT symkey_encrypt(const buffer_t *inbuf, + CRYPTO_INFO *asymkey, + buffer_t *sealed_key) { + buffer_t symkey_cipher =3D NULL_BUF; + struct pack_constbuf_t symkey_cipher32; + TPM_RESULT status =3D TPM_SUCCESS; + =20 + // Encrypt symmetric key + TPMTRYRETURN( VTSP_Bind( asymkey,=20 + inbuf, + &symkey_cipher)); + + symkey_cipher32.size =3D buffer_len(&symkey_cipher); + symkey_cipher32.data =3D symkey_cipher.bytes; + + TPMTRYRETURN( buffer_init(sealed_key, sizeof(UINT32) + symkey_cipher32= =2Esize, NULL)); + BSG_PackList(sealed_key->bytes, 1, + BSG_TPM_SIZE32_DATA, &symkey_cipher32); + goto egress; +abort_egress: +egress: + buffer_free( &symkey_cipher); + return status; +} + =20 + TPM_RESULT envelope_decrypt(const buffer_t *cipher, TCS_CONTEXT_HANDLE TCSContext, TPM_HANDLE keyHandle, @@ -125,7 +151,7 @@ buffer_t data_cipher =3D NULL_BUF,=20 symkey_clear =3D NULL_BUF,=20 symkey_cipher =3D NULL_BUF; - struct pack_buf_t symkey_cipher32, data_cipher32; + struct pack_buf_t symkey_cipher32 =3D NULL_PACK_BUF, data_cipher32 =3D= NULL_PACK_BUF; int i; =20 memset(&symkey, 0, sizeof(symkey_t)); @@ -175,26 +201,68 @@ buffer_free ( &data_cipher); buffer_free ( &symkey_clear); buffer_free ( &symkey_cipher); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &data_cipher32); Crypto_symcrypto_freekey (&symkey); + =20 return status; } =20 +TPM_RESULT symkey_decrypt(const buffer_t *cipher, + TCS_CONTEXT_HANDLE TCSContext, + TPM_HANDLE keyHandle, + const TPM_AUTHDATA *key_usage_auth, + buffer_t *symkey_clear) { + + TPM_RESULT status =3D TPM_SUCCESS; + symkey_t symkey; + buffer_t symkey_cipher =3D NULL_BUF; + struct pack_buf_t symkey_cipher32 =3D NULL_PACK_BUF; + int i; + + memset(&symkey, 0, sizeof(symkey_t)); + + BSG_UnpackList(cipher->bytes, 1, + BSG_TPM_SIZE32_DATA, &symkey_cipher32); + =20 + TPMTRYRETURN( buffer_init_alias_convert (&symkey_cipher,=20 + symkey_cipher32.size,=20 + symkey_cipher32.data) ); + =20 + // Decrypt Symmetric Key + TPMTRYRETURN( VTSP_Unbind( TCSContext, + keyHandle, + &symkey_cipher, + key_usage_auth, + symkey_clear, + &(vtpm_globals->keyAuth) ) ); + =20 + goto egress; + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to decrypt symmetric key status=3D= %d\n.", status); + =20 + egress: + BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32); + return status; +} + TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI,=20 const buffer_t *inbuf,=20 buffer_t *outbuf) { =20 TPM_RESULT status =3D TPM_SUCCESS; - int fh; + int fh =3D -1; long bytes_written; buffer_t sealed_NVM =3D NULL_BUF; - =20 - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_le= n(inbuf)); + const buffer_t* nvmbuf =3D inbuf; =20 - TPMTRYRETURN( envelope_encrypt(inbuf, + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_le= n(nvmbuf)); + + TPMTRYRETURN( envelope_encrypt(nvmbuf, &vtpm_globals->storageKey, &sealed_NVM) ); - =20 + // Write sealed blob off disk from NVMLocation // TODO: How to properly return from these. Do we care if we return fa= ilure // after writing the file? We can't get the old one back. @@ -205,7 +273,6 @@ status =3D TPM_IOERROR; goto abort_egress; } - close(fh); =20 Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &= myDMI->NVM_measurement); =20 =20 @@ -215,6 +282,7 @@ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n."); =20 egress: + close(fh); buffer_free(&sealed_NVM); return status; } @@ -229,7 +297,8 @@ =20 buffer_t sealed_NVM =3D NULL_BUF; long fh_size; - int fh, stat_ret, i; + int fh =3D -1; + int stat_ret, i; struct stat file_stat; TPM_DIGEST sealedNVMHash; =20 @@ -241,6 +310,7 @@ =20 //Read sealed blob off disk from NVMLocation fh =3D open(myDMI->NVMLocation, O_RDONLY); + printf("Filename: %s\n", myDMI->NVMLocation); stat_ret =3D fstat(fh, &file_stat); if (stat_ret =3D=3D 0)=20 fh_size =3D file_stat.st_size; @@ -254,7 +324,6 @@ status =3D TPM_IOERROR; goto abort_egress; } - close(fh); =20 vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%d],\n", buffer_len(&seal= ed_NVM)); =20 @@ -289,10 +358,173 @@ =20 egress: buffer_free( &sealed_NVM ); + close(fh); =20 return status; } =20 +TPM_RESULT VTPM_Handle_Get_NVM_Size( VTPM_DMI_RESOURCE *myDMI,=20 + const buffer_t *inbuf,=20 + buffer_t *outbuf) { + TPM_RESULT status =3D TPM_SUCCESS; + long fh_size; + int fh =3D -1; + int stat_ret; + struct stat file_stat; + UINT32 fh_size_pack; + + buffer_t sealedNVM; + buffer_init(&sealedNVM, 0, NULL); + struct pack_buf_t symkey_cipher32 =3D NULL_PACK_BUF, data_cipher32 =3D= NULL_PACK_BUF; + + fh =3D open(myDMI->NVMLocation, O_RDONLY); + printf("Filename: %s\n", myDMI->NVMLocation); + stat_ret =3D fstat(fh, &file_stat); + if (stat_ret =3D=3D 0)=20 + fh_size =3D file_stat.st_size; + else { + status =3D TPM_IOERROR; + goto abort_egress; + } + TPMTRYRETURN(buffer_init(&sealedNVM, fh_size, NULL)); + if (read(fh, sealedNVM.bytes, buffer_len(&sealedNVM)) !=3D fh_size) { + status =3D TPM_IOERROR; + goto abort_egress; + } + + BSG_UnpackList(sealedNVM.bytes, 2, + BSG_TPM_SIZE32_DATA, &symkey_cipher32, + BSG_TPM_SIZE32_DATA, &data_cipher32); + + TPMTRYRETURN(buffer_init(outbuf, sizeof(UINT32), NULL)); + BSG_PackList(outbuf->bytes, 1, + BSG_TYPE_UINT32, (BYTE*)&(data_cipher32.size)); + + + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to retreive size of NVM\n"); + + egress: + BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &data_cipher32); + buffer_free(&sealedNVM); + close(fh); + return status; +} + +TPM_RESULT VTPM_Handle_Load_Key(VTPM_DMI_RESOURCE *myDMI,=20 + const buffer_t *inbuf,=20 + buffer_t *outbuf) { + =20 + TPM_RESULT status =3D TPM_SUCCESS; + + buffer_t sealed_NVM =3D NULL_BUF; + long fh_size; + int fh =3D -1; + int stat_ret, i; + struct stat file_stat; + TPM_DIGEST sealedNVMHash; + =20 + if (myDMI->NVMLocation =3D=3D NULL) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file nam= e NULL.\n"); + status =3D TPM_AUTHFAIL; + goto abort_egress; + } + =20 + //Read sealed blob off disk from NVMLocation + fh =3D open(myDMI->NVMLocation, O_RDONLY); + printf("Filename: %s\n", myDMI->NVMLocation); + stat_ret =3D fstat(fh, &file_stat); + if (stat_ret =3D=3D 0)=20 + fh_size =3D file_stat.st_size; + else { + status =3D TPM_IOERROR; + goto abort_egress; + } + =20 + TPMTRYRETURN( buffer_init( &sealed_NVM, fh_size, NULL) ); + if (read(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM)) !=3D fh_size) = { + status =3D TPM_IOERROR; + goto abort_egress; + } + =20 + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Loading %d byte encryption key,\n", b= uffer_len(&sealed_NVM)); + =20 + Crypto_SHA1Full(sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &s= ealedNVMHash); =20 + =20 + // Verify measurement of sealed blob. + if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)= ) ) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadKey NVM measurement check fail= ed.\n"); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: "); + for (i=3D0; i< sizeof(TPM_DIGEST); i++) + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&myDMI->NVM_mea= surement)[i]); + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: "); + for (i=3D0; i< sizeof(TPM_DIGEST); i++) + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)= [i]); + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); + =20 + status =3D TPM_AUTHFAIL; + goto abort_egress; + } + =20 + //Decrypt the key into the output buffer + TPMTRYRETURN( symkey_decrypt(&sealed_NVM, + myDMI->TCSContext, + vtpm_globals->storageKeyHandle, + (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth, + outbuf) ); =20 + goto egress; + =20 + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to load Key\n."); + =20 + egress: + buffer_free( &sealed_NVM ); + close(fh); + =20 + return status; +} + +TPM_RESULT VTPM_Handle_Save_Key(VTPM_DMI_RESOURCE *myDMI, + const buffer_t *inbuf, + buffer_t *outbuf) { + TPM_RESULT status =3D TPM_SUCCESS; + int fh =3D -1; + long bytes_written; + buffer_t sealed_key =3D NULL_BUF; + =20 + TPMTRYRETURN( symkey_encrypt(inbuf, + &vtpm_globals->storageKey, + &sealed_key) ); + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d byte Encryption Key.\n", bu= ffer_len(inbuf)); + + // Write sealed blob off disk from NVMLocation + // TODO: How to properly return from these. Do we care if we return fa= ilure + // after writing the file? We can't get the old one back. + // TODO: Backup old file and try and recover that way. + fh =3D open(myDMI->NVMLocation, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD = | S_IWRITE); + if ( (bytes_written =3D write(fh, sealed_key.bytes, buffer_len(&sealed= _key) ) !=3D (long) buffer_len(&sealed_key))) { + vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed = to finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_key= )); + status =3D TPM_IOERROR; + goto abort_egress; + } + =20 + Crypto_SHA1Full (sealed_key.bytes, buffer_len(&sealed_key), (BYTE *) &= myDMI->NVM_measurement); =20 + =20 + goto egress; + =20 + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to save Key\n."); + =20 + egress: + close(fh); + buffer_free(&sealed_key); + return status; +} + =20 TPM_RESULT VTPM_SaveManagerData(void) { TPM_RESULT status=3DTPM_SUCCESS; @@ -364,6 +596,7 @@ BSG_TPM_DIGEST, &dmi_res->DMI_me= asurement); =20 } while (hashtable_iterator_advance(dmi_itr)); + free(dmi_itr); } =20 fh =3D open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); @@ -389,6 +622,7 @@ =20 free(flat_boot_key); free(flat_enc); + buffer_free(&clear_flat_global); buffer_free(&enc_flat_global); free(flat_dmis); close(fh); @@ -403,8 +637,9 @@ int fh, stat_ret, dmis=3D0; long fh_size =3D 0, step_size; BYTE *flat_table=3DNULL; - buffer_t unsealed_data, enc_table_abuf; - struct pack_buf_t storage_key_pack, boot_key_pack; + buffer_t unsealed_data =3D NULL_BUF; + buffer_t enc_table_abuf; + struct pack_buf_t storage_key_pack =3D NULL_PACK_BUF, boot_key_pack =3D= NULL_PACK_BUF; UINT32 *dmi_id_key, enc_size; BYTE vtpm_manager_gen; =20 @@ -438,9 +673,9 @@ BSG_TPM_SIZE32_DATA, &boot_key_pack, BSG_TYPE_UINT32, &enc_size); =20 - TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) ); TPMTRYRETURN(buffer_init_alias_convert(&enc_table_abuf, enc_size, flat= _table + step_size) ); - TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap, boot_key_pa= ck.size, boot_key_pack.data) ); + TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, boot_key_pack.siz= e, boot_key_pack.data) ); + =20 //Load Boot Key TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle, @@ -471,8 +706,8 @@ BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_aut= h, BSG_TPM_SIZE32_DATA, &storage_key_pack); =20 - TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) ); - TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_= key_pack.size, storage_key_pack.data) ); + TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, storage_key_pa= ck.size, storage_key_pack.data) ); + =20 // Per DMI values to be saved while ( step_size < fh_size ){ @@ -501,7 +736,10 @@ abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error =3D= %s\n", tpm_get_error_name(status)); egress: + BSG_Destroy(BSG_TPM_SIZE32_DATA, &boot_key_pack); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &storage_key_pack); =20 + buffer_free(&unsealed_data); free(flat_table); close(fh); =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpm_ipc.= c --- a/tools/vtpm_manager/manager/vtpm_ipc.c Thu Jul 01 14:17:13 2010 -040= 0 +++ b/tools/vtpm_manager/manager/vtpm_ipc.c Tue Jul 20 15:26:31 2010 -040= 0 @@ -41,15 +41,35 @@ #include "vtpmpriv.h" #include "log.h" =20 -int vtpm_ipc_init(vtpm_ipc_handle_t *ipc_h, char* name, int flags, BOOL = create) { +volatile sig_atomic_t IPC_QUIT_FLAG =3D 0; + +const static struct timeval TIMEOUT =3D { + .tv_sec =3D 1, + .tv_usec =3D 0 +}; + +int vtpm_ipc_init(vtpm_ipc_handle_t *ipc_h, char* name, int flags, BOOL = create, BOOL preopen) { + int rc; + ipc_h->name =3D name; ipc_h->flags =3D flags; ipc_h->fh =3D VTPM_IPC_CLOSED; =20 - if (create) - return(vtpm_ipc_create(ipc_h)); - else - return 0; + if (create) { + if((rc =3D vtpm_ipc_create(ipc_h) !=3D 0)) { + return rc; + } + } + + if(preopen) { + ipc_h->fh =3D open(ipc_h->name, ipc_h->flags); + if ( ipc_h->fh =3D=3D VTPM_IPC_CLOSED ) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open %s\n", ipc_h-= >name); + return -1; + } + } + return 0; + } =20 // Create the file that needs opening. Used only for FIFOs @@ -68,8 +88,6 @@ } } =20 - ipc_h->fh =3D VTPM_IPC_CLOSED; - return 0; } =20 @@ -78,6 +96,8 @@ int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_h= , BYTE *bytes, UINT32 size){ vtpm_ipc_handle_t *my_ipc_h; int result; + fd_set fds; + struct timeval timeout; =20 if (ipc_h) { my_ipc_h =3D ipc_h; @@ -94,9 +114,19 @@ return -1; } =20 + FD_ZERO(&fds); + while(!FD_ISSET( my_ipc_h->fh, &fds )) { + timeout =3D TIMEOUT; + if (IPC_QUIT_FLAG) { + return -1; + } + FD_SET(my_ipc_h->fh, &fds); + select(my_ipc_h->fh + 1, &fds, NULL, NULL, &timeout); + } + result =3D read(my_ipc_h->fh, bytes, size); if (result < 0) { - my_ipc_h->fh =3D VTPM_IPC_CLOSED; + my_ipc_h->fh =3D VTPM_IPC_CLOSED; } =20 return (result); @@ -106,6 +136,8 @@ int vtpm_ipc_write(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_= h, BYTE *bytes, UINT32 size) { vtpm_ipc_handle_t *my_ipc_h; int result; + fd_set fds; + struct timeval timeout; =20 if (ipc_h) { my_ipc_h =3D ipc_h; @@ -122,6 +154,16 @@ return -1; } =20 + FD_ZERO(&fds); + while(!FD_ISSET( my_ipc_h->fh, &fds )) { + timeout =3D TIMEOUT; + if (IPC_QUIT_FLAG) { + return -1; + } + FD_SET(my_ipc_h->fh, &fds); + select(my_ipc_h->fh + 1, NULL, &fds, NULL, &timeout); + } + result =3D write(my_ipc_h->fh, bytes, size); if (result < 0) { my_ipc_h->fh =3D VTPM_IPC_CLOSED; diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpm_ipc.= h --- a/tools/vtpm_manager/manager/vtpm_ipc.h Thu Jul 01 14:17:13 2010 -040= 0 +++ b/tools/vtpm_manager/manager/vtpm_ipc.h Tue Jul 20 15:26:31 2010 -040= 0 @@ -39,10 +39,14 @@ #ifndef __VTPM_IO_H__ #define __VTPM_IO_H__ =20 +#include + #include "tcg.h" =20 #define VTPM_IPC_CLOSED -1 =20 +extern volatile sig_atomic_t IPC_QUIT_FLAG; + // Represents an (somewhat) abstracted io handle. typedef struct vtpm_ipc_handle_t { int fh; // IO handle. @@ -53,7 +57,7 @@ } vtpm_ipc_handle_t; =20 =20 -int vtpm_ipc_init(vtpm_ipc_handle_t *ioh, char* name, int flags, BOOL cr= eate); +int vtpm_ipc_init(vtpm_ipc_handle_t *ioh, char* name, int flags, BOOL cr= eate, BOOL preopen); =20 // Create the file that needs opening. Used only for FIFOs // FYI: This may cause problems in other file IO schemes. We'll see. diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpm_mana= ger.c --- a/tools/vtpm_manager/manager/vtpm_manager.c Thu Jul 01 14:17:13 2010 = -0400 +++ b/tools/vtpm_manager/manager/vtpm_manager.c Tue Jul 20 15:26:31 2010 = -0400 @@ -44,6 +44,7 @@ #include "vtpm_manager.h" #include "vtpmpriv.h" #include "vtsp.h" +#include "tpmddl.h" #include "bsg.h" #include "hashtable.h" #include "hashtable_itr.h" @@ -54,8 +55,8 @@ VTPM_GLOBALS *vtpm_globals=3DNULL; =20 // --------------------------- Well Known Auths ------------------------= -- -const TPM_AUTHDATA SRK_AUTH =3D {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf= f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x= ff, 0xff, 0xff, 0xff}; +const TPM_AUTHDATA SRK_AUTH =3D {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0= 0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00, 0x00, 0x00, 0x00}; =20 #ifdef WELL_KNOWN_OWNER_AUTH static BYTE FIXED_OWNER_AUTH[20] =3D {0xff, 0xff, 0xff, 0xff, 0xff, 0xf= f, 0xff, 0xff, 0xff, 0xff, @@ -74,6 +75,67 @@ } =20 // --------------------------- Functions ------------------------------ +TPM_RESULT VTPM_FlushResources() { + TPM_RESULT status =3D TPM_SUCCESS; + + TDDL_BYTE buf[TCPA_MAX_BUFFER_LENGTH]; + TDDL_UINT32 bufsiz; + + UINT16 packedsz; + int size; + UINT32 handle; + BYTE* ptr; + + int i, j; + +#define RLISTSZ 6 + TPM_RESOURCE_TYPE reslist[RLISTSZ] =3D { TPM_RT_KEY, TPM_RT_AUTH, TPM_= RT_TRANS, TPM_RT_COUNTER, TPM_RT_DAA_TPM, TPM_RT_CONTEXT }; + + //Iterate through each resource type and flush all handles + for(i =3D 0; i < RLISTSZ; ++i) { + TPM_RESOURCE_TYPE res =3D reslist[i]; + // Get list of current key handles + if((status =3D TDDL_GetCapability( TPM_CAP_HANDLE, res, buf, &bufsi= z)) !=3D TPM_SUCCESS) { + //This can happen if the resource type is not supported + //If this happens just silently skip the resource type + if(status =3D=3D TPM_BAD_MODE) { + status =3D TPM_SUCCESS; + continue; + //Otherwise we just fail + } else { + TPMTRYRETURN(status); + } + } + +#if 0 + //DEBUG PRINTOUTS + printf("TPM_GetCapability(TPM_CAP_HANDLE, %lu)\n", (unsigned long) = res); + for(j =3D 0; j < bufsiz; ++j) { + printf("%02X ", buf[j]); + } + printf("\n"); +#endif + + ptr =3D buf; + ptr +=3D BSG_Unpack(BSG_TYPE_UINT16, ptr, &(packedsz)); + size =3D packedsz; + + //Flush each handle + if(size) { + vtpmloginfo(VTPM_LOG_VTPM, "Flushing %u handle(s) of type %lu\n", size,= (unsigned long) res); + for(j =3D 0; j < size; ++j) { + ptr +=3D BSG_Unpack(BSG_TPM_HANDLE, ptr, &(handle)); + TPMTRYRETURN(TDDL_FlushSpecific(handle, res)); + } + } + + } + + goto egress; +abort_egress: +egress: + return status; +} =20 TPM_RESULT VTPM_Create_Manager(){ =20 @@ -104,6 +166,7 @@ TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle,= (const TPM_AUTHDATA*)&vtpm_global= s->owner_usage_auth, =20 &vtpm_globals->keyAuth)); =20 + Crypto_RSACryptoInfoFree(&ek_cryptoInfo); } else { vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owne= r. Creating Keys off existing SRK.\n"); } @@ -203,6 +266,11 @@ vtpm_globals->manager_tcs_handle =3D 0; =20 TPMTRYRETURN(TCS_create()); + + // Blow away all stale handles left in the tpm + if(VTPM_FlushResources() !=3D TPM_SUCCESS) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing= anyway..\n"); + } =20 // Create TCS Context for service TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) ); @@ -228,7 +296,7 @@ TPMTRYRETURN( VTPM_Create_Manager() ); =20 TPMTRYRETURN( VTPM_SaveManagerData() ); } else if (serviceStatus !=3D TPM_SUCCESS) { - vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing manager file");= + vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing manager file\n"= ); exit(1); } =20 @@ -267,7 +335,7 @@ close_dmi( dmi_res ); // Not really interested in return code =20 } while (hashtable_iterator_advance(dmi_itr)); - free (dmi_itr); + free (dmi_itr); } =20 if ( VTPM_SaveManagerData() !=3D TPM_SUCCESS )=20 @@ -276,7 +344,21 @@ TCS_CloseContext(vtpm_globals->manager_tcs_handle); TCS_destroy(); =20 - hashtable_destroy(vtpm_globals->dmi_map, 1); + if (hashtable_count(vtpm_globals->dmi_map) > 0) { + dmi_itr =3D hashtable_iterator(vtpm_globals->dmi_map); + do { + dmi_res =3D (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr= ); + free_dmi(dmi_res); + } while (hashtable_iterator_advance(dmi_itr)); + free (dmi_itr); + } + hashtable_destroy(vtpm_globals->dmi_map, 0); + + /* Cleanup resources */ + Crypto_RSACryptoInfoFree(&vtpm_globals->bootKey); + Crypto_RSACryptoInfoFree(&vtpm_globals->storageKey); + buffer_free(&vtpm_globals->bootKeyWrap); + buffer_free(&vtpm_globals->storageKeyWrap); free(vtpm_globals); =20 Crypto_Exit(); diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpm_mana= ger.h --- a/tools/vtpm_manager/manager/vtpm_manager.h Thu Jul 01 14:17:13 2010 = -0400 +++ b/tools/vtpm_manager/manager/vtpm_manager.h Tue Jul 20 15:26:31 2010 = -0400 @@ -61,6 +61,9 @@ #define VTPM_ORD_TPMCOMMAND (VTPM_ORD_BASE + 3) // DMI issues HW TPM C= ommand #define VTPM_ORD_GET_MIG_KEY (VTPM_ORD_BASE + 4) // Get manager's migra= tion key #define VTPM_ORD_LOAD_MIG_KEY (VTPM_ORD_BASE + 5) // load dest migration= key=20 +#define VTPM_ORD_GETNVMSIZE (VTPM_ORD_BASE + 6) // DMI requests the si= ze of nvm storage blob +#define VTPM_ORD_SAVEKEY (VTPM_ORD_BASE + 7) // DMI requests encryp= tion key for persistent storage +#define VTPM_ORD_LOADKEY (VTPM_ORD_BASE + 8) // DMI requests symkey= to be regenerated =20 // Priviledged VTPM Commands (From management console) #define VTPM_ORD_OPEN (VTPM_PRIV_BASE + 1) // Creates/reopens DM= I @@ -147,4 +150,23 @@ =20 *********************************************************************/ =20 +#ifndef VTPM_STUBDOM +#define TPM_EMULATOR_PATH "/usr/bin/vtpmd" +#endif + +#define VTPM_BE_FNAME "/dev/vtpm" +#define VTPM_DUMMY_TX_BE_FNAME "/var/vtpm/fifos/dummy_out.fifo" +#define VTPM_DUMMY_RX_BE_FNAME "/var/vtpm/fifos/dummy_in.fifo" +#ifndef VTPM_STUBDOM +#define VTPM_TX_TPM_FNAME "/var/vtpm/fifos/tpm_cmd_to_%d.fifo" +#define VTPM_RX_TPM_FNAME "/var/vtpm/fifos/tpm_rsp_from_all.fifo" +#define VTPM_TX_VTPM_FNAME "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo" +#define VTPM_RX_VTPM_FNAME "/var/vtpm/fifos/vtpm_cmd_from_all.fifo" +#endif +#define VTPM_TX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" +#define VTPM_RX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" + +#define VTPM_TYPE_PVM_STRING "pvm" +#define VTPM_TYPE_HVM_STRING "hvm" + #endif //_VTPM_MANAGER_H_ diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpm_mana= ger_handler.c --- a/tools/vtpm_manager/manager/vtpm_manager_handler.c Thu Jul 01 14:17:= 13 2010 -0400 +++ b/tools/vtpm_manager/manager/vtpm_manager_handler.c Tue Jul 20 15:26:= 31 2010 -0400 @@ -41,6 +41,7 @@ #include #include #include +#include =20 #include "vtpm_manager.h" #include "vtpmpriv.h" @@ -55,6 +56,8 @@ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (modu= le, fmt, ##args ); #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, "[= %s]: " fmt, thread_name, ##args ); =20 +volatile sig_atomic_t HANDLER_QUIT_FLAG =3D 0; + // ---------------------- Prototypes ------------------- TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res, TPM_COMMAND_CODE ord, @@ -63,6 +66,7 @@ BOOL is_priv, char *thread_name); =20 +#ifndef VTPM_STUBDOM TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, vtpm_ipc_handle_t *rx_ipc_h, VTPM_DMI_RESOURCE *dmi_res, @@ -70,6 +74,7 @@ buffer_t *param_buf, buffer_t *result_buf, char *thread_name); +#endif =20 TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h,=20 vtpm_ipc_handle_t *rx_ipc_h, @@ -80,12 +85,13 @@ char *thread_name) { TPM_RESULT status =3D TPM_FAIL; // Should never return UINT32 dmi, in_param_size, cmd_size, out_param_size, out_mess= age_size, reply_size; - BYTE *cmd_header=3DNULL, *in_param=3DNULL, *out_message=3DN= ULL, *reply; + BYTE *cmd_header=3DNULL, *in_param=3DNULL, *out_header=3DNU= LL, *reply; buffer_t *command_buf=3DNULL, *result_buf=3DNULL; TPM_TAG tag; TPM_COMMAND_CODE ord; VTPM_DMI_RESOURCE *dmi_res; int size_read, size_write, i; + int locked; BOOL add_header=3DTRUE; // This indicates to prepend a header on resul= t_buf before sending =20 cmd_header =3D (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV); @@ -93,7 +99,11 @@ result_buf =3D (buffer_t *) malloc(sizeof(buffer_t)); =20 // ------------------------ Main Loop --------------------------------= - while(1) { + while(!HANDLER_QUIT_FLAG) { + locked =3D 0; + + buffer_init(command_buf, 0, NULL); + buffer_init(result_buf, 0, NULL); =20 vtpmhandlerloginfo(VTPM_LOG_VTPM, "%s waiting for messages.\n", thre= ad_name); =20 @@ -106,7 +116,9 @@ for (i=3D0; iis_owner =3D TRUE; =20 // -------------- Dispatch Commands to Handlers ----------- if ((tag =3D=3D VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK)) { @@ -162,6 +175,7 @@ } else { vtpm_lock_rdlock(); } + locked =3D 1; =20 if ( !(dmi_res =3D (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globa= ls->dmi_map, &dmi)) || (!dmi_res->connected) ) { @@ -174,10 +188,22 @@ if (tag =3D=3D VTPM_TAG_REQ) {=20 =20 status =3D vtpm_manager_handle_vtpm_cmd(dmi_res, ord, command_buf,= result_buf, is_priv, thread_name); + result_buf->is_owner =3D TRUE; =20 } else { // This is not a VTPM Command at all. if (fw_tpm) {=20 +#ifdef VTPM_STUBDOM + /* In stubdom mode, we allow the vtpm domains to send raw tpm commands = down the pipe=20 + * They can also just embed their tpm commands inside VTPM commands if = they wish to*/ + + /* Stick the header back onto the raw command (minus the dmiid) */ + buffer_prepend_raw(command_buf, VTPM_COMMAND_HEADER_SIZE_CLT, cmd_heade= r + sizeof(UINT32)); + status =3D VTPM_Handle_TPM_Command(dmi_res, command_buf, result_buf); +#else + /* In normal mode, this is used for the guest to forward a raw command = to the vtpm process */ status =3D vtpm_manager_handle_tpm_cmd(fw_tx_ipc_h, fw_rx_ipc_h,= dmi_res, cmd_header, command_buf, result_buf, thread_name); +#endif + result_buf->is_owner =3D TRUE; =20 // This means calling the DMI failed, not that the cmd failed in= the DMI // Since the return will be interpretted by a TPM app, all error= s are IO_ERRORs to the app @@ -207,36 +233,42 @@ // ------------------- Respond to Sender ------------------ // Errors while handling responses jump here to reply with error mes= sages - // NOTE: Currently there are no recoverable errors in multi-VM mode.= If one - // is added to the code, this ifdef should be removed. - // Also note this is NOT referring to errors in commands, but = rather - // this is about I/O errors and such. -#ifndef VTPM_MULTI_VM - abort_with_error: -#endif +abort_with_error: =20 if (add_header) {=20 // Prepend VTPM header with destination DM stamped out_param_size =3D buffer_len(result_buf); out_message_size =3D VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size= ; - reply_size =3D VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; - out_message =3D (BYTE *) malloc (reply_size); - reply =3D out_message; + out_header =3D (BYTE *) malloc (VTPM_COMMAND_HEADER_SIZE_SRV); =20 - BSG_PackList(out_message, 4, + BSG_PackList(out_header, 4, BSG_TYPE_UINT32, (BYTE *) &dmi, BSG_TPM_TAG, (BYTE *) &tag, BSG_TYPE_UINT32, (BYTE *) &out_message_size, BSG_TPM_RESULT, (BYTE *) &status); =20 - if (buffer_len(result_buf) > 0)=20 - memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->b= ytes, out_param_size); - //Note: Send message + dmi_id + buffer_prepend_raw(result_buf, VTPM_COMMAND_HEADER_SIZE_SRV, out_h= eader); + free(out_header); } else { - reply =3D result_buf->bytes; - reply_size =3D buffer_len(result_buf); +#ifdef VTPM_STUBDOM + //In stubdom mode, we need to always prepend the dmiid so the raw= command can be returned to the right domain + out_header =3D (BYTE*) malloc(sizeof(UINT32)); + BSG_PackList(out_header, 1, + BSG_TYPE_UINT32, (BYTE*) &dmi); + buffer_prepend_raw(result_buf, sizeof(UINT32), out_header); + free(out_header); +#endif } =20 + reply =3D result_buf->bytes; + reply_size =3D buffer_len(result_buf); +#ifndef VTPM_STUBDOM size_write =3D vtpm_ipc_write(tx_ipc_h, (dmi_res ? dmi_res->tx_vtpm_= ipc_h : NULL), reply, reply_size ); +#else + if(reply_size >=3D 4096) { + vtpmhandlerlogerror(VTPM_LOG_VTPM, "MESSAGE TOO BIG!!!"); + } + size_write =3D vtpm_ipc_write(tx_ipc_h, NULL, reply, reply_size ); +#endif if (size_write > 0) { vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x"); for (i=3D0; i < reply_size; i++)=20 @@ -247,7 +279,6 @@ vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s had error writing to ipc. A= borting... \n", thread_name); goto abort_command; } - free(out_message); out_message=3DNULL; =20 if (size_write < (int)reply_size) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full comman= d to ipc (%d/%d)\n", thread_name, size_write, reply_size); @@ -264,14 +295,22 @@ buffer_free(command_buf); =20 // If we have a write lock, save the manager table - if ((tag =3D=3D VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK) && + if (locked && (tag =3D=3D VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK) &&= (VTPM_SaveManagerData() !=3D TPM_SUCCESS) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save manager= data.\n"); } =20 - vtpm_lock_unlock(); + if(locked) { + vtpm_lock_unlock(); + } add_header =3D TRUE; // Reset to the default } // End while(1) + + free(cmd_header); + free(command_buf); + free(result_buf); + + vtpmhandlerloginfo(VTPM_LOG_VTPM, "exiting\n", thread_name); =20 } =20 @@ -313,6 +352,21 @@ status =3D VTPM_Handle_Load_Migration_key(command_buf,=20 result_buf); break; + case VTPM_ORD_GETNVMSIZE: + status =3D VTPM_Handle_Get_NVM_Size(dmi_res, + command_buf, + result_buf); + break; + case VTPM_ORD_SAVEKEY: + status =3D VTPM_Handle_Save_Key(dmi_res, + command_buf, + result_buf); + break; + case VTPM_ORD_LOADKEY: + status =3D VTPM_Handle_Load_Key(dmi_res, + command_buf, + result_buf); + break; =20 default: // Privileged handlers can do maintanance @@ -350,6 +404,7 @@ return(status); } =20 +#ifndef VTPM_STUBDOM ///////////////////////////////////////////////////////////////////// TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, vtpm_ipc_handle_t *rx_ipc_h, @@ -485,4 +540,5 @@ =20 return status; } +#endif =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpmd.c --- a/tools/vtpm_manager/manager/vtpmd.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/manager/vtpmd.c Tue Jul 20 15:26:31 2010 -0400 @@ -51,21 +51,6 @@ #include "log.h" #include "vtpm_ipc.h" =20 -#define TPM_EMULATOR_PATH "/usr/bin/vtpmd" - -#define VTPM_BE_FNAME "/dev/vtpm" -#define VTPM_DUMMY_TX_BE_FNAME "/var/vtpm/fifos/dummy_out.fifo" -#define VTPM_DUMMY_RX_BE_FNAME "/var/vtpm/fifos/dummy_in.fifo" -#define VTPM_TX_TPM_FNAME "/var/vtpm/fifos/tpm_cmd_to_%d.fifo" -#define VTPM_RX_TPM_FNAME "/var/vtpm/fifos/tpm_rsp_from_all.fifo" -#define VTPM_TX_VTPM_FNAME "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo" -#define VTPM_RX_VTPM_FNAME "/var/vtpm/fifos/vtpm_cmd_from_all.fifo" -#define VTPM_TX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" -#define VTPM_RX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" - -#define VTPM_TYPE_PVM_STRING "pvm" -#define VTPM_TYPE_HVM_STRING "hvm" - struct vtpm_thread_params_s { vtpm_ipc_handle_t *tx_ipc_h; vtpm_ipc_handle_t *rx_ipc_h; @@ -76,33 +61,27 @@ char *thread_name; }; =20 +#ifndef VTPM_STUBDOM // This is needed to all extra_close_dmi to close this to prevent a // broken pipe when no DMIs are left. static vtpm_ipc_handle_t *g_rx_tpm_ipc_h; +#endif =20 void *vtpm_manager_thread(void *arg_void) { - TPM_RESULT *status =3D (TPM_RESULT *) malloc(sizeof(TPM_RESULT) ); struct vtpm_thread_params_s *arg =3D (struct vtpm_thread_params_s *) a= rg_void; =20 - *status =3D VTPM_Manager_Handler(arg->tx_ipc_h, arg->rx_ipc_h, + VTPM_Manager_Handler(arg->tx_ipc_h, arg->rx_ipc_h, arg->fw_tpm, arg->fw_tx_ipc_h, arg->fw_= rx_ipc_h, arg->is_priv, arg->thread_name); =20 - return (status); + return NULL; } =20 - -void signal_handler(int reason) { - if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) { - vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal %d= =2E\n", reason); - } else { - // For old Linux Thread machines, signals are delivered to each thre= ad. Deal with them. - vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n"); - pthread_exit(NULL); +void signal_handler(int signal) { + if (pthread_equal(pthread_self(), vtpm_globals->master_thread)) { + vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal %s= (%d). Please wait..\n", strsignal(signal), signal); + HANDLER_QUIT_FLAG =3D IPC_QUIT_FLAG =3D 1; } - - VTPM_Stop_Manager(); - exit(-1); } =20 struct sigaction ctl_c_handler; @@ -110,6 +89,7 @@ TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE vm_type, = BYTE startup_mode) { =20 TPM_RESULT status =3D TPM_SUCCESS; +#ifndef VTPM_STUBDOM int fh; char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL char *tx_vtpm_name, *tx_tpm_name, *vm_type_string; @@ -136,8 +116,8 @@ sprintf(tx_tpm_name, VTPM_TX_TPM_FNAME, (uint32_t) dmi_res->dmi_id);= sprintf(tx_vtpm_name, VTPM_TX_VTPM_FNAME, (uint32_t) dmi_res->dmi_id= ); =20 - if ( (vtpm_ipc_init(dmi_res->tx_tpm_ipc_h, tx_tpm_name, O_WRONLY | O= _NONBLOCK, TRUE) !=3D 0) || - (vtpm_ipc_init(dmi_res->tx_vtpm_ipc_h, tx_vtpm_name, O_WRONLY, = TRUE) !=3D 0) ) { //FIXME: O_NONBLOCK? + if ( (vtpm_ipc_init(dmi_res->tx_tpm_ipc_h, tx_tpm_name, O_WRONLY | O= _NONBLOCK, TRUE, FALSE) !=3D 0) || + (vtpm_ipc_init(dmi_res->tx_vtpm_ipc_h, tx_vtpm_name, O_WRONLY, = TRUE, FALSE) !=3D 0) ) { //FIXME: O_NONBLOCK? status =3D TPM_IOERROR; goto abort_egress; } @@ -202,14 +182,17 @@ =20 } // If DMI =3D VTPM_CTL_DM status =3D TPM_SUCCESS; +#endif =20 abort_egress: + //FIXME: Everything should be freed here=20 return (status); } =20 TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) { TPM_RESULT status =3D TPM_SUCCESS; =20 +#ifndef VTPM_STUBDOM if (vtpm_globals->connected_dmis =3D=3D 0) { // No more DMI's connected. Close fifo to prevent a broken pipe. // This is hackish. Need to think of another way. @@ -223,6 +206,8 @@ =20 free(dmi_res->tx_tpm_ipc_h->name); free(dmi_res->tx_vtpm_ipc_h->name); + free(dmi_res->tx_tpm_ipc_h); + free(dmi_res->tx_vtpm_ipc_h); =20 #ifndef MANUAL_DM_LAUNCH if (dmi_res->dmi_id !=3D VTPM_CTL_DM) { @@ -242,14 +227,18 @@ #endif =20 } //endif ! dom0 +#endif return status; } =20 =20 int main(int argc, char **argv) { - vtpm_ipc_handle_t *tx_be_ipc_h, *rx_be_ipc_h, rx_tpm_ipc_h, rx_vtpm_ip= c_h, tx_hp_ipc_h, rx_hp_ipc_h;=20 - struct vtpm_thread_params_s be_thread_params, dmi_thread_params, hp_th= read_params; - pthread_t be_thread, dmi_thread, hp_thread; + vtpm_ipc_handle_t *tx_be_ipc_h, *rx_be_ipc_h, tx_hp_ipc_h, rx_hp_ipc_h= ;=20 + struct vtpm_thread_params_s be_thread_params, hp_thread_params; +#ifndef VTPM_STUBDOM + vtpm_ipc_handle_t rx_tpm_ipc_h, rx_vtpm_ipc_h; + struct vtpm_thread_params_s dmi_thread_params; +#endif =20 #ifdef DUMMY_BACKEND vtpm_ipc_handle_t tx_dummy_ipc_h, rx_dummy_ipc_h; @@ -258,7 +247,7 @@ #endif =20 vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n"); -=20 + // -------------------- Initialize Manager -----------------=20 if (VTPM_Init_Manager() !=3D TPM_SUCCESS) { vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during start= up.\n"); @@ -270,22 +259,22 @@ sigemptyset(&ctl_c_handler.sa_mask); ctl_c_handler.sa_flags =3D 0; =20 =20 - if (sigaction(SIGINT, &ctl_c_handler, NULL) =3D=3D -1)=20 + if ((sigaction(SIGINT, &ctl_c_handler, NULL) =3D=3D -1)=20 + || (sigaction(SIGQUIT, &ctl_c_handler, NULL) =3D=3D -1)=20 + || (sigaction(SIGHUP, &ctl_c_handler, NULL) =3D=3D -1) ) // For easier = debugging with gdb + { vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler. Ctl+b= reak will not stop manager gently.\n"); + } =20 - // For easier debuggin with gdb - if (sigaction(SIGHUP, &ctl_c_handler, NULL) =3D=3D -1)=20 - vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler. Ctl+b= reak will not stop manager gently.\n"); =20 - =20 + //Block all signals for child threads sigset_t sig_mask; - sigemptyset(&sig_mask); - sigaddset(&sig_mask, SIGPIPE); - sigprocmask(SIG_BLOCK, &sig_mask, NULL); + sigfillset(&sig_mask); + pthread_sigmask(SIG_SETMASK, &sig_mask, NULL); =20 // ------------------- Set up file ipc structures ---------- #ifdef DUMMY_BACKEND - if ( (vtpm_ipc_init(&tx_dummy_ipc_h, VTPM_DUMMY_TX_BE_FNAME, O_RDWR, T= RUE) !=3D 0) || - (vtpm_ipc_init(&rx_dummy_ipc_h, VTPM_DUMMY_RX_BE_FNAME, O_RDWR, T= RUE) !=3D 0) ) { + if ( (vtpm_ipc_init(&tx_dummy_ipc_h, VTPM_DUMMY_TX_BE_FNAME, O_RDWR, T= RUE, FALSE) !=3D 0) || + (vtpm_ipc_init(&rx_dummy_ipc_h, VTPM_DUMMY_RX_BE_FNAME, O_RDWR, T= RUE, FALSE) !=3D 0) ) { =20 vtpmlogerror(VTPM_LOG_VTPM, "Unable to create Dummy BE FIFOs.\n"); exit(-1); @@ -294,21 +283,26 @@ tx_be_ipc_h =3D &tx_dummy_ipc_h; rx_be_ipc_h =3D &rx_dummy_ipc_h; #else - vtpm_ipc_init(&real_be_ipc_h, VTPM_BE_FNAME, O_RDWR, FALSE); + vtpm_ipc_init(&real_be_ipc_h, VTPM_BE_FNAME, O_RDWR, FALSE, FALSE); =20 tx_be_ipc_h =3D &real_be_ipc_h; rx_be_ipc_h =3D &real_be_ipc_h; #endif =20 - if ( (vtpm_ipc_init(&rx_tpm_ipc_h, VTPM_RX_TPM_FNAME, O_RDONLY, TRUE) = !=3D 0) || - (vtpm_ipc_init(&rx_vtpm_ipc_h, VTPM_RX_VTPM_FNAME, O_RDWR, TRUE) = !=3D 0) || //FIXME: O_RDONLY? - (vtpm_ipc_init(&tx_hp_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE) !=3D= 0) || - (vtpm_ipc_init(&rx_hp_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE) !=3D= 0) ) { + if (=20 +#ifndef VTPM_STUBDOM + (vtpm_ipc_init(&rx_tpm_ipc_h, VTPM_RX_TPM_FNAME, O_RDONLY, TRUE, = FALSE) !=3D 0) || + (vtpm_ipc_init(&rx_vtpm_ipc_h, VTPM_RX_VTPM_FNAME, O_RDWR, TRUE, = FALSE) !=3D 0) || //FIXME: O_RDONLY? +#endif + (vtpm_ipc_init(&tx_hp_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE, TRU= E) !=3D 0) || + (vtpm_ipc_init(&rx_hp_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE, TRU= E) !=3D 0) ) { vtpmlogerror(VTPM_LOG_VTPM, "Unable to create initial FIFOs.\n"); exit(-1); } =20 +#ifndef VTPM_STUBDOM g_rx_tpm_ipc_h =3D &rx_tpm_ipc_h; +#endif =20 // -------------------- Set up thread params -------------=20 =20 @@ -316,10 +310,15 @@ be_thread_params.rx_ipc_h =3D rx_be_ipc_h; be_thread_params.fw_tpm =3D TRUE; be_thread_params.fw_tx_ipc_h =3D NULL; +#ifndef VTPM_STUBDOM be_thread_params.fw_rx_ipc_h =3D &rx_tpm_ipc_h; +#else + be_thread_params.fw_rx_ipc_h =3D NULL; +#endif be_thread_params.is_priv =3D FALSE; be_thread_params.thread_name =3D "Backend Listener"; =20 +#ifndef VTPM_STUBDOM dmi_thread_params.tx_ipc_h =3D NULL; dmi_thread_params.rx_ipc_h =3D &rx_vtpm_ipc_h; dmi_thread_params.fw_tpm =3D FALSE;=20 @@ -327,6 +326,7 @@ dmi_thread_params.fw_rx_ipc_h =3D NULL; dmi_thread_params.is_priv =3D FALSE;=20 dmi_thread_params.thread_name =3D "VTPM Listener"; +#endif =20 hp_thread_params.tx_ipc_h =3D &tx_hp_ipc_h; hp_thread_params.rx_ipc_h =3D &rx_hp_ipc_h; @@ -340,30 +340,39 @@ =20 vtpm_lock_init(); =20 - vtpm_globals->master_pid =3D pthread_self(); + vtpm_globals->master_thread =3D pthread_self(); + =20 - if (pthread_create(&be_thread, NULL, vtpm_manager_thread, &be_thread_p= arams) !=3D 0) { + if (pthread_create(&vtpm_globals->be_thread, NULL, vtpm_manager_thread= , &be_thread_params) !=3D 0) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n"); exit(-1); } =20 - if (pthread_create(&dmi_thread, NULL, vtpm_manager_thread, &dmi_thread= _params) !=3D 0) { +#ifndef VTPM_STUBDOM + if (pthread_create(&vtpm_globals->dmi_thread, NULL, vtpm_manager_threa= d, &dmi_thread_params) !=3D 0) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n"); exit(-1); } - +#endif =20 - if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_p= arams) !=3D 0) { + if (pthread_create(&vtpm_globals->hp_thread, NULL, vtpm_manager_thread= , &hp_thread_params) !=3D 0) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); exit(-1); } =20 + //Turn signals back on for the master thread only + sigemptyset(&sig_mask); + sigaddset(&sig_mask, SIGPIPE); + pthread_sigmask(SIG_SETMASK, &sig_mask, NULL); + //Join the other threads until exit time. - pthread_join(be_thread, NULL); - pthread_join(dmi_thread, NULL); - pthread_join(hp_thread, NULL); + pthread_join(vtpm_globals->be_thread, NULL); +#ifndef VTPM_STUBDOM + pthread_join(vtpm_globals->dmi_thread, NULL); +#endif + pthread_join(vtpm_globals->hp_thread, NULL); =20 - vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager shut down unexpectedly.\n");= + vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down...\n"); =20 VTPM_Stop_Manager(); vtpm_lock_destroy(); diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtpmpriv.= h --- a/tools/vtpm_manager/manager/vtpmpriv.h Thu Jul 01 14:17:13 2010 -040= 0 +++ b/tools/vtpm_manager/manager/vtpmpriv.h Tue Jul 20 15:26:31 2010 -040= 0 @@ -40,6 +40,8 @@ #ifndef __VTPMPRIV_H__ #define __VTPMPRIV_H__ =20 +#include + #include "vtpm_manager.h" #include "tcg.h" #include "tcs.h" @@ -54,16 +56,19 @@ #define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" #define VTPM_CTL_DM 0 =20 +extern volatile sig_atomic_t HANDLER_QUIT_FLAG; + // ------------------------ Private Structures ----------------------- typedef struct VTPM_DMI_RESOURCE_T { +#ifndef VTPM_STUBDOM // I/O info for Manager to talk to DMI's and controllers vtpm_ipc_handle_t *tx_vtpm_ipc_h; // TX VTPM Results to DMI vtpm_ipc_handle_t *rx_vtpm_ipc_h; // RX VTPM Commands from DMI= vtpm_ipc_handle_t *tx_tpm_ipc_h; // TX TPM Commands to DMI vtpm_ipc_handle_t *rx_tpm_ipc_h; // RX TPM Results from DMI + + pid_t dmi_pid; =20 -#ifndef VTPM_MULTI_VM=20 - pid_t dmi_pid; #endif =20 // Non-persistent Information @@ -77,6 +82,7 @@ BYTE dmi_type; TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the bl= ob TPM_DIGEST DMI_measurement; // Correct measurement of the = owning DMI + } VTPM_DMI_RESOURCE; =20 typedef struct tdVTPM_MIGKEY_LIST { @@ -89,8 +95,11 @@ =20 typedef struct tdVTPM_GLOBALS { // Non-persistent data -#ifndef VTPM_MULTI_VM - pid_t master_pid; + pthread_t master_thread; + pthread_t be_thread; + pthread_t hp_thread; +#ifndef VTPM_STUBDOM + pthread_t dmi_thread; #endif =20 int connected_dmis; // To close guest_rx when no d= mis are connected @@ -143,6 +152,11 @@ const buffer_t *inbuf,=20 buffer_t *outbuf); =20 +TPM_RESULT VTPM_Handle_Get_NVM_Size( VTPM_DMI_RESOURCE *myDMI,=20 + const buffer_t *inbuf,=20 + buffer_t *outbuf); + + TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,=20 buffer_t *inbuf,=20 buffer_t *outbuf); @@ -173,6 +187,9 @@ TPM_RESULT close_dmi(VTPM_DMI_RESOURCE *dmi_res); TPM_RESULT init_dmi(UINT32 dmi_id, BYTE type, VTPM_DMI_RESOURCE **dmi_r= es); =20 +/* Free's dmi_res and all of it's resources */ +void free_dmi(VTPM_DMI_RESOURCE *dmi_res); + TPM_RESULT envelope_encrypt(const buffer_t *inbuf, CRYPTO_INFO *asymkey, buffer_t *sealed_data); diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/manager/vtsp.c --- a/tools/vtpm_manager/manager/vtsp.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/manager/vtsp.c Tue Jul 20 15:26:31 2010 -0400 @@ -567,8 +567,7 @@ osapSharedSecret, auth, 0) ); =20 // Unpack/return key structure - TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) ); - TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.= data) ); + TPMTRYRETURN(buffer_init(pubKeyBuf, newKeyText.size, newKeyText.data) = ); =20 goto egress; =20 @@ -664,6 +663,7 @@ =20 // Destroy rsaKeyParms BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms); + BSG_Destroy(BSG_TPM_KEY, &newKey); =20 // Set encryption scheme cryptoinfo->encScheme =3D CRYPTO_ES_RSAESOAEP_SHA1_MGF1; @@ -733,8 +733,7 @@ hContext) ); =20 // Unpack/return key structure - TPMTRYRETURN(buffer_init(clear_data, 0, 0)); - TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, clear_dat= a_text) ); + TPMTRYRETURN(buffer_init(clear_data, clear_data_size, clear_data_text)= ); =20 goto egress; =20 @@ -793,8 +792,7 @@ vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n"); } =20 - buffer_init(outData, 0, NULL); - buffer_append_raw(outData, out_tmp_size, out_tmp); + buffer_init(outData, out_tmp_size, out_tmp); =20 vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] =3D 0x", out_tmp_size= ); for(i =3D 0 ; i < out_tmp_size ; i++) { diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/migration/vtpm_ma= nager_if.c --- a/tools/vtpm_manager/migration/vtpm_manager_if.c Thu Jul 01 14:17:13 = 2010 -0400 +++ b/tools/vtpm_manager/migration/vtpm_manager_if.c Tue Jul 20 15:26:31 = 2010 -0400 @@ -50,15 +50,12 @@ #include "vtpm_migrator.h" #include "vtpm_manager.h" =20 -#define VTPM_TX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" -#define VTPM_RX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" - static vtpm_ipc_handle_t tx_ipc_h, rx_ipc_h; =20 TPM_RESULT vtpm_manager_open(){ =20 - if ( (vtpm_ipc_init(&tx_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE) !=3D 0= ) || //FIXME: wronly - (vtpm_ipc_init(&rx_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE) !=3D 0= ) ) { //FIXME: rdonly + if ( (vtpm_ipc_init(&tx_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE, TRUE) = !=3D 0) || //FIXME: wronly + (vtpm_ipc_init(&rx_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE, TRUE) = !=3D 0) ) { //FIXME: rdonly vtpmlogerror(VTPM_LOG_VTPM, "Unable to connect to vtpm_manager.\n");= return TPM_IOERROR; }=20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/tcs/contextmgr.c --- a/tools/vtpm_manager/tcs/contextmgr.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/tcs/contextmgr.c Tue Jul 20 15:26:31 2010 -0400 @@ -195,6 +195,7 @@ =20 BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in HANDLE_LIST* pCurrentHandle; + HANDLE_LIST* pNext; BOOL returncode =3D TRUE; =20 vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n"); @@ -205,6 +206,7 @@ pCurrentHandle =3D pContextHandle->pHandleList; while (pCurrentHandle !=3D NULL) { =20 + pNext =3D pCurrentHandle->pNextHandle; switch (pCurrentHandle->type) { case TPM_RT_KEY: returncode =3D returncode && !TCSP_EvictKey(pContextHandle->handle= , pCurrentHandle->handle); @@ -216,7 +218,7 @@ returncode =3D FALSE; } =20 - pCurrentHandle =3D pCurrentHandle->pNextHandle; + pCurrentHandle =3D pNext; =20 } =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/tcs/tcs.c --- a/tools/vtpm_manager/tcs/tcs.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/tcs/tcs.c Tue Jul 20 15:26:31 2010 -0400 @@ -113,14 +113,13 @@ TCS_CONTEXT_HANDLE *hContext; =20 // Close all the TCS contexts. TCS should evict keys based on this - if (hashtable_count(context_ht) > 0) { + while (hashtable_count(context_ht) > 0) { context_itr =3D hashtable_iterator(context_ht); - do { - hContext =3D (TCS_CONTEXT_HANDLE *) hashtable_iterator_key(conte= xt_itr); - if (TCS_CloseContext(*hContext) !=3D TPM_SUCCESS)=20 - vtpmlogerror(VTPM_LOG_TCS, "Failed to close context %d properly.\n"= , *hContext); + + hContext =3D (TCS_CONTEXT_HANDLE *) hashtable_iterator_key(context= _itr); + if (TCS_CloseContext(*hContext) !=3D TPM_SUCCESS)=20 + vtpmlogerror(VTPM_LOG_TCS, "Failed to close context %d properly.= \n", *hContext); =20 - } while (hashtable_iterator_advance(context_itr)); free(context_itr); } hashtable_destroy(context_ht, 1); @@ -534,6 +533,10 @@ BSG_TYPE_UINT32, &handle); // fill paramSize again as we now have the correct size BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); + + if (!DeleteHandleFromList(hContext, handle)) { + vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); + } =20 // call the TPM driver if ((hRes =3D TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) = @@ -545,9 +548,6 @@ BSG_TYPE_UINT32, ¶mSize,=20 BSG_TPM_COMMAND_CODE, &returnCode); =20 - if (!DeleteHandleFromList(hContext, handle))=20 - vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); - =20 =20 if (returnCode =3D=3D TPM_SUCCESS && tag =3D=3D TPM_TAG_RSP_COMMAND)= { // Print debug info @@ -882,6 +882,7 @@ =20 memcpy(*prgbKey, tempBuf, *pcKeySize); =20 + BSG_Destroy(BSG_TPM_KEY, &wrappedKey); vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramS= ize); } else=20 vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return = code %s\n", tpm_get_error_name(returnCode));=20 @@ -980,6 +981,10 @@ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); =20 vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize =3D %d\n", InLength)= ; + + if (!DeleteHandleFromList(hContext, hKey)) { + vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); + } =20 =20 // call the TPM driver if ((hRes =3D TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) = =3D=3D TDDL_SUCCESS) { @@ -989,10 +994,6 @@ BSG_TYPE_UINT32, ¶mSize,=20 BSG_TPM_COMMAND_CODE, &returnCode); =20 - if (!DeleteHandleFromList(hContext, hKey)) { - vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); - } =20 - =20 if (returnCode =3D=3D TPM_SUCCESS && tag =3D=3D TPM_TAG_RSP_COMMAND)= { vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramS= ize); } else { @@ -1019,7 +1020,7 @@ TDDL_UINT32 OutLength =3D TCPA_MAX_BUFFER_LENGTH; =20 // check input params - if (bytesRequested =3D=3D NULL || *randomBytes =3D=3D NULL){ + if (bytesRequested =3D=3D NULL || randomBytes =3D=3D NULL){ return TPM_BAD_PARAMETER; } =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/tcs/tpmddl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/vtpm_manager/tcs/tpmddl.c Tue Jul 20 15:26:31 2010 -0400 @@ -0,0 +1,93 @@ +#include +#include "tpmddl.h" +#include "tcs.h" +#include "bsg.h" +#include "log.h" + +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) + +TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap, + TDDL_UINT32 sub, + TDDL_BYTE* buffer, + TDDL_UINT32* size) +{ + TPM_RESULT status; + + TPM_TAG tag =3D TPM_TAG_RQU_COMMAND; + UINT32 paramsize =3D 22; + UINT32 outsize; + TPM_COMMAND_CODE ord =3D TPM_ORD_GetCapability; + UINT32 subcapsize =3D 4; + + BYTE inbuf[TCPA_MAX_BUFFER_LENGTH]; + BYTE outbuf[TCPA_MAX_BUFFER_LENGTH]; + + int offset; + + BSG_PackList(inbuf, 6, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_COMMAND_CODE, &(ord), + BSG_TYPE_UINT32, &(cap), + BSG_TYPE_UINT32, &(subcapsize), + BSG_TYPE_UINT32, &(sub) + ); + + //Send the command, get the response + TPMTRYRETURN(TDDL_TransmitData( inbuf, paramsize, outbuf, &outsize));= + + offset =3D BSG_UnpackList(outbuf, 4, + BSG_TPM_TAG, &(tag),=20 + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_RESULT, &(status), + BSG_TYPE_UINT32, size + ); + if (status !=3D TPM_SUCCESS || tag !=3D TPM_TAG_RSP_COMMAND) { + return status; + } + if(*size >=3D TCPA_MAX_BUFFER_LENGTH - offset) { + return TPM_FAIL; + } + memcpy(buffer, outbuf + offset, *size); + +abort_egress: + return status; +} + +TDDL_RESULT TDDL_FlushSpecific(TDDL_UINT32 handle, TDDL_UINT32 res) { + /* FIXME: Add code here to check if TPM_FlushSpecific is not support= ed (on 1.1 only TPMS?) + * If this is the case then we need to use TPM_EvictKey for key handl= es + * and TPM_Terminate_Handle/TPM_Reset for auth handles */=20 + TPM_RESULT status; + + TPM_TAG tag =3D TPM_TAG_RQU_COMMAND; + UINT32 paramsize =3D 18; + TPM_COMMAND_CODE ord =3D TPM_ORD_FlushSpecific; + + BYTE inbuf[TCPA_MAX_BUFFER_LENGTH]; + BYTE outbuf[TCPA_MAX_BUFFER_LENGTH]; + UINT32 outsize; + + int offset; + + BSG_PackList(inbuf, 5, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_COMMAND_CODE, &(ord), + BSG_TPM_HANDLE, &(handle), + BSG_TPM_RESOURCE_TYPE, &(res) + ); + + //Send command + TPMTRYRETURN(TDDL_TransmitData( inbuf, paramsize, outbuf, &outsize ))= ; + + offset =3D BSG_UnpackList(outbuf, 4, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_RESULT, &(status) + ); + +abort_egress: + return status; + =20 +} diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/tcs/tpmddl.h --- a/tools/vtpm_manager/tcs/tpmddl.h Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/tcs/tpmddl.h Tue Jul 20 15:26:31 2010 -0400 @@ -66,4 +66,7 @@ TDDL_BYTE* buffer, TDDL_UINT32* size); =20 +TDDL_RESULT TDDL_FlushSpecific(TDDL_UINT32 handle,=20 + TDDL_UINT32 res); + #endif // __TPMDDL_H__ diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/tcs/transmit.c --- a/tools/vtpm_manager/tcs/transmit.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/tcs/transmit.c Tue Jul 20 15:26:31 2010 -0400 @@ -117,7 +117,7 @@ =20 g_tx_fd =3D open (TPM_TX_FNAME, O_RDWR); if (g_tx_fd < 0) { - vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed"); + vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed\n"); return TPM_IOERROR; } =20 diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/util/buffer.c --- a/tools/vtpm_manager/util/buffer.c Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/util/buffer.c Tue Jul 20 15:26:31 2010 -0400 @@ -39,6 +39,7 @@ #include =20 #include "tcg.h" +#include "log.h" #include "bsg.h" #include "buffer.h" =20 @@ -51,6 +52,7 @@ TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE*= initval) { if (initsize =3D=3D 0) { memset(buf, 0, sizeof(*buf)); + buf->bytes =3D NULL; return TPM_SUCCESS; } =20 @@ -62,8 +64,11 @@ buf->size =3D initsize; buf->alloc_size =3D initsize; =20 - if (initval) + if (initval) { memcpy (buf->bytes, initval, initsize); + } else { + memset(buf->bytes, 0, initsize); + } =20 buf->is_owner =3D TRUE; =20 @@ -190,6 +195,30 @@ return status; } =20 +TPM_RESULT buffer_prepend_raw(buffer_t * buf, tpm_size_t len, const BYTE= * bytes) { + TPM_RESULT status =3D TPM_SUCCESS; + long i; + + if (buf->alloc_size < buf->size + len) { + TPMTRYRETURN( buffer_priv_realloc (buf, buf->size + len) ); + } + + if(buf->size > 0) { + memmove(buf->bytes + len, buf->bytes, buf->size); + } + memcpy(buf->bytes, bytes, len); + + buf->size +=3D len; + + goto egress; + + abort_egress: + + egress: + + return status; +} + tpm_size_t buffer_len (const buffer_t* buf) { return buf->size; } @@ -199,7 +228,6 @@ free (buf->bytes); buf->bytes =3D NULL; buf->size =3D buf->alloc_size =3D 0; - =20 } =20 return TPM_SUCCESS; diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/util/buffer.h --- a/tools/vtpm_manager/util/buffer.h Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/util/buffer.h Tue Jul 20 15:26:31 2010 -0400 @@ -92,4 +92,6 @@ =20 TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE= * bytes); =20 +TPM_RESULT buffer_prepend_raw(buffer_t * buf, tpm_size_t len, const BYTE= * bytes); + #endif // _TOOLS_H_ diff -r 7c44921abfde -r 5793f5c2d67d tools/vtpm_manager/util/tcg.h --- a/tools/vtpm_manager/util/tcg.h Thu Jul 01 14:17:13 2010 -0400 +++ b/tools/vtpm_manager/util/tcg.h Tue Jul 20 15:26:31 2010 -0400 @@ -197,6 +197,7 @@ UINT32 size; BYTE * data; } pack_buf_t; +#define NULL_PACK_BUF {0,0} =20 typedef struct pack_constbuf_t { UINT32 size; @@ -295,6 +296,35 @@ #define TPM_ORD_LoadKeyContext (181UL + TPM_PROTECTED_ORDINAL)= #define TPM_ORD_SaveAuthContext (182UL + TPM_PROTECTED_ORDINAL)= #define TPM_ORD_LoadAuthContext (183UL + TPM_PROTECTED_ORDINAL)= +#define TPM_ORD_SaveContext (184UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_LoadContext (185UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_FlushSpecific (186UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_PCR_Reset (200UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_NV_DefineSpace (204UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_NV_WriteValue (205UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_NV_WriteValueAuth (206UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_NV_ReadValue (207UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_NV_ReadValueAuth (208UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_UpdateVerification (209UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_Manage (210UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_CreateKeyDelegation (212UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_CreateOwnerDelegation (213UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_VerifyDelegation (214UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_LoadOwnerDelegation (216UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_ReadAuth (217UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_Delegate_ReadTable (219UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_CreateCounter (220UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_IncrementCounter (221UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_ReadCounter (222UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_ReleaseCounter (223UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_ReleaseCounterOwner (224UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_EstablishTransport (230UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_ExecuteTransport (231UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_ReleaseTransportSigned (232UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_GetTicks (241UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_TickStampBlob (242UL + TPM_PROTECTED_= ORDINAL) +#define TPM_ORD_MAX (256UL + TPM_PROTECTED_= ORDINAL) + #define TSC_ORD_PhysicalPresence (10UL + TPM_CONNECTION_ORDINAL)= =20 =20 @@ -419,8 +449,16 @@ /// TPM_ResourceTypes #define TPM_RT_KEY 0x00000001 #define TPM_RT_AUTH 0x00000002 +#define TPM_RT_HASH 0x00000003 #define TPM_RT_TRANS 0x00000004 #define TPM_RT_CONTEXT 0x00000005 +#define TPM_RT_COUNTER 0x00000006 +#define TPM_RT_DELEGATE 0x00000007 +#define TPM_RT_DAA_TPM 0x00000008 +#define TPM_RT_DAA_V0 0x00000009 +#define TPM_RT_DAA_V1 0x0000000A + + =20 // TPM_PROTOCOL_ID values #define TPM_PID_OIAP 0x0001 @@ -447,6 +485,64 @@ #define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002 #define TPM_SS_RSASSAPKCS1v15_DER 0x0003 =20 +/* + * TPM_CAPABILITY_AREA Values for TPM_GetCapability ([TPM_Part2], Sectio= n 21.1) + */ +#define TPM_CAP_ORD 0x00000001 +#define TPM_CAP_ALG 0x00000002 +#define TPM_CAP_PID 0x00000003 +#define TPM_CAP_FLAG 0x00000004 +#define TPM_CAP_PROPERTY 0x00000005 +#define TPM_CAP_VERSION 0x00000006 +#define TPM_CAP_KEY_HANDLE 0x00000007 +#define TPM_CAP_CHECK_LOADED 0x00000008 +#define TPM_CAP_SYM_MODE 0x00000009 +#define TPM_CAP_KEY_STATUS 0x0000000C +#define TPM_CAP_NV_LIST 0x0000000D +#define TPM_CAP_MFR 0x00000010 +#define TPM_CAP_NV_INDEX 0x00000011 +#define TPM_CAP_TRANS_ALG 0x00000012 +#define TPM_CAP_HANDLE 0x00000014 +#define TPM_CAP_TRANS_ES 0x00000015 +#define TPM_CAP_AUTH_ENCRYPT 0x00000017 +#define TPM_CAP_SELECT_SIZE 0x00000018 +#define TPM_CAP_DA_LOGIC 0x00000019 +#define TPM_CAP_VERSION_VAL 0x0000001A + +/* subCap definitions ([TPM_Part2], Section 21.2) */ +#define TPM_CAP_PROP_PCR 0x00000101 +#define TPM_CAP_PROP_DIR 0x00000102 +#define TPM_CAP_PROP_MANUFACTURER 0x00000103 +#define TPM_CAP_PROP_KEYS 0x00000104 +#define TPM_CAP_PROP_MIN_COUNTER 0x00000107 +#define TPM_CAP_FLAG_PERMANENT 0x00000108 +#define TPM_CAP_FLAG_VOLATILE 0x00000109 +#define TPM_CAP_PROP_AUTHSESS 0x0000010A +#define TPM_CAP_PROP_TRANSESS 0x0000010B +#define TPM_CAP_PROP_COUNTERS 0x0000010C +#define TPM_CAP_PROP_MAX_AUTHSESS 0x0000010D +#define TPM_CAP_PROP_MAX_TRANSESS 0x0000010E +#define TPM_CAP_PROP_MAX_COUNTERS 0x0000010F +#define TPM_CAP_PROP_MAX_KEYS 0x00000110 +#define TPM_CAP_PROP_OWNER 0x00000111 +#define TPM_CAP_PROP_CONTEXT 0x00000112 +#define TPM_CAP_PROP_MAX_CONTEXT 0x00000113 +#define TPM_CAP_PROP_FAMILYROWS 0x00000114 +#define TPM_CAP_PROP_TIS_TIMEOUT 0x00000115 +#define TPM_CAP_PROP_STARTUP_EFFECT 0x00000116 +#define TPM_CAP_PROP_DELEGATE_ROW 0x00000117 +#define TPM_CAP_PROP_MAX_DAASESS 0x00000119 +#define TPM_CAP_PROP_DAASESS 0x0000011A +#define TPM_CAP_PROP_CONTEXT_DIST 0x0000011B +#define TPM_CAP_PROP_DAA_INTERRUPT 0x0000011C +#define TPM_CAP_PROP_SESSIONS 0x0000011D +#define TPM_CAP_PROP_MAX_SESSIONS 0x0000011E +#define TPM_CAP_PROP_CMK_RESTRICTION 0x0000011F +#define TPM_CAP_PROP_DURATION 0x00000120 +#define TPM_CAP_PROP_ACTIVE_COUNTER 0x00000122 +#define TPM_CAP_PROP_MAX_NV_AVAILABLE 0x00000123 +#define TPM_CAP_PROP_INPUT_BUFFER 0x00000124 + // TPM_KEY_USAGE values #define TPM_KEY_EK 0x0000=20 #define TPM_KEY_SIGNING 0x0010 --------------080201090103050803020605-- --------------ms070301090804070908050306 Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIHZzCC A5kwggMCoAMCAQICBD/xkcEwDQYJKoZIhvcNAQEFBQAwLzELMAkGA1UEBhMCVVMxDzANBgNV BAoTBkpIVUFQTDEPMA0GA1UECxMGQklTRENBMB4XDTA5MDcxNzE1MDgwOVoXDTEyMDcxNzE1 MzgwOVowZjELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkpIVUFQTDEPMA0GA1UECxMGUGVvcGxl MTUwFgYDVQQLEw9WUE5Hcm91cC1CSVNEQ0EwGwYDVQQDExRNYXR0aGV3IEUgRmlvcmF2YW50 ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyzeGk9zPA33fsB3uvk/Izs9GGHCpHI8b zXdBIVg6++S+jK53PoaWgmtSLr/c732ea1zPR6ACymwAWON+U5rB+VJAUZ4l/p0T3LZjE1Kq nbQJ+pgb+WAmBtdrxrtky61E9HD8dO70x37+ejhunpF9OuSU5MnOPmMx6ranvahUsOsCAwEA AaOCAYkwggGFMAsGA1UdDwQEAwIFIDAbBg0rBgEEAbMlCwMBAQEBBAoWCGZpb3JhbWUxMBsG DSsGAQQBsyULAwEBAQIEChIIMDAxMDQyNjEwWAYJYIZIAYb6ax4BBEsMSVRoZSBwcml2YXRl IGtleSBjb3JyZXNwb25kaW5nIHRvIHRoaXMgY2VydGlmaWNhdGUgbWF5IGhhdmUgYmVlbiBl eHBvcnRlZC4wKAYDVR0RBCEwH4EdTWF0dGhldy5GaW9yYXZhbnRlQGpodWFwbC5lZHUwUgYD VR0fBEswSTBHoEWgQ6RBMD8xCzAJBgNVBAYTAlVTMQ8wDQYDVQQKEwZKSFVBUEwxDzANBgNV BAsTBkJJU0RDQTEOMAwGA1UEAxMFQ1JMNDkwHwYDVR0jBBgwFoAUCDUpmxH52EU2CyWmF2EJ MB1yqeswHQYDVR0OBBYEFO3ziReJlElP3ilaLQ5gwsg0RlgoMAkGA1UdEwQCMAAwGQYJKoZI hvZ9B0EABAwwChsEVjcuMQMCBLAwDQYJKoZIhvcNAQEFBQADgYEAMOY3Zf6gx3gv/fDd11cz h2Daj+8NExx/2Le3c88gfDVhPVgVX5S52EjeFbK5yVP0Xlm82vRADO47dTA2PKbpp50rJcAZ rl5bg5tQ/WbLAaRITCtOJWVVKXD9V7X2o3Z/IM2op3hb4mmDXSDS+Hzn0Jd2mAXl4iHPfI0p XlXqA9QwggPGMIIDL6ADAgECAgQ/8cn9MA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNVBAYTAlVT MQ8wDQYDVQQKEwZKSFVBUEwxDzANBgNVBAsTBkJJU0RDQTAeFw0xMDA2MTExODIyMDZaFw0x MzA2MTExODUyMDZaMGYxCzAJBgNVBAYTAlVTMQ8wDQYDVQQKEwZKSFVBUEwxDzANBgNVBAsT BlBlb3BsZTE1MBYGA1UECxMPVlBOR3JvdXAtQklTRENBMBsGA1UEAxMUTWF0dGhldyBFIEZp b3JhdmFudGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ6W8FUj+qNTW+ZXFu3Xd8k6 PYgSXYu6s+JwDTjBTyuyTsuZ6SjdYoqLrJdvFP7HFCREueYD8AFmCSt7lckALAOGnYAyouQ6 A9VBw0BMKW2O4hyyXqtDT6+AamDapwhT2xOhwvM0ia6+Kip/oFVEE9/UiBanYiDycGS/BWE0 UP87AgMBAAGjggG2MIIBsjALBgNVHQ8EBAMCB4AwKwYDVR0QBCQwIoAPMjAxMDA2MTExODIy MDZagQ8yMDEyMDcxNzIyNTIwNlowGwYNKwYBBAGzJQsDAQEBAQQKFghmaW9yYW1lMTAbBg0r BgEEAbMlCwMBAQECBAoSCDAwMTA0MjYxMFgGCWCGSAGG+mseAQRLDElUaGUgcHJpdmF0ZSBr ZXkgY29ycmVzcG9uZGluZyB0byB0aGlzIGNlcnRpZmljYXRlIG1heSBoYXZlIGJlZW4gZXhw b3J0ZWQuMCgGA1UdEQQhMB+BHU1hdHRoZXcuRmlvcmF2YW50ZUBqaHVhcGwuZWR1MFIGA1Ud HwRLMEkwR6BFoEOkQTA/MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGSkhVQVBMMQ8wDQYDVQQL EwZCSVNEQ0ExDjAMBgNVBAMTBUNSTDU2MB8GA1UdIwQYMBaAFAg1KZsR+dhFNgslphdhCTAd cqnrMB0GA1UdDgQWBBTui2MYOq/cB2fs3ULQR59XWf2EzTAJBgNVHRMEAjAAMBkGCSqGSIb2 fQdBAAQMMAobBFY3LjEDAgSwMA0GCSqGSIb3DQEBBQUAA4GBACTvR0IeGDQoVS87maiuQESQ EQ/CaLoxmX3aO+arr4No1xUHtrBI7y58SWYJv6b/H3WWpKuPAlsI2ByrryKe7A40xLEH6Psu 0qTfzdjbyVlOUqnytVYGLTS0UaBiVAeUNWmfg4PeYN5Kqcn6VDCEiS/CClS7SVXzeH4IBVVG GfcMMYICMTCCAi0CAQEwNzAvMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGSkhVQVBMMQ8wDQYD VQQLEwZCSVNEQ0ECBD/xyf0wCQYFKw4DAhoFAKCCAVAwGAYJKoZIhvcNAQkDMQsGCSqGSIb3 DQEHATAcBgkqhkiG9w0BCQUxDxcNMTAwODI1MTUwNTIzWjAjBgkqhkiG9w0BCQQxFgQUpBDF v+hnU3zxfNoBpfIAdXNX3lswRgYJKwYBBAGCNxAEMTkwNzAvMQswCQYDVQQGEwJVUzEPMA0G A1UEChMGSkhVQVBMMQ8wDQYDVQQLEwZCSVNEQ0ECBD/xkcEwSAYLKoZIhvcNAQkQAgsxOaA3 MC8xCzAJBgNVBAYTAlVTMQ8wDQYDVQQKEwZKSFVBUEwxDzANBgNVBAsTBkJJU0RDQQIEP/GR wTBfBgkqhkiG9w0BCQ8xUjBQMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0D AgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZIhvcN AQEBBQAEgYBF1UzDelOK6cUqWL+9+k7nWjL6AICiDJ4bBx37AyAOCeNulBwjX3ou2CoSIjUy 4gUIuGfbG0GgN9ymYF1VIj0laXWeKN5WQiIc5NwetR+V4jkRDTmxVGuAxlXnfIxp5HbfK7kF /9LhY7uqJpGHjn+a/PTNiUDdi1bRT5/Skv5aOgAAAAAAAA== --------------ms070301090804070908050306-- --===============0493889955== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --===============0493889955==--