/[openpgpmdrv]/trunk/OpenPGPminidriver/SmartCard.c
ViewVC logotype

Annotation of /trunk/OpenPGPminidriver/SmartCard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide annotations)
Thu Mar 18 16:03:39 2010 UTC (15 years, 1 month ago) by vletoux
File MIME type: text/plain
File size: 9960 byte(s)
first working & stable version
1 vletoux 1 /* OpenPGP Smart Card Mini Driver
2     Copyright (C) 2009 Vincent Le Toux
3    
4     This library is Free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License version 2.1 as published by the Free Software Foundation.
7    
8     This library is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11     Lesser General Public License for more details.
12    
13     You should have received a copy of the GNU Lesser General Public
14     License along with this library; if not, write to the Free Software
15     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16     */
17    
18     #include <windows.h>
19     #include <cardmod.h>
20     #include <stdio.h>
21     #include "Tracing.h"
22     #include "Context.h"
23     #include "SmartCard.h"
24    
25     #pragma comment(lib,"Winscard")
26    
27 vletoux 8 DWORD SelectOpenPGPApplication(__in PCARD_DATA pCardData);
28 vletoux 1
29 vletoux 8 DWORD OCardReconnect(__in PCARD_DATA pCardData)
30 vletoux 1 {
31 vletoux 8 DWORD dwAP;
32     DWORD dwReturn;
33     __try
34     {
35     // reset the card
36     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
37     dwReturn = SCardReconnect(pCardData->hScard,
38     SCARD_SHARE_SHARED,
39     SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
40     SCARD_LEAVE_CARD,
41     &dwAP );
42     if (dwReturn)
43     {
44     Trace(WINEVENT_LEVEL_ERROR, L"SCardReconnect 0x%08X", dwReturn);
45     __leave;
46     }
47    
48     dwReturn = SelectOpenPGPApplication(pCardData);
49     }
50     __finally
51     {
52     }
53     return dwReturn;
54     }
55    
56     DWORD OCardSendCommand(__in PCARD_DATA pCardData, __in PBYTE pbCmd, __in DWORD dwCmdSize)
57     {
58 vletoux 1 DWORD dwReturn = 0;
59    
60     SCARD_IO_REQUEST ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
61     SCARD_IO_REQUEST ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
62     BYTE recvbuf[256];
63     DWORD recvlen = sizeof(recvbuf);
64     BYTE SW1, SW2;
65     __try
66     {
67    
68     dwReturn = SCardTransmit(pCardData->hScard,
69     SCARD_PCI_T1,
70     pbCmd,
71     dwCmdSize,
72     NULL,
73     recvbuf,
74     &recvlen);
75     if ( dwReturn != SCARD_S_SUCCESS )
76     {
77 vletoux 8 if (dwReturn == SCARD_W_RESET_CARD)
78     {
79     dwReturn = OCardReconnect(pCardData);
80     if (dwReturn)
81     {
82     __leave;
83     }
84     dwReturn = OCardSendCommand(pCardData,pbCmd, dwCmdSize);
85     __leave;
86     }
87 vletoux 1 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
88     __leave;
89     }
90     SW1 = recvbuf[recvlen-2];
91     SW2 = recvbuf[recvlen-1];
92 vletoux 9 if ( (SW1 == 0x6A) && (SW2 == 0x88) )
93     {
94     Trace(WINEVENT_LEVEL_ERROR, L"card reset");
95     recvlen = sizeof(recvbuf);
96     dwReturn = SelectOpenPGPApplication(pCardData);
97     if (dwReturn)
98     {
99     __leave;
100     }
101     dwReturn = SCardTransmit(pCardData->hScard,
102     SCARD_PCI_T1,
103     pbCmd,
104     dwCmdSize,
105     NULL,
106     recvbuf,
107     &recvlen);
108     SW1 = recvbuf[recvlen-2];
109     SW2 = recvbuf[recvlen-1];
110     }
111 vletoux 1 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
112     {
113    
114     }
115     else if ( (SW1 == 0x69) && (SW2 == 0x82) )
116     {
117     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
118     dwReturn = SCARD_W_WRONG_CHV;
119     __leave;
120     }
121     else if ( (SW1 == 0x69) && (SW2 == 0x83) )
122     {
123     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
124     dwReturn = SCARD_W_CHV_BLOCKED;
125     __leave;
126     }
127 vletoux 11 else if ( (SW1 == 0x69) && (SW2 == 0x85) )
128     {
129     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION");
130     dwReturn = SCARD_W_SECURITY_VIOLATION;
131     __leave;
132     }
133 vletoux 1 else
134     {
135     TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
136     Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
137     dwReturn = SCARD_F_UNKNOWN_ERROR;
138     __leave;
139     }
140     }
141     __finally
142     {
143     }
144     return dwReturn;
145     }
146    
147     DWORD SelectOpenPGPApplication(__in PCARD_DATA pCardData)
148     {
149     BYTE pbCmd[] = {0x00,
150     0xA4,
151     0x04,
152     0x00,
153     0x06,
154     0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
155     0x00
156     };
157    
158 vletoux 8 return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
159 vletoux 1 }
160    
161    
162 vletoux 8 DWORD OCardGetData(__in PCARD_DATA pCardData,
163 vletoux 1 __in PBYTE pbCmd, __in DWORD dwCmdSize,
164     __in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
165     {
166    
167     DWORD dwReturn;
168     BYTE pbGetResponse[] = {0x00,
169     0xC0,
170     0x00,
171     0x00,
172     0x00
173     };
174     DWORD dwGetResponseSize = ARRAYSIZE(pbGetResponse);
175     BYTE recvbuf[0x800];
176     DWORD recvlen = sizeof(recvbuf);
177     BYTE SW1, SW2;
178     DWORD dwDataSize = 0;
179     __try
180     {
181    
182     *pbResponse = NULL;
183     dwReturn = SCardTransmit(pCardData->hScard,
184     SCARD_PCI_T1,
185     pbCmd,
186     dwCmdSize,
187     NULL,
188     recvbuf,
189     &recvlen);
190    
191     do
192     {
193     if ( dwReturn != SCARD_S_SUCCESS )
194     {
195 vletoux 8 if (dwReturn == SCARD_W_RESET_CARD)
196     {
197     dwReturn = OCardReconnect(pCardData);
198     if (dwReturn)
199     {
200     __leave;
201     }
202     dwReturn = OCardGetData(pCardData,pbCmd, dwCmdSize,pbResponse, pdwResponseSize);
203     __leave;
204     }
205 vletoux 1 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
206     __leave;
207     }
208     SW1 = recvbuf[recvlen-2];
209     SW2 = recvbuf[recvlen-1];
210 vletoux 9 if ( (SW1 == 0x6A) && (SW2 == 0x88) )
211     {
212     Trace(WINEVENT_LEVEL_ERROR, L"card reset");
213     recvlen = sizeof(recvbuf);
214     dwReturn = SelectOpenPGPApplication(pCardData);
215     if (dwReturn)
216     {
217     __leave;
218     }
219     dwReturn = SCardTransmit(pCardData->hScard,
220     SCARD_PCI_T1,
221     pbCmd,
222     dwCmdSize,
223     NULL,
224     recvbuf,
225     &recvlen);
226     SW1 = recvbuf[recvlen-2];
227     SW2 = recvbuf[recvlen-1];
228     }
229 vletoux 1 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
230     {
231     dwDataSize = recvlen-2;
232     *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
233 vletoux 6 if (! *pbResponse)
234     {
235     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
236     dwReturn = SCARD_E_NO_MEMORY;
237     __leave;
238     }
239 vletoux 1 memcpy(*pbResponse, recvbuf, dwDataSize);
240     }
241     else if (SW1 == 0x61)
242     {
243     dwDataSize += SW2;
244     if (*pbResponse)
245     {
246     *pbResponse = pCardData->pfnCspReAlloc(*pbResponse, dwDataSize);
247     }
248     else
249     {
250     *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
251     }
252     dwGetResponseSize = ARRAYSIZE(pbGetResponse);
253     dwReturn = SCardTransmit(pCardData->hScard,
254     SCARD_PCI_T1,
255     pbGetResponse,
256     dwGetResponseSize,
257     NULL,
258     recvbuf,
259     &recvlen);
260     }
261     else if ( (SW1 == 0x69) && (SW2 == 0x82) )
262     {
263     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
264     dwReturn = SCARD_W_WRONG_CHV;
265     __leave;
266     }
267     else if ( (SW1 == 0x69) && (SW2 == 0x83) )
268     {
269     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
270     dwReturn = SCARD_W_CHV_BLOCKED;
271     __leave;
272     }
273 vletoux 11 else if ( (SW1 == 0x69) && (SW2 == 0x85) )
274     {
275     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION");
276     dwReturn = SCARD_W_SECURITY_VIOLATION;
277     __leave;
278     }
279 vletoux 1 else
280     {
281     TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
282     Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
283     dwReturn = SCARD_F_UNKNOWN_ERROR;
284     __leave;
285     }
286    
287     } while (SW1 == 0x61);
288     if (pdwResponseSize)
289     {
290     *pdwResponseSize = dwDataSize;
291     }
292     }
293     __finally
294     {
295     }
296     return dwReturn;
297     }
298    
299     DWORD CCIDfindFeature(BYTE featureTag, BYTE* features, DWORD featuresLength)
300     {
301     DWORD idx = 0;
302     int count;
303     while (idx < featuresLength) {
304     BYTE tag = features[idx];
305     idx++;
306     idx++;
307     if (featureTag == tag) {
308     DWORD feature = 0;
309     for (count = 0; count < 3; count++) {
310     feature |= features[idx] & 0xff;
311     idx++;
312     feature <<= 8;
313     }
314     feature |= features[idx] & 0xff;
315     return feature;
316     }
317     idx += 4;
318     }
319     return 0;
320     }
321    
322     DWORD CCIDgetFeatures(__in PCARD_DATA pCardData)
323     {
324     BYTE pbRecvBuffer[200];
325     DWORD dwRecvLength, dwReturn;
326     __try
327     {
328     POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
329    
330     pContext->SmartCardReaderFeatures.VERIFY_PIN_START = 0;
331     pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = 0;
332     pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = 0;
333     pContext->SmartCardReaderFeatures.MODIFY_PIN_START = 0;
334     pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = 0;
335     pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = 0;
336     pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = 0;
337     pContext->SmartCardReaderFeatures.ABORT = 0;
338    
339     dwReturn = SCardControl(pCardData->hScard,
340     SCARD_CTL_CODE(3400),
341     NULL,
342     0,
343     pbRecvBuffer,
344     sizeof(pbRecvBuffer),
345     &dwRecvLength);
346     if ( dwReturn )
347     {
348     Trace(WINEVENT_LEVEL_ERROR, L"SCardControl errorcode: [0x%02X]", dwReturn);
349     __leave;
350     }
351     pContext->SmartCardReaderFeatures.VERIFY_PIN_START = CCIDfindFeature(FEATURE_VERIFY_PIN_START, pbRecvBuffer, dwRecvLength);
352     pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = CCIDfindFeature(FEATURE_VERIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
353     pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_VERIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
354     pContext->SmartCardReaderFeatures.MODIFY_PIN_START = CCIDfindFeature(FEATURE_MODIFY_PIN_START, pbRecvBuffer, dwRecvLength);
355     pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = CCIDfindFeature(FEATURE_MODIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
356     pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_MODIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
357     pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = CCIDfindFeature(FEATURE_GET_KEY_PRESSED, pbRecvBuffer, dwRecvLength);
358     pContext->SmartCardReaderFeatures.ABORT = CCIDfindFeature(FEATURE_ABORT, pbRecvBuffer, dwRecvLength);
359     }
360     __finally
361     {
362     }
363     return dwReturn;
364     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26