TPM_RESULT envelope_encrypt(const buffer_t *inbuf, CRYPTO_INFO *asymkey, buffer_t *sealed_data) { TPM_RESULT status = TPM_SUCCESS; symkey_t symkey; buffer_t data_cipher = NULL_BUF, symkey_cipher = NULL_BUF; UINT32 i; struct pack_constbuf_t symkey_cipher32, data_cipher32; vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Input[%d]: 0x", buffer_len(inbuf)); for (i=0; i< buffer_len(inbuf); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); // Generate a sym key and encrypt state with it TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) ); TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, &data_cipher) ); // Encrypt symmetric key TPMTRYRETURN( VTSP_Bind( asymkey, &symkey.key, &symkey_cipher) ); // Create output blob: symkey_size + symkey_cipher + state_cipher_size + state_cipher symkey_cipher32.size = buffer_len(&symkey_cipher); symkey_cipher32.data = symkey_cipher.bytes; data_cipher32.size = buffer_len(&data_cipher); data_cipher32.data = data_cipher.bytes; TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) + symkey_cipher32.size + data_cipher32.size, NULL)); BSG_PackList(sealed_data->bytes, 2, BSG_TPM_SIZE32_DATA, &symkey_cipher32, BSG_TPM_SIZE32_DATA, &data_cipher32); vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher)); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Output[%d]: 0x", buffer_len(sealed_data)); for (i=0; i< buffer_len(sealed_data); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_data->bytes[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); goto egress; abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope encrypt\n."); egress: buffer_free ( &data_cipher); buffer_free ( &symkey_cipher); Crypto_symcrypto_freekey (&symkey); return status; }
static int load_root_pre(struct disk_root_sector *root, struct mem_tpm_mgr *dst) { int rc; aes_setup(&dst->tm_key_e, &dst->tm_key); rc = disk_read_crypt_sector(root, sizeof(*root), root_loc(dst), dst); if (rc) { vtpmloginfo(VTPM_LOG_VTPM, "root cmac verify failed in slot %d\n", dst->active_root); return 2; } dst->root_seals_valid = 1 + dst->active_root; dst->sequence = be64_native(root->v.sequence); return 0; }
TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, const buffer_t *inbuf, buffer_t *outbuf) { TPM_RESULT status = TPM_SUCCESS; int fh; long bytes_written; buffer_t sealed_NVM = NULL_BUF; vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(inbuf)); TPMTRYRETURN( envelope_encrypt(inbuf, &vtpm_globals->storageKey, &sealed_NVM) ); // Write sealed blob off disk from NVMLocation // TODO: How to properly return from these. Do we care if we return failure // after writing the file? We can't get the old one back. // TODO: Backup old file and try and recover that way. fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); if ( (bytes_written = write(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM) ) != (long) buffer_len(&sealed_NVM))) { vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_NVM)); status = TPM_IOERROR; goto abort_egress; } close(fh); Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &myDMI->NVM_measurement); goto egress; abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n."); egress: buffer_free(&sealed_NVM); return status; }
TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi, buffer_t *inbuf, buffer_t *outbuf) { TPM_RESULT status = TPM_SUCCESS; TPM_COMMAND_CODE *ord; ord = (TPM_COMMAND_CODE *) (inbuf->bytes + sizeof(TPM_TAG) + sizeof(UINT32)); switch (*ord) { // Forbidden for DMI use case TPM_ORD_TakeOwnership: case TPM_ORD_ChangeAuthOwner: case TPM_ORD_DirWriteAuth: case TPM_ORD_DirRead: case TPM_ORD_AuthorizeMigrationKey: case TPM_ORD_CreateMaintenanceArchive: case TPM_ORD_LoadMaintenanceArchive: case TPM_ORD_KillMaintenanceFeature: case TPM_ORD_LoadManuMaintPub: case TPM_ORD_ReadManuMaintPub: case TPM_ORD_SelfTestFull: case TPM_ORD_SelfTestStartup: case TPM_ORD_CertifySelfTest: case TPM_ORD_ContinueSelfTest: case TPM_ORD_GetTestResult: case TPM_ORD_Reset: case TPM_ORD_OwnerClear: case TPM_ORD_DisableOwnerClear: case TPM_ORD_ForceClear: case TPM_ORD_DisableForceClear: case TPM_ORD_GetCapabilityOwner: case TPM_ORD_OwnerSetDisable: case TPM_ORD_PhysicalEnable: case TPM_ORD_PhysicalDisable: case TPM_ORD_SetOwnerInstall: case TPM_ORD_PhysicalSetDeactivated: case TPM_ORD_SetTempDeactivated: case TPM_ORD_CreateEndorsementKeyPair: case TPM_ORD_GetAuditEvent: case TPM_ORD_GetAuditEventSigned: case TPM_ORD_GetOrdinalAuditStatus: case TPM_ORD_SetOrdinalAuditStatus: case TPM_ORD_SetRedirection: case TPM_ORD_FieldUpgrade: case TSC_ORD_PhysicalPresence: status = TPM_DISABLED_CMD; goto abort_egress; break; } // End ORD Switch // Call TCS with command TPMTRY(TPM_IOERROR, VTSP_RawTransmit( dmi->TCSContext,inbuf, outbuf) ); goto egress; abort_egress: vtpmloginfo(VTPM_LOG_VTPM, "TPM Command Failed in tpmpassthrough.\n"); egress: return status; }
TPM_RESULT vtpm_manager_command(TPM_COMMAND_CODE ord, buffer_t *command_param_buf, TPM_RESULT *cmd_status, /* out */ buffer_t *result_param_buf) { TPM_RESULT status = TPM_FAIL; int size_read, size_write, i; BYTE *adj_command, response_header[VTPM_COMMAND_HEADER_SIZE_SRV]; UINT32 dmi_id=0, adj_command_size, out_param_size, adj_param_size; TPM_TAG tag=VTPM_TAG_REQ; if ( (!command_param_buf) || (!result_param_buf) || (!cmd_status) ) { status = TPM_BAD_PARAMETER; goto abort_egress; } adj_command_size = VTPM_COMMAND_HEADER_SIZE_SRV + buffer_len(command_param_buf); adj_command = (BYTE *) malloc( adj_command_size ); if (!adj_command) { status = TPM_RESOURCES; goto abort_egress; } out_param_size = VTPM_COMMAND_HEADER_SIZE + buffer_len(command_param_buf); BSG_PackList(adj_command, 4, BSG_TYPE_UINT32, &dmi_id, BSG_TPM_TAG, &tag, BSG_TYPE_UINT32, &out_param_size, BSG_TPM_COMMAND_CODE, &ord ); memcpy(adj_command + VTPM_COMMAND_HEADER_SIZE_SRV, command_param_buf->bytes, buffer_len(command_param_buf)); size_write = vtpm_ipc_write(&tx_ipc_h, NULL, adj_command, adj_command_size); if (size_write > 0) { vtpmloginfo(VTPM_LOG_VTPM_DEEP, "SENT (MGR): 0x"); for (i=0; i< adj_command_size; i++) { vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", adj_command[i]); } vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error writing VTPM Manager console.\n"); status = TPM_IOERROR; goto abort_egress; } if (size_write != (int) adj_command_size ) vtpmlogerror(VTPM_LOG_VTPM, "Could not write entire command to mgr (%d/%d)\n", size_write, adj_command_size); // Read header for response to manager command size_read = vtpm_ipc_read(&rx_ipc_h, NULL, response_header, VTPM_COMMAND_HEADER_SIZE_SRV); if (size_read > 0) { vtpmloginfo(VTPM_LOG_VTPM_DEEP, "RECV (MGR): 0x"); for (i=0; i<size_read; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", response_header[i]); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error reading from vtpm manager.\n"); status = TPM_IOERROR; goto abort_egress; } if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) { vtpmlogerror(VTPM_LOG_VTPM, "Command from vtpm_manager shorter than std header.\n"); status = TPM_IOERROR; goto abort_egress; } // Unpack response from DMI for TPM command BSG_UnpackList(response_header, 4, BSG_TYPE_UINT32, &dmi_id, BSG_TPM_TAG, &tag, BSG_TYPE_UINT32, &out_param_size, BSG_TPM_COMMAND_CODE, cmd_status ); // If response has parameters, read them. // Note that out_param_size is in the client's context adj_param_size = out_param_size - VTPM_COMMAND_HEADER_SIZE; if (adj_param_size > 0) { TPMTRYRETURN( buffer_init( result_param_buf, adj_param_size, NULL) ); size_read = vtpm_ipc_read(&rx_ipc_h, NULL, result_param_buf->bytes, adj_param_size); if (size_read > 0) { for (i=0; i< size_read; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", result_param_buf->bytes[i]); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error reading from vtpm manager.\n"); goto abort_egress; } vtpmloginfomore(VTPM_LOG_VTPM, "\n"); if (size_read < (int)adj_param_size) { vtpmloginfomore(VTPM_LOG_VTPM, "\n"); vtpmlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than header indicates(%d).\n", size_read, adj_param_size); status = TPM_IOERROR; goto abort_egress; } } else { vtpmloginfomore(VTPM_LOG_VTPM, "\n"); } status=TPM_SUCCESS; goto egress; abort_egress: egress: return status; }
TPM_RESULT VTPM_LoadManagerData(void) { TPM_RESULT status=TPM_SUCCESS; int fh, stat_ret, dmis=0; long fh_size = 0, step_size; BYTE *flat_table=NULL; buffer_t unsealed_data, enc_table_abuf; struct pack_buf_t storage_key_pack, boot_key_pack; UINT32 *dmi_id_key, enc_size; BYTE vtpm_manager_gen; VTPM_DMI_RESOURCE *dmi_res; UINT32 dmi_id; BYTE dmi_type; struct stat file_stat; TPM_HANDLE boot_key_handle; TPM_AUTHDATA boot_usage_auth; memset(&boot_usage_auth, 0, sizeof(TPM_AUTHDATA)); fh = open(STATE_FILE, O_RDONLY ); stat_ret = fstat(fh, &file_stat); if (stat_ret == 0) fh_size = file_stat.st_size; else { status = TPM_IOERROR; goto abort_egress; } flat_table = (BYTE *) malloc(fh_size); if ((long) read(fh, flat_table, fh_size) != fh_size ) { status = TPM_IOERROR; goto abort_egress; } // Read Boot Key step_size = BSG_UnpackList( flat_table, 2, BSG_TPM_SIZE32_DATA, &boot_key_pack, BSG_TYPE_UINT32, &enc_size); 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_pack.size, boot_key_pack.data) ); //Load Boot Key TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle, TPM_SRK_KEYHANDLE, &vtpm_globals->bootKeyWrap, &SRK_AUTH, &boot_key_handle, &vtpm_globals->keyAuth, &vtpm_globals->bootKey, FALSE) ); TPMTRYRETURN( envelope_decrypt(&enc_table_abuf, vtpm_globals->manager_tcs_handle, boot_key_handle, (const TPM_AUTHDATA*) &boot_usage_auth, &unsealed_data) ); step_size += enc_size; if (*unsealed_data.bytes != VTPM_MANAGER_GEN) { // Once there is more than one gen, this will include some compatability stuff vtpmlogerror(VTPM_LOG_VTPM, "Warning: Manager Data file is gen %d, which this manager is gen %d.\n", vtpm_manager_gen, VTPM_MANAGER_GEN); } // Global Values needing to be saved BSG_UnpackList( unsealed_data.bytes, 4, BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) ); TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) ); // Per DMI values to be saved while ( step_size < fh_size ){ if (fh_size - step_size < (long) (sizeof(UINT32) + sizeof(BYTE) + 2*sizeof(TPM_DIGEST))) { vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of manager state.\n", fh_size-step_size); step_size = fh_size; } else { step_size += BSG_UnpackList(flat_table + step_size, 2, BSG_TYPE_UINT32, &dmi_id, BSG_TYPE_BYTE, &dmi_type); //TODO: Try and gracefully recover from problems. TPMTRYRETURN(init_dmi(dmi_id, dmi_type, &dmi_res) ); dmis++; step_size += BSG_UnpackList(flat_table + step_size, 2, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); } } vtpmloginfo(VTPM_LOG_VTPM, "Loaded saved state (dmis = %d).\n", dmis); goto egress; abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error = %s\n", tpm_get_error_name(status)); egress: free(flat_table); close(fh); // TODO: Could be nice and evict BootKey. (Need to add EvictKey to VTSP. return status; }
TPM_RESULT VTPM_SaveManagerData(void) { TPM_RESULT status=TPM_SUCCESS; int fh, dmis=-1; BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL; buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF; UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap); UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes}; BYTE vtpm_manager_gen = VTPM_MANAGER_GEN; struct hashtable_itr *dmi_itr; VTPM_DMI_RESOURCE *dmi_res; UINT32 boot_key_size = 0, flat_dmis_size = 0; // Initially fill these with buffer sizes for each data type. Later fill // in actual size, once flattened. boot_key_size = sizeof(UINT32) + // bootkeysize bootKeySize; // boot key TPMTRYRETURN(buffer_init(&clear_flat_global,sizeof(BYTE) + // manager version 3*sizeof(TPM_DIGEST) + // Auths sizeof(UINT32) +// storagekeysize storageKeySize, NULL) ); // storage key flat_boot_key = (BYTE *) malloc( boot_key_size ); flat_enc = (BYTE *) malloc( sizeof(UINT32) ); boot_key_size = BSG_PackList(flat_boot_key, 1, BSG_TPM_SIZE32_DATA, &boot_key_pack); BSG_PackList(clear_flat_global.bytes, 4, BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); TPMTRYRETURN(envelope_encrypt(&clear_flat_global, &vtpm_globals->bootKey, &enc_flat_global) ); BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc); // Per DMI values to be saved (if any exit) if (hashtable_count(vtpm_globals->dmi_map) > 1) { flat_dmis = (BYTE *) malloc( (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) (sizeof(UINT32) +sizeof(BYTE) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr); dmis++; // No need to save dmi0. if (dmi_res->dmi_id == 0) continue; flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); } while (hashtable_iterator_advance(dmi_itr)); } fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); if (fh == -1) { vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", STATE_FILE); status = TPM_IOERROR; goto abort_egress; } if ( ( write(fh, flat_boot_key, boot_key_size) != boot_key_size ) || ( write(fh, flat_enc, sizeof(UINT32)) != sizeof(UINT32) ) || ( write(fh, enc_flat_global.bytes, buffer_len(&enc_flat_global)) != buffer_len(&enc_flat_global) ) || ( write(fh, flat_dmis, flat_dmis_size) != flat_dmis_size ) ) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to completely write service data.\n"); status = TPM_IOERROR; goto abort_egress; } goto egress; abort_egress: egress: free(flat_boot_key); free(flat_enc); buffer_free(&enc_flat_global); free(flat_dmis); close(fh); vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Manager state (status = %d, dmis = %d)\n", (int) status, dmis); return status; }
/* Expected Params: inbuf = null, outbuf = sealed blob size, sealed blob.*/ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, const buffer_t *inbuf, buffer_t *outbuf) { TPM_RESULT status = TPM_SUCCESS; buffer_t sealed_NVM = NULL_BUF; long fh_size; int fh, stat_ret, i; struct stat file_stat; TPM_DIGEST sealedNVMHash; if (myDMI->NVMLocation == NULL) { vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name NULL.\n"); status = TPM_AUTHFAIL; goto abort_egress; } //Read sealed blob off disk from NVMLocation fh = open(myDMI->NVMLocation, O_RDONLY); stat_ret = fstat(fh, &file_stat); if (stat_ret == 0) fh_size = file_stat.st_size; else { status = TPM_IOERROR; goto abort_egress; } TPMTRYRETURN( buffer_init( &sealed_NVM, fh_size, NULL) ); if (read(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM)) != fh_size) { status = TPM_IOERROR; goto abort_egress; } close(fh); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%d],\n", buffer_len(&sealed_NVM)); Crypto_SHA1Full(sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &sealedNVMHash); // Verify measurement of sealed blob. if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) { vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadNVM NVM measurement check failed.\n"); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: "); for (i=0; i< sizeof(TPM_DIGEST); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&myDMI->NVM_measurement)[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: "); for (i=0; i< sizeof(TPM_DIGEST); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); status = TPM_AUTHFAIL; goto abort_egress; } TPMTRYRETURN( envelope_decrypt(&sealed_NVM, myDMI->TCSContext, vtpm_globals->storageKeyHandle, (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth, outbuf) ); goto egress; abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n."); egress: buffer_free( &sealed_NVM ); return status; }
TPM_RESULT envelope_decrypt(const buffer_t *cipher, TCS_CONTEXT_HANDLE TCSContext, TPM_HANDLE keyHandle, const TPM_AUTHDATA *key_usage_auth, buffer_t *unsealed_data) { TPM_RESULT status = TPM_SUCCESS; symkey_t symkey; buffer_t data_cipher = NULL_BUF, symkey_clear = NULL_BUF, symkey_cipher = NULL_BUF; struct pack_buf_t symkey_cipher32, data_cipher32; int i; memset(&symkey, 0, sizeof(symkey_t)); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%d]: 0x", buffer_len(cipher) ); for (i=0; i< buffer_len(cipher); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher->bytes[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); BSG_UnpackList(cipher->bytes, 2, BSG_TPM_SIZE32_DATA, &symkey_cipher32, BSG_TPM_SIZE32_DATA, &data_cipher32); TPMTRYRETURN( buffer_init_alias_convert (&symkey_cipher, symkey_cipher32.size, symkey_cipher32.data) ); TPMTRYRETURN( buffer_init_alias_convert (&data_cipher, data_cipher32.size, data_cipher32.data) ); // Decrypt Symmetric Key TPMTRYRETURN( VTSP_Unbind( TCSContext, keyHandle, &symkey_cipher, key_usage_auth, &symkey_clear, &(vtpm_globals->keyAuth) ) ); // create symmetric key using saved bits Crypto_symcrypto_initkey (&symkey, &symkey_clear); // Decrypt State TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) ); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x", buffer_len(unsealed_data)); for (i=0; i< buffer_len(unsealed_data); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", unsealed_data->bytes[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); goto egress; abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope decrypt data\n."); egress: buffer_free ( &data_cipher); buffer_free ( &symkey_clear); buffer_free ( &symkey_cipher); Crypto_symcrypto_freekey (&symkey); return status; }
TPM_RESULT vtpm_migratord_command(TPM_COMMAND_CODE ord, buffer_t *command_param_buf, TPM_RESULT *cmd_status, /* out */ buffer_t *result_param_buf) { TPM_RESULT status = TPM_FAIL; int size_read, size_write, i; BYTE *command, response_header[VTPM_COMMAND_HEADER_SIZE]; UINT32 dmi_id=0, command_size, out_param_size, adj_param_size; TPM_TAG tag=VTPM_MTAG_REQ; if ( (!command_param_buf) || (!result_param_buf) || (!cmd_status) ) { status = TPM_BAD_PARAMETER; goto abort_egress; } command_size = VTPM_COMMAND_HEADER_SIZE + buffer_len(command_param_buf); command = (BYTE *) malloc( command_size ); if (!command) { status = TPM_RESOURCES; goto abort_egress; } BSG_PackList(command, 3, BSG_TPM_TAG, &tag, BSG_TYPE_UINT32, &command_size, BSG_TPM_COMMAND_CODE, &ord ); memcpy(command + VTPM_COMMAND_HEADER_SIZE, command_param_buf->bytes, buffer_len(command_param_buf)); size_write = write(sock_desc, command, command_size); if (size_write > 0) { vtpmloginfo(VTPM_LOG_VTPM_DEEP, "SENT (MIGd): 0x"); for (i=0; i< command_size; i++) { vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", command[i]); } vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error writing to migration server via network.\n"); status = TPM_IOERROR; goto abort_egress; } if (size_write != (int) command_size ) vtpmlogerror(VTPM_LOG_VTPM, "Could not write entire command to migration server (%d/%d)\n", size_write, command_size); // Read header for response size_read = read(sock_desc, response_header, VTPM_COMMAND_HEADER_SIZE); if (size_read > 0) { vtpmloginfo(VTPM_LOG_VTPM_DEEP, "RECV (MIGd): 0x"); for (i=0; i<size_read; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", response_header[i]); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error reading from Migration Server.\n"); status = TPM_IOERROR; goto abort_egress; } if (size_read < (int) VTPM_COMMAND_HEADER_SIZE) { vtpmlogerror(VTPM_LOG_VTPM, "Command from migration server shorter than std header.\n"); status = TPM_IOERROR; goto abort_egress; } // Unpack response from DMI for TPM command BSG_UnpackList(response_header, 3, BSG_TPM_TAG, &tag, BSG_TYPE_UINT32, &out_param_size, BSG_TPM_COMMAND_CODE, cmd_status ); // If response has parameters, read them. adj_param_size = out_param_size - VTPM_COMMAND_HEADER_SIZE; if (adj_param_size > 0) { TPMTRYRETURN( buffer_init( result_param_buf, adj_param_size, NULL) ); size_read = read(sock_desc, result_param_buf->bytes, adj_param_size); if (size_read > 0) { for (i=0; i< size_read; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", result_param_buf->bytes[i]); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error reading from migration server.\n"); goto abort_egress; } vtpmloginfomore(VTPM_LOG_VTPM, "\n"); if (size_read < (int)adj_param_size) { vtpmloginfomore(VTPM_LOG_VTPM, "\n"); vtpmlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than header indicates(%d).\n", size_read, adj_param_size); status = TPM_IOERROR; goto abort_egress; } } else { vtpmloginfomore(VTPM_LOG_VTPM, "\n"); } status=TPM_SUCCESS; goto egress; abort_egress: egress: return status; }
int main() { /* network variables */ int sock_descr, client_sock=-1, len; struct sockaddr_in addr; struct sockaddr_in client_addr; unsigned int client_length; int bytes; /* variables for processing of command */ TPM_RESULT status = TPM_FAIL; BYTE cmd_header[VTPM_COMMAND_HEADER_SIZE]; TPM_TAG tag; TPM_COMMAND_CODE ord; UINT32 in_param_size, adj_param_size; int i, size_read, size_write; buffer_t in_param_buf=NULL_BUF, result_buf=NULL_BUF; /* setup socket */ sock_descr = socket(AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(VTPM_MIG_PORT); if (bind(sock_descr, (struct sockaddr *)&addr, sizeof(addr)) == -1 ) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to bind to port %d.\n", VTPM_MIG_PORT); return 1; } listen(sock_descr, 10); for(;;) { // ============ clear client info and wait for connection ========== memset(&client_addr, 0, sizeof(client_addr)); client_length = sizeof(client_addr); vtpmloginfo(VTPM_LOG_VTPM, "Waiting for incoming migrations...\n"); client_sock=accept(sock_descr, &client_addr, &client_length); if (client_sock == -1) { vtpmlogerror(VTPM_LOG_VTPM, "Incoming connectionn failed.\n"); goto abort_command; } else { vtpmloginfo(VTPM_LOG_VTPM, "Incoming connection accepted.\n"); } // =================== Read incoming command ====================== size_read = read( client_sock, cmd_header, VTPM_COMMAND_HEADER_SIZE); if (size_read > 0) { vtpmloginfo(VTPM_LOG_VTPM_DEEP, "RECV: 0x"); for (i=0; i<size_read; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error reading from socket.\n"); build_error_msg(&result_buf, TPM_IOERROR); goto abort_command_with_error; } if (size_read < (int) VTPM_COMMAND_HEADER_SIZE) { vtpmlogerror(VTPM_LOG_VTPM, "Command from socket shorter than std header.\n"); build_error_msg(&result_buf, TPM_BAD_PARAMETER); goto abort_command_with_error; } // Unpack response from client BSG_UnpackList(cmd_header, 3, BSG_TPM_TAG, &tag, BSG_TYPE_UINT32, &in_param_size, BSG_TPM_COMMAND_CODE, &ord ); // If response has parameters, read them. // Note that out_param_size is in the client's context adj_param_size = in_param_size - VTPM_COMMAND_HEADER_SIZE; if (adj_param_size > 0) { buffer_init( &in_param_buf, adj_param_size, NULL); size_read = read(client_sock, in_param_buf.bytes, adj_param_size); if (size_read > 0) { for (i=0; i< size_read; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param_buf.bytes[i]); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error reading from socket.\n"); build_error_msg(&result_buf, TPM_IOERROR); goto abort_command_with_error; } vtpmloginfomore(VTPM_LOG_VTPM, "\n"); if (size_read < (int)adj_param_size) { vtpmloginfomore(VTPM_LOG_VTPM, "\n"); vtpmlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than header indicates(%d).\n", size_read, adj_param_size); build_error_msg(&result_buf, TPM_BAD_PARAMETER); goto abort_command_with_error; } } else { vtpmloginfomore(VTPM_LOG_VTPM, "\n"); } /* Handle Command */ switch (ord) { case VTPM_MORD_MIG_STEP2: handle_vtpm_mig_step2(&in_param_buf, &result_buf); break; case VTPM_MORD_MIG_STEP3: handle_vtpm_mig_step3(&in_param_buf, &result_buf); break; default: build_error_msg(&result_buf, TPM_BAD_PARAMETER); goto abort_command_with_error; } abort_command_with_error: /* Write Response */ size_write = write(client_sock, result_buf.bytes, buffer_len(&result_buf)); if (size_write > 0) { vtpmloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x"); for (i=0; i< buffer_len(&result_buf); i++) { vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", result_buf.bytes[i]); } vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); } else { vtpmlogerror(VTPM_LOG_VTPM, "Error writing response to client.\n"); goto abort_command; } if (size_write != (int) buffer_len(&result_buf) ) vtpmlogerror(VTPM_LOG_VTPM, "Could not send entire response to client(%d/%d)\n", size_write, buffer_len(&result_buf)); abort_command: close(client_sock); buffer_free(&in_param_buf); buffer_free(&result_buf); } // For (;;) return 0; }