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

Contents of /trunk/OpenPGPminidriver/CryptoOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (show annotations)
Thu Mar 11 20:32:26 2010 UTC (15 years, 1 month ago) by vletoux
File MIME type: text/plain
File size: 41518 byte(s)
improvement of the quality of the project.
More test for the qualification of the driver success but not all ...

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 "CryptoOperations.h"
25 #include "PinOperations.h"
26 #include "PublicDataOperations.h"
27 #include "tlv.h"
28
29 OPENPGP_CONTAINER_INFO Containers[] =
30 {
31 {0xB6, 0xCE, 0xC7, CALG_RSA_SIGN, AT_SIGNATURE, ROLE_SIGNATURE},
32 {0xA4, 0xD0, 0xC9, CALG_RSA_SIGN, AT_SIGNATURE, ROLE_AUTHENTICATION},
33 {0xB8, 0xCF, 0xC8, CALG_RSA_KEYX, AT_KEYEXCHANGE, ROLE_CONFIDENTIALITY}
34
35 };
36
37 typedef struct _OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM
38 {
39 ALG_ID aiHashAlg;
40 DWORD dwHashSize;
41 PBYTE pbEncodedOid;
42 DWORD dwEncodedOidSize;
43 } OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM, *POPENPGP_SUPPORTED_SIGNATURE_ALGORITHM;
44
45 BYTE dwSHA1EncodedOid[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
46 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
47 BYTE dwSHA256EncodedOid[] = {0x30, 0x31, 0x30, 0x0D,0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
48 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
49 BYTE dwSHA384EncodedOid[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
50 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
51 BYTE dwSHA512EncodedOid[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
52 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
53
54 OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM SignatureAlgorithm[] =
55 {
56 {CALG_SHA1,20,
57 dwSHA1EncodedOid,
58 ARRAYSIZE(dwSHA1EncodedOid)},
59 {CALG_SHA-256,32,
60 dwSHA256EncodedOid,
61 ARRAYSIZE(dwSHA256EncodedOid)},
62 {CALG_SHA-384,48,
63 dwSHA384EncodedOid,
64 ARRAYSIZE(dwSHA384EncodedOid)},
65 {CALG_SHA-512,64,
66 dwSHA512EncodedOid,
67 ARRAYSIZE(dwSHA512EncodedOid)},
68 };
69
70 DWORD dwSignatureAlgorithmCount = ARRAYSIZE(SignatureAlgorithm);
71
72
73
74 typedef struct _RSAPUBLICKEYBLOB
75 {
76 BLOBHEADER blobheader;
77 RSAPUBKEY rsapubkey;
78 BYTE modulus[sizeof(DWORD)];
79 } RSAPUBLICKEYBLOB, *PRSAPUBLICKEYBLOB;
80
81
82 DWORD OCardGetKeyAlgorithmAttributes(__in PCARD_DATA pCardData,
83 __in OPENPGP_CONTAINER dwContainer,
84 __out POPENPGP_ALGORITHM_ATTRIBUTE pAttributes)
85 {
86 DWORD dwReturn;
87 PSTR szAlgorithmAttributes = NULL;
88 PBYTE pbData = NULL;
89 DWORD dwResponseSize;
90 WORD wTemp;
91 __try
92 {
93 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
94 switch(dwContainer)
95 {
96 case Signature:
97 szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
98 break;
99 case Authentication:
100 szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
101 break;
102 case Confidentiality:
103 szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
104 break;
105 default:
106 dwReturn = SCARD_E_NO_KEY_CONTAINER;
107 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
108 __leave;
109 }
110 dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szAlgorithmAttributes, &pbData, &dwResponseSize);
111 if (dwReturn)
112 {
113 __leave;
114 }
115 if (dwResponseSize != sizeof(OPENPGP_ALGORITHM_ATTRIBUTE))
116 {
117 dwReturn = SCARD_E_UNEXPECTED;
118 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED");
119 __leave;
120 }
121 memcpy(pAttributes, pbData, dwResponseSize);
122 // big endian, little endian ...
123 wTemp = pAttributes->wExponentLengthInBit;
124 pAttributes->wExponentLengthInBit = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
125 wTemp = pAttributes->wModulusLengthInBit;
126 pAttributes->wModulusLengthInBit = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
127
128 dwReturn = 0;
129 }
130 __finally
131 {
132 if (pbData)
133 pCardData->pfnCspFree(pbData);
134 }
135 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
136 return dwReturn;
137 }
138
139 DWORD OCardSetKeyAlgorithmAttributes(__in PCARD_DATA pCardData,
140 __in OPENPGP_CONTAINER dwContainer,
141 __out POPENPGP_ALGORITHM_ATTRIBUTE pAttributes)
142 {
143 DWORD dwReturn;
144 PSTR szAlgorithmAttributes = NULL;
145 OPENPGP_ALGORITHM_ATTRIBUTE TempAttributes;
146 WORD wTemp;
147 __try
148 {
149 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
150 switch(dwContainer)
151 {
152 case Signature:
153 szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
154 break;
155 case Authentication:
156 szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
157 break;
158 case Confidentiality:
159 szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
160 break;
161 default:
162 dwReturn = SCARD_E_NO_KEY_CONTAINER;
163 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
164 __leave;
165 }
166 memcpy(&TempAttributes, pAttributes, sizeof(OPENPGP_ALGORITHM_ATTRIBUTE));
167 wTemp = TempAttributes.wExponentLengthInBit;
168 TempAttributes.wExponentLengthInBit = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
169 wTemp = TempAttributes.wModulusLengthInBit;
170 TempAttributes.wModulusLengthInBit = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
171
172 dwReturn = OCardWriteFile(pCardData, szOpenPGPDir, szAlgorithmAttributes, (PBYTE) &TempAttributes, sizeof(OPENPGP_ALGORITHM_ATTRIBUTE));
173 if (dwReturn)
174 {
175 __leave;
176 }
177 dwReturn = 0;
178 }
179 __finally
180 {
181 }
182 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
183 return dwReturn;
184 }
185
186 DWORD BuildSingleTlv(__in PBYTE buffer, __in BYTE bTlv, __in DWORD dwTlvSize, __inout PDWORD pdwOffset)
187 {
188 DWORD dwSize = 1;
189 buffer[(*pdwOffset)++] = bTlv;
190 // truncate if too long
191 if (dwTlvSize > 0xFFFF) dwTlvSize = 0xFFFF;
192 if (dwTlvSize < 0x7F)
193 {
194 buffer[(*pdwOffset)++] = (BYTE) dwTlvSize;
195 dwSize++;
196 }
197 else if (dwTlvSize < 0xFF)
198 {
199 buffer[(*pdwOffset)++] = 0x81;
200 buffer[(*pdwOffset)++] = (BYTE) dwTlvSize;
201 dwSize+=2;
202 }
203 else
204 {
205 buffer[(*pdwOffset)++] = 0x82;
206 buffer[(*pdwOffset)++] = (BYTE) (dwTlvSize / 0x100);
207 buffer[(*pdwOffset)++] = (BYTE) (dwTlvSize % 0x100);
208 dwSize+=3;
209 }
210 return dwSize;
211 }
212
213 DWORD BuildPrivateKeyTlv(__in PCARD_DATA pCardData, __in PRSAPUBLICKEYBLOB pbPublicKeyBlob,
214 __in OPENPGP_CONTAINER dwContainer, __in BYTE bFormat,
215 __out PBYTE * ppbTlv, __out PDWORD pdwTlvSize)
216 {
217 // structure of the keyblob
218 //BLOBHEADER blobheader;
219 //RSAPUBKEY rsapubkey;
220 //BYTE modulus[rsapubkey.bitlen/8];
221 //BYTE prime1[rsapubkey.bitlen/16];
222 //BYTE prime2[rsapubkey.bitlen/16];
223 //BYTE exponent1[rsapubkey.bitlen/16];
224 //BYTE exponent2[rsapubkey.bitlen/16];
225 //BYTE coefficient[rsapubkey.bitlen/16];
226 //BYTE privateExponent[rsapubkey.bitlen/8];
227 DWORD dwReturn = 0;
228
229 DWORD bitlen = pbPublicKeyBlob->rsapubkey.bitlen;
230 PBYTE pbPublicKeyData = (PBYTE) &(pbPublicKeyBlob->modulus);
231 // 7F48 len is < 7F so its encoded len is 1 bytes
232 // 3 bytes max + length * 7 potential plv
233 BYTE b7F48Header[(3 +1) * 7 + 3] = {0x7F, 0x48};
234 BYTE b5F48Header[3 + 2] = {0x5F, 0x48};
235 BYTE b4DHeader[3 + 1] = {0x4D};
236 DWORD dwOffset = 0;
237 DWORD dw7F48HeaderSize, dw5F48HeaderSize, dw4DHeaderSize;
238 DWORD dwKeyDataSize, dwExtendedHeaderListSize;
239 DWORD dwI;
240 __try
241 {
242 // build the 7F48 header + the data into a buffer
243 dwOffset = 3;
244 dw7F48HeaderSize = 0;
245 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x91, sizeof(DWORD), &dwOffset);
246 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x92, bitlen / 16, &dwOffset);
247 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x93, bitlen / 16, &dwOffset);
248 if (bFormat & 2)
249 {
250 // add crt (chineese reminder theorem) template
251 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x94, bitlen / 16, &dwOffset);
252 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x95, bitlen / 16, &dwOffset);
253 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x96, bitlen / 16, &dwOffset);
254 }
255 if (bFormat & 1)
256 {
257 dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x97, bitlen / 8, &dwOffset);
258 }
259 b7F48Header[2] = (BYTE) dw7F48HeaderSize;
260 dw7F48HeaderSize += 3; // before = only content, after += header size
261 // build 5F48 header in a buffer
262 // size of the data
263 dwKeyDataSize = sizeof(DWORD) // e
264 + bitlen / 16 //prime1
265 + bitlen / 16 //prime2
266 ;
267 if (bFormat & 2)
268 {
269 dwKeyDataSize+= bitlen / 16 //coefficient
270 + bitlen / 16 //exp1
271 + bitlen / 16 //exp2
272 ;
273 }
274 if (bFormat & 1)
275 {
276 dwKeyDataSize+= bitlen / 8 ; //modulus
277 }
278 dwOffset = 1;
279 dw5F48HeaderSize = 1 + BuildSingleTlv(b5F48Header, 0x48, dwKeyDataSize, &dwOffset);
280 // build the extended header list in a buffer
281 dwExtendedHeaderListSize = 2 // for the crt to indicate the private key
282 + dw7F48HeaderSize
283 + dw5F48HeaderSize
284 + dwKeyDataSize;
285 dwOffset = 0;
286 dw4DHeaderSize = BuildSingleTlv(b4DHeader, 0x4D, dwExtendedHeaderListSize, &dwOffset);
287
288 // allocate the memory
289 *pdwTlvSize = dw4DHeaderSize + dwExtendedHeaderListSize;
290 *ppbTlv = pCardData->pfnCspAlloc(*pdwTlvSize);
291 if (! *ppbTlv)
292 {
293 dwReturn = SCARD_E_NO_MEMORY;
294 __leave;
295 }
296 // 4D header
297 dwOffset = 0;
298 memcpy(*ppbTlv + dwOffset, b4DHeader, dw4DHeaderSize);
299 dwOffset += dw4DHeaderSize;
300 // control reference templace
301 (*ppbTlv)[dwOffset++] = Containers[dwContainer].bKeyTag;
302 (*ppbTlv)[dwOffset++] = 0;
303 // cardholder private key template
304 memcpy(*ppbTlv + dwOffset, b7F48Header, dw7F48HeaderSize);
305 dwOffset += dw7F48HeaderSize;
306 // Concatenation of key data header
307 memcpy(*ppbTlv + dwOffset, b5F48Header, dw5F48HeaderSize);
308 dwOffset += dw5F48HeaderSize;
309 // Concatenation of key data
310 // exponent little => big endian
311 (*ppbTlv)[dwOffset++] = (BYTE) (pbPublicKeyBlob->rsapubkey.pubexp / 0x1000000);
312 (*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x1000000) / 0x10000);
313 (*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x10000) / 0x100);
314 (*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x100) / 0x1);
315 // prime1
316 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2*bitlen)/16, bitlen / 16);
317 for(dwI = 0; dwI < bitlen / 16; dwI++)
318 {
319 (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(3*bitlen)/16 - 1 - dwI];
320 }
321 dwOffset += bitlen / 16;
322
323 // prime2
324 for(dwI = 0; dwI < bitlen / 16; dwI++)
325 {
326 (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(4*bitlen)/16 - 1 - dwI];
327 }
328 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (3*bitlen)/16, bitlen / 16);
329 dwOffset += bitlen / 16;
330 if (bFormat & 2)
331 {
332 // coeff
333 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1 + 3) * bitlen / 16 , bitlen / 16);
334 for(dwI = 0; dwI < bitlen / 16; dwI++)
335 {
336 (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(7*bitlen)/16 - 1 - dwI];
337 }
338 dwOffset += bitlen / 16;
339 // exponent1
340 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1 + 1) * bitlen / 16 , bitlen / 16);
341 for(dwI = 0; dwI < bitlen / 16; dwI++)
342 {
343 (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(5*bitlen)/16 - 1 - dwI];
344 }
345 dwOffset += bitlen / 16;
346 // exponent2
347 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1 + 2) * bitlen / 16 , bitlen / 16);
348 for(dwI = 0; dwI < bitlen / 16; dwI++)
349 {
350 (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(6*bitlen)/16 - 1 - dwI];
351 }
352 dwOffset += bitlen / 16;
353 }
354 if (bFormat & 1)
355 {
356 // modulus
357 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData, bitlen / 8);
358 for(dwI = 0; dwI < bitlen / 8; dwI++)
359 {
360 (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[bitlen / 8 - 1 - dwI];
361 }
362 }
363 }
364 __finally
365 {
366 }
367 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
368 return dwReturn;
369 }
370
371 DWORD UpdateGenerationDateTime(__in PCARD_DATA pCardData, __in OPENPGP_CONTAINER dwContainer,
372 __out PDWORD pdwSecondsSince1970)
373 {
374 DWORD dwReturn = 0;
375 LARGE_INTEGER UnixZeroTime = {0}, WindowsTime;
376 SYSTEMTIME WindowsSystemTime;
377 FILETIME WindowsFileTime;
378 BYTE pbCommand[] = {0x00, 0xDA, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
379 DWORD dwCommandSize = ARRAYSIZE(pbCommand);
380 __try
381 {
382 UnixZeroTime.QuadPart = 116444736000000000I64; // january 1st 1970
383 GetSystemTime(&WindowsSystemTime);
384 SystemTimeToFileTime(&WindowsSystemTime, &WindowsFileTime);
385 /* It is not recommended that you add and subtract values from the FILETIME
386 structure to obtain relative times. Instead, you should copy the low- and high-order
387 parts of the file time to a ULARGE_INTEGER structure, perform 64-bit arithmetic
388 on the QuadPart member, and copy the LowPart and HighPart members into the
389 FILETIME structure.
390
391 Do not cast a pointer to a FILETIME structure to either a ULARGE_INTEGER*
392 or __int64* value because it can cause alignment faults on 64-bit Windows.
393 */
394 WindowsTime.HighPart = WindowsFileTime.dwHighDateTime;
395 WindowsTime.LowPart = WindowsFileTime.dwLowDateTime;
396 *pdwSecondsSince1970 = (DWORD)((WindowsTime.QuadPart - UnixZeroTime.QuadPart) / 10000000);
397
398 pbCommand[3] = Containers[dwContainer].bDateTimeTag;
399 pbCommand[5] = (BYTE) (*pdwSecondsSince1970 / 0x1000000);
400 pbCommand[6] = (BYTE) ((*pdwSecondsSince1970 % 0x1000000) / 0x10000);
401 pbCommand[7] = (BYTE) ((*pdwSecondsSince1970 % 0x10000) / 0x100);
402 pbCommand[8] = (BYTE) ((*pdwSecondsSince1970 % 0x100) / 0x1);
403 dwReturn = OCardSendCommand(pCardData, pbCommand, dwCommandSize);
404 }
405 __finally
406 {
407 }
408 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
409 return dwReturn;
410 }
411
412 DWORD UpdateFingerPrint(__in PCARD_DATA pCardData, __in OPENPGP_CONTAINER dwContainer,
413 __in DWORD dwSecondsSince1970,
414 __in PBYTE pbModulus, __in DWORD dwModulusSizeInBit,
415 __in BOOL fIsModulusInBigEndian,
416 __in DWORD dwExponent)
417 {
418 // modulus in input are in big endian
419 // rfc4880 12.2
420 DWORD dwReturn = 0;
421 PBYTE pbBuffer = NULL;
422 DWORD dwBufferSize;
423 DWORD dwOffset = 0;
424 HCRYPTPROV hProv = 0;
425 HCRYPTHASH hHash = 0;
426 BYTE pbCommand[25] = {0x00, 0xDA, 0x00, 0x00, 0x14};
427 DWORD dwCommandSize = ARRAYSIZE(pbCommand);
428 DWORD dwHashLen = 0x14;
429 __try
430 {
431 dwBufferSize = dwModulusSizeInBit / 8 + sizeof(DWORD) + 10 + 3;
432 pbBuffer = (PBYTE) pCardData->pfnCspAlloc(dwBufferSize);
433 if (!pbBuffer)
434 {
435 dwReturn = SCARD_E_NO_MEMORY;
436 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
437 __leave;
438 }
439 pbBuffer[dwOffset++] = 0x99;
440 // -3 because of the header size
441 pbBuffer[dwOffset++] = (BYTE) ((dwBufferSize-3) / 0x100);
442 pbBuffer[dwOffset++] = (BYTE) ((dwBufferSize-3) % 0x100);
443 // rfc4880 5.5.2
444 // version
445 pbBuffer[dwOffset++] = 4;
446 // timestamp
447 pbBuffer[dwOffset++] = (BYTE) (dwSecondsSince1970 / 0x1000000);
448 pbBuffer[dwOffset++] = (BYTE) ((dwSecondsSince1970 % 0x1000000) / 0x10000);
449 pbBuffer[dwOffset++] = (BYTE) ((dwSecondsSince1970 % 0x10000) / 0x100);
450 pbBuffer[dwOffset++] = (BYTE) ((dwSecondsSince1970 % 0x100) / 0x1);
451 // RSA
452 pbBuffer[dwOffset++] = 1;
453 // size of modulus
454 pbBuffer[dwOffset++] = (BYTE) ((dwModulusSizeInBit % 0x10000) / 0x100);
455 pbBuffer[dwOffset++] = (BYTE) ((dwModulusSizeInBit % 0x100) / 0x1);
456 if (fIsModulusInBigEndian)
457 {
458 memcpy(pbBuffer + dwOffset, pbModulus, dwModulusSizeInBit / 8);
459 }
460 else
461 {
462 DWORD dwI;
463 for(dwI = 0; dwI < dwModulusSizeInBit / 8; dwI++)
464 {
465 pbBuffer[dwOffset + dwI] = pbModulus[dwModulusSizeInBit / 8 - 1 - dwI];
466 }
467 }
468 // size of exponent
469 pbBuffer[dwOffset++] = 0;
470 pbBuffer[dwOffset++] = sizeof(DWORD);
471 // exponent
472 pbBuffer[dwOffset++] = (BYTE) (dwExponent / 0x1000000);
473 pbBuffer[dwOffset++] = (BYTE) ((dwExponent % 0x1000000) / 0x10000);
474 pbBuffer[dwOffset++] = (BYTE) ((dwExponent % 0x10000) / 0x100);
475 pbBuffer[dwOffset++] = (BYTE) ((dwExponent % 0x100) / 0x1);
476
477 // hash using SHA1
478 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
479 {
480 dwReturn = GetLastError();
481 Trace(WINEVENT_LEVEL_ERROR, L"CryptAcquireContext 0x%08X", dwReturn);
482 __leave;
483 }
484 if(!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
485 {
486 dwReturn = GetLastError();
487 Trace(WINEVENT_LEVEL_ERROR, L"CryptCreateHash 0x%08X", dwReturn);
488 __leave;
489 }
490 if(!CryptHashData(hHash, pbBuffer, dwBufferSize, 0))
491 {
492 dwReturn = GetLastError();
493 Trace(WINEVENT_LEVEL_ERROR, L"CryptHashData 0x%08X", dwReturn);
494 __leave;
495 }
496 if(!CryptGetHashParam(hHash, HP_HASHVAL, pbCommand + 5, &dwHashLen, 0)) {
497 dwReturn = GetLastError();
498 Trace(WINEVENT_LEVEL_ERROR, L"CryptGetHashParam 0x%08X", dwReturn);
499 __leave;
500 }
501 pbCommand[3] = Containers[dwContainer].bSignatureTag;
502 dwReturn = OCardSendCommand(pCardData, pbCommand, dwCommandSize);
503
504 }
505 __finally
506 {
507 if (pbBuffer)
508 pCardData->pfnCspFree(pbBuffer);
509 if(hHash)
510 CryptDestroyHash(hHash);
511 if(hProv)
512 CryptReleaseContext(hProv,0);
513
514 }
515 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
516 return dwReturn;
517
518 }
519
520 DWORD OCardReadPublicKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, PBYTE *pbPublicKey, PDWORD pdwPublicKeySize)
521 {
522 DWORD dwReturn;
523 PBYTE pbData = NULL;
524 DWORD dwResponseSize = 0;
525 BYTE pbCmd[] = {0x00,
526 0x47,
527 0x81,
528 0x00,
529 0x00,
530 0x00,
531 0x02,
532 0x00,
533 0x00,
534 0x00,
535 0x00
536 };
537 DWORD dwCmdSize;
538 POPENPGP_CONTEXT pContext;
539 PBYTE pbModulus;
540 DWORD dwModulusSize, dwI;
541 PBYTE pbExponent;
542 PRSAPUBLICKEYBLOB pbBlob = NULL;
543 DWORD dwTotalTlvSize, dwOffset;
544 __try
545 {
546 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
547 if (dwContainer >= MaxContainer)
548 {
549 dwReturn = SCARD_E_NO_KEY_CONTAINER;
550 Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
551 __leave;
552 }
553 pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
554 pbCmd[7] = Containers[dwContainer].bKeyTag;
555 dwCmdSize = 9;
556 if (pContext->fExtentedLeLcFields)
557 {
558 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
559 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
560 }
561 else
562 {
563 pbCmd[dwCmdSize++] = 0xFF;
564 }
565
566 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
567 if (dwReturn)
568 {
569 __leave;
570 }
571 dwOffset = 2;
572 dwTotalTlvSize = getTlvSize(pbData + 2,&dwOffset) + 2;
573 if (!find_tlv(pbData + dwOffset,0x81,dwTotalTlvSize,&pbModulus,&dwModulusSize))
574 {
575 dwReturn = SCARD_E_UNEXPECTED;
576 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
577 __leave;
578 }
579 if (!find_tlv(pbData + dwOffset,0x82,dwTotalTlvSize, (PBYTE*)&pbExponent,NULL))
580 {
581 dwReturn = SCARD_E_UNEXPECTED;
582 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
583 __leave;
584 }
585 Trace(WINEVENT_LEVEL_INFO, L"dwModulusSize %d bits", dwModulusSize * 8);
586 *pdwPublicKeySize = sizeof(RSAPUBLICKEYBLOB) + dwModulusSize - sizeof(DWORD);
587 *pbPublicKey = pCardData->pfnCspAlloc(*pdwPublicKeySize);
588 if (!*pbPublicKey)
589 {
590 dwReturn = SCARD_E_NO_MEMORY;
591 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY %d", dwContainer);
592 __leave;
593 }
594 pbBlob = (PRSAPUBLICKEYBLOB) *pbPublicKey;
595 memset(pbBlob,0,*pdwPublicKeySize);
596 pbBlob->blobheader.bType = PUBLICKEYBLOB;
597 pbBlob->blobheader.bVersion = CUR_BLOB_VERSION;
598 pbBlob->blobheader.reserved = 0;
599 pbBlob->blobheader.aiKeyAlg = Containers[dwContainer].aiKeyAlg;
600 pbBlob->rsapubkey.magic = 0x31415352; //'RSA1';
601 pbBlob->rsapubkey.bitlen = dwModulusSize*8;
602 pbBlob->rsapubkey.pubexp = pbExponent[0] * 0x1000000 + pbExponent[1] * 0x10000 + pbExponent[2] * 0x100 + pbExponent[3];
603 // convert big endian into little endian
604 //memcpy(pbBlob->modulus, pbModulus, dwModulusSize);
605 for (dwI = 0; dwI < dwModulusSize; dwI++)
606 {
607 pbBlob->modulus[dwI] = pbModulus[dwModulusSize - 1 - dwI];
608 }
609
610 dwReturn = 0;
611 }
612 __finally
613 {
614 }
615 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
616 return dwReturn;
617 }
618
619 DWORD OCardCreateKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, DWORD dwBitLen)
620 {
621 DWORD dwReturn;
622 PBYTE pbData = NULL;
623 DWORD dwResponseSize = 0, dwCmdSize;
624 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
625 POPENPGP_CONTEXT pContext;
626 DWORD dwSecondsSince1970;
627 PBYTE pbModulus, pbExponent;
628 DWORD dwModulusSize, dwExponent;
629 BYTE pbCmd[] = {0x00,
630 0x47,
631 0x80,
632 0x00,
633 0x00,
634 0x00,
635 0x02,
636 0x00,
637 0x00,
638 0x00,
639 0x00
640 };
641 DWORD dwTotalTlvSize, dwOffset;
642 __try
643 {
644 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
645 if (dwContainer >= MaxContainer)
646 {
647 dwReturn = SCARD_E_NO_KEY_CONTAINER;
648 Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
649 __leave;
650 }
651 // key len
652 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
653 if (dwReturn)
654 {
655 __leave;
656 }
657 Attributes.wModulusLengthInBit = (WORD) dwBitLen;
658 dwReturn = OCardSetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
659 if (dwReturn)
660 {
661 __leave;
662 }
663
664 pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
665 pbCmd[7] = Containers[dwContainer].bKeyTag;
666 dwCmdSize = 9;
667 if (pContext->fExtentedLeLcFields)
668 {
669 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
670 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
671 }
672 else
673 {
674 pbCmd[dwCmdSize++] = 0xFF;
675 }
676
677 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
678 if (dwReturn)
679 {
680 __leave;
681 }
682 dwOffset = 2;
683 dwTotalTlvSize = getTlvSize(pbData + 2,&dwOffset) + 2;
684 if (!find_tlv(pbData + dwOffset,0x81,dwTotalTlvSize, &pbModulus,&dwModulusSize))
685 {
686 dwReturn = SCARD_E_UNEXPECTED;
687 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
688 __leave;
689 }
690 if (!find_tlv(pbData + dwOffset,0x82,dwTotalTlvSize, (PBYTE*)&pbExponent,NULL))
691 {
692 dwReturn = SCARD_E_UNEXPECTED;
693 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
694 __leave;
695 }
696 dwExponent = pbExponent[0] * 0x1000000 + pbExponent[1] * 0x10000 + pbExponent[2] * 0x100 + pbExponent[3];
697 dwReturn = UpdateGenerationDateTime(pCardData, dwContainer, &dwSecondsSince1970);
698 if (dwReturn)
699 {
700 __leave;
701 }
702 dwReturn = UpdateFingerPrint(pCardData, dwContainer, dwSecondsSince1970,
703 pbModulus,
704 dwModulusSize * 8,
705 TRUE,
706 dwExponent
707 );
708 if (dwReturn)
709 {
710 __leave;
711 }
712 switch(dwContainer)
713 {
714 case Signature:
715 pContext->fHasSignature = TRUE;
716 break;
717 case Authentication:
718 pContext->fHasAuthentication = TRUE;
719 break;
720 case Confidentiality:
721 pContext->fHasDecryption = TRUE;
722 break;
723 }
724 }
725 __finally
726 {
727 if (pbData)
728 pCardData->pfnCspFree(pbData);
729 }
730 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
731 return dwReturn;
732 }
733
734 DWORD OCardImportKey(PCARD_DATA pCardData,
735 OPENPGP_CONTAINER dwContainer,
736 PBYTE pBlob,
737 DWORD dwKeySize)
738 {
739 DWORD dwReturn;
740 PSTR szAlgorithmAttributes = NULL;
741 PBYTE pbTlv = NULL;
742 DWORD dwTlvSize;
743 PBYTE pbCommand = NULL;
744 DWORD dwCommandSize;
745 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
746 PRSAPUBLICKEYBLOB pbPublicKeyBlob = (PRSAPUBLICKEYBLOB) pBlob;
747 BYTE bCommand[] = {0x00,0xDB,0x3F,0xFF};
748 DWORD dwSecondsSince1970;
749 __try
750 {
751 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
752 // check blob
753 if (pbPublicKeyBlob->blobheader.aiKeyAlg != CALG_RSA_SIGN &&
754 pbPublicKeyBlob->blobheader.aiKeyAlg != CALG_RSA_KEYX)
755 {
756 Trace(WINEVENT_LEVEL_ERROR, L"Wrong aiKeyAlg %d", pbPublicKeyBlob->blobheader.aiKeyAlg);
757 dwReturn = SCARD_E_INVALID_PARAMETER;
758 __leave;
759 }
760 if (pbPublicKeyBlob->blobheader.bType != PRIVATEKEYBLOB)
761 {
762 Trace(WINEVENT_LEVEL_ERROR, L"Wrong bType %d", pbPublicKeyBlob->blobheader.bType);
763 dwReturn = SCARD_E_INVALID_PARAMETER;
764 __leave;
765 }
766 if (pbPublicKeyBlob->rsapubkey.magic != 0x32415352)
767 {
768 Trace(WINEVENT_LEVEL_ERROR, L"Wrong magic");
769 dwReturn = SCARD_E_INVALID_PARAMETER;
770 __leave;
771 }
772
773 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
774 if (dwReturn)
775 {
776 __leave;
777 }
778 Attributes.wModulusLengthInBit = (WORD) pbPublicKeyBlob->rsapubkey.bitlen;
779 dwReturn = OCardSetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
780 if (dwReturn)
781 {
782 __leave;
783 }
784 dwReturn = BuildPrivateKeyTlv(pCardData, pbPublicKeyBlob, dwContainer, Attributes.bFormat, &pbTlv, &dwTlvSize);
785 if (dwReturn)
786 {
787 __leave;
788 }
789 if (dwTlvSize > 0xFF)
790 {
791 dwCommandSize = 7 + dwTlvSize;
792
793 }
794 else
795 {
796 dwCommandSize = 5 + dwTlvSize;
797 }
798 pbCommand = pCardData->pfnCspAlloc(dwCommandSize);
799 if (!pbCommand)
800 {
801 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
802 dwReturn = SCARD_E_NO_MEMORY;
803 __leave;
804 }
805 memcpy(pbCommand, bCommand, 4);
806 if (dwTlvSize > 0xFF)
807 {
808 pbCommand[4] = 0;
809 pbCommand[5] = (BYTE)(dwTlvSize / 0x100);
810 pbCommand[6] = (BYTE)(dwTlvSize % 0x100);
811 memcpy(pbCommand + 7, pbTlv, dwTlvSize);
812 }
813 else
814 {
815 pbCommand[4] = (BYTE) dwTlvSize;
816 memcpy(pbCommand + 5, pbTlv, dwTlvSize);
817 }
818 dwReturn = OCardSendCommand(pCardData, pbCommand, dwCommandSize);
819 if (dwReturn)
820 {
821 __leave;
822 }
823 dwReturn = UpdateGenerationDateTime(pCardData, dwContainer, &dwSecondsSince1970);
824 if (dwReturn)
825 {
826 __leave;
827 }
828 dwReturn = UpdateFingerPrint(pCardData, dwContainer, dwSecondsSince1970,
829 pbPublicKeyBlob->modulus,
830 pbPublicKeyBlob->rsapubkey.bitlen,
831 FALSE,
832 pbPublicKeyBlob->rsapubkey.pubexp
833 );
834 if (dwReturn)
835 {
836 __leave;
837 }
838 switch(dwContainer)
839 {
840 case Signature:
841 pContext->fHasSignature = TRUE;
842 break;
843 case Authentication:
844 pContext->fHasAuthentication = TRUE;
845 break;
846 case Confidentiality:
847 pContext->fHasDecryption = TRUE;
848 break;
849 }
850 }
851 __finally
852 {
853 if (pbCommand)
854 {
855 SecureZeroMemory(pbCommand, dwCommandSize);
856 pCardData->pfnCspFree(pbCommand);
857 }
858 if (pbTlv)
859 {
860 SecureZeroMemory(pbTlv, dwTlvSize);
861 pCardData->pfnCspFree(pbTlv);
862 }
863 }
864 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
865 return dwReturn;
866 }
867
868 DWORD OCardSign(PCARD_DATA pCardData,
869 PCARD_SIGNING_INFO pInfo)
870 {
871 DWORD dwReturn;
872 PBYTE pbData = NULL;
873 DWORD dwCmdSize = 0, dwI;
874 POPENPGP_CONTEXT pContext;
875 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
876 BYTE pbCmd[6 + 256 + 256] = {0x00,
877 0x2A,
878 0x9E,
879 0x9A,
880 0x00,
881 0x00,
882 };
883 __try
884 {
885 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
886 if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_BUFFER_SIZE_ONLY | CRYPT_NOHASHOID | CRYPT_TYPE2_FORMAT))
887 {
888 Trace(WINEVENT_LEVEL_ERROR, L"wrong flag %d", pInfo->dwSigningFlags);
889 dwReturn = SCARD_E_INVALID_PARAMETER;
890 __leave;
891 }
892 if (pInfo->dwSigningFlags & CARD_PADDING_INFO_PRESENT)
893 {
894 if ( pInfo->dwPaddingType == CARD_PADDING_PKCS1)
895 {
896 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
897 Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PKCS1");
898 __leave;
899 }
900 else if (pInfo->dwPaddingType == CARD_PADDING_PSS)
901 {
902 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
903 Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
904 __leave;
905 }
906 else
907 {
908 dwReturn = SCARD_E_INVALID_PARAMETER;
909 Trace(WINEVENT_LEVEL_ERROR, L"pInfo->dwPaddingType = %d", pInfo->dwPaddingType);
910 __leave;
911 }
912 }
913 if (!(pInfo->aiHashAlg & ALG_CLASS_HASH))
914 {
915 dwReturn = SCARD_E_INVALID_PARAMETER;
916 Trace(WINEVENT_LEVEL_ERROR, L"pInfo->aiHashAlg == %d", pInfo->aiHashAlg);
917 __leave;
918 }
919 for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
920 {
921 if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
922 {
923 // found
924 break;
925 }
926 }
927 if (dwI >= dwSignatureAlgorithmCount)
928 {
929 Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
930 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
931 __leave;
932 }
933 if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
934 {
935 Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
936 dwReturn = SCARD_E_INVALID_PARAMETER;
937 __leave;
938 }
939 if (pInfo->bContainerIndex != Signature)
940 {
941 dwReturn = SCARD_E_NO_KEY_CONTAINER;
942 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
943 __leave;
944 }
945 if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
946 {
947 // optimisation :
948 // return the buffer size only
949 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, Signature, &Attributes);
950 if (dwReturn)
951 {
952 __leave;
953 }
954 pInfo->cbSignedData = Attributes.wModulusLengthInBit/8;
955 dwReturn = 0;
956 __leave;
957 }
958
959 pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
960
961 dwCmdSize = 5;
962 if (pContext->fExtentedLeLcFields)
963 {
964 dwCmdSize++;
965 }
966 pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwI].dwEncodedOidSize + pInfo->cbData);
967 memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwI].pbEncodedOid,SignatureAlgorithm[dwI].dwEncodedOidSize);
968 dwCmdSize += SignatureAlgorithm[dwI].dwEncodedOidSize;
969 /*for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
970 {
971 pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
972 }*/
973 memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
974 dwCmdSize += pInfo->cbData;
975
976
977 if (pContext->fExtentedLeLcFields)
978 {
979 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
980 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
981 }
982 else
983 {
984 pbCmd[dwCmdSize++] = 0;
985 }
986 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
987 if (dwReturn == SCARD_W_WRONG_CHV)
988 {
989 dwReturn = SCARD_W_SECURITY_VIOLATION;
990 __leave;
991 }
992 if (dwReturn)
993 {
994 __leave;
995 }
996 // revert the BYTES
997 for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
998 {
999 BYTE bTemp = pInfo->pbSignedData[dwI];
1000 pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
1001 pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
1002 }
1003 }
1004 __finally
1005 {
1006 if (dwReturn)
1007 {
1008 if (pInfo->pbSignedData)
1009 pCardData->pfnCspFree(pInfo->pbSignedData);
1010 }
1011 }
1012 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1013 return dwReturn;
1014 }
1015
1016 DWORD OCardAuthenticate(PCARD_DATA pCardData,
1017 PCARD_SIGNING_INFO pInfo)
1018 {
1019 DWORD dwReturn;
1020 PBYTE pbData = NULL;
1021 DWORD dwCmdSize = 0, dwI;
1022 POPENPGP_CONTEXT pContext;
1023 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
1024 BYTE pbCmd[6 + 256 + 256] = {0x00,
1025 0x88,
1026 0x00,
1027 0x00,
1028 0x00,
1029 0x00,
1030 };
1031 __try
1032 {
1033 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1034 if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_BUFFER_SIZE_ONLY | CRYPT_NOHASHOID | CRYPT_TYPE2_FORMAT))
1035 {
1036 Trace(WINEVENT_LEVEL_ERROR, L"wrong flag %d", pInfo->dwSigningFlags);
1037 dwReturn = SCARD_E_INVALID_PARAMETER;
1038 __leave;
1039 }
1040 if (pInfo->dwSigningFlags & CARD_PADDING_INFO_PRESENT)
1041 {
1042 if ( pInfo->dwPaddingType == CARD_PADDING_PKCS1)
1043 {
1044 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1045 Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PKCS1");
1046 __leave;
1047 }
1048 else if (pInfo->dwPaddingType == CARD_PADDING_PSS)
1049 {
1050 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1051 Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
1052 __leave;
1053 }
1054 else
1055 {
1056 dwReturn = SCARD_E_INVALID_PARAMETER;
1057 Trace(WINEVENT_LEVEL_ERROR, L"pInfo->dwPaddingType = %d", pInfo->dwPaddingType);
1058 __leave;
1059 }
1060 }
1061 for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
1062 {
1063 if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
1064 {
1065 // found
1066 break;
1067 }
1068 }
1069 if (dwI >= dwSignatureAlgorithmCount)
1070 {
1071 Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
1072 __leave;
1073 }
1074 if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
1075 {
1076 Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
1077 __leave;
1078 }
1079 if (pInfo->bContainerIndex != Authentication)
1080 {
1081 dwReturn = SCARD_E_NO_KEY_CONTAINER;
1082 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1083 __leave;
1084 }
1085 if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
1086 {
1087 // optimisation :
1088 // return the buffer size only
1089 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, Signature, &Attributes);
1090 if (dwReturn)
1091 {
1092 __leave;
1093 }
1094 pInfo->cbSignedData = Attributes.wModulusLengthInBit/8;
1095 dwReturn = 0;
1096 __leave;
1097 }
1098
1099 pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1100
1101 dwCmdSize = 5;
1102 if (pContext->fExtentedLeLcFields)
1103 {
1104 dwCmdSize++;
1105 }
1106 pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwI].dwEncodedOidSize + pInfo->cbData);
1107 memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwI].pbEncodedOid,SignatureAlgorithm[dwI].dwEncodedOidSize);
1108 dwCmdSize += SignatureAlgorithm[dwI].dwEncodedOidSize;
1109 /*for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
1110 {
1111 pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
1112 }*/
1113 memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
1114 dwCmdSize += pInfo->cbData;
1115
1116
1117 if (pContext->fExtentedLeLcFields)
1118 {
1119 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
1120 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
1121 }
1122 else
1123 {
1124 pbCmd[dwCmdSize++] = 0;
1125 }
1126 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
1127 if (dwReturn == SCARD_W_WRONG_CHV)
1128 {
1129 dwReturn = SCARD_W_SECURITY_VIOLATION;
1130 __leave;
1131 }
1132 if (dwReturn)
1133 {
1134 __leave;
1135 }
1136 // revert the BYTES
1137 for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
1138 {
1139 BYTE bTemp = pInfo->pbSignedData[dwI];
1140 pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
1141 pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
1142 }
1143 }
1144 __finally
1145 {
1146 if (dwReturn)
1147 {
1148 if (pInfo->pbSignedData)
1149 pCardData->pfnCspFree(pInfo->pbSignedData);
1150 }
1151 }
1152 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1153 return dwReturn;
1154 }
1155
1156 DWORD OCardDecrypt(PCARD_DATA pCardData,
1157 PCARD_RSA_DECRYPT_INFO pInfo)
1158 {
1159 DWORD dwReturn;
1160 PBYTE pbData = NULL;
1161 DWORD dwCmdSize = 0, dwResponseSize;
1162 BYTE pbCmd[6 + 256 + 256] = {0x00,
1163 0x2A,
1164 0x80,
1165 0x86,
1166 0x00,
1167 };
1168 POPENPGP_CONTEXT pContext;
1169 DWORD dwI;
1170 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
1171 __try
1172 {
1173 Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1174 if (pInfo->bContainerIndex >= MaxContainer)
1175 {
1176 dwReturn = SCARD_E_NO_KEY_CONTAINER;
1177 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1178 __leave;
1179 }
1180 if (pInfo->bContainerIndex != Confidentiality)
1181 {
1182 dwReturn = SCARD_E_NO_KEY_CONTAINER;
1183 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1184 __leave;
1185 }
1186 // check the buffer size
1187 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, Confidentiality, &Attributes);
1188 if (dwReturn)
1189 {
1190 __leave;
1191 }
1192 if (pInfo->cbData < (DWORD)(Attributes.wModulusLengthInBit/8))
1193 {
1194 dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
1195 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d", pInfo->cbData);
1196 __leave;
1197 }
1198 pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1199 dwCmdSize = 5;
1200 if (pContext->fExtentedLeLcFields)
1201 {
1202 pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) / 0x100);
1203 pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
1204 }
1205 else
1206 {
1207 pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
1208 }
1209 pbCmd[dwCmdSize++] = 0;
1210 //little endian => big endian
1211 for(dwI = 0; dwI < pInfo->cbData; dwI++)
1212 {
1213 pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData -1 -dwI];
1214 }
1215 dwCmdSize += pInfo->cbData;
1216 if (pContext->fExtentedLeLcFields)
1217 {
1218 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
1219 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
1220 }
1221 else
1222 {
1223 pbCmd[dwCmdSize++] = 0;
1224 }
1225 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
1226 if (dwReturn)
1227 {
1228 __leave;
1229 }
1230
1231 // CryptDecrypt expects the data decrypted using rsa (only the mathematical computation)
1232 // this means the data with the padding (removed by the card)
1233 // and in little endian (while the card return the data in big endian)
1234 // so we rebuilt the padding in reverse order
1235
1236 if ( pInfo->cbData < dwResponseSize + 3 + 11)
1237 {
1238 dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
1239 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d expected = %d", pInfo->cbData, dwResponseSize);
1240 __leave;
1241 }
1242
1243 pInfo->pbData[pInfo->cbData - 1] = 0; // start byte
1244 pInfo->pbData[pInfo->cbData - 2] = 02; // block type
1245 // padding
1246 memset(pInfo->pbData + dwResponseSize + 1,1,pInfo->cbData - 3 - dwResponseSize);
1247 pInfo->pbData[dwResponseSize] = 0; // separator
1248 // data field in reverse order
1249 for(dwI = 0; dwI < dwResponseSize; dwI++)
1250 {
1251 pInfo->pbData[dwI] = pbData[dwResponseSize - 1 - dwI];
1252 }
1253 }
1254 __finally
1255 {
1256 if (pbData)
1257 {
1258 SecureZeroMemory(pbData, dwResponseSize);
1259 pCardData->pfnCspFree(pbData);
1260 }
1261 }
1262 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1263 return dwReturn;
1264 }
1265
1266
1267 DWORD OCardReadContainerMapFile(__in PCARD_DATA pCardData,
1268 __in PBYTE* ppbResponse, __in PDWORD pdwResponseSize)
1269 {
1270 DWORD dwReturn = 0;
1271 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1272 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
1273 __try
1274 {
1275 PCONTAINER_MAP_RECORD pContainer = NULL;
1276 BOOL fIsDefaultContainerSet = FALSE;
1277 *pdwResponseSize = sizeof(CONTAINER_MAP_RECORD) * MaxContainer;
1278 *ppbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
1279 if (! *ppbResponse )
1280 {
1281 dwReturn = SCARD_E_NO_MEMORY;
1282 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
1283 __leave;
1284 }
1285 pContainer = (PCONTAINER_MAP_RECORD) *ppbResponse;
1286 memset(pContainer,0,sizeof(CONTAINER_MAP_RECORD) * 3);
1287
1288 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, Authentication, &Attributes);
1289 if (dwReturn)
1290 {
1291 __leave;
1292 }
1293 pContainer[Authentication].wSigKeySizeBits = Attributes.wModulusLengthInBit;
1294 swprintf_s(pContainer[Authentication].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
1295 L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Authenticate",
1296 pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
1297 pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
1298 pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
1299 pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
1300 if (pContext->fHasAuthentication)
1301 {
1302 pContainer[Authentication].bFlags = CONTAINER_MAP_VALID_CONTAINER | CONTAINER_MAP_DEFAULT_CONTAINER;
1303 fIsDefaultContainerSet = TRUE;
1304 }
1305 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, Signature, &Attributes);
1306 if (dwReturn)
1307 {
1308 __leave;
1309 }
1310 pContainer[Signature].wSigKeySizeBits = Attributes.wModulusLengthInBit;
1311 swprintf_s(pContainer[Signature].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
1312 L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Signature",
1313 pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
1314 pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
1315 pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
1316 pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
1317 if (pContext->fHasSignature)
1318 {
1319 pContainer[Signature].bFlags = CONTAINER_MAP_VALID_CONTAINER;
1320 if (!fIsDefaultContainerSet)
1321 {
1322 pContainer[Signature].bFlags |= CONTAINER_MAP_DEFAULT_CONTAINER;
1323 fIsDefaultContainerSet = TRUE;
1324 }
1325 }
1326
1327 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, Confidentiality, &Attributes);
1328 if (dwReturn)
1329 {
1330 __leave;
1331 }
1332 pContainer[Confidentiality].wKeyExchangeKeySizeBits = Attributes.wModulusLengthInBit;
1333
1334 swprintf_s(pContainer[Confidentiality].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
1335 L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Confidential",
1336 pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
1337 pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
1338 pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
1339 pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
1340 if (pContext->fHasDecryption)
1341 {
1342 pContainer[Confidentiality].bFlags = CONTAINER_MAP_VALID_CONTAINER;
1343 if (!fIsDefaultContainerSet)
1344 {
1345 pContainer[Confidentiality].bFlags |= CONTAINER_MAP_DEFAULT_CONTAINER;
1346 fIsDefaultContainerSet = TRUE;
1347 }
1348 }
1349 }
1350 __finally
1351 {
1352 }
1353 return dwReturn;
1354 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26