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

Contents of /trunk/OpenPGPminidriver/SmartCard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show 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 /* 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 DWORD SelectOpenPGPApplication(__in PCARD_DATA pCardData);
28
29 DWORD OCardReconnect(__in PCARD_DATA pCardData)
30 {
31 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 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 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 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
88 __leave;
89 }
90 SW1 = recvbuf[recvlen-2];
91 SW2 = recvbuf[recvlen-1];
92 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 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 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 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 return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
159 }
160
161
162 DWORD OCardGetData(__in PCARD_DATA pCardData,
163 __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 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 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
206 __leave;
207 }
208 SW1 = recvbuf[recvlen-2];
209 SW2 = recvbuf[recvlen-1];
210 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 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
230 {
231 dwDataSize = recvlen-2;
232 *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
233 if (! *pbResponse)
234 {
235 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
236 dwReturn = SCARD_E_NO_MEMORY;
237 __leave;
238 }
239 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 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 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