Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
yubihsm_winusb.c File Reference
#include <windows.h>
#include <winusb.h>
#include <string.h>
#include <setupapi.h>
#include "yubihsm.h"
#include "internal.h"
#include "yubihsm_usb.h"
#include "debug_lib.h"
Include dependency graph for yubihsm_winusb.c:

Go to the source code of this file.

Classes

struct  state
 

Macros

#define PIPE_OUT   0x01
 
#define PIPE_IN   0x81
 

Functions

void usb_set_serial (yh_backend *state, unsigned long serial)
 
bool usb_open_device (yh_backend *backend)
 
yh_backendbackend_create (void)
 
void usb_close (yh_backend *state)
 
void usb_destroy (yh_backend **state)
 
int usb_write (yh_backend *state, unsigned char *buf, long unsigned len)
 
int usb_read (yh_backend *state, unsigned char *buf, long unsigned *len)
 

Macro Definition Documentation

◆ PIPE_IN

#define PIPE_IN   0x81

Definition at line 40 of file yubihsm_winusb.c.

◆ PIPE_OUT

#define PIPE_OUT   0x01

Definition at line 39 of file yubihsm_winusb.c.

Function Documentation

◆ backend_create()

yh_backend * backend_create ( void )

Definition at line 254 of file yubihsm_winusb.c.

254 {
255 yh_backend *backend = calloc(1, sizeof(yh_backend));
256 return backend;
257}

◆ usb_close()

void usb_close ( yh_backend * state)

Definition at line 259 of file yubihsm_winusb.c.

259 {
260 if (state && state->hDevice != INVALID_HANDLE_VALUE) {
261 CloseHandle(state->hDevice);
262 state->hDevice = INVALID_HANDLE_VALUE;
263 }
264 if (state && state->hWinUSB != INVALID_HANDLE_VALUE) {
265 WinUsb_Free(state->hWinUSB);
266 state->hWinUSB = INVALID_HANDLE_VALUE;
267 }
268}
WINUSB_INTERFACE_HANDLE hWinUSB
HANDLE hDevice

◆ usb_destroy()

void usb_destroy ( yh_backend ** state)

Definition at line 270 of file yubihsm_winusb.c.

270 {
271 if (state && *state) {
272 free(*state);
273 *state = NULL;
274 }
275}

◆ usb_open_device()

bool usb_open_device ( yh_backend * backend)

Definition at line 46 of file yubihsm_winusb.c.

46 {
47 BOOL bResult = TRUE;
48 HDEVINFO hDeviceInfo;
49 SP_DEVINFO_DATA DeviceInfoData;
50 SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
51 PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
52 ULONG requiredLength = 0;
53 DWORD index = 0;
54 HANDLE hnd = INVALID_HANDLE_VALUE;
55 WINUSB_INTERFACE_HANDLE wusbHnd = INVALID_HANDLE_VALUE;
56
57 // Get information about all the installed devices for the specified
58 // device interface class.
59 hDeviceInfo = SetupDiGetClassDevs(&devGUID, NULL, NULL,
60 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
61
62 if (hDeviceInfo == INVALID_HANDLE_VALUE) {
63 DBG_ERR("SetupDiGetClassDevs failed, error=%lx\n", GetLastError());
64 return false;
65 }
66
67 // Enumerate all the device interfaces in the device information set.
68 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
69
70 for (index = 0; SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData);
71 index++) {
72
73 deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
74
75 // Get information about the device interface.
76
77 bResult = SetupDiEnumDeviceInterfaces(hDeviceInfo, &DeviceInfoData,
78 &devGUID, 0, &deviceInterfaceData);
79
80 if (!bResult) {
81 // Check if last item
82 if (GetLastError() == ERROR_NO_MORE_ITEMS) {
83 DBG_ERR("No more items found");
84 goto out;
85 }
86
87 // Check for some other error
88 DBG_ERR("SetupDiEnumDeviceInterfaces(1) failed, error=%lx\n",
89 GetLastError());
90 goto out;
91 }
92
93 // Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA
94 // which we need to allocate, so we have to call this function twice.
95 // First to get the size so that we know how much to allocate
96 // Second, the actual call with the allocated buffer
97
98 bResult = SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData,
99 NULL, 0, &requiredLength, NULL);
100
101 if (!bResult && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
102 DBG_ERR("SetupDiEnumDeviceInterfaces(2) failed, error=%lx\n",
103 GetLastError());
104 goto out;
105 }
106
107 // Get the interface detailed data and allocate storage
108 pInterfaceDetailData = malloc(requiredLength);
109 pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
110
111 // Now call it with the correct size and allocated buffer
112 bResult =
113 SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData,
114 pInterfaceDetailData, requiredLength,
115 NULL, &DeviceInfoData);
116
117 if (!bResult) {
118 DBG_ERR("SetupDiGetDeviceInterfaceDetail failed, error=%lx\n",
119 GetLastError());
120 goto out;
121 }
122
123 hnd =
124 CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE,
125 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
126 FILE_FLAG_OVERLAPPED, NULL);
127
128 free(pInterfaceDetailData);
129 pInterfaceDetailData = NULL;
130
131 if (hnd == INVALID_HANDLE_VALUE) {
132 DBG_ERR("CreateFile failed, error=%lx", GetLastError());
133 continue;
134 }
135
136 if (!WinUsb_Initialize(hnd, &wusbHnd)) {
137 DBG_ERR("WinUsb_Initialize failed, error=%lx", GetLastError());
138 goto next;
139 }
140
141 if (backend->serial != 0) {
142 USB_DEVICE_DESCRIPTOR desc;
143 ULONG written;
144 unsigned char ser_num[128] = {0};
145
146 if (!WinUsb_GetDescriptor(wusbHnd, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
147 (unsigned char *) &desc, sizeof(desc),
148 &written)) {
149 DBG_ERR("WinUsb_GetDescriptor failed, error=%lx", GetLastError());
150 goto next;
151 }
152
153 if (!WinUsb_GetDescriptor(wusbHnd, USB_STRING_DESCRIPTOR_TYPE,
154 desc.iSerialNumber,
155 0x0409, // English (US)
156 ser_num, sizeof(ser_num), &written)) {
157 DBG_ERR("WinUsb_GetDescriptor failed, error=%lx", GetLastError());
158 goto next;
159 }
160
161 DBG_INFO("Extracted serial %ls (%lu bytes) from device desc %d",
162 (wchar_t *) (ser_num + 2), written, desc.iSerialNumber);
163
164 unsigned long devSerial = wcstoul((wchar_t *) (ser_num + 2), NULL, 10);
165 if (devSerial != backend->serial) {
166 DBG_INFO("Device has serial %lu, not matching searched %lu", devSerial,
167 backend->serial);
168 goto next;
169 }
170 }
171 break;
172 next:
173 if (wusbHnd != INVALID_HANDLE_VALUE) {
174 WinUsb_Free(wusbHnd);
175 wusbHnd = INVALID_HANDLE_VALUE;
176 }
177 if (hnd != INVALID_HANDLE_VALUE) {
178 CloseHandle(hnd);
179 hnd = INVALID_HANDLE_VALUE;
180 }
181 continue;
182 }
183
184 if (wusbHnd != INVALID_HANDLE_VALUE) {
185
186 // Make sure we get a ZLP at the end every time
187 bResult = WinUsb_SetPipePolicy(wusbHnd, PIPE_OUT, SHORT_PACKET_TERMINATE, 1,
188 (PVOID) "\x1");
189 if (!bResult) {
190 DBG_ERR("SetPipePolicy failed");
191 WinUsb_Free(wusbHnd);
192 wusbHnd = INVALID_HANDLE_VALUE;
193 CloseHandle(hnd);
194 hnd = INVALID_HANDLE_VALUE;
195 goto out;
196 }
197
198 {
199 // we set up a dummy read with a 10ms timeout here, if the timeout is too
200 // short this times out before it has time to complete. The reason for
201 // doing this is that there might be data left in the device buffers from
202 // earlier transactions, this should flush it.
203 unsigned char buf[YH_MSG_BUF_SIZE];
204 unsigned long transferred = 0;
205 unsigned long timeout = 10;
206
207 bResult = WinUsb_SetPipePolicy(wusbHnd, PIPE_IN, PIPE_TRANSFER_TIMEOUT,
208 sizeof(timeout), &timeout);
209 if (!bResult) {
210 DBG_ERR("SetPipePolicy failed");
211 WinUsb_Free(wusbHnd);
212 wusbHnd = INVALID_HANDLE_VALUE;
213 CloseHandle(hnd);
214 hnd = INVALID_HANDLE_VALUE;
215 goto out;
216 }
217
218 if (WinUsb_ReadPipe(wusbHnd, PIPE_IN, buf, sizeof(buf), &transferred,
219 0)) {
220 DBG_INFO("%lu bytes of stale data read", transferred);
221 }
222
223 timeout = 0;
224 bResult = WinUsb_SetPipePolicy(wusbHnd, PIPE_IN, PIPE_TRANSFER_TIMEOUT,
225 sizeof(timeout), &timeout);
226 if (!bResult) {
227 DBG_ERR("SetPipePolicy failed");
228 WinUsb_Free(wusbHnd);
229 wusbHnd = INVALID_HANDLE_VALUE;
230 CloseHandle(hnd);
231 hnd = INVALID_HANDLE_VALUE;
232 goto out;
233 }
234 }
235 }
236
237out:
238 backend->hDevice = hnd;
239 backend->hWinUSB = wusbHnd;
240
241 if (hDeviceInfo) {
242 SetupDiDestroyDeviceInfoList(hDeviceInfo);
243 }
244
245 free(pInterfaceDetailData);
246
247 if (wusbHnd != INVALID_HANDLE_VALUE) {
248 return true;
249 } else {
250 return false;
251 }
252}
#define DBG_ERR(...)
Definition debug_lib.h:76
#define DBG_INFO(...)
Definition debug_lib.h:63
uint32_t next(octet_iterator &it, octet_iterator end)
Definition checked.h:137
#define TRUE
Definition pkcs11.h:1209
unsigned long serial
#define YH_MSG_BUF_SIZE
Maximum length of message buffer.
Definition yubihsm.h:93
uint8_t buf[2048]
#define PIPE_IN
#define PIPE_OUT

◆ usb_read()

int usb_read ( yh_backend * state,
unsigned char * buf,
long unsigned * len )

Definition at line 302 of file yubihsm_winusb.c.

302 {
303 long unsigned transferred = 0;
304 BOOL bResult;
305
306 if (state->hWinUSB == INVALID_HANDLE_VALUE) {
307 DBG_ERR("No connected device");
308 return 0;
309 }
310
311 DBG_INFO("Doing usb read");
312
313 bResult =
314 WinUsb_ReadPipe(state->hWinUSB, PIPE_IN, buf, *len, &transferred, 0);
315 if (!bResult) {
316 DBG_ERR("WinUsb_ReadPipe failed, error=%lx\n", GetLastError());
317 return 0;
318 }
319 DBG_INFO("Read %lu bytes", transferred);
320 *len = transferred;
321 return 1;
322}
size_t len

◆ usb_set_serial()

void usb_set_serial ( yh_backend * state,
unsigned long serial )

Definition at line 42 of file yubihsm_winusb.c.

42 {
44}
uint32_t serial

◆ usb_write()

int usb_write ( yh_backend * state,
unsigned char * buf,
long unsigned len )

Definition at line 277 of file yubihsm_winusb.c.

277 {
278 long unsigned transferred;
279
280 if (state->hWinUSB == INVALID_HANDLE_VALUE) {
281 DBG_ERR("No connected device");
282 return 0;
283 }
284
285 BOOL bResult =
286 WinUsb_WritePipe(state->hWinUSB, PIPE_OUT, buf, len, &transferred, 0);
287 if (bResult) {
288 DBG_INFO("Written %lu bytes", transferred);
289 } else {
290 DBG_ERR("WinUsb_WritePipe failed, error=%lx", GetLastError());
291 return 0;
292 }
293
294 if (transferred != len) {
295 DBG_ERR("Transferred did not match len of write %lu-%lu", transferred, len);
296 return 0;
297 }
298
299 return 1;
300}