1*5c591343SA. Cody Schuffelen // VCOM-TPM.cpp : Defines the entry point for the console application. 2*5c591343SA. Cody Schuffelen // 3*5c591343SA. Cody Schuffelen 4*5c591343SA. Cody Schuffelen #include "stdafx.h" 5*5c591343SA. Cody Schuffelen 6*5c591343SA. Cody Schuffelen HANDLE hVCom = INVALID_HANDLE_VALUE; 7*5c591343SA. Cody Schuffelen LPCTSTR vcomPort = TEXT("COM6"); 8*5c591343SA. Cody Schuffelen unsigned int vcomTimeout = 5 * 60 * 1000; 9*5c591343SA. Cody Schuffelen 10*5c591343SA. Cody Schuffelen #ifndef TPM_RC_SUCCESS 11*5c591343SA. Cody Schuffelen #define TPM_RC_SUCCESS 0 12*5c591343SA. Cody Schuffelen #endif 13*5c591343SA. Cody Schuffelen 14*5c591343SA. Cody Schuffelen unsigned int GetTimeStamp(void) 15*5c591343SA. Cody Schuffelen { 16*5c591343SA. Cody Schuffelen FILETIME now = { 0 }; 17*5c591343SA. Cody Schuffelen LARGE_INTEGER convert = { 0 }; 18*5c591343SA. Cody Schuffelen 19*5c591343SA. Cody Schuffelen // Get the current timestamp 20*5c591343SA. Cody Schuffelen GetSystemTimeAsFileTime(&now); 21*5c591343SA. Cody Schuffelen convert.LowPart = now.dwLowDateTime; 22*5c591343SA. Cody Schuffelen convert.HighPart = now.dwHighDateTime; 23*5c591343SA. Cody Schuffelen convert.QuadPart = (convert.QuadPart - (UINT64)(11644473600000 * 10000)) / 10000000; 24*5c591343SA. Cody Schuffelen return convert.LowPart; 25*5c591343SA. Cody Schuffelen } 26*5c591343SA. Cody Schuffelen 27*5c591343SA. Cody Schuffelen unsigned int SetTpmResponseTimeout(unsigned int timeout) 28*5c591343SA. Cody Schuffelen { 29*5c591343SA. Cody Schuffelen COMMTIMEOUTS to = { 0 }; 30*5c591343SA. Cody Schuffelen to.ReadIntervalTimeout = 0; 31*5c591343SA. Cody Schuffelen to.ReadTotalTimeoutMultiplier = 0; 32*5c591343SA. Cody Schuffelen to.ReadTotalTimeoutConstant = timeout; 33*5c591343SA. Cody Schuffelen to.WriteTotalTimeoutMultiplier = 0; 34*5c591343SA. Cody Schuffelen to.WriteTotalTimeoutConstant = 0; 35*5c591343SA. Cody Schuffelen if (!SetCommTimeouts(hVCom, &to)) 36*5c591343SA. Cody Schuffelen { 37*5c591343SA. Cody Schuffelen return GetLastError(); 38*5c591343SA. Cody Schuffelen } 39*5c591343SA. Cody Schuffelen else 40*5c591343SA. Cody Schuffelen { 41*5c591343SA. Cody Schuffelen return 0; 42*5c591343SA. Cody Schuffelen } 43*5c591343SA. Cody Schuffelen } 44*5c591343SA. Cody Schuffelen 45*5c591343SA. Cody Schuffelen unsigned int SendTpmSignal(signalCode_t signal, 46*5c591343SA. Cody Schuffelen unsigned int timeout, 47*5c591343SA. Cody Schuffelen BYTE* dataIn, 48*5c591343SA. Cody Schuffelen unsigned int dataInSize, 49*5c591343SA. Cody Schuffelen BYTE* dataOut, 50*5c591343SA. Cody Schuffelen unsigned int dataOutSize, 51*5c591343SA. Cody Schuffelen unsigned int* dataOutUsed 52*5c591343SA. Cody Schuffelen ) 53*5c591343SA. Cody Schuffelen { 54*5c591343SA. Cody Schuffelen unsigned int result = 0; 55*5c591343SA. Cody Schuffelen DWORD written = 0; 56*5c591343SA. Cody Schuffelen unsigned int signalBufSize = sizeof(signalWrapper_t) + dataInSize; 57*5c591343SA. Cody Schuffelen BYTE* signalBuf = (BYTE*)malloc(signalBufSize); 58*5c591343SA. Cody Schuffelen pSignalWrapper_t sig = (pSignalWrapper_t)signalBuf; 59*5c591343SA. Cody Schuffelen sig->s.magic = SIGNALMAGIC; 60*5c591343SA. Cody Schuffelen sig->s.signal = signal; 61*5c591343SA. Cody Schuffelen sig->s.dataSize = dataInSize; 62*5c591343SA. Cody Schuffelen if (dataInSize > 0) 63*5c591343SA. Cody Schuffelen { 64*5c591343SA. Cody Schuffelen memcpy(&signalBuf[sizeof(signalWrapper_t)], dataIn, dataInSize); 65*5c591343SA. Cody Schuffelen } 66*5c591343SA. Cody Schuffelen 67*5c591343SA. Cody Schuffelen PurgeComm(hVCom, PURGE_RXCLEAR | PURGE_TXCLEAR); 68*5c591343SA. Cody Schuffelen if (!WriteFile(hVCom, signalBuf, signalBufSize, &written, NULL)) 69*5c591343SA. Cody Schuffelen { 70*5c591343SA. Cody Schuffelen result = GetLastError(); 71*5c591343SA. Cody Schuffelen goto Cleanup; 72*5c591343SA. Cody Schuffelen } 73*5c591343SA. Cody Schuffelen 74*5c591343SA. Cody Schuffelen if (signal == SignalCommand) 75*5c591343SA. Cody Schuffelen { 76*5c591343SA. Cody Schuffelen DWORD read = 0; 77*5c591343SA. Cody Schuffelen unsigned int rspSize = 0; 78*5c591343SA. Cody Schuffelen 79*5c591343SA. Cody Schuffelen SetTpmResponseTimeout(timeout - 1000); 80*5c591343SA. Cody Schuffelen if (!ReadFile(hVCom, &rspSize, sizeof(rspSize), (LPDWORD)&read, NULL)) 81*5c591343SA. Cody Schuffelen { 82*5c591343SA. Cody Schuffelen result = GetLastError(); 83*5c591343SA. Cody Schuffelen goto Cleanup; 84*5c591343SA. Cody Schuffelen } 85*5c591343SA. Cody Schuffelen if (read == 0) 86*5c591343SA. Cody Schuffelen { 87*5c591343SA. Cody Schuffelen result = GetLastError(); 88*5c591343SA. Cody Schuffelen goto Cleanup; 89*5c591343SA. Cody Schuffelen } 90*5c591343SA. Cody Schuffelen 91*5c591343SA. Cody Schuffelen read = 0; 92*5c591343SA. Cody Schuffelen SetTpmResponseTimeout(1000); 93*5c591343SA. Cody Schuffelen if ((!ReadFile(hVCom, dataOut, min(rspSize, dataOutSize), (LPDWORD)&read, NULL)) || 94*5c591343SA. Cody Schuffelen (read != rspSize)) 95*5c591343SA. Cody Schuffelen { 96*5c591343SA. Cody Schuffelen result = GetLastError(); 97*5c591343SA. Cody Schuffelen goto Cleanup; 98*5c591343SA. Cody Schuffelen } 99*5c591343SA. Cody Schuffelen *dataOutUsed = read; 100*5c591343SA. Cody Schuffelen PurgeComm(hVCom, PURGE_RXCLEAR); 101*5c591343SA. Cody Schuffelen } 102*5c591343SA. Cody Schuffelen 103*5c591343SA. Cody Schuffelen Cleanup: 104*5c591343SA. Cody Schuffelen if (signalBuf) free(signalBuf); 105*5c591343SA. Cody Schuffelen return result; 106*5c591343SA. Cody Schuffelen } 107*5c591343SA. Cody Schuffelen 108*5c591343SA. Cody Schuffelen BYTE* GenerateTpmCommandPayload(unsigned int locality, 109*5c591343SA. Cody Schuffelen BYTE* cmd, 110*5c591343SA. Cody Schuffelen UINT32 cmdSize, 111*5c591343SA. Cody Schuffelen unsigned int* dataInSize 112*5c591343SA. Cody Schuffelen ) 113*5c591343SA. Cody Schuffelen { 114*5c591343SA. Cody Schuffelen pSignalPayload_t payload = NULL; 115*5c591343SA. Cody Schuffelen *dataInSize = sizeof(payload->SignalCommandPayload) - sizeof(unsigned char) + cmdSize; 116*5c591343SA. Cody Schuffelen BYTE* dataIn = (BYTE*)malloc(*dataInSize); 117*5c591343SA. Cody Schuffelen payload = (pSignalPayload_t)dataIn; 118*5c591343SA. Cody Schuffelen payload->SignalCommandPayload.locality = locality; 119*5c591343SA. Cody Schuffelen payload->SignalCommandPayload.cmdSize = cmdSize; 120*5c591343SA. Cody Schuffelen memcpy(payload->SignalCommandPayload.cmd, cmd, cmdSize); 121*5c591343SA. Cody Schuffelen return dataIn; 122*5c591343SA. Cody Schuffelen } 123*5c591343SA. Cody Schuffelen 124*5c591343SA. Cody Schuffelen unsigned int OpenTpmConnection(LPCTSTR comPort) 125*5c591343SA. Cody Schuffelen { 126*5c591343SA. Cody Schuffelen DCB dcb = { 0 }; 127*5c591343SA. Cody Schuffelen if (hVCom != INVALID_HANDLE_VALUE) 128*5c591343SA. Cody Schuffelen { 129*5c591343SA. Cody Schuffelen CloseHandle(hVCom); 130*5c591343SA. Cody Schuffelen hVCom = INVALID_HANDLE_VALUE; 131*5c591343SA. Cody Schuffelen } 132*5c591343SA. Cody Schuffelen dcb.DCBlength = sizeof(DCB); 133*5c591343SA. Cody Schuffelen dcb.BaudRate = CBR_115200; 134*5c591343SA. Cody Schuffelen dcb.fBinary = TRUE; 135*5c591343SA. Cody Schuffelen dcb.fParity = FALSE; 136*5c591343SA. Cody Schuffelen dcb.ByteSize = 8; 137*5c591343SA. Cody Schuffelen dcb.Parity = NOPARITY; 138*5c591343SA. Cody Schuffelen dcb.StopBits = ONESTOPBIT; 139*5c591343SA. Cody Schuffelen if (((hVCom = CreateFile(comPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) || 140*5c591343SA. Cody Schuffelen (!SetCommState(hVCom, &dcb))) 141*5c591343SA. Cody Schuffelen { 142*5c591343SA. Cody Schuffelen return GetLastError(); 143*5c591343SA. Cody Schuffelen } 144*5c591343SA. Cody Schuffelen PurgeComm(hVCom, PURGE_RXCLEAR); 145*5c591343SA. Cody Schuffelen unsigned int time = GetTimeStamp(); 146*5c591343SA. Cody Schuffelen SendTpmSignal(SignalSetClock, 500, (BYTE*)&time, sizeof(time), NULL, 0, NULL); 147*5c591343SA. Cody Schuffelen 148*5c591343SA. Cody Schuffelen return 0; 149*5c591343SA. Cody Schuffelen } 150*5c591343SA. Cody Schuffelen 151*5c591343SA. Cody Schuffelen UINT32 TPMVComSubmitCommand( 152*5c591343SA. Cody Schuffelen BOOL CloseContext, 153*5c591343SA. Cody Schuffelen BYTE* pbCommand, 154*5c591343SA. Cody Schuffelen UINT32 cbCommand, 155*5c591343SA. Cody Schuffelen BYTE* pbResponse, 156*5c591343SA. Cody Schuffelen UINT32 cbResponse, 157*5c591343SA. Cody Schuffelen UINT32* pcbResponse 158*5c591343SA. Cody Schuffelen ) 159*5c591343SA. Cody Schuffelen { 160*5c591343SA. Cody Schuffelen UINT32 result = TPM_RC_SUCCESS; 161*5c591343SA. Cody Schuffelen BYTE* dataIn = NULL; 162*5c591343SA. Cody Schuffelen unsigned int dataInSize = 0; 163*5c591343SA. Cody Schuffelen if (hVCom == INVALID_HANDLE_VALUE) 164*5c591343SA. Cody Schuffelen { 165*5c591343SA. Cody Schuffelen OpenTpmConnection(vcomPort); 166*5c591343SA. Cody Schuffelen } 167*5c591343SA. Cody Schuffelen 168*5c591343SA. Cody Schuffelen dataIn = GenerateTpmCommandPayload(0, pbCommand, cbCommand, &dataInSize); 169*5c591343SA. Cody Schuffelen result = SendTpmSignal(SignalCommand, vcomTimeout, dataIn, dataInSize, pbResponse, cbResponse, pcbResponse); 170*5c591343SA. Cody Schuffelen 171*5c591343SA. Cody Schuffelen if (CloseContext) 172*5c591343SA. Cody Schuffelen { 173*5c591343SA. Cody Schuffelen CloseHandle(hVCom); 174*5c591343SA. Cody Schuffelen hVCom = INVALID_HANDLE_VALUE; 175*5c591343SA. Cody Schuffelen } 176*5c591343SA. Cody Schuffelen 177*5c591343SA. Cody Schuffelen if (dataIn) free(dataIn); 178*5c591343SA. Cody Schuffelen return result; 179*5c591343SA. Cody Schuffelen } 180*5c591343SA. Cody Schuffelen 181*5c591343SA. Cody Schuffelen void TPMVComTeardown(void) 182*5c591343SA. Cody Schuffelen { 183*5c591343SA. Cody Schuffelen if (hVCom != INVALID_HANDLE_VALUE) 184*5c591343SA. Cody Schuffelen { 185*5c591343SA. Cody Schuffelen CloseHandle(hVCom); 186*5c591343SA. Cody Schuffelen hVCom = INVALID_HANDLE_VALUE; 187*5c591343SA. Cody Schuffelen } 188*5c591343SA. Cody Schuffelen } 189*5c591343SA. Cody Schuffelen 190*5c591343SA. Cody Schuffelen BOOL TPMStartup() 191*5c591343SA. Cody Schuffelen { 192*5c591343SA. Cody Schuffelen unsigned char startupClear[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; 193*5c591343SA. Cody Schuffelen unsigned char response[10]; 194*5c591343SA. Cody Schuffelen unsigned int responseSize; 195*5c591343SA. Cody Schuffelen 196*5c591343SA. Cody Schuffelen return ((TPMVComSubmitCommand(FALSE, startupClear, sizeof(startupClear), response, sizeof(response), &responseSize) == TPM_RC_SUCCESS) && 197*5c591343SA. Cody Schuffelen (responseSize == sizeof(response)) && 198*5c591343SA. Cody Schuffelen (*((unsigned int*)&response[sizeof(unsigned short) + sizeof(unsigned int)]) == 0)); 199*5c591343SA. Cody Schuffelen } 200*5c591343SA. Cody Schuffelen 201*5c591343SA. Cody Schuffelen UINT32 TPMShutdown() 202*5c591343SA. Cody Schuffelen { 203*5c591343SA. Cody Schuffelen unsigned char shutdownClear[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00 }; 204*5c591343SA. Cody Schuffelen unsigned char response[10]; 205*5c591343SA. Cody Schuffelen unsigned int responseSize; 206*5c591343SA. Cody Schuffelen 207*5c591343SA. Cody Schuffelen return ((TPMVComSubmitCommand(TRUE, shutdownClear, sizeof(shutdownClear), response, sizeof(response), &responseSize) == TPM_RC_SUCCESS) && 208*5c591343SA. Cody Schuffelen (responseSize == sizeof(response)) && 209*5c591343SA. Cody Schuffelen (*((unsigned int*)&response[sizeof(unsigned short) + sizeof(unsigned int)]) == 0)); 210*5c591343SA. Cody Schuffelen } 211*5c591343SA. Cody Schuffelen 212*5c591343SA. Cody Schuffelen int main() 213*5c591343SA. Cody Schuffelen { 214*5c591343SA. Cody Schuffelen if (!TPMStartup()) goto Cleanup; 215*5c591343SA. Cody Schuffelen 216*5c591343SA. Cody Schuffelen if (SendTpmSignal(SignalCancelOn, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; 217*5c591343SA. Cody Schuffelen if (SendTpmSignal(SignalCancelOff, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; 218*5c591343SA. Cody Schuffelen 219*5c591343SA. Cody Schuffelen // if (SendTpmSignal(SignalShutdown, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; 220*5c591343SA. Cody Schuffelen // if (SendTpmSignal(SignalReset, 1000, NULL, 0, NULL, 0, NULL)) goto Cleanup; 221*5c591343SA. Cody Schuffelen 222*5c591343SA. Cody Schuffelen Cleanup: 223*5c591343SA. Cody Schuffelen TPMShutdown(); 224*5c591343SA. Cody Schuffelen return 0; 225*5c591343SA. Cody Schuffelen } 226*5c591343SA. Cody Schuffelen 227*5c591343SA. Cody Schuffelen