eprint don't need \n in the format
[pam_pcsc_cr.git] / ykneo.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <stdlib.h>
5 #include <string.h>
6 #include <alloca.h>
7
8 #include "token.h"
9
10 #define NAMEPFX "YubikeyNEO"
11
12 static const BYTE selcmd[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xA0,
13                                 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x00};
14 static const BYTE yk_cmd[] = {0x00, 0x01, 0xff, 0x00};
15
16 static BYTE cr_for_slot[3] = {0xff, 0x30, 0x38};
17
18 static int slot = 2;    /* second by default, people tend to leave */
19                         /* the first with factory settings.        */
20
21 static int ykn_parse_option(char *key, char *val)
22 {
23         if (!strcmp(key, "slot")) {
24                 if (!strcmp(val, "1")) {
25                         slot = 1;
26                 } else if (!strcmp(val, "2")) {
27                         slot = 2;
28                 } else {
29                         return -1;
30                 }
31         } else {
32                 return -1;
33         }
34         return 0;
35 }
36
37 static DWORD ykn_check_atr_hb(BYTE *str, DWORD size)
38 {
39         if (size < strlen(NAMEPFX)) return SCARD_W_UNSUPPORTED_CARD;
40         if (memcmp(str, NAMEPFX, strlen(NAMEPFX)))
41                 return SCARD_W_UNSUPPORTED_CARD;
42         return SCARD_S_SUCCESS;
43 }
44
45 static DWORD ykn_prologue(SCARDHANDLE hCard)
46 {
47         BYTE buf[258];
48         DWORD rsize = sizeof(buf);
49         DWORD rc = SCardBeginTransaction(hCard);
50         if (rc) return rc;
51         rc = SCardTransmit(hCard, &pioSendPci, selcmd, sizeof(selcmd),
52                 NULL, buf, &rsize);
53         if (rc) return rc;
54         if ((buf[rsize-2] == 0x90) && (buf[rsize-1] == 0x00))
55                 return SCARD_S_SUCCESS;
56         else return SCARD_W_CARD_NOT_AUTHENTICATED;
57 }
58
59 static DWORD ykn_getserial(SCARDHANDLE hCard, BYTE *recv, LPDWORD recvsize_p)
60 {
61         DWORD rc;
62         BYTE rbuf[4 + 2];
63         DWORD rsize = sizeof(rbuf);
64         BYTE sbuf[sizeof(yk_cmd) + 1];
65         unsigned int serial;
66
67         memcpy(sbuf, yk_cmd, sizeof(yk_cmd));
68         sbuf[2] = 0x10; /* read serial */
69         sbuf[4] = rsize;
70         rc = SCardTransmit(hCard, &pioSendPci, sbuf, sizeof(sbuf),
71                         NULL, rbuf, &rsize);
72         if (rc) return rc;
73         if ((rbuf[rsize-2] != 0x90) || (rbuf[rsize-1] != 0x00))
74                 return SCARD_W_CARD_NOT_AUTHENTICATED;
75         serial = (rbuf[0]<<24) + (rbuf[1]<<16) + (rbuf[2]<<8) + (rbuf[3]);
76         rc = snprintf(recv, *recvsize_p, "%u", serial);
77         *recvsize_p = rc;
78         return SCARD_S_SUCCESS;
79 }
80
81 static DWORD ykn_trancieve(SCARDHANDLE hCard,
82         BYTE *send, DWORD sendsize, BYTE *recv, LPDWORD recvsize_p)
83 {
84         DWORD rc;
85         DWORD rsize = *recvsize_p + 2;
86         BYTE *rbuf = alloca(rsize);
87         BYTE *sbuf = alloca(sendsize + 6);
88         memcpy(sbuf, yk_cmd, sizeof(yk_cmd));
89         sbuf[2] = cr_for_slot[slot];
90         sbuf[sizeof(yk_cmd)] = sendsize;
91         memcpy(sbuf + sizeof(yk_cmd) + 1, send, sendsize);
92         sbuf[sendsize + 5] = rsize;
93         rc = SCardTransmit(hCard, &pioSendPci, sbuf, sendsize + 6,
94                 NULL, rbuf, &rsize);
95         if (rc) return rc;
96         if ((rbuf[rsize-2] != 0x90) || (rbuf[rsize-1] != 0x00))
97                 return SCARD_W_CARD_NOT_AUTHENTICATED;
98         memcpy(recv, rbuf, rsize - 2);
99         *recvsize_p = rsize - 2;
100         return SCARD_S_SUCCESS;
101 }
102
103 static DWORD ykn_epilogue(SCARDHANDLE hCard)
104 {
105         return SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
106 }
107
108 struct token_interface ykneo_interface = {
109         .name           = "ykneo",
110         .parse_option   = ykn_parse_option,
111         .check_atr_hb   = ykn_check_atr_hb,
112         .prologue       = ykn_prologue,
113         .getserial      = ykn_getserial,
114         .trancieve      = ykn_trancieve,
115         .epilogue       = ykn_epilogue,
116 };