]> err.no Git - yubikey-personalization.old/commitdiff
Added common routines (shouldn't they be in a separate package, say yubico-c?)
authorlevitte <levitte@b62f149e-849f-11dd-9899-c7ba65f7c4c7>
Thu, 18 Sep 2008 14:29:52 +0000 (14:29 +0000)
committerlevitte <levitte@b62f149e-849f-11dd-9899-c7ba65f7c4c7>
Thu, 18 Sep 2008 14:29:52 +0000 (14:29 +0000)
git-svn-id: https://yubikey-personalization.googlecode.com/svn/trunk@4 b62f149e-849f-11dd-9899-c7ba65f7c4c7

common/ykdef.h [new file with mode: 0644]
common/ykutil.c [new file with mode: 0644]
common/ykutil.h [new file with mode: 0644]
common/yubikey.c [new file with mode: 0644]
common/yubikey.h [new file with mode: 0644]

diff --git a/common/ykdef.h b/common/ykdef.h
new file mode 100644 (file)
index 0000000..50b7fbe
--- /dev/null
@@ -0,0 +1,114 @@
+/*****************************************************************************************
+**                                                                                     **
+**             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__
+
+// 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
+
+typedef struct {
+       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
+} TICKET;
+
+// 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
+
+typedef struct {
+       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
+} CONFIG;
+
+// 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
+
+typedef struct {
+       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
+} NAV;
+
+#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
+
+typedef struct {
+       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
+} STATUS;
+
+// Modified hex string mapping
+
+#define        MODHEX_MAP              "cbdefghijklnrtuv"
+
+#endif // __YKDEF_H_INCLUDED__
diff --git a/common/ykutil.c b/common/ykutil.c
new file mode 100644 (file)
index 0000000..efb39b2
--- /dev/null
@@ -0,0 +1,141 @@
+/*************************************************************************\r
+**                                                                      **\r
+**      Y K U T I L  -  Yubikey utilities                              **\r
+**                                                                      **\r
+**      Copyright 2008 Yubico AB                                       **\r
+**                                                                      **\r
+**      Date           / Sig / Rev  / History                          **\r
+**      2008-06-05     / J E / 0.00 / Main                             **\r
+**                                                                      **\r
+*************************************************************************/\r
+\r
+#include "ykutil.h"\r
+#include "yubikey.h"\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <aes128.h>\r
+\r
+/*************************************************************************\r
+**  function getCRC                                                    **\r
+**  Calculate ISO13239 checksum of buffer                              **\r
+**                                                                      **\r
+**     unsigned short getCRC(const unsigned char *buf, int bcnt)       **\r
+**                                                                      **\r
+**  Where:                                                              **\r
+**     "buf" is pointer to buffer                                      **\r
+**     "bcnt" is size of the buffer                                    **\r
+**                                                                     **\r
+**     Returns: ISO13239 checksum                                      **\r
+**                                                                      **\r
+*************************************************************************/\r
+\r
+unsigned short getCRC(const unsigned char *buf, int bcnt)\r
+{\r
+       unsigned short crc = 0xffff;\r
+       int i;\r
+\r
+       while (bcnt--) {\r
+               crc ^= *buf++;\r
+               for (i = 0; i < 8; i++) crc = (crc & 1) ? ((crc >> 1) ^ 0x8408) : (crc >> 1);\r
+       }\r
+\r
+       return crc;\r
+}\r
+\r
+/*************************************************************************\r
+**  function modhexDecode                                              **\r
+**  Decodes modhex string into binary                                  **\r
+**                                                                      **\r
+**     int modhexDecode(unsigned char *dst, const unsigned char *src,  **\r
+**                                      int dstSize)                   **\r
+**                                                                      **\r
+**  Where:                                                              **\r
+**     "dst" is pointer to decoded binary data                         **\r
+**     "src" is pointer to modhex string                               **\r
+**     "dstSize" is size of the destination buffer                     **\r
+**                                                                     **\r
+**     Returns: Number of bytes decoded                                **\r
+**                                                                      **\r
+*************************************************************************/\r
+\r
+int modhexDecode(unsigned char *dst, const unsigned char *src, int dstSize)\r
+{\r
+       static const char trans[] = MODHEX_MAP;\r
+       unsigned char b, flag = 0;\r
+       int bcnt;\r
+       char *p1;\r
+\r
+       for (bcnt = 0; *src && (bcnt < dstSize); src++) {\r
+               if (p1 = strchr(trans, tolower(*src)))\r
+                       b = (unsigned char) (p1 - trans);\r
+               else\r
+                       b = 0;\r
+\r
+               if (flag = !flag) \r
+                       *dst = b;\r
+               else {\r
+                       *dst = (*dst << 4) | b;\r
+                       dst++;\r
+                       bcnt++;\r
+               }\r
+       }\r
+\r
+       return bcnt;\r
+}\r
+\r
+/*************************************************************************\r
+**  function parseOTP                                                  **\r
+**  Parses OTP string and inserts result in TICKET structure           **\r
+**                                                                      **\r
+**     int parseOTP(TICKET *tkt, unsigned char *fixed,                 **\r
+**                              int *fixedSize, const char *str,       **\r
+**                              const char *key)                       **\r
+**                                                                      **\r
+**  Where:                                                              **\r
+**     "tkt" is pointer to receiving TICKET structure                  **\r
+**     "fixed" is pointer to receiving fixed part buffer               **\r
+**     "fixedSize" is pointer to receiving size of fixed part          **\r
+**     "str" is pointer to ascii OTP string                            **\r
+**     "key" is pointer to AES key                                     **\r
+**                                                                     **\r
+**     Returns: Nonzero if successful, zero otherwise                  **\r
+**                                                                      **\r
+*************************************************************************/\r
+\r
+int parseOTP(TICKET *tkt, unsigned char *fixed, int *fixedSize, const char *str, const unsigned char *key)\r
+{\r
+       int i, j;\r
+       unsigned char bin[FIXED_SIZE + sizeof(TICKET)];\r
+\r
+       // Convert from modhex to binary. Must be at least sizeof(TICKET) bytes\r
+\r
+       if ((i = modhexDecode(bin, str, sizeof(bin))) < sizeof(TICKET)) return 0;\r
+\r
+       // The ticket is located in the last 16 bytes\r
+\r
+       memcpy(tkt, bin + i - sizeof(TICKET), sizeof(TICKET));\r
+\r
+       // Decrypt the stuff\r
+\r
+       aesDecrypt((unsigned char *) tkt, key);\r
+\r
+       // Is the checksum okay ?\r
+\r
+       j = getCRC((unsigned char *) tkt, sizeof(TICKET));\r
+       ENDIAN_SWAP(j);\r
+       if (j != CRC_OK_RESIDUE) return 0;\r
+\r
+       // Shape up little-endian fields (if applicable)\r
+\r
+       ENDIAN_SWAP(tkt->rnd);\r
+       ENDIAN_SWAP(tkt->tstpl);\r
+       ENDIAN_SWAP(tkt->useCtr);\r
+\r
+       // Insert fixed id (if present)\r
+\r
+       *fixedSize = i - sizeof(TICKET);\r
+       \r
+       if (*fixedSize) memcpy(fixed, bin, *fixedSize);\r
+\r
+       return 1;\r
+}\r
diff --git a/common/ykutil.h b/common/ykutil.h
new file mode 100644 (file)
index 0000000..af75ce0
--- /dev/null
@@ -0,0 +1,19 @@
+/*************************************************************************\r
+**                                                                      **\r
+**      Y K U T I L  -  Yubikey utilities                              **\r
+**                                                                      **\r
+**      Copyright 2008 Yubico AB                                       **\r
+**                                                                      **\r
+**      Date           / Sig / Rev  / History                          **\r
+**      2008-06-05     / J E / 0.00 / Main                             **\r
+**                                                                      **\r
+*************************************************************************/\r
+\r
+#include <ykdef.h>\r
+\r
+#define        CRC_OK_RESIDUE  0xf0b8\r
+\r
+extern unsigned short getCRC(const unsigned char *, int);\r
+extern int modhexDecode(unsigned char *, const unsigned char *, int);\r
+extern int parseOTP(TICKET *tkt, unsigned char *fixed, int *fixedSize, const char *str, const unsigned char *key);\r
+\r
diff --git a/common/yubikey.c b/common/yubikey.c
new file mode 100644 (file)
index 0000000..8977038
--- /dev/null
@@ -0,0 +1,292 @@
+/*************************************************************************
+**                                                                      **
+**      Y U B I K E Y  -  Basic LibUSB programming API for the Yubikey **
+**                                                                      **
+**      Copyright 2008 Yubico AB                                       **
+**                                                                      **
+**      Date           / Sig / Rev  / History                          **
+**      2008-06-05     / J E / 0.00 / Main                             **
+**                                                                      **
+*************************************************************************/
+
+#include <usb.h>               // Rename to avoid clash with windows USBxxx headers
+#include "yubikey.h"
+#include <ykutil.h>
+
+#define        YUBICO_VID                              0x1050
+#define        YUBIKEY_PID                             0x0010
+
+#define HID_GET_REPORT                 0x01
+#define HID_SET_REPORT                 0x09
+
+#define        FEATURE_RPT_SIZE                8
+
+#define        REPORT_TYPE_FEATURE             0x03
+
+/*************************************************************************
+**  function hidSetReport                                              **
+**  Set HID report                                                     **
+**                                                                      **
+**  int hidSetReport(YUBIKEY yk, int reportType, int reportNumber,     **
+**                                      char *buffer, int size)        **
+**                                                                      **
+**  Where:                                                              **
+**  "yk" is handle to open Yubikey                                     **
+**     "reportType" is HID report type (in, out or feature)            **
+**     "reportNumber" is report identifier                             **
+**     "buffer" is pointer to in buffer                                **
+**     "size" is size of the buffer                                    **
+**                                                                     **
+**     Returns: Nonzero if successful, zero otherwise                  **
+**                                                                      **
+*************************************************************************/
+
+static int hidSetReport(YUBIKEY yk, int reportType, int reportNumber, char *buffer, int size)
+{
+    return usb_control_msg(yk, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, HID_SET_REPORT,
+                               reportType << 8 | reportNumber, 0, buffer, size, 1000) > 0;
+}
+
+/*************************************************************************
+**  function hidGetReport                                              **
+**  Get HID report                                                     **
+**                                                                      **
+**  int hidGetReport(YUBIKEY yk, int reportType, int reportNumber,     **
+**                                      char *buffer, int size)        **
+**                                                                      **
+**  Where:                                                              **
+**  "yk" is handle to open Yubikey                                     **
+**     "reportType" is HID report type (in, out or feature)            **
+**     "reportNumber" is report identifier                             **
+**     "buffer" is pointer to in buffer                                **
+**     "size" is size of the buffer                                    **
+**                                                                     **
+**     Returns: Number of bytes read. Zero if failure                  **
+**                                                                      **
+*************************************************************************/
+
+static int hidGetReport(YUBIKEY yk, int reportType, int reportNumber, char *buffer, int size)
+{
+  int m = usb_claim_interface(yk, 0);
+  printf ("m %d: %s\n", m, usb_strerror ());
+
+    return usb_control_msg(yk, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN, HID_GET_REPORT,
+                                   reportType << 8 | reportNumber, 0, buffer, size, 1000) > 0;
+}
+
+/*************************************************************************
+**  function ykInit                                                    **
+**  Initiates libUsb and other stuff. Call this one first              **
+**                                                                      **
+**  void ykInit(void)                                                  **
+**                                                                      **
+*************************************************************************/
+
+int ykInit(void)
+{
+       usb_init();
+
+       if (usb_find_busses()) return usb_find_devices();
+
+       return 0;
+}
+
+/*************************************************************************
+**  function ykOpen                                                    **
+**  Opens first Yubikey found for subsequent operations                        **
+**                                                                      **
+**  YUBIKEY ykOpen(void)                                               **
+**                                                                      **
+**  Returns: Handle to opened Yubikey                                  **
+**                                                                      **
+*************************************************************************/
+
+YUBIKEY ykOpen(void)
+{
+       struct usb_bus *bus;
+       struct usb_device *dev;
+
+       // Find first instance of the Yubikey
+
+       for (bus = usb_get_busses(); bus; bus = bus->next)
+               for (dev = bus->devices; dev; dev = dev->next)
+                       if (dev->descriptor.idVendor == YUBICO_VID && dev->descriptor.idProduct == YUBIKEY_PID) return usb_open(dev);
+
+       return (YUBIKEY) 0;
+}
+
+/*************************************************************************
+**  function ykClose                                                   **
+**  Closes open Yubikey handle                                         **
+**                                                                      **
+**  void ykClose(void)                                                 **
+**                                                                      **
+*************************************************************************/
+
+void ykClose(YUBIKEY *yk)
+{
+       usb_close((usb_dev_handle *) yk);
+}
+
+/*************************************************************************
+**  function ykGetStatus                                               **
+**  Read the Yubikey status structure                                  **
+**                                                                      **
+**  int ykGetStatus(YUBIKEY *yk, STATUS *status, int forceUpdate)      **
+**                                                                      **
+**  Where:                                                              **
+**  "yk" is handle to open Yubikey                                     **
+**     "status" is pointer to returned status structure                **
+**     "forceUpdate" is set to nonzero to force update of dynamic fields **
+**                                                                     **
+**     Returns: Nonzero if successful, zero otherwise                  **
+**                                                                      **
+*************************************************************************/
+
+int ykGetStatus(YUBIKEY yk, STATUS *status, int forceUpdate)
+{
+       unsigned char buf[FEATURE_RPT_SIZE];
+
+       // Read status structure
+
+       memset(buf, 0, sizeof(buf));
+
+       if (!hidGetReport(yk, REPORT_TYPE_FEATURE, 0, buf, FEATURE_RPT_SIZE)) return 0;
+
+       memcpy(status, buf + 1, sizeof(STATUS)); 
+       ENDIAN_SWAP(status->touchLevel);
+
+       // If force update, force Yubikey to update its dynamic
+       // status value(s)
+
+       if (forceUpdate) {
+               memset(buf, 0, sizeof(buf));
+               buf[FEATURE_RPT_SIZE - 1] = 0x8a;       // Invalid partition = update only
+               hidSetReport(yk, REPORT_TYPE_FEATURE, 0, buf, FEATURE_RPT_SIZE);
+       }
+
+       return 1;
+}
+
+/*************************************************************************
+**  function ykWriteSlot                                               **
+**  Writes data to Yubikey slot                                                **
+**                                                                      **
+**  static int ykWriteSlot(YUBIKEY *yk, unsigned char slot,            **
+**                        const void *buf, int bcnt)                   **
+**                                                                      **
+**  Where:                                                              **
+**  "yk" is handle to open Yubikey                                     **
+**     "slot" is slot number to write to                               **
+**     "buf" is pointer to write data buffer                           **
+**     "bcnt" is number of bytes to write                              **
+**                                                                     **
+**     Returns: Nonzero if successful, zero otherwise                  **
+**                                                                      **
+*************************************************************************/
+
+static int ykWriteSlot(YUBIKEY *yk, unsigned char slot, const void *dt, int bcnt)
+{
+       unsigned char buf[FEATURE_RPT_SIZE], data[SLOT_DATA_SIZE + FEATURE_RPT_SIZE];
+       int i, j, pos, part;
+
+       // Insert data and set slot #
+
+       memset(data, 0, sizeof(data));
+       memcpy(data, dt, bcnt);
+       data[SLOT_DATA_SIZE] = slot;
+
+       // Append slot checksum
+
+       i = getCRC(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 (buf[i] = data[pos++]) j = 1;
+               if (!j && (part > 0x80) && (pos < SLOT_DATA_SIZE)) continue;
+
+               buf[i] = part;
+
+               if (!hidSetReport(yk, REPORT_TYPE_FEATURE, 0, buf, 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(buf, 0, sizeof(buf));
+                       if (!hidGetReport(yk, REPORT_TYPE_FEATURE, 0, buf, FEATURE_RPT_SIZE)) return 0; 
+                       if (!buf[FEATURE_RPT_SIZE - 1]) break;
+                       sleep(10);
+               }
+
+               // If timeout, something has gone wrong
+
+               if (i >= 50) return 0;  
+       }
+
+       return 1;
+}
+
+/*************************************************************************
+**  function ykWriteConfig                                             **
+**  Writes key config structure                                                **
+**                                                                      **
+**  int ykGetStatus(YUBIKEY *yk, STATUS *status, unsigned char accCode)        **
+**                                                                      **
+**  Where:                                                              **
+**  "yk" is handle to open Yubikey                                     **
+**     "cfg" is pointer to configuration structure. NULL to zap        **
+**     "accCode" is current program access code. NULL if none          **
+**                                                                     **
+**     Returns: Nonzero if successful, zero otherwise                  **
+**                                                                      **
+*************************************************************************/
+
+int ykWriteConfig(YUBIKEY *yk, CONFIG *cfg, unsigned char *accCode)
+{
+       unsigned char buf[sizeof(CONFIG) + ACC_CODE_SIZE];
+       STATUS stat;
+       int seq;
+
+       // Get current seqence # from status block
+
+       if (!ykGetStatus(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 = ~getCRC((unsigned char *) cfg, sizeof(CONFIG) - sizeof(cfg->crc));
+               ENDIAN_SWAP(cfg->crc);
+               memcpy(buf, cfg, sizeof(CONFIG));
+       }
+
+       // Append current access code if present
+
+       if (accCode) memcpy(buf + sizeof(CONFIG), accCode, ACC_CODE_SIZE);
+
+       // Write to Yubikey
+
+       if (!ykWriteSlot(yk, SLOT_CONFIG, buf, sizeof(buf))) return 0;
+
+       // Verify update
+
+       if (!ykGetStatus(yk, &stat, 0)) return 0;
+
+       if (cfg) return stat.pgmSeq != seq;
+
+       return stat.pgmSeq == 0;
+}
diff --git a/common/yubikey.h b/common/yubikey.h
new file mode 100644 (file)
index 0000000..2631885
--- /dev/null
@@ -0,0 +1,40 @@
+/*************************************************************************\r
+**                                                                      **\r
+**      Y U B I K E Y  -  Basic LibUSB programming API for the Yubikey **\r
+**                                                                      **\r
+**      Copyright 2008 Yubico AB                                       **\r
+**                                                                      **\r
+**      Date           / Sig / Rev  / History                          **\r
+**      2008-06-05     / J E / 0.00 / Main                             **\r
+**                                                                      **\r
+**************************************************************************\r
+**\r
+**     For binary compatibility, ykdef structures must be byte-aligned\r
+**     Furthermore - define ENDIAN_SWAP appropriately\r
+*/\r
+\r
+#ifdef _WIN32\r
+#pragma pack(push, 1)\r
+#endif\r
+\r
+#include <ykdef.h>\r
+\r
+#ifdef _WIN32\r
+#pragma pack(pop)\r
+#endif\r
+\r
+#ifdef _WIN32\r
+// Little endian\r
+#define        ENDIAN_SWAP(x)\r
+#else\r
+// Big endian\r
+#define        ENDIAN_SWAP(x)  x = ((x) >> 8) | ((x) << 8)\r
+#endif\r
+\r
+typedef void YUBIKEY;\r
+\r
+extern int ykInit(void);\r
+extern YUBIKEY * ykOpen(void);\r
+extern void ykClose(YUBIKEY *);\r
+extern int ykGetStatus(YUBIKEY *, STATUS *, int);\r
+extern int ykWriteConfig(YUBIKEY *, CONFIG *, unsigned char *);\r