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

Contents of /trunk/OpenPGPminidriver/SmartCard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show 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 /* 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 /** called to re-select the Openpgp application when a SCARD_W_RESET occured */
30 DWORD OCardReconnect(__in PCARD_DATA pCardData)
31 {
32 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 /** send a command to the smart card with no response expected */
58 DWORD OCardSendCommand(__in PCARD_DATA pCardData, __in PBYTE pbCmd, __in DWORD dwCmdSize)
59 {
60 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 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 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
90 __leave;
91 }
92 SW1 = recvbuf[recvlen-2];
93 SW2 = recvbuf[recvlen-1];
94 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 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 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 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 /** send the select open pgp application apdu */
150 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 return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
162 }
163
164 /** send a command to the smart card with response expected */
165 DWORD OCardGetData(__in PCARD_DATA pCardData,
166 __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 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 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
209 __leave;
210 }
211 SW1 = recvbuf[recvlen-2];
212 SW2 = recvbuf[recvlen-1];
213 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 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
233 {
234 dwDataSize = recvlen-2;
235 *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
236 if (! *pbResponse)
237 {
238 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
239 dwReturn = SCARD_E_NO_MEMORY;
240 __leave;
241 }
242 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 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 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