// VCOM-TPM.cpp : Defines the entry point for the console application. // #include "stdafx.h" HANDLE hVCom = INVALID_HANDLE_VALUE; LPCTSTR vcomPort = TEXT("COM6"); unsigned int vcomTimeout = 5 * 60 * 1000; #ifndef TPM_RC_SUCCESS #define TPM_RC_SUCCESS 0 #endif unsigned int GetTimeStamp(void) { FILETIME now = { 0 }; LARGE_INTEGER convert = { 0 }; // Get the current timestamp GetSystemTimeAsFileTime(&now); convert.LowPart = now.dwLowDateTime; convert.HighPart = now.dwHighDateTime; convert.QuadPart = (convert.QuadPart - (UINT64)(11644473600000 * 10000)) / 10000000; return convert.LowPart; } unsigned int SetTpmResponseTimeout(unsigned int timeout) { COMMTIMEOUTS to = { 0 }; to.ReadIntervalTimeout = 0; to.ReadTotalTimeoutMultiplier = 0; to.ReadTotalTimeoutConstant = timeout; to.WriteTotalTimeoutMultiplier = 0; to.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(hVCom, &to)) { return GetLastError(); } else { return 0; } } unsigned int SendTpmSignal(signalCode_t signal, unsigned int timeout, BYTE* dataIn, unsigned int dataInSize, BYTE* dataOut, unsigned int dataOutSize, unsigned int* dataOutUsed ) { unsigned int result = 0; DWORD written = 0; unsigned int signalBufSize = sizeof(signalWrapper_t) + dataInSize; BYTE* signalBuf = (BYTE*)malloc(signalBufSize); pSignalWrapper_t sig = (pSignalWrapper_t)signalBuf; sig->s.magic = SIGNALMAGIC; sig->s.signal = signal; sig->s.dataSize = dataInSize; if (dataInSize > 0) { memcpy(&signalBuf[sizeof(signalWrapper_t)], dataIn, dataInSize); } PurgeComm(hVCom, PURGE_RXCLEAR | PURGE_TXCLEAR); if (!WriteFile(hVCom, signalBuf, signalBufSize, &written, NULL)) { result = GetLastError(); goto Cleanup; } if (signal == SignalCommand) { DWORD read = 0; unsigned int rspSize = 0; SetTpmResponseTimeout(timeout - 1000); if (!ReadFile(hVCom, &rspSize, sizeof(rspSize), (LPDWORD)&read, NULL)) { result = GetLastError(); goto Cleanup; } if (read == 0) { result = GetLastError(); goto Cleanup; } read = 0; SetTpmResponseTimeout(1000); if ((!ReadFile(hVCom, dataOut, min(rspSize, dataOutSize), (LPDWORD)&read, NULL)) || (read != rspSize)) { result = GetLastError(); goto Cleanup; } *dataOutUsed = read; PurgeComm(hVCom, PURGE_RXCLEAR); } Cleanup: if (signalBuf) free(signalBuf); return result; } BYTE* GenerateTpmCommandPayload(unsigned int locality, BYTE* cmd, UINT32 cmdSize, unsigned int* dataInSize ) { pSignalPayload_t payload = NULL; *dataInSize = sizeof(payload->SignalCommandPayload) - sizeof(unsigned char) + cmdSize; BYTE* dataIn = (BYTE*)malloc(*dataInSize); payload = (pSignalPayload_t)dataIn; payload->SignalCommandPayload.locality = locality; payload->SignalCommandPayload.cmdSize = cmdSize; memcpy(payload->SignalCommandPayload.cmd, cmd, cmdSize); return dataIn; } unsigned int OpenTpmConnection(LPCTSTR comPort) { DCB dcb = { 0 }; if (hVCom != INVALID_HANDLE_VALUE) { CloseHandle(hVCom); hVCom = INVALID_HANDLE_VALUE; } dcb.DCBlength = sizeof(DCB); dcb.BaudRate = CBR_115200; dcb.fBinary = TRUE; dcb.fParity = FALSE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (((hVCom = CreateFile(comPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) || (!SetCommState(hVCom, &dcb))) { return GetLastError(); } PurgeComm(hVCom, PURGE_RXCLEAR); unsigned int time = GetTimeStamp(); SendTpmSignal(SignalSetClock, 500, (BYTE*)&time, sizeof(time), NULL, 0, NULL); return 0; } UINT32 TPMVComSubmitCommand( BOOL CloseContext, BYTE* pbCommand, UINT32 cbCommand, BYTE* pbResponse, UINT32 cbResponse, UINT32* pcbResponse ) { UINT32 result = TPM_RC_SUCCESS; BYTE* dataIn = NULL; unsigned int dataInSize = 0; if (hVCom == INVALID_HANDLE_VALUE) { OpenTpmConnection(vcomPort); } dataIn = GenerateTpmCommandPayload(0, pbCommand, cbCommand, &dataInSize); result = SendTpmSignal(SignalCommand, vcomTimeout, dataIn, dataInSize, pbResponse, cbResponse, pcbResponse); if (CloseContext) { CloseHandle(hVCom); hVCom = INVALID_HANDLE_VALUE; } if (dataIn) free(dataIn); return result; } void TPMVComTeardown(void) { if (hVCom != INVALID_HANDLE_VALUE) { CloseHandle(hVCom); hVCom = INVALID_HANDLE_VALUE; } } BOOL TPMStartup() { unsigned char startupClear[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; unsigned char response[10]; unsigned int responseSize; return ((TPMVComSubmitCommand(FALSE, startupClear, sizeof(startupClear), response, sizeof(response), &responseSize) == TPM_RC_SUCCESS) && (responseSize == sizeof(response)) && (*((unsigned int*)&response[sizeof(unsigned short) + sizeof(unsigned int)]) == 0)); } UINT32 TPMShutdown() { unsigned char shutdownClear[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00 }; unsigned char response[10]; unsigned int responseSize; return ((TPMVComSubmitCommand(TRUE, shutdownClear, sizeof(shutdownClear), response, sizeof(response), &responseSize) == TPM_RC_SUCCESS) && (responseSize == sizeof(response)) && (*((unsigned int*)&response[sizeof(unsigned short) + sizeof(unsigned int)]) == 0)); } int main() { if (!TPMStartup()) goto Cleanup; if (SendTpmSignal(SignalCancelOn, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; if (SendTpmSignal(SignalCancelOff, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; // if (SendTpmSignal(SignalShutdown, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; // if (SendTpmSignal(SignalReset, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; Cleanup: TPMShutdown(); return 0; }