From b5c51ad7d4d901b8e9564d154b48f71be6c72d71 Mon Sep 17 00:00:00 2001 From: Simon Josefsson Date: Tue, 4 Aug 2009 09:32:59 +0000 Subject: [PATCH] Add libusb-1.0 support from Tollef Fog Heen. --- AUTHORS | 3 + NEWS | 3 + configure.ac | 7 +- ykcore/Makefile.am | 7 +- ykcore/ykcore_libusb-1.0.c | 192 +++++++++++++++++++++++++++++++++++++ 5 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 ykcore/ykcore_libusb-1.0.c diff --git a/AUTHORS b/AUTHORS index b6290ed..c08798d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -17,3 +17,6 @@ Added ykp_AES_key_from_hex and ykpersonalize -a parameter. Christer Kaivo-oja Mac OS X port. + +Tollef Fog Heen +Support for libusb-1.0 backend. diff --git a/NEWS b/NEWS index 0cd62ad..7402aef 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ Yubikey-personalize NEWS -- History of user-visible changes. -*- outline -*- * Version 0.93 (unreleased) +** Support for libusb-1.0 through --with-backend=libusb-1.0. +Thanks to Tollef Fog Heen. + ** Clarify -a parameter. Thanks to Alphonse R.M. Hoge. diff --git a/configure.ac b/configure.ac index dd18a27..f66ad51 100644 --- a/configure.ac +++ b/configure.ac @@ -62,7 +62,7 @@ AC_ARG_WITH([backend], [AS_HELP_STRING([--with-backend=ARG], [use specific backend; 'libusb' or 'osx'])]) AC_MSG_CHECKING([for backend]) -if test x$with_backend != xosx && test x$with_backend != xlibusb; then +if test x$with_backend != xosx && test x$with_backend != xlibusb && test x$with_backend != xlibusb-1.0; then AC_CANONICAL_HOST case "$host" in *-darwin*) with_backend=osx ;; @@ -71,8 +71,13 @@ if test x$with_backend != xosx && test x$with_backend != xlibusb; then fi AC_MSG_RESULT([$with_backend]) 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) +if test x$with_backend = xlibusb-1.0; then + PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) +fi + if test x$with_backend = xlibusb; then AC_LIB_HAVE_LINKFLAGS(usb,, [#include ], [usb_init()]) if test "$ac_cv_libusb" != yes; then diff --git a/ykcore/Makefile.am b/ykcore/Makefile.am index 3b595a3..c5ddc52 100644 --- a/ykcore/Makefile.am +++ b/ykcore/Makefile.am @@ -28,7 +28,12 @@ noinst_LTLIBRARIES = libykcore.la libykcore_la_SOURCES = ykdef.h ykcore.h ykcore_lcl.h ykcore_backend.h \ ykcore.c ykstatus.h ykstatus.c yktsd.h -libykcore_la_LIBADD = $(LTLIBYUBIKEY) $(LTLIBUSB) +libykcore_la_LIBADD = $(LTLIBYUBIKEY) $(LTLIBUSB) @LIBUSB_LIBS@ + +if BACKEND_LIBUSB_1_0 +libykcore_la_SOURCES += ykcore_libusb-1.0.c +AM_CFLAGS = @LIBUSB_CFLAGS@ +endif if BACKEND_LIBUSB libykcore_la_SOURCES += ykcore_libusb.c diff --git a/ykcore/ykcore_libusb-1.0.c b/ykcore/ykcore_libusb-1.0.c new file mode 100644 index 0000000..ec944f1 --- /dev/null +++ b/ykcore/ykcore_libusb-1.0.c @@ -0,0 +1,192 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Copyright (c) 2009, Tollef Fog Heen + * Copyright (c) 2008, 2009, 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 +#include +#include + +#include "ykcore.h" +#include "ykdef.h" +#include "ykcore_backend.h" + +#define HID_GET_REPORT 0x01 +#define HID_SET_REPORT 0x09 + +static int ykl_errno; + +/************************************************************************* + ** function _ykusb_write ** + ** Set HID report ** + ** ** + ** int _ykusb_write(YUBIKEY *yk, int report_type, int report_number, ** + ** char *buffer, int size) ** + ** ** + ** Where: ** + ** "yk" is handle to open Yubikey ** + ** "report_type" is HID report type (in, out or feature) ** + ** "report_number" is report identifier ** + ** "buffer" is pointer to in buffer ** + ** "size" is size of the buffer ** + ** ** + ** Returns: Nonzero if successful, zero otherwise ** + ** ** + *************************************************************************/ + +int _ykusb_write(void *dev, int report_type, int report_number, + char *buffer, int size) +{ + ykl_errno = libusb_claim_interface((libusb_device_handle *)dev, 0); + + if (ykl_errno == 0) { + int rc2; + ykl_errno = libusb_control_transfer((libusb_device_handle *)dev, + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE | + LIBUSB_ENDPOINT_OUT, + HID_SET_REPORT, + report_type << 8 | report_number, 0, + buffer, size, + 1000); + /* preserve a control message error over an interface + release one */ + rc2 = libusb_release_interface((libusb_device_handle *)dev, 0); + if (ykl_errno > 0 && rc2 < 0) + ykl_errno = rc2; + } + if (ykl_errno > 0) + return 1; + yk_errno = YK_EUSBERR; + return 0; +} + +/************************************************************************* +** function _ykusb_read ** +** Get HID report ** +** ** +** int _ykusb_read(YUBIKEY *dev, int report_type, int report_number, ** +** char *buffer, int size) ** +** ** +** Where: ** +** "dev" is handle to open Yubikey ** +** "report_type" is HID report type (in, out or feature) ** +** "report_number" is report identifier ** +** "buffer" is pointer to in buffer ** +** "size" is size of the buffer ** +** ** +** Returns: Number of bytes read. Zero if failure ** +** ** +*************************************************************************/ + +int _ykusb_read(void *dev, int report_type, int report_number, + char *buffer, int size) +{ + ykl_errno = libusb_claim_interface((libusb_device_handle *)dev, 0); + + if (ykl_errno == 0) { + int rc2; + ykl_errno = libusb_control_transfer((libusb_device_handle *)dev, + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE | + LIBUSB_ENDPOINT_IN, + HID_GET_REPORT, + report_type << 8 | report_number, 0, + buffer, size, + 1000); + /* preserve a control message error over an interface + release one */ + rc2 = libusb_release_interface((libusb_device_handle *)dev, 0); + if (ykl_errno > 0 && rc2 < 0) + ykl_errno = rc2; + } + if (ykl_errno > 0) + return ykl_errno; + yk_errno = YK_EUSBERR; + return 0; +} + +int _ykusb_start(void) +{ + int rc; + libusb_init(NULL); + return 1; +} + +extern int _ykusb_stop(void) +{ + libusb_exit(NULL); + return 1; +} + +void *_ykusb_open_device(int vendor_id, int product_id) +{ + libusb_device *dev; + libusb_device_handle *h = NULL; + struct libusb_device_descriptor desc; + libusb_device **list; + size_t cnt = libusb_get_device_list(NULL, &list); + size_t i = 0; + int rc = YK_ENOKEY; + + for (i = 0; i < cnt; i++) { + dev = list[i]; + ykl_errno = libusb_get_device_descriptor(dev, &desc); + if (ykl_errno != 0) + goto done; + + if (desc.idVendor == YUBICO_VID && desc.idProduct == YUBIKEY_PID) { + rc = YK_EUSBERR; + ykl_errno = libusb_open(dev, &h); + if (ykl_errno != 0) + goto done; + ykl_errno = libusb_detach_kernel_driver(h, 0); + goto done; + } + } + done: + libusb_free_device_list(list, 1); + if (h == NULL) + yk_errno = rc; + return h; +} + +int _ykusb_close_device(void *yk) +{ + libusb_attach_kernel_driver(yk, 0); + libusb_close((libusb_device_handle *) yk); + return 1; +} + +const char *_ykusb_strerror() +{ + static char buf[512]; + snprintf(buf, sizeof(buf), "%s %d", "NOT IMPLEMENTED", ykl_errno); + return buf; +} -- 2.39.5