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