From: Eugene Crosser Date: Sun, 29 Sep 2013 20:35:59 +0000 (+0400) Subject: Initial import X-Git-Url: http://www.average.org/gitweb/?p=pam_pcsc_cr.git;a=commitdiff_plain;h=7c4066e68330f89016e939a6ad34036f9e00c11d Initial import --- 7c4066e68330f89016e939a6ad34036f9e00c11d diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..db68800 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +# 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 diff --git a/pcsc_cr.c b/pcsc_cr.c new file mode 100644 index 0000000..0354c32 --- /dev/null +++ b/pcsc_cr.c @@ -0,0 +1,99 @@ +#include +#include "token.h" +#include + +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); +} diff --git a/pcsc_cr.h b/pcsc_cr.h new file mode 100644 index 0000000..da97333 --- /dev/null +++ b/pcsc_cr.h @@ -0,0 +1,7 @@ +#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 diff --git a/test_cr.c b/test_cr.c new file mode 100644 index 0000000..2d66d5f --- /dev/null +++ b/test_cr.c @@ -0,0 +1,20 @@ +#include +#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; +} diff --git a/token.h b/token.h new file mode 100644 index 0000000..743aafb --- /dev/null +++ b/token.h @@ -0,0 +1,16 @@ +#ifndef _TOKEN_H +#define _TOKEN_H + +#include + +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 diff --git a/ykneo.c b/ykneo.c new file mode 100644 index 0000000..3399f71 --- /dev/null +++ b/ykneo.c @@ -0,0 +1,65 @@ +#include +#include + +#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, +};