add more debug prints
[pam_pcsc_cr.git] / pcsc_cr.c
1 /*
2 Copyright (c) 2013 Eugene Crosser
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12     1. The origin of this software must not be misrepresented; you must
13     not claim that you wrote the original software. If you use this
14     software in a product, an acknowledgment in the product documentation
15     would be appreciated but is not required.
16
17     2. Altered source versions must be plainly marked as such, and must
18     not be misrepresented as being the original software.
19
20     3. This notice may not be removed or altered from any source
21     distribution.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 #include <stdio.h>
28 #include <string.h>
29 #include <alloca.h>
30 #include "token.h"
31 #include <reader.h>
32
33 extern struct token_interface ykneo_interface;
34
35 static struct token_interface *types[] = {
36         &ykneo_interface,
37         NULL,
38 };
39
40 SCARD_IO_REQUEST pioSendPci;
41
42 static LONG find_hb(BYTE *atr, DWORD atrsize, BYTE **hb, LPDWORD hbsize)
43 {
44         int i, j, cont;
45         if (atrsize < 2) return SCARD_W_UNSUPPORTED_CARD;
46         switch (atr[0]) {
47         case 0x3B: break;
48         case 0x3F: break;
49         default: return SCARD_W_UNSUPPORTED_CARD;
50         }
51         *hbsize = atr[1]&0x0f;
52         i=1;
53         do {
54                 cont = atr[i]>>4;
55                 for (j = 0; j < 4; j++) if (cont & (0x01 << j)) i++;
56         } while ((cont & 0x08) && (i < atrsize));
57         if ((i + (*hbsize) + 2) != atrsize)
58                 return SCARD_W_UNSUPPORTED_CARD;
59         *hb = atr + i + 1;
60         return SCARD_S_SUCCESS;
61 }
62
63 long pcsc_cr(const unsigned char *chal, const int csize,
64                 unsigned char *resp, int *rsize)
65 {
66         struct token_interface *type;
67         LONG rc;
68         SCARDCONTEXT hContext;
69         LPTSTR readers, rdr;
70         SCARDHANDLE hCard;
71         DWORD nrdrs = SCARD_AUTOALLOCATE, activeproto;
72         BYTE atr[33];
73         DWORD atrsize;
74         BYTE *hb;
75         DWORD hbsize;
76         DWORD lrsize;
77         int i;
78
79         rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
80         if (rc) return rc;
81         rc = SCardListReaders(hContext, NULL, (LPTSTR)&readers, &nrdrs);
82         if (rc) return rc;
83         for (rdr=readers; rdr < readers + nrdrs - 1; rdr += strlen(rdr) + 1) {
84                 rc = SCardConnect(hContext, rdr, SCARD_SHARE_SHARED,
85                         SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
86                         &hCard, &activeproto);
87                 if (rc) continue;
88                 switch (activeproto) {
89                 case SCARD_PROTOCOL_T0:
90                         pioSendPci = *SCARD_PCI_T0;
91                         break;
92                 case SCARD_PROTOCOL_T1:
93                         pioSendPci = *SCARD_PCI_T1;
94                         break;
95                 }
96                 atrsize = sizeof(atr);
97                 rc = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING,
98                         atr, &atrsize);
99                 if (rc) goto disconnect;
100                 rc = find_hb(atr, atrsize, &hb, &hbsize);
101                 if (rc) goto disconnect;
102                 for (i = 0; types[i]; i++) {
103                         type = types[i];
104                         rc = type->check_atr_hb(hb, hbsize);
105                         if (rc == 0) break;
106                 }
107                 if (rc) goto disconnect;
108                 rc = type->prologue(hCard);
109                 if (rc == 0) break;
110         disconnect:
111                 (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD);
112         }
113         if (rc) goto free_out;
114 #if 0
115         char serial[16];
116         memset(serial, 'z', sizeof(serial));
117         serial[sizeof(serial) - 1] - '\0';
118         lrsize = sizeof(serial);
119         rc = type->getserial(hCard, &serial, &lrsize);
120         if (rc) goto disc_free_out;
121         printf("Serial is %s\n", serial);
122 #endif
123         lrsize = *rsize;
124         rc = type->trancieve(hCard, (BYTE*)chal, csize, resp, &lrsize);
125         if (rc) goto disc_free_out;
126         *rsize = lrsize;
127         rc = type->epilogue(hCard);
128 disc_free_out:
129         (void)SCardDisconnect(hCard, SCARD_EJECT_CARD);
130 free_out:
131         (void)SCardFreeMemory(hContext, readers);
132         return rc;
133 }
134
135 char *pcsc_errstr(long err) {
136         return pcsc_stringify_error(err);
137 }
138
139 int pcsc_option(const char *option)
140 {
141         char *name, *key, *val;
142         int i, rc = -1;
143         struct token_interface *type;
144
145         name=(char *)alloca(strlen(option)+1);
146         strcpy(name, option);
147         if ((key = strchr(name, ':'))) *(key++) = '\0';
148         else return -1;
149         if ((val = strchr(key, '='))) *(val++) = '\0';
150         else return -1;
151         if (*val == '\0') return -1;
152         for (i = 0; types[i]; i++) {
153                 type = types[i];
154                 if (!strcmp(type->name,name)) {
155                         rc = type->parse_option(key, val);
156                         break;
157                 }
158         }
159         return rc;
160 }