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

Contents of /trunk/OpenPGPminidriver/ContextManagement.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: 11405 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 "Tracing.h"
21 #include "Context.h"
22 #include "Smartcard.h"
23 #include "PublicDataOperations.h"
24 #include "CryptoOperations.h"
25
26 SCARD_ATRMASK SupportedATR [] =
27 {
28 { // v2
29 21,
30 //3B DA 18 FF 81 B1 FE 75 1F 03 00 31 C5 73 C0 01 40 00 90 00 0C
31 {0x3B,0xDA,0x18,0xFF,0x81,0xB1,0xFE,0x75,0x1F,0x03,
32 0x00,0x31,0xC5,0x73,0xC0,0x01,0x40,0x00,0x90,0x00,0x0C},
33 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
34 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
35 },
36 { // v1
37 20,
38 //3B FA 13 00 FF 81 31 80 45 00 31 C1 73 C0 01 00 00 90 00 B1
39 {0x3B,0xFA,0x13,0x00,0xFF,0x81,0x31,0x80,0x45,0x00,
40 0x31,0xC1,0x73,0xC0,0x01,0x00,0x00,0x90,0x00,0xB1},
41 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
42 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
43 }
44 };
45 DWORD dwSupportedATRCount = ARRAYSIZE(SupportedATR);
46
47 BOOL find_compacttlv(__in PBYTE pbData, __in DWORD dwTotalSize, __in BYTE bCode, __out PBYTE *pbDataOut, __out_opt PDWORD pdwSize)
48 {
49 DWORD dwOffset = 0;
50 DWORD dwSize;
51 while (dwOffset < dwTotalSize)
52 {
53 if (bCode * 0x10 == (pbData[dwOffset] & 0xF0) )
54 {
55 dwSize = (pbData[dwOffset] & 0x0F);
56 if (pdwSize)
57 {
58 *pdwSize = dwSize;
59 }
60 dwOffset++;
61 // size sequence
62
63 *pbDataOut = pbData + dwOffset;
64 return TRUE;
65 }
66 else
67 {
68
69 dwSize = (pbData[dwOffset] & 0x0F);
70 dwOffset += dwSize + 1;
71 }
72 }
73 return FALSE;
74 }
75
76
77
78 DWORD CheckContextEx(__in PCARD_DATA pCardData, __in BOOL fOpenPGPContextShouldBeNotNull)
79 {
80 DWORD dwReturn;
81 DWORD dwI, dwJ;
82 BOOL fFound = FALSE;
83 BOOL fRightATRLenFound = FALSE;
84 DWORD dwMinSupportedVersion;
85 __try
86 {
87 if ( pCardData == NULL )
88 {
89 Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
90 dwReturn = SCARD_E_INVALID_PARAMETER;
91 __leave;
92 }
93 if (pCardData->pbAtr == NULL)
94 {
95 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->pbAtr == NULL");
96 dwReturn = SCARD_E_INVALID_PARAMETER;
97 __leave;
98 }
99 if (fRunOnVistaAndLater)
100 {
101 dwMinSupportedVersion = CARD_DATA_VERSION_SIX;
102 }
103 else
104 {
105 // only a subset of functions is supported
106 // so the project don't pass the ms test
107 // we do this so the driver can operate under XP
108 dwMinSupportedVersion = CARD_DATA_VERSION_FIVE;
109 }
110 if (pCardData->dwVersion < dwMinSupportedVersion)
111 {
112 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->dwVersion(%d) < dwMinSupportedVersion(%d)", pCardData->dwVersion, dwMinSupportedVersion);
113 dwReturn = ERROR_REVISION_MISMATCH;
114 __leave;
115 }
116 pCardData->dwVersion = min(pCardData->dwVersion, CARD_DATA_VERSION_SEVEN);
117 for (dwI = 0; dwI < dwSupportedATRCount; dwI++)
118 {
119 if (SupportedATR[dwI].cbAtr == pCardData->cbAtr)
120 {
121 BYTE pbAtr[36];
122 fRightATRLenFound = TRUE;
123 memcpy(pbAtr, pCardData->pbAtr, SupportedATR[dwI].cbAtr);
124 for( dwJ = 0; dwJ < SupportedATR[dwI].cbAtr; dwJ++)
125 {
126 pbAtr[dwJ] &= SupportedATR[dwI].rgbMask[dwJ];
127 }
128 if (memcmp(pbAtr, SupportedATR[dwI].rgbAtr, SupportedATR[dwI].cbAtr) == 0)
129 {
130 fFound = TRUE;
131 //Trace(WINEVENT_LEVEL_VERBOSE, L"card match ATR %d", dwI);
132 break;
133 }
134
135 }
136 }
137 if (!fRightATRLenFound)
138 {
139 Trace(WINEVENT_LEVEL_ERROR, L"card doesn't match ATR len %d",pCardData->cbAtr);
140 dwReturn = SCARD_E_INVALID_PARAMETER;
141 __leave;
142 }
143 if (!fFound)
144 {
145 Trace(WINEVENT_LEVEL_ERROR, L"card doesn't match ATR");
146 dwReturn = SCARD_E_UNKNOWN_CARD;
147 __leave;
148 }
149
150 if ( pCardData->pwszCardName == NULL )
151 {
152 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->pwszCardName");
153 dwReturn = SCARD_E_INVALID_PARAMETER;
154 __leave;
155 }
156 /* Memory management functions */
157 if ( ( pCardData->pfnCspAlloc == NULL ) ||
158 ( pCardData->pfnCspReAlloc == NULL ) ||
159 ( pCardData->pfnCspFree == NULL ) )
160 {
161 Trace(WINEVENT_LEVEL_ERROR, L"Memory functions null");
162 dwReturn = SCARD_E_INVALID_PARAMETER;
163 __leave;
164 }
165 if (fOpenPGPContextShouldBeNotNull)
166 {
167 if (!pCardData->pvVendorSpecific)
168 {
169 // not found =>
170 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->pvVendorSpecific == NULL");
171 dwReturn = SCARD_E_UNEXPECTED;
172 __leave;
173 }
174 }
175 else
176 {
177 pCardData->pvVendorSpecific = NULL;
178 }
179 dwReturn = 0;
180 }
181 __finally
182 {
183 }
184 return dwReturn;
185 }
186
187 DWORD CheckContext(__in PCARD_DATA pCardData)
188 {
189 return CheckContextEx(pCardData, TRUE);
190 }
191
192 DWORD CleanContext(__in PCARD_DATA pCardData)
193 {
194 DWORD dwReturn = 0, dwI;
195 __try
196 {
197 if (pCardData)
198 {
199 if ( pCardData->pvVendorSpecific)
200 {
201 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
202 for(dwI = 0; dwI < KeyMax; dwI++)
203 {
204 if (pContext->pbModulusInLittleEndian[dwI] != NULL)
205 {
206 pCardData->pfnCspFree(pContext->pbModulusInLittleEndian[dwI]);
207 pContext->pbModulusInLittleEndian[dwI] = NULL;
208 }
209 }
210 pCardData->pfnCspFree( pCardData->pvVendorSpecific);
211 pCardData->pvVendorSpecific = NULL;
212 }
213 else
214 {
215 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->pvVendorSpecific == NULL");
216 }
217 }
218 else
219 {
220 Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
221 dwReturn = SCARD_E_INVALID_PARAMETER;
222 __leave;
223 }
224 }
225 __finally
226 {
227 }
228 return dwReturn;
229 }
230
231
232 DWORD CreateContext(__in PCARD_DATA pCardData, __in DWORD dwFlags)
233 {
234 DWORD dwReturn;
235 PBYTE pbCapabilities = NULL, pbCardCapabilities;
236 PBYTE pbExtendedCapabilities = NULL;
237 PBYTE pbApplicationIdentifier = NULL;
238 PBYTE pbFingerPrint = NULL;
239 DWORD dwCapabilitiesSize,
240 dwCardCapabilitiesSize,
241 dwApplicationIdentifierSize,
242 dwExtendedCapabilitiesSize,
243 dwFingerPrintSize;
244 DWORD dwI, dwJ;
245 BYTE bCategoryIndicator, bStatusIndicator;
246 POPENPGP_CONTEXT pContext;
247 __try
248 {
249 dwReturn = CheckContextEx(pCardData, FALSE);
250 if (dwReturn)
251 {
252 Trace(WINEVENT_LEVEL_ERROR, L"CheckContext");
253 __leave;
254 }
255 if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE))
256 {
257 if (pCardData->hSCardCtx == 0)
258 {
259 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->hSCardCtx == NULL");
260 dwReturn = SCARD_E_INVALID_HANDLE;
261 __leave;
262 }
263 if (pCardData->hScard == 0)
264 {
265 Trace(WINEVENT_LEVEL_ERROR, L"pCardData->hScard == NULL");
266 dwReturn = SCARD_E_INVALID_HANDLE;
267 __leave;
268 }
269 }
270
271 // not found => initialize context
272 pContext = pCardData->pfnCspAlloc(sizeof(OPENPGP_CONTEXT));
273 if (!pContext)
274 {
275 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
276 dwReturn = SCARD_E_NO_MEMORY;
277 __leave;
278 }
279 memset(pContext, 0, sizeof(OPENPGP_CONTEXT));
280 pCardData->pvVendorSpecific = pContext;
281
282 dwReturn = SelectOpenPGPApplication(pCardData);
283 if (dwReturn)
284 {
285 Trace(WINEVENT_LEVEL_ERROR, L"No SelectOpenPGPApplication");
286 __leave;
287 }
288 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPApplicationIdentifier, &pbApplicationIdentifier, &dwApplicationIdentifierSize);
289 if (dwReturn)
290 {
291 __leave;
292 }
293 if (dwApplicationIdentifierSize != sizeof(OPENPGP_AID))
294 {
295 Trace(WINEVENT_LEVEL_ERROR, L"dwApplicationIdentifierSize = %02X", dwApplicationIdentifierSize);
296 dwReturn = SCARD_E_UNEXPECTED;
297 __leave;
298 }
299 memcpy(&(pContext->Aid),pbApplicationIdentifier,sizeof(OPENPGP_AID));
300 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPHistoricalBytes, &pbCapabilities, &dwCapabilitiesSize);
301 if (dwReturn)
302 {
303 __leave;
304 }
305 bCategoryIndicator = pbCapabilities[0];
306 if (bCategoryIndicator != 0)
307 {
308 Trace(WINEVENT_LEVEL_ERROR, L"bCategoryIndicator = %02X", bCategoryIndicator);
309 dwReturn = SCARD_E_UNEXPECTED;
310 __leave;
311 }
312 bStatusIndicator = pbCapabilities[dwCapabilitiesSize -3];
313 if (bStatusIndicator != 0 && bStatusIndicator != 03 && bStatusIndicator != 05)
314 {
315 Trace(WINEVENT_LEVEL_ERROR, L"bStatusIndicator = %02X", bStatusIndicator);
316 dwReturn = SCARD_E_UNEXPECTED;
317 __leave;
318 }
319 if (!find_compacttlv(pbCapabilities + 1, dwCapabilitiesSize - 1, 7, &pbCardCapabilities, &dwCardCapabilitiesSize))
320 {
321 Trace(WINEVENT_LEVEL_ERROR, L"tlv not found");
322 dwReturn = SCARD_E_UNEXPECTED;
323 __leave;
324 }
325 if (dwCardCapabilitiesSize != 3)
326 {
327 Trace(WINEVENT_LEVEL_ERROR, L"dwCardCapabilitiesSize = %02X", dwCardCapabilitiesSize);
328 dwReturn = SCARD_E_UNEXPECTED;
329 __leave;
330 }
331 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPExtendedCap, &pbExtendedCapabilities, &dwExtendedCapabilitiesSize);
332 if (dwReturn)
333 {
334 __leave;
335 }
336 pContext->fExtentedLeLcFields = ((pbCardCapabilities[2] & 0x40)?TRUE:FALSE);
337 pContext->fSupportCommandChaining = ((pbCardCapabilities[2] & 0x80)?TRUE:FALSE);
338 if (pbExtendedCapabilities[0] & 0x80)
339 {
340 switch(pbExtendedCapabilities[1])
341 {
342 case 0:
343 pContext->aiSecureMessagingAlg = CALG_3DES;
344 break;
345 case 1:
346 pContext->aiSecureMessagingAlg = CALG_AES_128;
347 break;
348 }
349 Trace(WINEVENT_LEVEL_VERBOSE, L"secure messaging supported with aiAlg = %d", pContext->aiSecureMessagingAlg);
350 }
351 pContext->dwMaxChallengeLength = pbExtendedCapabilities[2] * 0x100 + pbExtendedCapabilities[3];
352 pContext->dwMaxCertificateLength = pbExtendedCapabilities[4] * 0x100 + pbExtendedCapabilities[5];
353 pContext->dwMaxCommandDataLength = pbExtendedCapabilities[6] * 0x100 + pbExtendedCapabilities[7];
354 pContext->dwMaxResponseLength = pbExtendedCapabilities[8] * 0x100 + pbExtendedCapabilities[9];
355 pContext->fIsReadOnly = TRUE;
356 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPFingerprint, &pbFingerPrint, &dwFingerPrintSize);
357 if (dwReturn)
358 {
359 __leave;
360 }
361 if (dwFingerPrintSize != 60)
362 {
363 Trace(WINEVENT_LEVEL_ERROR, L"dwFingerPrintSize = %02X", dwFingerPrintSize);
364 dwReturn = SCARD_E_UNEXPECTED;
365 __leave;
366 }
367 memcpy(pContext->bFingerPrint, pbFingerPrint, 60);
368 for(dwJ = 0; dwJ < KeyMax; dwJ++)
369 {
370 pContext->fHasKey[dwJ] = FALSE;
371 for( dwI = dwJ * 20; dwI < dwJ * 20 + 20; dwI++)
372 {
373 if (pbFingerPrint[dwI] != 0)
374 {
375 pContext->fHasKey[dwJ] = TRUE;
376 break;
377 }
378 }
379 }
380 /*dwReturn = CCIDgetFeatures(pCardData);
381 if (dwReturn)
382 {
383 __leave;
384 }*/
385 dwReturn = 0;
386 }
387 __finally
388 {
389 if (pbFingerPrint)
390 pCardData->pfnCspFree(pbFingerPrint);
391 if (pbApplicationIdentifier)
392 pCardData->pfnCspFree(pbApplicationIdentifier);
393 if (pbCapabilities)
394 pCardData->pfnCspFree(pbCapabilities);
395 if (pbExtendedCapabilities)
396 pCardData->pfnCspFree(pbExtendedCapabilities);
397 }
398 return dwReturn;
399 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26