From: Simon Josefsson Date: Tue, 5 May 2009 14:33:27 +0000 (+0000) Subject: Fix make distcheck by pulling in ykcore stuff. X-Git-Tag: yubikey-personalisation_1.3.5-1~4^2~171 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1b5aea5a63e707e06270f932dab33ff007504b7;p=yubikey-personalization.old Fix make distcheck by pulling in ykcore stuff. --- diff --git a/Makefile.am b/Makefile.am index e99c608..dc4dc03 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,6 @@ # Written by Richard Levitte . # Copyright (c) 2008, 2009 Yubico AB # All rights reserved. -# -# Copyright (c) 2008, 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 @@ -31,19 +28,20 @@ # Subdirectories -SUBDIRS=@subdirs@ +SUBDIRS=ykcore ACLOCAL_AMFLAGS = -I m4 -AM_CPPFLAGS = -I./yubikey-core -I./rfc4634 +AM_CPPFLAGS = -I$(srcdir)/ykcore -I$(srcdir)/rfc4634 # The library. lib_LTLIBRARIES = libykpers.la -libykpers_la_SOURCES = ykpers.h ykpers.c ykpbkdf2.h ykpbkdf2.c \ - rfc4634/hmac.c rfc4634/usha.c rfc4634/sha.h \ - rfc4634/sha1.c rfc4634/sha224-256.c rfc4634/sha384-512.c -libykpers_la_LIBADD = $(LTLIBYUBIKEY) ./yubikey-core/libykcore.la -lusb +libykpers_la_SOURCES = ykpers.h ykpers.c ykpbkdf2.h ykpbkdf2.c +libykpers_la_SOURCES += rfc4634/hmac.c rfc4634/usha.c rfc4634/sha.h \ + rfc4634/sha1.c rfc4634/sha224-256.c rfc4634/sha384-512.c \ + rfc4634/sha-private.h +libykpers_la_LIBADD = $(LTLIBYUBIKEY) ./ykcore/libykcore.la -lusb libykpers_la_LDFLAGS = -no-undefined \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) @@ -52,12 +50,12 @@ libykpers_la_LDFLAGS = -no-undefined \ bin_PROGRAMS = ykpersonalize ykpersonalize_SOURCES = ykpersonalize.c -ykpersonalize_LDADD = ./libykpers.la ./yubikey-core/libykcore.la +ykpersonalize_LDADD = ./libykpers.la ./ykcore/libykcore.la # Self tests. AM_LDFLAGS = -no-install -LDADD = ./libykpers.la ./yubikey-core/libykcore.la +LDADD = ./libykpers.la ctests = selftest$(EXEEXT) check_PROGRAMS = $(ctests) diff --git a/README b/README index ccc15c8..32f65a6 100644 --- a/README +++ b/README @@ -1,28 +1,17 @@ =Dependencies= -This package depends on another yubikey package called yubikey-core. +Yubico-c-client is needed, see http://code.google.com/p/yubico-c/ -The current best way to get a working yubikey-core is to fetch it as -follows: - - svn checkout http://yubikey-core.googlecode.com/svn/trunk/ yubikey-core - -You can do that in a completely separate directory as well as directly -in the directory where you found this file. If you do the former, -just make sure there's a soft link here with the name yubikey-core, as -follows: - - ln -s /PATH/TO/yubikey-core yubikey-core - -Also, yubikey-core depends on the development files for libusb, so you -will have to get those as well. Getting and installing them depends -on your operating systems, here are example for a few flavors: +Yubikey-personalization depends on libusb, so you will have to get it. +Getting and installing them depends on your operating systems, here +are example for a few flavors: (Debian) apt-get install libusb-dev (Fedora) yum install libusb-devel + =Build instructions= -autoreconf -fvi +autoreconf --install ./configure make check diff --git a/configure.ac b/configure.ac index e23cef9..985db4f 100644 --- a/configure.ac +++ b/configure.ac @@ -39,46 +39,14 @@ AC_SUBST(LT_CURRENT, 1) AC_SUBST(LT_REVISION, 0) AC_SUBST(LT_AGE, 0) -AC_ARG_WITH([usb], [ AS_HELP_STRING([--with-usb], [set libusb root path])]) - AM_INIT_AUTOMAKE([-Wall -Werror]) AC_PROG_CC AC_LIBTOOL_WIN32_DLL AC_PROG_LIBTOOL -# This really checks a directory -AC_CHECK_FILES([yubikey-core/configure.ac yubikey-core/ykcore.h],,AC_MSG_FAILURE(yubikey-core directory not found. - -************************************ -Please provide by checking out http://yubikey-core.googlecode.com/svn/trunk -with svn and creating a symbolic link `yubikey-core' to that checkout -************************************ -)) -#AC_SEARCH_LIBS([yubikey_parse],[yubikey],,AC_MSG_FAILURE(libyubikey not found)) - -# Check that the yubikey-core we try to use is modern enough -AC_MSG_CHECKING(if yubikey-core/ykcore.h declares yk_usb_strerror) -AC_EGREP_CPP([yk_usb_strerror], - [#include "yubikey-core/ykcore.h"], - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - AC_MSG_FAILURE(yubikey-core/ykcore.h does not declare yk_usb_strerror. -You probably need to update yubikey-core)) - -if test "$with_usb" != "yes"; then - if test "$with_usb" != ""; then - CFLAGS="$CFLAGS -I$with_usb/include" - CXXFLAGS="$CXXFLAGS -I$with_usb/include" - CPPFLAGS="$CPPFLAGS -I$with_usb/include" - LIBS="$LIBS -L$with_usb/lib" - fi -fi - -AC_CHECK_HEADER([usb.h]) -AC_CHECK_LIB([usb], [usb_init]) - -if test "$ac_cv_header_usb_h" == no; then - AC_MSG_WARN([Missing libusb]) +AC_LIB_HAVE_LINKFLAGS(usb,, [#include ], [usb_init()]) +if test "$ac_cv_libusb" != yes; then + AC_MSG_ERROR([libusb not found, please install usb.h and libusb.so]) fi AC_LIB_HAVE_LINKFLAGS(yubikey,, [#include ], @@ -87,6 +55,8 @@ if test "$ac_cv_libyubikey" != yes; then AC_MSG_ERROR([libyubikey not found, see http://code.google.com/p/yubico-c/]) fi -AC_CONFIG_SUBDIRS(yubikey-core) -AC_CONFIG_FILES(Makefile) +AC_CONFIG_FILES([ + Makefile + ykcore/Makefile +]) AC_OUTPUT diff --git a/ykcore/Makefile.am b/ykcore/Makefile.am new file mode 100644 index 0000000..cb488db --- /dev/null +++ b/ykcore/Makefile.am @@ -0,0 +1,32 @@ +# Copyright (c) 2008, 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. + +noinst_LTLIBRARIES = libykcore.la +libykcore_la_SOURCES = ykdef.h ykcore.h ykcore_backend.h ykcore.c \ + ykstatus.h ykstatus.c +libykcore_la_LIBADD = $(LTLIBYUBIKEY) +EXTRA_DIST = ykcore_libusb.c ykcore_win32.c diff --git a/ykcore/ykcore.c b/ykcore/ykcore.c new file mode 100644 index 0000000..e35fa6b --- /dev/null +++ b/ykcore/ykcore.c @@ -0,0 +1,305 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * 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 "ykcore.h" +#include "ykdef.h" +#include "ykcore_backend.h" + +/* Include platform-specific backends for the USB routines */ +#ifdef _WIN32 +# include "ykcore_win32.c" +#elif defined(__APPLE__) +# include "ykcore_osx.c" +#else +# include "ykcore_libusb.c" +#endif + +#include + +int yk_init(void) +{ + _ykusb_start(); +} + +int yk_release(void) +{ + _ykusb_start(); +} + +YUBIKEY *yk_open_first_key(void) +{ + struct usb_bus *bus; + struct usb_device *dev; + YUBIKEY *yk = _ykusb_open_device(YUBICO_VID, YUBIKEY_PID); + int rc = yk_errno; + + if (yk) { + STATUS st; + + if (!yk_get_status(yk, &st)) { + rc = yk_errno; + yk_close_key(yk); + yk = NULL; + } else { + if (!(st.versionMajor == 1 && st.versionMinor == 3)) { + rc = YK_EFIRMWARE; + yk_close_key(yk); + yk = NULL; + } + } + } + yk_errno = rc; + return yk; +} + +int yk_close_key(YUBIKEY *yk) +{ + return _ykusb_close_device(yk); +} + +int yk_get_status(YUBIKEY *k, STATUS *status) +{ + unsigned int status_count = 0; + + if (!yk_read_from_key(k, 0, status, sizeof(STATUS), &status_count)) + return 0; + + if (status_count != sizeof(STATUS)) { + yk_errno = YK_EWRONGSIZ; + return 0; + } + + status->touchLevel = endian_swap_16(status->touchLevel); + + return 1; +} + +int yk_write_config(YUBIKEY *yk, CONFIG *cfg, unsigned char *acc_code) +{ + unsigned char buf[sizeof(CONFIG) + ACC_CODE_SIZE]; + STATUS stat; + int seq; + + /* Get current seqence # from status block */ + + if (!yk_get_status(yk, &stat /*, 0*/)) + return 0; + + seq = stat.pgmSeq; + + /* Update checksum and insert config block in buffer if present */ + + memset(buf, 0, sizeof(buf)); + + if (cfg) { + cfg->crc = ~yubikey_crc16 ((unsigned char *) cfg, + sizeof(CONFIG) - sizeof(cfg->crc)); + cfg->crc = endian_swap_16(cfg->crc); + memcpy(buf, cfg, sizeof(CONFIG)); + } + + /* Append current access code if present */ + + if (acc_code) + memcpy(buf + sizeof(CONFIG), acc_code, ACC_CODE_SIZE); + + /* Write to Yubikey */ + + if (!yk_write_to_key(yk, SLOT_CONFIG, buf, sizeof(buf))) + return 0; + + /* Verify update */ + + if (!yk_get_status(yk, &stat /*, 0*/)) + return 0; + + yk_errno = YK_EWRITEERR; + if (cfg) { + return stat.pgmSeq != seq; + } + + return stat.pgmSeq == 0; + +} + +/* As soon as we find a way to safely detect if we're in a threaded environment + or not, this should be changed to support per-thread locations. Until then, + we only support non-threaded applications. */ +static int _yk_errno = 0; + +int * const _yk_errno_location(void) +{ + return &_yk_errno; +} + +static const char *errtext[] = { + "", + "USB error", + "wrong size", + "write error", + "timeout", + "no yubikey present", + "unsupported firmware version", + "out of memory", + "no status structure given", + "not yet implemented" +}; +const char *yk_strerror(int errnum) +{ + if (errnum < sizeof(errtext)/sizeof(errtext[0])) + return errtext[errnum]; + return NULL; +} +const char *yk_usb_strerror() +{ + return _ykusb_strerror(); +} + +/* Note: we currently have no idea whatsoever how to read things larger + than FEATURE_RPT_SIZE - 1. We also have no idea what to do with the + slot parameter, it currently is there for future purposes only. */ +int yk_read_from_key(YUBIKEY *yk, uint8_t slot, + void *buf, unsigned int bufsize, unsigned int *bufcount) +{ + unsigned char data[FEATURE_RPT_SIZE]; + + if (bufsize > FEATURE_RPT_SIZE - 1) { + yk_errno = YK_EWRONGSIZ; + return 0; + } + + memset(data, 0, sizeof(data)); + + if (!_ykusb_read(yk, REPORT_TYPE_FEATURE, 0, data, FEATURE_RPT_SIZE)) + return 0; + + /* This makes it apparent that there's some mysterious value in + the first byte... I wonder what... /Richard Levitte */ + memcpy(buf, data + 1, bufsize); + *bufcount = bufsize; + + return 1; +} + +int yk_write_to_key(YUBIKEY *yk, uint8_t slot, const void *buf, int bufcount) +{ + unsigned char repbuf[FEATURE_RPT_SIZE]; + unsigned char data[SLOT_DATA_SIZE + FEATURE_RPT_SIZE]; + int i, j, pos, part; + + /* Insert data and set slot # */ + + memset(data, 0, sizeof(data)); + memcpy(data, buf, bufcount); + data[SLOT_DATA_SIZE] = slot; + + /* Append slot checksum */ + + i = yubikey_crc16 (data, SLOT_DATA_SIZE); + data[SLOT_DATA_SIZE + 1] = (unsigned char) (i & 0xff); + data[SLOT_DATA_SIZE + 2] = (unsigned char) (i >> 8); + + /* Chop up the data into parts that fits into the payload of a + feature report. Set the part number | 0x80 in the end + of the feature report. When the Yubikey has processed it, + it will clear this byte, signaling that the next part can be + sent */ + + for (pos = 0, part = 0x80; pos < (SLOT_DATA_SIZE + 4); part++) { + + /* Ignore parts that are all zeroes except first and last + to speed up the transfer */ + + for (i = j = 0; i < (FEATURE_RPT_SIZE - 1); i++) + if (repbuf[i] = data[pos++]) j = 1; + if (!j && (part > 0x80) && (pos < SLOT_DATA_SIZE)) + continue; + + repbuf[i] = part; + + if (!_ykusb_write(yk, REPORT_TYPE_FEATURE, 0, + repbuf, FEATURE_RPT_SIZE)) + return 0; + + /* When the last byte in the feature report is cleared by + the Yubikey, the next part can be sent */ + + for (i = 0; i < 50; i++) { + memset(repbuf, 0, sizeof(repbuf)); + if (!_ykusb_read(yk, REPORT_TYPE_FEATURE, 0, + repbuf, FEATURE_RPT_SIZE)) + return 0; + if (!repbuf[FEATURE_RPT_SIZE - 1]) + break; + Sleep(10); + } + + /* If timeout, something has gone wrong */ + + if (i >= 50) { + yk_errno = YK_ETIMEOUT; + return 0; + } + } + + return 1; +} + +int yk_force_key_update(YUBIKEY *yk) +{ + unsigned char buf[FEATURE_RPT_SIZE]; + + memset(buf, 0, sizeof(buf)); + buf[FEATURE_RPT_SIZE - 1] = 0x8a; /* Invalid partition = update only */ + if (!_ykusb_write(yk, REPORT_TYPE_FEATURE, 0, buf, FEATURE_RPT_SIZE)) + return 0; + + return 1; +} + +uint16_t endian_swap_16(uint16_t x) +{ + static int testflag = -1; + + if (testflag == -1) { + uint16_t testword = 0x0102; + unsigned char *testchars = (unsigned char *)&testword; + if (*testchars == '\1') + testflag = 1; /* Big endian arch, swap needed */ + else + testflag = 0; /* Little endian arch, no swap needed */ + } + + if (testflag) + x = (x >> 8) | ((x & 0xff) << 8); + + return x; +} + diff --git a/ykcore/ykcore.h b/ykcore/ykcore.h new file mode 100644 index 0000000..702c8f7 --- /dev/null +++ b/ykcore/ykcore.h @@ -0,0 +1,154 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * 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. + */ + +#ifndef __YKCORE_H_INCLUDED__ +#define __YKCORE_H_INCLUDED__ + +#include +#include +#include + +/************************************************************************* + ** + ** N O T E : For all functions that return a value, 0 och NULL indicates + ** an error, other values indicate success. + ** + ************************************************************************/ + +/************************************************************************* + * + * Structures used. They are further defined in ykdef.h + * + ****/ + +typedef struct yubikey_st YUBIKEY; /* Really a USB device handle. */ +typedef struct status_st STATUS; /* Status structure, + filled by yk_get_status(). */ + +typedef struct ticket_st TICKET; /* Ticket structure... */ +typedef struct config_st CONFIG; /* Configuration structure. + Other libraries provide access. */ +typedef struct nav_st NAV; /* Navigation structure. + Other libraries provide access. */ + +/************************************************************************* + * + * Library initialisation functions. + * + ****/ +extern int yk_init(void); +extern int yk_release(void); + +/************************************************************************* + * + * Functions to get and release the key itself. + * + ****/ +extern YUBIKEY *yk_open_first_key(void); /* opens the first key available */ +extern int yk_close_key(YUBIKEY *k); /* closes a previously opened key */ + +/************************************************************************* + * + * Functions to get data from the key. + * + ****/ +/* fetches key status into the structure given by `status' */ +extern int yk_get_status(YUBIKEY *k, STATUS *status /*, int forceUpdate */); + +/************************************************************************* + * + * Functions to write data to the key. + * + ****/ + +/* writes the given configuration to the key. If the configuration is NULL, + zap the key configuration. + acc_code has to be provided of the key has a protecting access code. */ +extern int yk_write_config(YUBIKEY *k, CONFIG *cfg, unsigned char *acc_code); + +/************************************************************************* + * + * Error handling fuctions + * + ****/ +extern int * const _yk_errno_location(void); +#define yk_errno (*_yk_errno_location()) +const char *yk_strerror(int errnum); +/* The following function is only useful if yk_errno == YK_EUSBERR and + no other USB-related operations have been performed since the time of + error. */ +const char *yk_usb_strerror(); + +#define YK_EUSBERR 0x01 /* USB error reporting should be used */ +#define YK_EWRONGSIZ 0x02 +#define YK_EWRITEERR 0x03 +#define YK_ETIMEOUT 0x04 +#define YK_ENOKEY 0x05 +#define YK_EFIRMWARE 0x06 +#define YK_ENOMEM 0x07 +#define YK_ENOSTATUS 0x07 +#define YK_ENOTYETIMPL 0x08 + +/*=======================================================================* + +/************************************************************************* + ** + ** = = = = = = = = = B I G F A T W A R N I N G = = = = = = = = = + ** + ** DO NOT USE THE FOLLOWING FUCTIONS DIRECTLY UNLESS YOU WRITE CORE ROUTINES! + ** + ** These functions are declared here only to make sure they get defined + ** correctly internally. + ** + ** YOU HAVE BEEN WARNED! + ** + ****/ + +/************************************************************************* + * + * Functions to send and receive data to/from the key. + * + ****/ +extern int yk_read_from_key(YUBIKEY *k, uint8_t slot, + void *buf, unsigned int bufsize, + unsigned int *bufcount); +extern int yk_write_to_key(YUBIKEY *k, uint8_t slot, + const void *buf, int bufcount); + +/************************************************************************* + * + * Internal helper functions + * + ****/ + +/* Swaps the two bytes between little and big endian on big endian machines */ +extern uint16_t endian_swap_16(uint16_t x); + +#endif /* __YKCORE_H_INCLUDED__ */ diff --git a/ykcore/ykcore_backend.h b/ykcore/ykcore_backend.h new file mode 100644 index 0000000..7a01525 --- /dev/null +++ b/ykcore/ykcore_backend.h @@ -0,0 +1,52 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Written by Richard Levitte + * Copyright (c) 2008, 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. + */ + +#ifndef __YKCORE_BACKEND_H_INCLUDED__ +#define __YKCORE_BACKEND_H_INCLUDED__ + +#define FEATURE_RPT_SIZE 8 + +#define REPORT_TYPE_FEATURE 0x03 + +int _ykusb_start(void); +int _ykusb_stop(void); + +void * _ykusb_open_device(int vendor_id, int product_id); +int _ykusb_close_device(void *); + +int _ykusb_read(void *dev, int report_type, int report_number, + char *buffer, int buffer_size); +int _ykusb_write(void *dev, int report_type, int report_number, + char *buffer, int buffer_size); + +const char *_ykusb_strerror(); + +#endif /* __YKCORE_BACKEND_H_INCLUDED__ */ diff --git a/ykcore/ykcore_libusb.c b/ykcore/ykcore_libusb.c new file mode 100644 index 0000000..144422d --- /dev/null +++ b/ykcore/ykcore_libusb.c @@ -0,0 +1,186 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Copyright (c) 2008, 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_backend.h" + +#ifndef _WIN32 +#define Sleep(x) usleep((x)*1000) +#endif + +#define HID_GET_REPORT 0x01 +#define HID_SET_REPORT 0x09 + +/************************************************************************* + ** 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) +{ + int rc = usb_claim_interface((usb_dev_handle *)dev, 0); + + if (rc >= 0) { + int rc2; + rc = usb_control_msg((usb_dev_handle *)dev, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_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 = usb_release_interface((usb_dev_handle *)dev, 0); + if (rc >= 0 && rc2 < 0) + rc = rc2; + } + if (rc >= 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) +{ + int rc = usb_claim_interface((usb_dev_handle *)dev, 0); + + if (rc >= 0) { + int rc2; + rc = usb_control_msg((usb_dev_handle *)dev, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_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 = usb_release_interface((usb_dev_handle *)dev, 0); + if (rc >= 0 && rc2 < 0) + rc = rc2; + } + if (rc >= 0) + return 1; + yk_errno = YK_EUSBERR; + return 0; +} + +int _ykusb_start(void) +{ + int rc; + usb_init(); + + rc = usb_find_busses(); + if (rc >= 0) + rc = usb_find_devices(); + + if (rc >= 0) + return 1; + yk_errno = YK_EUSBERR; + return 0; +} + +extern int _ykusb_stop(void) +{ + return 1; +} + +void *_ykusb_open_device(int vendor_id, int product_id) +{ + struct usb_bus *bus; + struct usb_device *dev; + struct usb_dev_handle *h = NULL; + int rc = YK_EUSBERR; + + for (bus = usb_get_busses(); bus; bus = bus->next) { + rc = YK_ENOKEY; + for (dev = bus->devices; dev; dev = dev->next) + if (dev->descriptor.idVendor == YUBICO_VID + && dev->descriptor.idProduct == YUBIKEY_PID) { + rc = YK_EUSBERR; + h = usb_open(dev); + goto done; + } + } + done: + if (h == NULL) + yk_errno = rc; + return h; +} + +int _ykusb_close_device(void *yk) +{ + int rc = usb_close((usb_dev_handle *) yk); + + if (rc >= 0) + return 1; + yk_errno = YK_EUSBERR; + return 0; +} + +const char *_ykusb_strerror() +{ + return usb_strerror(); +} diff --git a/ykcore/ykcore_osx.c b/ykcore/ykcore_osx.c new file mode 100644 index 0000000..2a92c1c --- /dev/null +++ b/ykcore/ykcore_osx.c @@ -0,0 +1,4 @@ +/* -*- 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_stub.c b/ykcore/ykcore_stub.c new file mode 100644 index 0000000..7cf99fd --- /dev/null +++ b/ykcore/ykcore_stub.c @@ -0,0 +1,75 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Copyright (c) 2008, 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. + */ + +#error "To be implemented!" + +int _ykusb_start(void) +{ + yk_errno = YK_ENOTYETIMPL; + return 0; +} + +int _ykusb_stop(void) +{ + yk_errno = YK_ENOTYETIMPL; + return 0; +} + +void * _ykusb_open_device(int vendor_id, int product_id) +{ + yk_errno = YK_ENOTYETIMPL; + return NULL; +} + +int _ykusb_close_device(void *) +{ + yk_errno = YK_ENOTYETIMPL; + return 0; +} + +int _ykusb_read(void *dev, int report_type, int report_number, + char *buffer, int buffer_size) +{ + yk_errno = YK_ENOTYETIMPL; + return 0; +} + +int _ykusb_write(void *dev, int report_type, int report_number, + char *buffer, int buffer_size) +{ + yk_errno = YK_ENOTYETIMPL; + return 0; +} + +const char *_ykusb_strerror() +{ + yk_errno = YK_ENOTYETIMPL; + return 0; +} diff --git a/ykcore/ykcore_win32.c b/ykcore/ykcore_win32.c new file mode 100644 index 0000000..2a92c1c --- /dev/null +++ b/ykcore/ykcore_win32.c @@ -0,0 +1,4 @@ +/* -*- 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/ykdef.h b/ykcore/ykdef.h new file mode 100644 index 0000000..626b5bc --- /dev/null +++ b/ykcore/ykdef.h @@ -0,0 +1,129 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/***************************************************************************************** +** ** +** Y K D E F - Common Yubikey project header ** +** ** +** Date / Rev / Sign / Remark ** +** 06-06-03 / 0.9.0 / J E / Main ** +** 06-08-25 / 1.0.0 / J E / Rewritten for final spec ** +** 08-06-03 / 1.3.0 / J E / Added static OTP feature ** +** ** +*****************************************************************************************/ + +#ifndef __YKDEF_H_INCLUDED__ +#define __YKDEF_H_INCLUDED__ + +/* We need the structures defined here to be packed byte-wise */ +#if defined(_WIN32) || defined(__GNUC__) +#pragma pack(push, 1) +#endif + +/* USB Identity */ + +#define YUBICO_VID 0x1050 +#define YUBIKEY_PID 0x0010 + +/* Slot entries */ + +#define SLOT_CONFIG 1 +#define SLOT_NAV 2 + +#define SLOT_DATA_SIZE 64 + +/* Ticket structure */ + +#define UID_SIZE 6 /* Size of secret ID field */ + +struct ticket_st { + unsigned char uid[UID_SIZE]; /* Unique (secret) ID */ + unsigned short useCtr; /* Use counter (incremented by 1 at first use after power up) + usage flag in msb */ + unsigned short tstpl; /* Timestamp incremented by approx 8Hz (low part) */ + unsigned char tstph; /* Timestamp (high part) */ + unsigned char sessionCtr; /* Number of times used within session. 0 for first use. After it wraps from 0xff to 1 */ + unsigned short rnd; /* Pseudo-random value */ + unsigned short crc; /* CRC16 value of all fields */ +}; + +/* Activation modifier of sessionUse field (bitfields not uses as they are not portable) */ + +#define TICKET_ACT_HIDRPT 0x8000 /* Ticket generated at activation by keyboard (scroll/num/caps) */ +#define TICKET_CTR_MASK 0x7fff /* Mask for useCtr value (except HID flag) */ + +/* Configuration structure */ + +#define FIXED_SIZE 16 /* Max size of fixed field */ +#define KEY_SIZE 16 /* Size of AES key */ +#define ACC_CODE_SIZE 6 /* Size of access code to re-program device */ + +struct config_st { + unsigned char fixed[FIXED_SIZE];/* Fixed data in binary format */ + unsigned char uid[UID_SIZE]; /* Fixed UID part of ticket */ + unsigned char key[KEY_SIZE]; /* AES key */ + unsigned char accCode[ACC_CODE_SIZE]; /* Access code to re-program device */ + unsigned char fixedSize; /* Number of bytes in fixed field (0 if not used) */ + unsigned char pgmSeq; /* Program sequence number (ignored at programming - updated by firmware) */ + unsigned char tktFlags; /* Ticket configuration flags */ + unsigned char cfgFlags; /* General configuration flags */ + unsigned short ctrOffs; /* Counter offset value (ignored at programming - updated by firmware) */ + unsigned short crc; /* CRC16 value of all fields */ +}; + +/* Ticket flags */ + +#define TKTFLAG_TAB_FIRST 0x01 /* Send TAB before first part */ +#define TKTFLAG_APPEND_TAB1 0x02 /* Send TAB after first part */ +#define TKTFLAG_APPEND_TAB2 0x04 /* Send TAB after second part */ +#define TKTFLAG_APPEND_DELAY1 0x08 /* Add 0.5s delay after first part */ +#define TKTFLAG_APPEND_DELAY2 0x10 /* Add 0.5s delay after second part */ +#define TKTFLAG_APPEND_CR 0x20 /* Append CR as final character */ + +/* Configuration flags */ + +#define CFGFLAG_SEND_REF 0x01 /* Send reference string (0..F) before data */ +#define CFGFLAG_TICKET_FIRST 0x02 /* Send ticket first (default is fixed part) */ +#define CFGFLAG_PACING_10MS 0x04 /* Add 10ms intra-key pacing */ +#define CFGFLAG_PACING_20MS 0x08 /* Add 20ms intra-key pacing */ +#define CFGFLAG_ALLOW_HIDTRIG 0x10 /* Allow trigger through HID/keyboard */ +#define CFGFLAG_STATIC_TICKET 0x20 /* Static ticket generation */ + +/* Navigation */ + +#define MAX_URL 48 + +struct nav_st { + unsigned char scancode[MAX_URL];/* Scancode (lower 7 bits) */ + unsigned char scanmod[MAX_URL >> 2]; /* Modifier fields (packed 2 bits each) */ + unsigned char flags; /* NAVFLAG_xxx flags */ + unsigned char filler; /* Filler byte */ + unsigned short crc; /* CRC16 value of all fields */ +}; + +#define SCANMOD_SHIFT 0x80 /* Highest bit in scancode */ +#define SCANMOD_ALT_GR 0x01 /* Lowest bit in mod */ +#define SCANMOD_WIN 0x02 /* WIN key */ + +/* Navigation flags */ + +#define NAVFLAG_INSERT_TRIG 0x01 /* Automatic trigger when device is inserted */ +#define NAVFLAG_APPEND_TKT 0x02 /* Append ticket to URL */ +#define NAVFLAG_DUAL_KEY_USAGE 0x04 /* Dual usage of key: Short = ticket Long = Navigate */ + +/* Status block */ + +struct status_st { + unsigned char versionMajor; /* Firmware version information */ + unsigned char versionMinor; + unsigned char versionBuild; + unsigned char pgmSeq; /* Programming sequence number. 0 if no valid configuration */ + unsigned short touchLevel; /* Level from touch detector */ +}; + +/* Modified hex string mapping */ + +#define MODHEX_MAP "cbdefghijklnrtuv" + +#if defined(_WIN32) || defined(__GNUC__) +#pragma pack(pop) +#endif + +#endif /* __YKDEF_H_INCLUDED__ */ diff --git a/ykcore/ykstatus.c b/ykcore/ykstatus.c new file mode 100644 index 0000000..7f11bda --- /dev/null +++ b/ykcore/ykstatus.c @@ -0,0 +1,89 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Written by Richard Levitte + * Copyright (c) 2008, 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 "ykdef.h" +#include "ykstatus.h" + +STATUS *ykds_alloc(void) +{ + STATUS *st = malloc(sizeof(STATUS)); + if (!st) { + yk_errno = YK_ENOMEM; + } + return st; +} + +void ykds_free(STATUS *st) +{ + free(st); +} + +STATUS *ykds_static(void) +{ + static STATUS st; + return &st; +} + +extern int ykds_version_major(const STATUS *st) +{ + if (st) + return st->versionMajor; + yk_errno = YK_ENOSTATUS; + return 0; +} +extern int ykds_version_minor(const STATUS *st) +{ + if (st) + return st->versionMinor; + yk_errno = YK_ENOSTATUS; + return 0; +} +extern int ykds_version_build(const STATUS *st) +{ + if (st) + return st->versionBuild; + yk_errno = YK_ENOSTATUS; + return 0; +} +extern int ykds_pgm_seq(const STATUS *st) +{ + if (st) + return st->pgmSeq; + yk_errno = YK_ENOSTATUS; + return 0; +} +extern int ykds_touch_level(const STATUS *st) +{ + if (st) + return st->touchLevel; + yk_errno = YK_ENOSTATUS; + return 0; +} diff --git a/ykcore/ykstatus.h b/ykcore/ykstatus.h new file mode 100644 index 0000000..5e80cc8 --- /dev/null +++ b/ykcore/ykstatus.h @@ -0,0 +1,52 @@ +/* -*- mode:C; c-file-style: "bsd" -*- */ +/* + * Written by Richard Levitte + * Copyright (c) 2008, 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. + */ + +#ifndef __YKDATA_H_INCLUDED__ +#define __YKDATA_H_INCLUDED__ + +#include "ykcore.h" + +/* Allocate and free status structures */ +extern STATUS *ykds_alloc(void); +extern void ykds_free(STATUS *st); + +/* Return static status structure, to be used for quick checks. + USE WITH CAUTION, as this is a SHARED OBJECT. */ +extern STATUS *ykds_static(void); + +/* Accessor functions */ +extern int ykds_version_major(const STATUS *st); +extern int ykds_version_minor(const STATUS *st); +extern int ykds_version_build(const STATUS *st); +extern int ykds_pgm_seq(const STATUS *st); +extern int ykds_touch_level(const STATUS *st); + +#endif /* __YKDATA_H_INCLUDED__ */