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

Annotation of /trunk/OpenPGPminidriver/CryptoOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26