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

Contents of /trunk/OpenPGPminidriver/SmartCard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show 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 /* 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
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 return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
153 }
154
155
156 DWORD OCardGetData(__in PCARD_DATA pCardData,
157 __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 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 Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
200 __leave;
201 }
202 SW1 = recvbuf[recvlen-2];
203 SW2 = recvbuf[recvlen-1];
204 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 if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
224 {
225 dwDataSize = recvlen-2;
226 *pbResponse = pCardData->pfnCspAlloc(dwDataSize);
227 if (! *pbResponse)
228 {
229 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
230 dwReturn = SCARD_E_NO_MEMORY;
231 __leave;
232 }
233 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