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

Contents of /trunk/OpenPGPminidriver/PublicDataOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Mon Mar 15 18:23:17 2010 UTC (15 years, 1 month ago) by vletoux
File MIME type: text/plain
File size: 14638 byte(s)
first beta 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 <stdio.h>
20 #include <cardmod.h>
21 #include "Tracing.h"
22 #include "Context.h"
23 #include "SmartCard.h"
24 #include "PublicDataOperations.h"
25 #include "CryptoOperations.h"
26 #include "tlv.h"
27
28 typedef enum _OPENPGP_FILE_TYPE
29 {
30 StoredOnSmartCard,
31 Virtual,
32 } OPENPGP_FILE_TYPE;
33
34 #define OPENPGP_FILE_OPTIONAL 1
35 #define OPENPGP_FILE_WRITE_ONLY 2
36 #define OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING 4
37 #define OPENPGP_FILE_CONF_IS_AUTH 8
38
39 typedef struct _OPENPGP_FILE
40 {
41 PCHAR szDirectory;
42 PCHAR szFile;
43 OPENPGP_FILE_TYPE dwFileType;
44 DWORD dwTag;
45 DWORD dwTlv;
46 CARD_FILE_ACCESS_CONDITION dwAccess;
47 DWORD dwFlag;
48 } OPENPGP_FILE, *POPENPGP_FILE;
49
50
51 #define szCARD_APPLICATION_FILE "cardapps"
52
53 OPENPGP_FILE Files[] =
54 {
55 {szOpenPGPDir, szOpenPGPFingerprint, StoredOnSmartCard, 0x6E, 0xC5, EveryoneReadAdminWriteAc},
56 {szOpenPGPDir, szOpenPGPStatus, StoredOnSmartCard, 0xC4, 0, EveryoneReadAdminWriteAc},
57 {szOpenPGPDir, szOpenPGPApplicationIdentifier, StoredOnSmartCard, 0x4F, 0, UnknownAc},
58 {szOpenPGPDir, szOpenPGPLogin, StoredOnSmartCard, 0x5E, 0, EveryoneReadAdminWriteAc},
59 {szOpenPGPDir, szOpenPGPName, StoredOnSmartCard, 0x65, 0x5B, EveryoneReadAdminWriteAc},
60 {szOpenPGPDir, szOpenPGPLanguage, StoredOnSmartCard, 0x65, 0x5F2D, EveryoneReadAdminWriteAc},
61 {szOpenPGPDir, szOpenPGPSex, StoredOnSmartCard, 0x65, 0x5F35,EveryoneReadAdminWriteAc},
62 {szOpenPGPDir, szOpenPGPUrl, StoredOnSmartCard, 0x5F50, 0, EveryoneReadAdminWriteAc},
63 {szOpenPGPDir, szOpenPGPHistoricalBytes, StoredOnSmartCard, 0x5F52, 0, UnknownAc},
64 {szOpenPGPDir, szOpenPGPCertificate, StoredOnSmartCard, 0x7F21, 0, EveryoneReadAdminWriteAc, OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING},
65 {szOpenPGPDir, szOpenPGPExtendedCap, StoredOnSmartCard, 0x6E, 0xC0, UnknownAc},
66 {szOpenPGPDir, szOpenPGPAlgoAttributesSignature, StoredOnSmartCard, 0x6E, 0xC1, UnknownAc},
67 {szOpenPGPDir, szOpenPGPAlgoAttributesDecryption, StoredOnSmartCard, 0x6E, 0xC2,UnknownAc},
68 {szOpenPGPDir, szOpenPGPAlgoAttributesAuthentication, StoredOnSmartCard, 0x6E, 0xC3, UnknownAc },
69 {szOpenPGPDir, szOpenPGPPUK, StoredOnSmartCard, 0xD3, 0, UnknownAc, OPENPGP_FILE_WRITE_ONLY },
70 {NULL, szCARD_IDENTIFIER_FILE, StoredOnSmartCard, 0x4F, 0, EveryoneReadAdminWriteAc},
71 {NULL, szCARD_APPLICATION_FILE, Virtual, 0, 0, EveryoneReadAdminWriteAc},
72 {NULL, szCACHE_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},
73 {szBASE_CSP_DIR, szCONTAINER_MAP_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},
74 {szBASE_CSP_DIR, "ksc1", StoredOnSmartCard, 0x7F21, 0, EveryoneReadAdminWriteAc, OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING | OPENPGP_FILE_CONF_IS_AUTH},
75 {szBASE_CSP_DIR, "ksc2", StoredOnSmartCard, 0x7F21, 0, EveryoneReadAdminWriteAc, OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING},
76
77 };
78
79 DWORD dwFileCount = ARRAYSIZE(Files);
80
81 DWORD OCardDirectoryList(__in PCARD_DATA pCardData,
82 __in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
83 {
84 // hardcoded
85 *pdwResponseSize = 16;
86 *pbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
87 if (!*pbResponse)
88 {
89 return SCARD_E_NO_MEMORY;
90 }
91 memcpy(*pbResponse, "openpgp\0mscp\0\0\0\0", *pdwResponseSize);
92 return 0;
93 }
94
95
96 // read file
97 DWORD OCardReadFile(__in PCARD_DATA pCardData,
98 __in_opt PSTR szDirectory, __in PSTR szFile,
99 __in PBYTE* ppbResponse, __in PDWORD pdwResponseSize)
100 {
101 DWORD dwI;
102 DWORD dwReturn = 0;
103 BOOL fDirectoryFound = FALSE;
104 BOOL fFileFound = FALSE;
105 BYTE pbCmd[] = {0x00, 0xCA, 0x00, 0x00, 0x00};
106 DWORD dwCmdSize = ARRAYSIZE(pbCmd);
107 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
108 PBYTE pbData = NULL;
109 __try
110 {
111 *pdwResponseSize = 0;
112 for(dwI = 0; dwI < dwFileCount; dwI++)
113 {
114 BOOL fMatch = FALSE;
115 if (szDirectory == NULL)
116 {
117 if (!Files[dwI].szDirectory) fMatch = TRUE;
118 }
119 else
120 {
121 if (Files[dwI].szDirectory && _stricmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
122 }
123 if (fMatch)
124 {
125 fDirectoryFound = TRUE;
126 if (_stricmp(szFile, Files[dwI].szFile) == 0)
127 {
128 fFileFound = TRUE;
129 break;
130 }
131 }
132 }
133 if (!fFileFound)
134 {
135 if (fDirectoryFound)
136 {
137 dwReturn = SCARD_E_FILE_NOT_FOUND;
138 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
139 }
140 else
141 {
142 dwReturn = SCARD_E_DIR_NOT_FOUND;
143 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szDirectory);
144 }
145 __leave;
146 }
147 if (Files[dwI].dwFileType == StoredOnSmartCard)
148 {
149 pbCmd[2] = (BYTE) (Files[dwI].dwTag / 0x100);
150 pbCmd[3] = (BYTE) (Files[dwI].dwTag % 0x100);
151 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, pdwResponseSize);
152 if (dwReturn)
153 {
154 __leave;
155 }
156 if (Files[dwI].dwTlv)
157 {
158 PBYTE pbPointer;
159 //TraceDump(0,pbData,*pdwResponseSize);
160 if (find_tlv(pbData, Files[dwI].dwTlv, *pdwResponseSize, &pbPointer, pdwResponseSize))
161 {
162 *ppbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
163 if (!*ppbResponse )
164 {
165 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
166 dwReturn = SCARD_E_NO_MEMORY;
167 }
168 memcpy(*ppbResponse, pbPointer, *pdwResponseSize);
169 }
170 else
171 {
172 dwReturn = SCARD_E_FILE_NOT_FOUND;
173 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
174 }
175 }
176 else
177 {
178 *ppbResponse = pbData;
179 // do not free the data !
180 pbData = NULL;
181 }
182 }
183 else
184 {
185 if (szDirectory == NULL)
186 {
187 if (_stricmp(szFile, szCARD_APPLICATION_FILE) == 0)
188 {
189 dwReturn = OCardDirectoryList(pCardData, ppbResponse, pdwResponseSize);
190 }
191 else if (_stricmp(szFile, szCACHE_FILE) == 0)
192 {
193 *pdwResponseSize = sizeof(CARD_CACHE_FILE_FORMAT);
194 *ppbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
195 memset(*ppbResponse,0,*pdwResponseSize);
196 }
197 else
198 {
199 dwReturn = SCARD_E_FILE_NOT_FOUND;
200 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
201 }
202 }
203 else if (_stricmp(szDirectory,szBASE_CSP_DIR) == 0)
204 {
205 if (_stricmp(szFile, szCONTAINER_MAP_FILE) == 0)
206 {
207 dwReturn = OCardReadContainerMapFile(pCardData, ppbResponse, pdwResponseSize);
208 }
209 else
210 {
211 dwReturn = SCARD_E_FILE_NOT_FOUND;
212 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
213 }
214 }
215 else
216 {
217 dwReturn = SCARD_E_DIR_NOT_FOUND;
218 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szDirectory);
219 }
220 }
221 if (dwReturn)
222 {
223 __leave;
224 }
225 // add to the cache
226 dwReturn = 0;
227
228 }
229 __finally
230 {
231 if( pbData)
232 pCardData->pfnCspFree(pbData);
233 }
234 Trace(WINEVENT_LEVEL_VERBOSE, L"%S\\%S dwReturn = 0x%08X size = %d",szDirectory, szFile, dwReturn, *pdwResponseSize);
235 return dwReturn;
236 }
237
238 DWORD OCardEnumFile(__in PCARD_DATA pCardData,
239 __in_opt PSTR szDirectory,
240 __in PBYTE* pbResponse, __in PDWORD pdwResponseSize)
241 {
242 DWORD dwReturn = 0, dwTempReturn;
243 DWORD dwI, dwSize;
244 BOOL fDirectoryFound = FALSE;
245 BOOL fAddToOuput;
246 __try
247 {
248 *pbResponse = NULL;
249 *pdwResponseSize = 0;
250
251 // compute the max size of the buffer
252 dwSize = 0;
253 for(dwI = 0; dwI < dwFileCount; dwI++)
254 {
255 BOOL fMatch = FALSE;
256 if (szDirectory == NULL)
257 {
258 if (!Files[dwI].szDirectory) fMatch = TRUE;
259 }
260 else
261 {
262 if (Files[dwI].szDirectory && _stricmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
263 }
264 if (fMatch && !(Files[dwI].dwFileType & OPENPGP_FILE_WRITE_ONLY))
265 {
266 dwSize += (DWORD) strlen( Files[dwI].szFile) + 1;
267 }
268 }
269 dwSize += 1;
270 *pbResponse = pCardData->pfnCspAlloc(dwSize);
271 if (!*pbResponse)
272 {
273 dwReturn = SCARD_E_NO_MEMORY;
274 __leave;
275 }
276 for(dwI = 0; dwI < dwFileCount; dwI++)
277 {
278 BOOL fMatch = FALSE;
279 if (szDirectory == NULL)
280 {
281 if (!Files[dwI].szDirectory) fMatch = TRUE;
282 }
283 else
284 {
285 if (Files[dwI].szDirectory && _stricmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
286 }
287 if (fMatch)
288 {
289 fDirectoryFound = TRUE;
290 fAddToOuput = TRUE;
291 if (Files[dwI].dwFlag & OPENPGP_FILE_WRITE_ONLY)
292 {
293 fAddToOuput = FALSE;
294 }
295 if (fAddToOuput && (Files[dwI].dwFlag & OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING))
296 {
297 PBYTE pbData = NULL;
298 DWORD dwSize;
299 fAddToOuput = FALSE;
300 // check if the file exists and be read
301 dwTempReturn = OCardReadFile(pCardData, szDirectory, Files[dwI].szFile, &pbData, &dwSize);
302 if (!dwTempReturn)
303 {
304 pCardData->pfnCspFree(pbData);
305 if (dwSize > 0)
306 {
307 fAddToOuput = TRUE;
308 }
309 }
310 }
311 if (fAddToOuput && (Files[dwI].dwFlag & OPENPGP_FILE_CONF_IS_AUTH))
312 {
313 dwTempReturn = OCardIsConfidentialityKeyTheSameThanAuthentication(pCardData);
314 if (dwReturn)
315 {
316 fAddToOuput = FALSE;
317 }
318 }
319 if (fAddToOuput)
320 {
321 dwSize = (DWORD) strlen( Files[dwI].szFile) + 1;
322 memcpy(*pbResponse + *pdwResponseSize, Files[dwI].szFile, dwSize);
323 *pdwResponseSize += dwSize;
324 }
325 }
326 }
327 if (!fDirectoryFound)
328 {
329 dwReturn = SCARD_E_DIR_NOT_FOUND;
330 __leave;
331 }
332 (*pbResponse)[*pdwResponseSize] = '\0';
333 *pdwResponseSize += 1;
334 dwReturn = 0;
335 }
336 __finally
337 {
338 }
339 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
340 return dwReturn;
341 }
342
343 // read file
344 DWORD OCardGetFileInfo(__in PCARD_DATA pCardData,
345 __in_opt PSTR szDirectory, __in PSTR szFile,
346 __inout PCARD_FILE_INFO pCardFileInfo)
347 {
348 DWORD dwReturn = 0;
349 PBYTE pbData = NULL;
350 DWORD dwSize, dwI;
351 __try
352 {
353 dwReturn = OCardReadFile(pCardData, szDirectory, szFile, &pbData, &dwSize);
354 if (dwReturn)
355 {
356 __leave;
357 }
358 pCardData->pfnCspFree(pbData);
359 pCardFileInfo->cbFileSize = dwSize;
360 pCardFileInfo->AccessCondition = InvalidAc;
361 for(dwI = 0; dwI < dwFileCount; dwI++)
362 {
363 BOOL fMatch = FALSE;
364 if (szDirectory == NULL)
365 {
366 if (!Files[dwI].szDirectory) fMatch = TRUE;
367 }
368 else
369 {
370 if (Files[dwI].szDirectory && _stricmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
371 }
372 if (fMatch)
373 {
374 if (_stricmp(szFile, Files[dwI].szFile) == 0)
375 {
376 pCardFileInfo->AccessCondition = Files[dwI].dwAccess;
377 break;
378 }
379 }
380 }
381 dwReturn = 0;
382 }
383 __finally
384 {
385 }
386 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
387 return dwReturn;
388 }
389
390 DWORD OCardWriteFile(__in PCARD_DATA pCardData,
391 __in_opt PSTR szDirectory, __in PSTR szFile,
392 __in PBYTE pbData, __in DWORD dwSize)
393 {
394 DWORD dwI;
395 DWORD dwReturn = 0;
396 BOOL fDirectoryFound = FALSE;
397 BOOL fFileFound = FALSE;
398 BYTE pbCmd[5 + 256] = {0x00, 0xDA, 0x00, 0x00, 0x00};
399 DWORD dwCmdSize = 0;
400 __try
401 {
402 if (dwSize > 255)
403 {
404 dwReturn = SCARD_E_INVALID_PARAMETER;
405 Trace(WINEVENT_LEVEL_ERROR, L"dwSize %d",dwSize);
406 __leave;
407 }
408
409
410 for(dwI = 0; dwI < dwFileCount; dwI++)
411 {
412 BOOL fMatch = FALSE;
413 if (szDirectory == NULL)
414 {
415 if (!Files[dwI].szDirectory) fMatch = TRUE;
416 }
417 else
418 {
419 if (Files[dwI].szDirectory && _stricmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
420 }
421 if (fMatch)
422 {
423 fDirectoryFound = TRUE;
424 if (_stricmp(szFile, Files[dwI].szFile) == 0)
425 {
426 fFileFound = TRUE;
427 break;
428 }
429 }
430 }
431 if (!fFileFound)
432 {
433 if (fDirectoryFound)
434 {
435 dwReturn = SCARD_E_FILE_NOT_FOUND;
436 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
437 }
438 else
439 {
440 dwReturn = SCARD_E_DIR_NOT_FOUND;
441 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szDirectory);
442 }
443 __leave;
444 }
445 if (Files[dwI].dwFileType == StoredOnSmartCard)
446 {
447 if (Files[dwI].dwTlv > 0)
448 {
449 pbCmd[2] = (BYTE) (Files[dwI].dwTlv / 0x100);
450 pbCmd[3] = (BYTE) (Files[dwI].dwTlv % 0x100);
451 }
452 else
453 {
454 pbCmd[2] = (BYTE) (Files[dwI].dwTag / 0x100);
455 pbCmd[3] = (BYTE) (Files[dwI].dwTag % 0x100);
456 }
457 pbCmd[4] = (BYTE) dwSize;
458 if (dwSize)
459 {
460 memcpy(pbCmd + 5, pbData, dwSize);
461 }
462 dwCmdSize = dwSize + 5;
463 dwReturn = OCardSendCommand(pCardData, pbCmd, dwCmdSize);
464 if (dwReturn)
465 {
466 __leave;
467 }
468 }
469 else
470 {
471 dwReturn = SCARD_W_SECURITY_VIOLATION;
472 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION %S",szFile);
473 __leave;
474 }
475
476
477 }
478 __finally
479 {
480 }
481 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
482 return dwReturn;
483 }
484
485 DWORD OCardDeleteFile(__in PCARD_DATA pCardData,
486 __in_opt PSTR szDirectory, __in PSTR szFile)
487 {
488 return OCardWriteFile(pCardData, szDirectory, szFile, NULL, 0);
489 }
490
491 // just change the flag in Files
492 DWORD OCardCreateFile(__in PCARD_DATA pCardData,
493 __in_opt PSTR szDirectory, __in PSTR szFile)
494 {
495 DWORD dwI;
496 DWORD dwReturn = 0;
497 BOOL fDirectoryFound = FALSE;
498 BOOL fFileFound = FALSE;
499 __try
500 {
501 for(dwI = 0; dwI < dwFileCount; dwI++)
502 {
503 BOOL fMatch = FALSE;
504 if (szDirectory == NULL)
505 {
506 if (!Files[dwI].szDirectory) fMatch = TRUE;
507 }
508 else
509 {
510 if (Files[dwI].szDirectory && _stricmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
511 }
512 if (fMatch)
513 {
514 fDirectoryFound = TRUE;
515 if (_stricmp(szFile, Files[dwI].szFile) == 0)
516 {
517 fFileFound = TRUE;
518 break;
519 }
520 }
521 }
522 if (!fDirectoryFound)
523 {
524 dwReturn = SCARD_E_DIR_NOT_FOUND;
525 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szFile);
526 __leave;
527 }
528 if (!fFileFound)
529 {
530 dwReturn = SCARD_W_SECURITY_VIOLATION;
531 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION %S",szFile);
532 __leave;
533 }
534
535 }
536 __finally
537 {
538 }
539 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
540 return dwReturn;
541 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26