--- /dev/null
+# http://pcsclite.alioth.debian.org/pcsclite.html
+
+CFLAGS += -g $(shell pkg-config --cflags libpcsclite)
+LDLIBS += $(shell pkg-config --libs libpcsclite)
+
+test_cr: test_cr.o pcsc_cr.o ykneo.o
--- /dev/null
+#include <string.h>
+#include "token.h"
+#include <reader.h>
+
+extern struct token_interface ykneo_interface;
+
+static struct token_interface *types[] = {
+ &ykneo_interface,
+ NULL,
+};
+
+SCARD_IO_REQUEST pioSendPci;
+
+static LONG find_hb(LPTSTR atr, DWORD atrsize, LPTSTR *hb, LPDWORD hbsize)
+{
+ int i, j, cont;
+ if (atrsize < 2) return SCARD_W_UNSUPPORTED_CARD;
+ switch (atr[0]) {
+ case 0x3B: break;
+ case 0x3F: break;
+ default: return SCARD_W_UNSUPPORTED_CARD;
+ }
+ *hbsize = atr[1]&0x0f;
+ i=1;
+ do {
+ cont = atr[i]>>4;
+ for (j = 0; j < 4; j++) if (cont & (0x01 << j)) i++;
+ } while ((cont & 0x08) && (i < atrsize));
+ if ((i + (*hbsize) + 2) != atrsize)
+ return SCARD_W_UNSUPPORTED_CARD;
+ *hb = atr + i + 1;
+ return SCARD_S_SUCCESS;
+}
+
+long pcsc_cr(unsigned char *chal, int csize, unsigned char *resp, int *rsize)
+{
+ struct token_interface *type;
+ LONG rc;
+ SCARDCONTEXT hContext;
+ LPTSTR readers, rdr;
+ SCARDHANDLE hCard;
+ DWORD nrdrs = SCARD_AUTOALLOCATE, activeproto;
+ BYTE atr[33];
+ DWORD atrsize;
+ LPTSTR hb;
+ DWORD hbsize;
+ DWORD lrsize;
+ int i;
+
+ rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
+ if (rc) return rc;
+ rc = SCardListReaders(hContext, NULL, (LPTSTR)&readers, &nrdrs);
+ if (rc) return rc;
+ for (rdr=readers; rdr < readers + nrdrs - 1; rdr += strlen(rdr) + 1) {
+ rc = SCardConnect(hContext, rdr, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
+ &hCard, &activeproto);
+ if (rc) continue;
+ switch (activeproto) {
+ case SCARD_PROTOCOL_T0:
+ pioSendPci = *SCARD_PCI_T0;
+ break;
+ case SCARD_PROTOCOL_T1:
+ pioSendPci = *SCARD_PCI_T1;
+ break;
+ }
+ atrsize = sizeof(atr);
+ rc = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING,
+ atr, &atrsize);
+ if (rc) goto disconnect;
+ rc = find_hb(atr, atrsize, &hb, &hbsize);
+ if (rc) goto disconnect;
+ for (i = 0; types[i]; i++) {
+ type = types[i];
+ rc = type->check_atr_hb(hb, hbsize);
+ if (rc == 0) break;
+ }
+ if (rc) goto disconnect;
+ rc = type->prologue(hCard, NULL);
+ if (rc == 0) break;
+ disconnect:
+ (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD);
+ }
+ if (rc) goto free_out;
+ lrsize = *rsize;
+ rc = type->trancieve(hCard, NULL, chal, csize, resp, &lrsize);
+ if (rc) goto disc_free_out;
+ *rsize = lrsize;
+ rc = type->epilogue(hCard, NULL);
+disc_free_out:
+ (void)SCardDisconnect(hCard, SCARD_EJECT_CARD);
+free_out:
+ (void)SCardFreeMemory(hContext, readers);
+ return rc;
+}
+
+char *pcsc_errstr(long err) {
+ return pcsc_stringify_error(err);
+}
--- /dev/null
+#ifndef _PCSC_CR_H
+#define _PCSC_CR_H
+
+long pcsc_cr(unsigned char *chal, int csize, unsigned char *resp, int *rsize);
+char *pcsc_errstr(long err);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include "pcsc_cr.h"
+
+char chal[] = {
+0x0f,0x65,0xd1,0x3a,0xfe,0xcb,0xc4,0xb9,0x52,0xb1,0x60,0xcf,0xe8,0x55,0x6a,0xdd,0xfb,0xef,0xf6,0x55,0x83,0x4c,0x8d,0xea,0x38,0xea,0x3b,0x26,0xf7,0x0a,0xe8,0x0d,0x31,0x38,0xee,0x16,0x5d,0xab,0x8b,0x7f,0xf0,0x1b,0xe3,0xbe,0xd8,0x4b,0x6e,0x44,0x42,0x8d,0x0f,0xc1,0x3b,0x23,0xea,0xfe,0xc0,0x68,0xc1,0x0f,0x60,0x6c,0xf4};
+
+int main(int argc, char *argv[])
+{
+ unsigned char rbuf[20];
+ int rsize = sizeof(rbuf);
+ int i;
+ long rc;
+
+ memset(rbuf, 0xFE, sizeof(rbuf));
+ rc = pcsc_cr(chal, sizeof(chal), rbuf, &rsize);
+ printf("rc=%ld (%s) rsize=%d:", rc, pcsc_errstr(rc), rsize);
+ for (i = 0; i < rsize; i++) printf(" %02x", rbuf[i]);
+ printf("\n");
+ return rc;
+}
--- /dev/null
+#ifndef _TOKEN_H
+#define _TOKEN_H
+
+#include <winscard.h>
+
+extern SCARD_IO_REQUEST pioSendPci;
+
+struct token_interface {
+ DWORD (*check_atr_hb)(LPTSTR str, DWORD size);
+ DWORD (*prologue)(SCARDHANDLE hCard,LPTSTR envp[]);
+ DWORD (*trancieve)(SCARDHANDLE hCard,LPTSTR envp[],
+ LPTSTR send, DWORD sendsize, LPTSTR recv, LPDWORD recvsize_p);
+ DWORD (*epilogue)(SCARDHANDLE hCard,LPTSTR envp[]);
+};
+
+#endif
--- /dev/null
+#include <string.h>
+#include <alloca.h>
+
+#include "token.h"
+
+#define NAMEPFX "YubikeyNEO"
+
+static const BYTE selcmd[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xA0,
+ 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x00};
+static const BYTE cr_cmd[] = {0x00, 0x01, 0x38, 0x00};
+
+static DWORD ykn_check_atr_hb(LPTSTR str, DWORD size)
+{
+ if (size < strlen(NAMEPFX)) return SCARD_W_UNSUPPORTED_CARD;
+ if (memcmp(str, NAMEPFX, strlen(NAMEPFX)))
+ return SCARD_W_UNSUPPORTED_CARD;
+ return SCARD_S_SUCCESS;
+}
+
+static DWORD ykn_prologue(SCARDHANDLE hCard,LPTSTR envp[])
+{
+ BYTE buf[258];
+ DWORD rsize = sizeof(buf);
+ DWORD rc = SCardBeginTransaction(hCard);
+ if (rc) return rc;
+ rc = SCardTransmit(hCard, &pioSendPci, selcmd, sizeof(selcmd),
+ NULL, buf, &rsize);
+ if (rc) return rc;
+ if ((buf[rsize-2] == 0x90) && (buf[rsize-1] == 0x00))
+ return SCARD_S_SUCCESS;
+ else return SCARD_W_CARD_NOT_AUTHENTICATED;
+}
+
+static DWORD ykn_trancieve(SCARDHANDLE hCard,LPTSTR envp[],
+ LPTSTR send, DWORD sendsize, LPTSTR recv, LPDWORD recvsize_p)
+{
+ DWORD rc;
+ DWORD rsize = *recvsize_p + 2;
+ BYTE *rbuf = alloca(rsize);
+ BYTE *sbuf = alloca(sendsize + 6);
+ memcpy(sbuf, cr_cmd, sizeof(cr_cmd));
+ sbuf[sizeof(cr_cmd)] = sendsize;
+ memcpy(sbuf + sizeof(cr_cmd) + 1, send, sendsize);
+ sbuf[sendsize + 5] = rsize;
+ rc = SCardTransmit(hCard, &pioSendPci, sbuf, sendsize + 6,
+ NULL, rbuf, &rsize);
+ if (rc) return rc;
+ if ((rbuf[rsize-2] != 0x90) || (rbuf[rsize-1] != 0x00))
+ return SCARD_W_CARD_NOT_AUTHENTICATED;
+ memcpy(recv, rbuf, rsize - 2);
+ *recvsize_p = rsize - 2;
+ return SCARD_S_SUCCESS;
+}
+
+static DWORD ykn_epilogue(SCARDHANDLE hCard,LPTSTR envp[])
+{
+ return SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+}
+
+struct token_interface ykneo_interface = {
+ .check_atr_hb = ykn_check_atr_hb,
+ .prologue = ykn_prologue,
+ .trancieve = ykn_trancieve,
+ .epilogue = ykn_epilogue,
+};