# Written by Richard Levitte <richard@levitte.org>.
# 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
# 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)
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)
=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
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.h>], [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 <yubikey.h>],
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
--- /dev/null
+# 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
--- /dev/null
+/* -*- 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 <yubikey.h>
+
+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;
+}
+
--- /dev/null
+/* -*- 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 <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/*************************************************************************
+ **
+ ** 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__ */
--- /dev/null
+/* -*- mode:C; c-file-style: "bsd" -*- */
+/*
+ * Written by Richard Levitte <richar@levitte.org>
+ * 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__ */
--- /dev/null
+/* -*- 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 <usb.h>
+#include <stdio.h>
+#include <string.h>
+
+#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();
+}
--- /dev/null
+/* -*- 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"
--- /dev/null
+/* -*- 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;
+}
--- /dev/null
+/* -*- 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"
--- /dev/null
+/* -*- 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__ */
--- /dev/null
+/* -*- mode:C; c-file-style: "bsd" -*- */
+/*
+ * Written by Richard Levitte <richard@levitte.org>
+ * 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;
+}
--- /dev/null
+/* -*- mode:C; c-file-style: "bsd" -*- */
+/*
+ * Written by Richard Levitte <richard@levitte.org>
+ * 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__ */