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

Annotation of /trunk/OpenPGPminidriver/PinOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide 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 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 "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 vletoux 6 DWORD dwMinPinSize = 0, dwMaxPinSize, dwSize;
32 vletoux 1 __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 vletoux 11 break;
43 vletoux 1 case ROLE_PUK:
44 vletoux 11 // undocumented
45     dwMinPinSize = 8;
46 vletoux 1 break;
47     case ROLE_ADMIN:
48     dwMinPinSize = 8;
49     break;
50     default:
51 vletoux 11 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INVALID_PARAMETER PinId = %d",PinId);
52 vletoux 1 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 vletoux 8 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPStatus, &pbResponse, &dwSize);
63     if (dwReturn)
64     {
65     __leave;
66     }
67 vletoux 1 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 vletoux 6 DWORD dwReturn, dwSize;
102 vletoux 1 PBYTE pbResponse = NULL;
103     __try
104     {
105     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
106 vletoux 8 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPStatus, &pbResponse, &dwSize);
107 vletoux 1 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 vletoux 10 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
137 vletoux 1 // 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 vletoux 11 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 vletoux 1 pbCmd[4] = (BYTE) cbPin;
172     memcpy(pbCmd + 5, pbPin, cbPin);
173 vletoux 8 dwReturn = OCardSendCommand(pCardData, pbCmd, 5 + cbPin);
174 vletoux 1 if (dwReturn)
175     {
176 vletoux 8 Trace(WINEVENT_LEVEL_VERBOSE, L"Authentication failed");
177 vletoux 1 __leave;
178     }
179 vletoux 8 Trace(WINEVENT_LEVEL_VERBOSE, L"Authentication successfull");
180 vletoux 10 if (PinId == ROLE_ADMIN)
181     {
182     pContext->fDoesTheAdminHasBeenAuthenticatedAtLeastOnce = TRUE;
183     }
184 vletoux 1 }
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 vletoux 8 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 vletoux 1 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 vletoux 11 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 vletoux 1 pbCmd[4] = (BYTE) (cbOldPin + cbNewPin);
244     memcpy(pbCmd + 5, pbOldPin, cbOldPin);
245     memcpy(pbCmd + 5 + cbOldPin, pbNewPin, cbNewPin);
246 vletoux 8 dwReturn = OCardSendCommand(pCardData, pbCmd, 5 + cbOldPin + cbNewPin);
247 vletoux 1 }
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 vletoux 8 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 vletoux 11 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 vletoux 1 switch(PinId)
287     {
288     case ROLE_ADMIN:
289     // authenticate the admin
290     dwReturn = VerifyPIN(pCardData, PinId, pbAuthenticator, cbAuthenticator);
291 vletoux 8 if (dwReturn)
292 vletoux 1 {
293 vletoux 8 __leave;
294 vletoux 1 }
295 vletoux 8 pbCmd[4] = (BYTE) cbNewPin;
296 vletoux 1 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 vletoux 8 }
305 vletoux 1 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 vletoux 8 dwReturn = OCardSendCommand(pCardData, pbCmd, dwCmdSize);
316 vletoux 1 }
317     __finally
318     {
319     SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
320     }
321     return dwReturn;
322     }
323    
324 vletoux 8 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 vletoux 1 DWORD Deauthenticate(__in PCARD_DATA pCardData)
354     {
355 vletoux 9 /*DWORD dwCode, dwSize;
356 vletoux 1 DWORD dwReturn;
357     __try
358     {
359     // reset the card
360     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
361 vletoux 9 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 vletoux 1 {
365 vletoux 9 Trace(WINEVENT_LEVEL_ERROR, L"SCardControl 0x%08X", dwReturn);
366 vletoux 1 __leave;
367     }
368 vletoux 9 Sleep(200);
369 vletoux 1 dwReturn = SelectOpenPGPApplication(pCardData);
370     }
371     __finally
372     {
373     }
374 vletoux 9 return dwReturn;*/
375     return SCARD_E_UNSUPPORTED_FEATURE;
376 vletoux 8 }
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 vletoux 1 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26