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