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

Annotation of /trunk/OpenPGPminidriver/SmartCard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (hide annotations)
Mon Mar 15 09:47:30 2010 UTC (15 years, 1 month ago) by vletoux
File MIME type: text/plain
File size: 9602 byte(s)
more test success
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     else
128     {
129     TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
130     Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
131     dwReturn = SCARD_F_UNKNOWN_ERROR;
132     __leave;
133     }
134     }
135     __finally
136     {
137     }
138     return dwReturn;
139     }
140    
141     DWORD SelectOpenPGPApplication(__in PCARD_DATA pCardData)
142     {
143     BYTE pbCmd[] = {0x00,
144     0xA4,
145     0x04,
146     0x00,
147     0x06,
148     0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
149     0x00
150     };
151    
152 vletoux 8 return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
153 vletoux 1 }
154    
155    
156 vletoux 8 DWORD OCardGetData(__in PCARD_DATA pCardData,
157 vletoux 1 __in PBYTE pbCmd, __in DWORD dwCmdSize,
158     __in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
159     {
160    
161     DWORD dwReturn;
162     BYTE pbGetResponse[] = {0x00,
163     0xC0,
164     0x00,
165     0x00,
166     0x00
167     };
168     DWORD dwGetResponseSize = ARRAYSIZE(pbGetResponse);
169     BYTE recvbuf[0x800];
170     DWORD recvlen = sizeof(recvbuf);
171     BYTE SW1, SW2;
172     DWORD dwDataSize = 0;
173     __try
174     {
175    
176     *pbResponse = NULL;
177     dwReturn = SCardTransmit(pCardData->hScard,
178     SCARD_PCI_T1,
179     pbCmd,
180     dwCmdSize,
181     NULL,
182     recvbuf,
183     &recvlen);
184    
185     do
186     {
187     if ( dwReturn != SCARD_S_SUCCESS )
188     {
189 vletoux 8 if (dwReturn == SCARD_W_RESET_CARD)
190     {
191     dwReturn = OCardReconnect(pCardData);
192     if (dwReturn)
193     {
194     __leave;
195     }
196     dwReturn = OCardGetData(pCardData,pbCmd, dwCmdSize,pbResponse, pdwResponseSize);
197     __leave;
198     }
199 vletoux 1 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
200     __leave;
201     }
202     SW1 = recvbuf[recvlen-2];
203     SW2 = recvbuf[recvlen-1];
204 vletoux 9 if ( (SW1 == 0x6A) && (SW2 == 0x88) )
205     {
206     Trace(WINEVENT_LEVEL_ERROR, L"card reset");
207     recvlen = sizeof(recvbuf);
208     dwReturn = SelectOpenPGPApplication(pCardData);
209     if (dwReturn)
210     {
211     __leave;
212     }
213     dwReturn = SCardTransmit(pCardData->hScard,
214     SCARD_PCI_T1,
215     pbCmd,
216     dwCmdSize,
217     NULL,
218     recvbuf,
219     &recvlen);
220     SW1 = recvbuf[recvlen-2];
221     SW2 = recvbuf[recvlen-1];
222     }
223 vletoux 1 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
224     {
225     dwDataSize = recvlen-2;
226     *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
227 vletoux 6 if (! *pbResponse)
228     {
229     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
230     dwReturn = SCARD_E_NO_MEMORY;
231     __leave;
232     }
233 vletoux 1 memcpy(*pbResponse, recvbuf, dwDataSize);
234     }
235     else if (SW1 == 0x61)
236     {
237     dwDataSize += SW2;
238     if (*pbResponse)
239     {
240     *pbResponse = pCardData->pfnCspReAlloc(*pbResponse, dwDataSize);
241     }
242     else
243     {
244     *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
245     }
246     dwGetResponseSize = ARRAYSIZE(pbGetResponse);
247     dwReturn = SCardTransmit(pCardData->hScard,
248     SCARD_PCI_T1,
249     pbGetResponse,
250     dwGetResponseSize,
251     NULL,
252     recvbuf,
253     &recvlen);
254     }
255     else if ( (SW1 == 0x69) && (SW2 == 0x82) )
256     {
257     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
258     dwReturn = SCARD_W_WRONG_CHV;
259     __leave;
260     }
261     else if ( (SW1 == 0x69) && (SW2 == 0x83) )
262     {
263     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
264     dwReturn = SCARD_W_CHV_BLOCKED;
265     __leave;
266     }
267     else
268     {
269     TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
270     Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
271     dwReturn = SCARD_F_UNKNOWN_ERROR;
272     __leave;
273     }
274    
275     } while (SW1 == 0x61);
276     if (pdwResponseSize)
277     {
278     *pdwResponseSize = dwDataSize;
279     }
280     }
281     __finally
282     {
283     }
284     return dwReturn;
285     }
286    
287     DWORD CCIDfindFeature(BYTE featureTag, BYTE* features, DWORD featuresLength)
288     {
289     DWORD idx = 0;
290     int count;
291     while (idx < featuresLength) {
292     BYTE tag = features[idx];
293     idx++;
294     idx++;
295     if (featureTag == tag) {
296     DWORD feature = 0;
297     for (count = 0; count < 3; count++) {
298     feature |= features[idx] & 0xff;
299     idx++;
300     feature <<= 8;
301     }
302     feature |= features[idx] & 0xff;
303     return feature;
304     }
305     idx += 4;
306     }
307     return 0;
308     }
309    
310     DWORD CCIDgetFeatures(__in PCARD_DATA pCardData)
311     {
312     BYTE pbRecvBuffer[200];
313     DWORD dwRecvLength, dwReturn;
314     __try
315     {
316     POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
317    
318     pContext->SmartCardReaderFeatures.VERIFY_PIN_START = 0;
319     pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = 0;
320     pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = 0;
321     pContext->SmartCardReaderFeatures.MODIFY_PIN_START = 0;
322     pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = 0;
323     pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = 0;
324     pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = 0;
325     pContext->SmartCardReaderFeatures.ABORT = 0;
326    
327     dwReturn = SCardControl(pCardData->hScard,
328     SCARD_CTL_CODE(3400),
329     NULL,
330     0,
331     pbRecvBuffer,
332     sizeof(pbRecvBuffer),
333     &dwRecvLength);
334     if ( dwReturn )
335     {
336     Trace(WINEVENT_LEVEL_ERROR, L"SCardControl errorcode: [0x%02X]", dwReturn);
337     __leave;
338     }
339     pContext->SmartCardReaderFeatures.VERIFY_PIN_START = CCIDfindFeature(FEATURE_VERIFY_PIN_START, pbRecvBuffer, dwRecvLength);
340     pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = CCIDfindFeature(FEATURE_VERIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
341     pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_VERIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
342     pContext->SmartCardReaderFeatures.MODIFY_PIN_START = CCIDfindFeature(FEATURE_MODIFY_PIN_START, pbRecvBuffer, dwRecvLength);
343     pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = CCIDfindFeature(FEATURE_MODIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
344     pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_MODIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
345     pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = CCIDfindFeature(FEATURE_GET_KEY_PRESSED, pbRecvBuffer, dwRecvLength);
346     pContext->SmartCardReaderFeatures.ABORT = CCIDfindFeature(FEATURE_ABORT, pbRecvBuffer, dwRecvLength);
347     }
348     __finally
349     {
350     }
351     return dwReturn;
352     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26