From 0ff85dea3dce8eea4ef3edc2272b835e88ef32c6 Mon Sep 17 00:00:00 2001 From: Simon Josefsson Date: Sat, 9 Apr 2011 08:47:47 +0200 Subject: [PATCH] Add native Windows backend. --- configure.ac | 8 +- ykcore/Makefile.am | 8 +- ykcore/ykcore_win32.c | 4 - ykcore/ykcore_windows.c | 193 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 7 deletions(-) delete mode 100644 ykcore/ykcore_win32.c create mode 100644 ykcore/ykcore_windows.c diff --git a/configure.ac b/configure.ac index c0ecc7c..18e32d7 100644 --- a/configure.ac +++ b/configure.ac @@ -62,7 +62,7 @@ fi AC_ARG_WITH([backend], [AS_HELP_STRING([--with-backend=ARG], - [use specific backend; 'libusb-1.0', 'libusb' or 'osx'])], + [use specific backend; 'libusb-1.0', 'libusb', 'osx' or 'windows'])], [], [with_backend=check]) @@ -71,6 +71,7 @@ if test "x$with_backend" = xcheck; then AC_MSG_CHECKING([for backend]) case "$host" in *-darwin*) with_backend=osx ;; + *-mingw*) with_backend=windows ;; *) PKG_CHECK_EXISTS([libusb-1.0], [with_backend=libusb-1.0], [with_backend=libusb]) @@ -110,9 +111,14 @@ if test x$with_backend = xosx; then LDFLAGS="$LDFLAGS -framework IOKit -framework CoreFoundation" fi +if test x$with_backend = xwindows; then + LDFLAGS="$LDFLAGS -luuid -lsetupapi -lhid" +fi + AM_CONDITIONAL([BACKEND_LIBUSB], test x$with_backend = xlibusb) AM_CONDITIONAL([BACKEND_LIBUSB_1_0], test x$with_backend = xlibusb-1.0) AM_CONDITIONAL([BACKEND_OSX], test x$with_backend = xosx) +AM_CONDITIONAL([BACKEND_WINDOWS], test x$with_backend = xwindows) gl_LD_VERSION_SCRIPT diff --git a/ykcore/Makefile.am b/ykcore/Makefile.am index c21e8c8..03ac1e4 100644 --- a/ykcore/Makefile.am +++ b/ykcore/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (c) 2008, 2009, Yubico AB +# Copyright (c) 2008, 2009, 2011, Yubico AB # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -43,4 +43,8 @@ if BACKEND_OSX libykcore_la_SOURCES += ykcore_osx.c endif -EXTRA_DIST = ykcore_stub.c ykcore_win32.c +if BACKEND_WINDOWS +libykcore_la_SOURCES += ykcore_windows.c +endif + +EXTRA_DIST = ykcore_stub.c diff --git a/ykcore/ykcore_win32.c b/ykcore/ykcore_win32.c deleted file mode 100644 index 2a92c1c..0000000 --- a/ykcore/ykcore_win32.c +++ /dev/null @@ -1,4 +0,0 @@ -/* -*- mode:C; c-file-style: "bsd" -*- */ -/* Please implement this. Have a look at ykcore_libusb.c or some other - already implemented backend for inspiration. */ -#include "ykcore_stub.c" diff --git a/ykcore/ykcore_windows.c b/ykcore/ykcore_windows.c new file mode 100644 index 0000000..e87da7b --- /dev/null +++ b/ykcore/ykcore_windows.c @@ -0,0 +1,193 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Copyright (c) 2008, 2011, Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ykcore.h" +#include "ykdef.h" +#include "ykcore_backend.h" + +#include +#include +#include +#include +typedef LONG NTSTATUS; +#include + +BOOLEAN __stdcall HidD_GetAttributes( + HANDLE HidDeviceObject, + PHIDD_ATTRIBUTES Attributes + ); +BOOLEAN __stdcall HidD_GetFeature( + HANDLE HidDeviceObject, + PVOID ReportBuffer, + ULONG ReportBufferLength + ); +BOOLEAN __stdcall HidD_SetFeature( + HANDLE HidDeviceObject, + PVOID ReportBuffer, + ULONG ReportBufferLength + ); + +int _ykusb_start(void) +{ + return 1; +} + +int _ykusb_stop(void) +{ + return 1; +} + +void * _ykusb_open_device(int vendor_id, int product_id) +{ + HDEVINFO hi; + SP_DEVICE_INTERFACE_DATA di; + PSP_DEVICE_INTERFACE_DETAIL_DATA pi; + int i, numDev = 0; + LPTSTR path = 0; + DWORD len, rc; + HANDLE ret_handle = NULL; + + yk_errno = YK_EUSBERR; + + hi = SetupDiGetClassDevs(&GUID_DEVINTERFACE_KEYBOARD, 0, 0, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (hi == INVALID_HANDLE_VALUE) + return NULL; + + di.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); + + for (i = 0; i < 1000; i++) { + if (!SetupDiEnumDeviceInterfaces(hi, 0, &GUID_DEVINTERFACE_KEYBOARD, i, &di)) + break; + + if (SetupDiGetDeviceInterfaceDetail(hi, &di, 0, 0, &len, 0) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; + + pi = malloc (len); + if (!pi) { + yk_errno = YK_ENOMEM; + goto done; + } + pi->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); + + rc = SetupDiGetDeviceInterfaceDetail(hi, &di, pi, len, &len, 0); + if (rc) { + HANDLE m_handle; + + m_handle = CreateFile(pi->DevicePath, GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (m_handle != INVALID_HANDLE_VALUE) { + HIDD_ATTRIBUTES devInfo; + + if (HidD_GetAttributes(m_handle, &devInfo)) { + if (devInfo.VendorID == vendor_id && devInfo.ProductID == product_id) { + ret_handle = m_handle; + free (pi); + goto done; + } + } + } + CloseHandle (m_handle); + } + + free (pi); + + if (!rc) + break; + } + + yk_errno = YK_ENOKEY; + +done: + SetupDiDestroyDeviceInfoList(hi); + return ret_handle; +} + +int _ykusb_close_device(void *yk) +{ + HANDLE h = yk; + + CloseHandle(h); + + return 1; +} + +#define EXPECT_SIZE 8 +#define FEATURE_BUF_SIZE 9 + +int _ykusb_read(void *dev, int report_type, int report_number, + char *buffer, int buffer_size) +{ + HANDLE h = dev; + BYTE buf[FEATURE_BUF_SIZE]; + + if (buffer_size != EXPECT_SIZE) { + yk_errno = YK_EUSBERR; + return 0; + } + + memset(buf, 0, sizeof(buf)); + + if (!HidD_GetFeature(h, buf, sizeof (buf))) { + yk_errno = YK_EUSBERR; + return 0; + } + + memcpy (buffer, buf + 1, buffer_size); + + return buffer_size; +} + +int _ykusb_write(void *dev, int report_type, int report_number, + char *buffer, int buffer_size) +{ + HANDLE h = dev; + BYTE buf[FEATURE_BUF_SIZE]; + + if (buffer_size != EXPECT_SIZE) { + yk_errno = YK_EUSBERR; + return 0; + } + + buf[0] = 0; + memcpy (buf + 1, buffer, buffer_size); + + if (!HidD_SetFeature(h, buf, sizeof (buf))) { + yk_errno = YK_EUSBERR; + return 0; + } + + return 1; +} + +const char *_ykusb_strerror(void) +{ + return "USB error\n"; +} -- 2.39.5