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

Annotation of /trunk/OpenPGPminidriver/SmartCard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Wed Mar 31 08:58:46 2010 UTC (15 years, 1 month ago) by vletoux
File MIME type: text/plain
File size: 10220 byte(s)
first msi Release
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 12 /** called to re-select the Openpgp application when a SCARD_W_RESET occured */
30 vletoux 8 DWORD OCardReconnect(__in PCARD_DATA pCardData)
31 vletoux 1 {
32 vletoux 8 DWORD dwAP;
33     DWORD dwReturn;
34     __try
35     {
36     // reset the card
37     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
38     dwReturn = SCardReconnect(pCardData->hScard,
39     SCARD_SHARE_SHARED,
40     SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
41     SCARD_LEAVE_CARD,
42     &dwAP );
43     if (dwReturn)
44     {
45     Trace(WINEVENT_LEVEL_ERROR, L"SCardReconnect 0x%08X", dwReturn);
46     __leave;
47     }
48    
49     dwReturn = SelectOpenPGPApplication(pCardData);
50     }
51     __finally
52     {
53     }
54     return dwReturn;
55     }
56    
57 vletoux 12 /** send a command to the smart card with no response expected */
58 vletoux 8 DWORD OCardSendCommand(__in PCARD_DATA pCardData, __in PBYTE pbCmd, __in DWORD dwCmdSize)
59     {
60 vletoux 1 DWORD dwReturn = 0;
61    
62     SCARD_IO_REQUEST ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
63     SCARD_IO_REQUEST ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
64     BYTE recvbuf[256];
65     DWORD recvlen = sizeof(recvbuf);
66     BYTE SW1, SW2;
67     __try
68     {
69    
70     dwReturn = SCardTransmit(pCardData->hScard,
71     SCARD_PCI_T1,
72     pbCmd,
73     dwCmdSize,
74     NULL,
75     recvbuf,
76     &recvlen);
77     if ( dwReturn != SCARD_S_SUCCESS )
78     {
79 vletoux 8 if (dwReturn == SCARD_W_RESET_CARD)
80     {
81     dwReturn = OCardReconnect(pCardData);
82     if (dwReturn)
83     {
84     __leave;
85     }
86     dwReturn = OCardSendCommand(pCardData,pbCmd, dwCmdSize);
87     __leave;
88     }
89 vletoux 1 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
90     __leave;
91     }
92     SW1 = recvbuf[recvlen-2];
93     SW2 = recvbuf[recvlen-1];
94 vletoux 9 if ( (SW1 == 0x6A) && (SW2 == 0x88) )
95     {
96     Trace(WINEVENT_LEVEL_ERROR, L"card reset");
97     recvlen = sizeof(recvbuf);
98     dwReturn = SelectOpenPGPApplication(pCardData);
99     if (dwReturn)
100     {
101     __leave;
102     }
103     dwReturn = SCardTransmit(pCardData->hScard,
104     SCARD_PCI_T1,
105     pbCmd,
106     dwCmdSize,
107     NULL,
108     recvbuf,
109     &recvlen);
110     SW1 = recvbuf[recvlen-2];
111     SW2 = recvbuf[recvlen-1];
112     }
113 vletoux 1 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
114     {
115    
116     }
117     else if ( (SW1 == 0x69) && (SW2 == 0x82) )
118     {
119     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
120     dwReturn = SCARD_W_WRONG_CHV;
121     __leave;
122     }
123     else if ( (SW1 == 0x69) && (SW2 == 0x83) )
124     {
125     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
126     dwReturn = SCARD_W_CHV_BLOCKED;
127     __leave;
128     }
129 vletoux 11 else if ( (SW1 == 0x69) && (SW2 == 0x85) )
130     {
131     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION");
132     dwReturn = SCARD_W_SECURITY_VIOLATION;
133     __leave;
134     }
135 vletoux 1 else
136     {
137     TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
138     Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
139     dwReturn = SCARD_F_UNKNOWN_ERROR;
140     __leave;
141     }
142     }
143     __finally
144     {
145     }
146     return dwReturn;
147     }
148    
149 vletoux 12 /** send the select open pgp application apdu */
150 vletoux 1 DWORD SelectOpenPGPApplication(__in PCARD_DATA pCardData)
151     {
152     BYTE pbCmd[] = {0x00,
153     0xA4,
154     0x04,
155     0x00,
156     0x06,
157     0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
158     0x00
159     };
160    
161 vletoux 8 return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
162 vletoux 1 }
163    
164 vletoux 12 /** send a command to the smart card with response expected */
165 vletoux 8 DWORD OCardGetData(__in PCARD_DATA pCardData,
166 vletoux 1 __in PBYTE pbCmd, __in DWORD dwCmdSize,
167     __in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
168     {
169    
170     DWORD dwReturn;
171     BYTE pbGetResponse[] = {0x00,
172     0xC0,
173     0x00,
174     0x00,
175     0x00
176     };
177     DWORD dwGetResponseSize = ARRAYSIZE(pbGetResponse);
178     BYTE recvbuf[0x800];
179     DWORD recvlen = sizeof(recvbuf);
180     BYTE SW1, SW2;
181     DWORD dwDataSize = 0;
182     __try
183     {
184    
185     *pbResponse = NULL;
186     dwReturn = SCardTransmit(pCardData->hScard,
187     SCARD_PCI_T1,
188     pbCmd,
189     dwCmdSize,
190     NULL,
191     recvbuf,
192     &recvlen);
193    
194     do
195     {
196     if ( dwReturn != SCARD_S_SUCCESS )
197     {
198 vletoux 8 if (dwReturn == SCARD_W_RESET_CARD)
199     {
200     dwReturn = OCardReconnect(pCardData);
201     if (dwReturn)
202     {
203     __leave;
204     }
205     dwReturn = OCardGetData(pCardData,pbCmd, dwCmdSize,pbResponse, pdwResponseSize);
206     __leave;
207     }
208 vletoux 1 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
209     __leave;
210     }
211     SW1 = recvbuf[recvlen-2];
212     SW2 = recvbuf[recvlen-1];
213 vletoux 9 if ( (SW1 == 0x6A) && (SW2 == 0x88) )
214     {
215     Trace(WINEVENT_LEVEL_ERROR, L"card reset");
216     recvlen = sizeof(recvbuf);
217     dwReturn = SelectOpenPGPApplication(pCardData);
218     if (dwReturn)
219     {
220     __leave;
221     }
222     dwReturn = SCardTransmit(pCardData->hScard,
223     SCARD_PCI_T1,
224     pbCmd,
225     dwCmdSize,
226     NULL,
227     recvbuf,
228     &recvlen);
229     SW1 = recvbuf[recvlen-2];
230     SW2 = recvbuf[recvlen-1];
231     }
232 vletoux 1 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
233     {
234     dwDataSize = recvlen-2;
235     *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
236 vletoux 6 if (! *pbResponse)
237     {
238     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
239     dwReturn = SCARD_E_NO_MEMORY;
240     __leave;
241     }
242 vletoux 1 memcpy(*pbResponse, recvbuf, dwDataSize);
243     }
244     else if (SW1 == 0x61)
245     {
246     dwDataSize += SW2;
247     if (*pbResponse)
248     {
249     *pbResponse = pCardData->pfnCspReAlloc(*pbResponse, dwDataSize);
250     }
251     else
252     {
253     *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
254     }
255     dwGetResponseSize = ARRAYSIZE(pbGetResponse);
256     dwReturn = SCardTransmit(pCardData->hScard,
257     SCARD_PCI_T1,
258     pbGetResponse,
259     dwGetResponseSize,
260     NULL,
261     recvbuf,
262     &recvlen);
263     }
264     else if ( (SW1 == 0x69) && (SW2 == 0x82) )
265     {
266     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
267     dwReturn = SCARD_W_WRONG_CHV;
268     __leave;
269     }
270     else if ( (SW1 == 0x69) && (SW2 == 0x83) )
271     {
272     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
273     dwReturn = SCARD_W_CHV_BLOCKED;
274     __leave;
275     }
276 vletoux 11 else if ( (SW1 == 0x69) && (SW2 == 0x85) )
277     {
278     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION");
279     dwReturn = SCARD_W_SECURITY_VIOLATION;
280     __leave;
281     }
282 vletoux 1 else
283     {
284     TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
285     Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
286     dwReturn = SCARD_F_UNKNOWN_ERROR;
287     __leave;
288     }
289    
290     } while (SW1 == 0x61);
291     if (pdwResponseSize)
292     {
293     *pdwResponseSize = dwDataSize;
294     }
295     }
296     __finally
297     {
298     }
299     return dwReturn;
300     }
301    
302     DWORD CCIDfindFeature(BYTE featureTag, BYTE* features, DWORD featuresLength)
303     {
304     DWORD idx = 0;
305     int count;
306     while (idx < featuresLength) {
307     BYTE tag = features[idx];
308     idx++;
309     idx++;
310     if (featureTag == tag) {
311     DWORD feature = 0;
312     for (count = 0; count < 3; count++) {
313     feature |= features[idx] & 0xff;
314     idx++;
315     feature <<= 8;
316     }
317     feature |= features[idx] & 0xff;
318     return feature;
319     }
320     idx += 4;
321     }
322     return 0;
323     }
324    
325     DWORD CCIDgetFeatures(__in PCARD_DATA pCardData)
326     {
327     BYTE pbRecvBuffer[200];
328     DWORD dwRecvLength, dwReturn;
329     __try
330     {
331     POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
332    
333     pContext->SmartCardReaderFeatures.VERIFY_PIN_START = 0;
334     pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = 0;
335     pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = 0;
336     pContext->SmartCardReaderFeatures.MODIFY_PIN_START = 0;
337     pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = 0;
338     pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = 0;
339     pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = 0;
340     pContext->SmartCardReaderFeatures.ABORT = 0;
341    
342     dwReturn = SCardControl(pCardData->hScard,
343     SCARD_CTL_CODE(3400),
344     NULL,
345     0,
346     pbRecvBuffer,
347     sizeof(pbRecvBuffer),
348     &dwRecvLength);
349     if ( dwReturn )
350     {
351     Trace(WINEVENT_LEVEL_ERROR, L"SCardControl errorcode: [0x%02X]", dwReturn);
352     __leave;
353     }
354     pContext->SmartCardReaderFeatures.VERIFY_PIN_START = CCIDfindFeature(FEATURE_VERIFY_PIN_START, pbRecvBuffer, dwRecvLength);
355     pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = CCIDfindFeature(FEATURE_VERIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
356     pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_VERIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
357     pContext->SmartCardReaderFeatures.MODIFY_PIN_START = CCIDfindFeature(FEATURE_MODIFY_PIN_START, pbRecvBuffer, dwRecvLength);
358     pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = CCIDfindFeature(FEATURE_MODIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
359     pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_MODIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
360     pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = CCIDfindFeature(FEATURE_GET_KEY_PRESSED, pbRecvBuffer, dwRecvLength);
361     pContext->SmartCardReaderFeatures.ABORT = CCIDfindFeature(FEATURE_ABORT, pbRecvBuffer, dwRecvLength);
362     }
363     __finally
364     {
365     }
366     return dwReturn;
367     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26