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