Initial import
[pam_pcsc_cr.git] / ykneo.c
1 #include <string.h>
2 #include <alloca.h>
3
4 #include "token.h"
5
6 #define NAMEPFX "YubikeyNEO"
7
8 static const BYTE selcmd[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xA0,
9                                 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x00};
10 static const BYTE cr_cmd[] = {0x00, 0x01, 0x38, 0x00};
11
12 static DWORD ykn_check_atr_hb(LPTSTR str, DWORD size)
13 {
14         if (size < strlen(NAMEPFX)) return SCARD_W_UNSUPPORTED_CARD;
15         if (memcmp(str, NAMEPFX, strlen(NAMEPFX)))
16                 return SCARD_W_UNSUPPORTED_CARD;
17         return SCARD_S_SUCCESS;
18 }
19
20 static DWORD ykn_prologue(SCARDHANDLE hCard,LPTSTR envp[])
21 {
22         BYTE buf[258];
23         DWORD rsize = sizeof(buf);
24         DWORD rc = SCardBeginTransaction(hCard);
25         if (rc) return rc;
26         rc = SCardTransmit(hCard, &pioSendPci, selcmd, sizeof(selcmd),
27                 NULL, buf, &rsize);
28         if (rc) return rc;
29         if ((buf[rsize-2] == 0x90) && (buf[rsize-1] == 0x00))
30                 return SCARD_S_SUCCESS;
31         else return SCARD_W_CARD_NOT_AUTHENTICATED;
32 }
33
34 static DWORD ykn_trancieve(SCARDHANDLE hCard,LPTSTR envp[],
35         LPTSTR send, DWORD sendsize, LPTSTR recv, LPDWORD recvsize_p)
36 {
37         DWORD rc;
38         DWORD rsize = *recvsize_p + 2;
39         BYTE *rbuf = alloca(rsize);
40         BYTE *sbuf = alloca(sendsize + 6);
41         memcpy(sbuf, cr_cmd, sizeof(cr_cmd));
42         sbuf[sizeof(cr_cmd)] = sendsize;
43         memcpy(sbuf + sizeof(cr_cmd) + 1, send, sendsize);
44         sbuf[sendsize + 5] = rsize;
45         rc = SCardTransmit(hCard, &pioSendPci, sbuf, sendsize + 6,
46                 NULL, rbuf, &rsize);
47         if (rc) return rc;
48         if ((rbuf[rsize-2] != 0x90) || (rbuf[rsize-1] != 0x00))
49                 return SCARD_W_CARD_NOT_AUTHENTICATED;
50         memcpy(recv, rbuf, rsize - 2);
51         *recvsize_p = rsize - 2;
52         return SCARD_S_SUCCESS;
53 }
54
55 static DWORD ykn_epilogue(SCARDHANDLE hCard,LPTSTR envp[])
56 {
57         return SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
58 }
59
60 struct token_interface ykneo_interface = {
61         .check_atr_hb   = ykn_check_atr_hb,
62         .prologue       = ykn_prologue,
63         .trancieve      = ykn_trancieve,
64         .epilogue       = ykn_epilogue,
65 };