Initial import
[pam_pcsc_cr.git] / pcsc_cr.c
1 #include <string.h>
2 #include "token.h"
3 #include <reader.h>
4
5 extern struct token_interface ykneo_interface;
6
7 static struct token_interface *types[] = {
8         &ykneo_interface,
9         NULL,
10 };
11
12 SCARD_IO_REQUEST pioSendPci;
13
14 static LONG find_hb(LPTSTR atr, DWORD atrsize, LPTSTR *hb, LPDWORD hbsize)
15 {
16         int i, j, cont;
17         if (atrsize < 2) return SCARD_W_UNSUPPORTED_CARD;
18         switch (atr[0]) {
19         case 0x3B: break;
20         case 0x3F: break;
21         default: return SCARD_W_UNSUPPORTED_CARD;
22         }
23         *hbsize = atr[1]&0x0f;
24         i=1;
25         do {
26                 cont = atr[i]>>4;
27                 for (j = 0; j < 4; j++) if (cont & (0x01 << j)) i++;
28         } while ((cont & 0x08) && (i < atrsize));
29         if ((i + (*hbsize) + 2) != atrsize)
30                 return SCARD_W_UNSUPPORTED_CARD;
31         *hb = atr + i + 1;
32         return SCARD_S_SUCCESS;
33 }
34
35 long pcsc_cr(unsigned char *chal, int csize, unsigned char *resp, int *rsize)
36 {
37         struct token_interface *type;
38         LONG rc;
39         SCARDCONTEXT hContext;
40         LPTSTR readers, rdr;
41         SCARDHANDLE hCard;
42         DWORD nrdrs = SCARD_AUTOALLOCATE, activeproto;
43         BYTE atr[33];
44         DWORD atrsize;
45         LPTSTR hb;
46         DWORD hbsize;
47         DWORD lrsize;
48         int i;
49
50         rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
51         if (rc) return rc;
52         rc = SCardListReaders(hContext, NULL, (LPTSTR)&readers, &nrdrs);
53         if (rc) return rc;
54         for (rdr=readers; rdr < readers + nrdrs - 1; rdr += strlen(rdr) + 1) {
55                 rc = SCardConnect(hContext, rdr, SCARD_SHARE_SHARED,
56                         SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
57                         &hCard, &activeproto);
58                 if (rc) continue;
59                 switch (activeproto) {
60                 case SCARD_PROTOCOL_T0:
61                         pioSendPci = *SCARD_PCI_T0;
62                         break;
63                 case SCARD_PROTOCOL_T1:
64                         pioSendPci = *SCARD_PCI_T1;
65                         break;
66                 }
67                 atrsize = sizeof(atr);
68                 rc = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING,
69                         atr, &atrsize);
70                 if (rc) goto disconnect;
71                 rc = find_hb(atr, atrsize, &hb, &hbsize);
72                 if (rc) goto disconnect;
73                 for (i = 0; types[i]; i++) {
74                         type = types[i];
75                         rc = type->check_atr_hb(hb, hbsize);
76                         if (rc == 0) break;
77                 }
78                 if (rc) goto disconnect;
79                 rc = type->prologue(hCard, NULL);
80                 if (rc == 0) break;
81         disconnect:
82                 (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD);
83         }
84         if (rc) goto free_out;
85         lrsize = *rsize;
86         rc = type->trancieve(hCard, NULL, chal, csize, resp, &lrsize);
87         if (rc) goto disc_free_out;
88         *rsize = lrsize;
89         rc = type->epilogue(hCard, NULL);
90 disc_free_out:
91         (void)SCardDisconnect(hCard, SCARD_EJECT_CARD);
92 free_out:
93         (void)SCardFreeMemory(hContext, readers);
94         return rc;
95 }
96
97 char *pcsc_errstr(long err) {
98         return pcsc_stringify_error(err);
99 }