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

Contents of /trunk/OpenPGPminidriver/PinOperations.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: 12174 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 "Tracing.h"
21 #include "Context.h"
22 #include "SmartCard.h"
23 #include "PublicDataOperations.h"
24 #include "PinOperations.h"
25
26
27 DWORD CheckPinLength(__in PCARD_DATA pCardData, __in PIN_ID PinId, __in DWORD cbPin)
28 {
29 DWORD dwReturn;
30 PBYTE pbResponse = NULL;
31 DWORD dwMinPinSize = 0, dwMaxPinSize, dwSize;
32 __try
33 {
34 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
35 // check min Pin length
36 // (hard coded in specication)
37 switch(PinId)
38 {
39 case ROLE_SIGNATURE:
40 case ROLE_AUTHENTICATION:
41 dwMinPinSize = 6;
42 break;
43 case ROLE_PUK:
44 // undocumented
45 dwMinPinSize = 8;
46 break;
47 case ROLE_ADMIN:
48 dwMinPinSize = 8;
49 break;
50 default:
51 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INVALID_PARAMETER PinId = %d",PinId);
52 dwReturn = SCARD_E_INVALID_PARAMETER;
53 __leave;
54 }
55 if (cbPin < dwMinPinSize)
56 {
57 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV ROLE = %d cbPin = %d minPinSize = %d",PinId, cbPin, dwMinPinSize);
58 dwReturn = SCARD_W_WRONG_CHV;
59 __leave;
60 }
61 // check in status DO
62 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPStatus, &pbResponse, &dwSize);
63 if (dwReturn)
64 {
65 __leave;
66 }
67 switch(PinId)
68 {
69 case ROLE_SIGNATURE:
70 case ROLE_AUTHENTICATION:
71 dwMaxPinSize = pbResponse[1];
72 break;
73 case ROLE_PUK:
74 dwMaxPinSize = pbResponse[2];
75 break;
76 case ROLE_ADMIN:
77 dwMaxPinSize = pbResponse[3];
78 break;
79 default:
80 dwReturn = SCARD_E_INVALID_PARAMETER;
81 __leave;
82 }
83 if (cbPin > dwMaxPinSize)
84 {
85 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV ROLE = %d cbPin = %d dwMaxPinSize = %d", PinId, cbPin, dwMaxPinSize);
86 dwReturn = SCARD_W_WRONG_CHV;
87 __leave;
88 }
89 dwReturn = 0;
90 }
91 __finally
92 {
93 if (pbResponse)
94 pCardData->pfnCspFree(pbResponse);
95 }
96 return dwReturn;
97 }
98
99 DWORD GetRemainingPin(__in PCARD_DATA pCardData, __in PIN_ID PinId, __out PDWORD pdwCounter)
100 {
101 DWORD dwReturn, dwSize;
102 PBYTE pbResponse = NULL;
103 __try
104 {
105 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
106 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPStatus, &pbResponse, &dwSize);
107 switch(PinId)
108 {
109 case ROLE_SIGNATURE:
110 case ROLE_AUTHENTICATION:
111 *pdwCounter = pbResponse[4];
112 break;
113 case ROLE_PUK:
114 *pdwCounter = pbResponse[5];
115 break;
116 case ROLE_ADMIN:
117 *pdwCounter = pbResponse[6];
118 break;
119 default:
120 dwReturn = SCARD_E_INVALID_PARAMETER;
121 __leave;
122 }
123 }
124 __finally
125 {
126 if (pbResponse)
127 pCardData->pfnCspFree(pbResponse);
128 }
129 return dwReturn;
130 }
131
132 DWORD VerifyPIN(__in PCARD_DATA pCardData,__in PIN_ID PinId,
133 __in_bcount(cbPin) PBYTE pbPin, __in DWORD cbPin)
134 {
135 DWORD dwReturn;
136 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
137 // 256 because the size of the PIN must fit in a Byte
138 BYTE pbCmd[256 + 5] = {0x00,
139 0x20,
140 0x00,
141 0x82,
142 0x00
143 };
144 __try
145 {
146 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
147 switch(PinId)
148 {
149 case ROLE_SIGNATURE:
150 pbCmd[3] = 0x81;
151 break;
152 case ROLE_AUTHENTICATION:
153 pbCmd[3] = 0x82;
154 break;
155 case ROLE_ADMIN:
156 pbCmd[3] = 0x83;
157 break;
158 case ROLE_PUK:
159 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
160 __leave;
161 default:
162 dwReturn = SCARD_E_INVALID_PARAMETER;
163 __leave;
164 }
165 if (cbPin > 256)
166 {
167 Trace(WINEVENT_LEVEL_ERROR, L"Error failure PinId=%d cbPin = %d",PinId, cbPin);
168 dwReturn = SCARD_E_INVALID_PARAMETER;
169 __leave;
170 }
171 pbCmd[4] = (BYTE) cbPin;
172 memcpy(pbCmd + 5, pbPin, cbPin);
173 dwReturn = OCardSendCommand(pCardData, pbCmd, 5 + cbPin);
174 if (dwReturn)
175 {
176 Trace(WINEVENT_LEVEL_VERBOSE, L"Authentication failed");
177 __leave;
178 }
179 Trace(WINEVENT_LEVEL_VERBOSE, L"Authentication successfull");
180 if (PinId == ROLE_ADMIN)
181 {
182 pContext->fDoesTheAdminHasBeenAuthenticatedAtLeastOnce = TRUE;
183 }
184 }
185 __finally
186 {
187 SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
188 }
189
190 return dwReturn;
191 }
192
193 DWORD ChangePIN(__in PCARD_DATA pCardData, __in PIN_ID PinId,
194 __in_bcount(cbPin) PBYTE pbOldPin, __in DWORD cbOldPin,
195 __in_bcount(cbPin) PBYTE pbNewPin, __in DWORD cbNewPin
196 )
197 {
198 DWORD dwReturn;
199 // 256 because the size of the PIN must fit in a Byte
200 BYTE pbCmd[256 + 256 + 6] = {0x00,
201 0x24,
202 0x00,
203 0x81,
204 0x00
205 };
206 __try
207 {
208 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
209 dwReturn = CheckPinLength(pCardData, PinId, cbNewPin);
210 if (dwReturn)
211 {
212 Trace(WINEVENT_LEVEL_ERROR, L"Invalid len %d",cbNewPin);
213 dwReturn = SCARD_E_INVALID_PARAMETER;
214 __leave;
215 }
216 dwReturn = CheckPinLength(pCardData, PinId, cbOldPin);
217 if (dwReturn)
218 {
219 __leave;
220 }
221 switch(PinId)
222 {
223 case ROLE_SIGNATURE:
224 case ROLE_AUTHENTICATION:
225 pbCmd[3] = 0x81;
226 break;
227 case ROLE_ADMIN:
228 pbCmd[3] = 0x83;
229 break;
230 case ROLE_PUK:
231 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
232 __leave;
233 default:
234 dwReturn = SCARD_E_INVALID_PARAMETER;
235 __leave;
236 }
237 if (cbOldPin + cbNewPin > 256)
238 {
239 Trace(WINEVENT_LEVEL_ERROR, L"Error failure PinId=%d cbOldPin = %d cbNewPin = %d",PinId, cbOldPin, cbNewPin);
240 dwReturn = SCARD_E_INVALID_PARAMETER;
241 __leave;
242 }
243 pbCmd[4] = (BYTE) (cbOldPin + cbNewPin);
244 memcpy(pbCmd + 5, pbOldPin, cbOldPin);
245 memcpy(pbCmd + 5 + cbOldPin, pbNewPin, cbNewPin);
246 dwReturn = OCardSendCommand(pCardData, pbCmd, 5 + cbOldPin + cbNewPin);
247 }
248 __finally
249 {
250 SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
251 }
252 return dwReturn;
253 }
254
255 /** only the user PIN can be reseted => target is implicit*/
256 DWORD ResetUserPIN(__in PCARD_DATA pCardData, __in PIN_ID PinId,
257 __in_bcount(cbPin) PBYTE pbAuthenticator, __in DWORD cbAuthenticator,
258 __in_bcount(cbPin) PBYTE pbNewPin, __in DWORD cbNewPin
259 )
260 {
261 DWORD dwReturn;
262 BYTE pbCmd[256 + 5] = {0x00,
263 0x2C,
264 0x02,
265 0x81,
266 0x00
267 };
268 DWORD dwCmdSize;
269
270 __try
271 {
272 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
273 dwReturn = CheckPinLength(pCardData, ROLE_USER, cbNewPin);
274 if (dwReturn)
275 {
276 Trace(WINEVENT_LEVEL_ERROR, L"Invalid len %d",cbNewPin);
277 dwReturn = SCARD_E_INVALID_PARAMETER;
278 __leave;
279 }
280 if (cbNewPin + cbAuthenticator> 256)
281 {
282 Trace(WINEVENT_LEVEL_ERROR, L"Error failure PinId=%d cbNewPin = %d cbAuthenticator = %d",PinId, cbNewPin, cbAuthenticator);
283 dwReturn = SCARD_E_INVALID_PARAMETER;
284 __leave;
285 }
286 switch(PinId)
287 {
288 case ROLE_ADMIN:
289 // authenticate the admin
290 dwReturn = VerifyPIN(pCardData, PinId, pbAuthenticator, cbAuthenticator);
291 if (dwReturn)
292 {
293 __leave;
294 }
295 pbCmd[4] = (BYTE) cbNewPin;
296 memcpy(pbCmd + 5, pbNewPin, cbNewPin);
297 dwCmdSize = 5 + cbNewPin;
298 break;
299 case ROLE_PUK:
300 dwReturn = CheckPinLength(pCardData, PinId, cbAuthenticator);
301 if (dwReturn)
302 {
303 __leave;
304 }
305 pbCmd[2] = 0x00;
306 pbCmd[4] = (BYTE) (cbAuthenticator + cbNewPin);
307 memcpy(pbCmd + 5, pbAuthenticator, cbAuthenticator);
308 memcpy(pbCmd + 5 + cbAuthenticator, pbNewPin, cbNewPin);
309 dwCmdSize = 5 + cbNewPin + cbAuthenticator;
310 break;
311 default:
312 dwReturn = SCARD_E_INVALID_PARAMETER;
313 __leave;
314 }
315 dwReturn = OCardSendCommand(pCardData, pbCmd, dwCmdSize);
316 }
317 __finally
318 {
319 SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
320 }
321 return dwReturn;
322 }
323
324 DWORD SetPUK(__in PCARD_DATA pCardData,
325 __in_bcount(cbPin) PBYTE pbAdminPin, __in DWORD cbAdminPin,
326 __in_bcount(cbPin) PBYTE pbPuk, __in DWORD cbPuk
327 )
328 {
329 DWORD dwReturn;
330 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
331 __try
332 {
333 dwReturn = CheckPinLength(pCardData, ROLE_PUK, cbPuk);
334 if (dwReturn)
335 {
336 Trace(WINEVENT_LEVEL_ERROR, L"Invalid len %d",cbPuk);
337 dwReturn = SCARD_E_INVALID_PARAMETER;
338 __leave;
339 }
340 dwReturn = VerifyPIN(pCardData, ROLE_ADMIN, pbAdminPin, cbAdminPin);
341 if (dwReturn)
342 {
343 __leave;
344 }
345 dwReturn = OCardWriteFile(pCardData, szOpenPGPDir, szOpenPGPPUK, pbPuk, cbPuk);
346 }
347 __finally
348 {
349 }
350 return dwReturn;
351 }
352
353 DWORD Deauthenticate(__in PCARD_DATA pCardData)
354 {
355 /*DWORD dwCode, dwSize;
356 DWORD dwReturn;
357 __try
358 {
359 // reset the card
360 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
361 dwCode = SCARD_COLD_RESET;
362 dwReturn = SCardControl(pCardData->hScard, IOCTL_SMARTCARD_POWER,&dwCode,4,NULL,0,&dwSize);
363 if (dwReturn && dwReturn != SCARD_W_RESET_CARD)
364 {
365 Trace(WINEVENT_LEVEL_ERROR, L"SCardControl 0x%08X", dwReturn);
366 __leave;
367 }
368 Sleep(200);
369 dwReturn = SelectOpenPGPApplication(pCardData);
370 }
371 __finally
372 {
373 }
374 return dwReturn;*/
375 return SCARD_E_UNSUPPORTED_FEATURE;
376 }
377
378
379 DWORD GetPinInfo(DWORD __in dwPinIndex, __inout PPIN_INFO pPinInfo)
380 {
381 DWORD dwReturn=0, dwVersion;
382 __try
383 {
384 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwPinIndex=%d",dwPinIndex);
385 dwVersion = (pPinInfo->dwVersion == 0) ? PIN_INFO_CURRENT_VERSION : pPinInfo->dwVersion;
386 if ( dwVersion != PIN_INFO_CURRENT_VERSION )
387 {
388 Trace(WINEVENT_LEVEL_ERROR, L"dwVersion %d", dwVersion);
389 dwReturn = ERROR_REVISION_MISMATCH;
390 __leave;
391 }
392 pPinInfo->dwVersion = dwVersion;
393 switch(dwPinIndex)
394 {
395 case ROLE_SIGNATURE:
396 pPinInfo->PinType = AlphaNumericPinType;
397 pPinInfo->PinPurpose = DigitalSignaturePin;
398 pPinInfo->dwChangePermission = CREATE_PIN_SET(ROLE_SIGNATURE);
399 SET_PIN(pPinInfo->dwChangePermission, ROLE_AUTHENTICATION);
400 pPinInfo->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN);
401 SET_PIN(pPinInfo->dwUnblockPermission, ROLE_PUK);
402 pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
403 pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
404 pPinInfo->dwFlags = 0;
405 break;
406 case ROLE_AUTHENTICATION:
407 pPinInfo->PinType = AlphaNumericPinType;
408 pPinInfo->PinPurpose = AuthenticationPin;
409 pPinInfo->dwChangePermission = CREATE_PIN_SET(ROLE_SIGNATURE);
410 SET_PIN(pPinInfo->dwChangePermission, ROLE_AUTHENTICATION);
411 pPinInfo->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN);
412 SET_PIN(pPinInfo->dwUnblockPermission, ROLE_PUK);
413 pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
414 pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
415 pPinInfo->dwFlags = 0;
416 break;
417 case ROLE_ADMIN:
418 pPinInfo->PinType = AlphaNumericPinType;
419 pPinInfo->PinPurpose = AdministratorPin;
420 pPinInfo->dwChangePermission = CREATE_PIN_SET(ROLE_ADMIN);
421 pPinInfo->dwUnblockPermission = 0;
422 pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
423 pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
424 pPinInfo->dwFlags = 0;
425 break;
426 case ROLE_PUK:
427 pPinInfo->PinType = AlphaNumericPinType;
428 pPinInfo->PinPurpose = UnblockOnlyPin;
429 pPinInfo->dwChangePermission = CREATE_PIN_SET(ROLE_ADMIN);
430 pPinInfo->dwUnblockPermission = 0;
431 pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
432 pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
433 pPinInfo->dwFlags = 0;
434 break;
435 default:
436 Trace(WINEVENT_LEVEL_ERROR, L"dwPinIndex == %d", dwPinIndex);
437 dwReturn = SCARD_E_INVALID_PARAMETER ;
438 __leave;
439 }
440 }
441 __finally
442 {
443 }
444 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
445 return dwReturn;
446 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26