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

Annotation of /trunk/OpenPGPminidriver/CryptoOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide annotations)
Tue Mar 2 18:54:34 2010 UTC (15 years, 2 months ago) by vletoux
File MIME type: text/plain
File size: 37542 byte(s)
authentication 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 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
192 vletoux 1 return dwReturn;
193     }
194    
195     DWORD SetKeyAlgorithmAttributes(__in PCARD_DATA pCardData,
196     __in OPENPGP_CONTAINER dwContainer,
197     __out POPENPGP_ALGORITHM_ATTRIBUTE pAttributes)
198     {
199     DWORD dwReturn;
200     PSTR szAlgorithmAttributes = NULL;
201     OPENPGP_ALGORITHM_ATTRIBUTE TempAttributes;
202     WORD wTemp;
203     __try
204     {
205     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
206     switch(dwContainer)
207     {
208     case Signature:
209     szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
210     break;
211     case Authentication:
212     szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
213     break;
214     case Confidentiality:
215     szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
216     break;
217     default:
218     dwReturn = SCARD_E_NO_KEY_CONTAINER;
219     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
220     __leave;
221     }
222     memcpy(&TempAttributes, pAttributes, sizeof(OPENPGP_ALGORITHM_ATTRIBUTE));
223     wTemp = TempAttributes.wExponentLength;
224     TempAttributes.wExponentLength = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
225     wTemp = TempAttributes.wModulusLength;
226     TempAttributes.wModulusLength = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
227    
228     dwReturn = SCardWriteFile(pCardData, szOpenPGPDir, szAlgorithmAttributes, (PBYTE) &TempAttributes, sizeof(OPENPGP_ALGORITHM_ATTRIBUTE));
229     if (dwReturn)
230     {
231     __leave;
232     }
233     dwReturn = 0;
234     }
235     __finally
236     {
237     }
238 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
239 vletoux 1 return dwReturn;
240     }
241    
242 vletoux 2 DWORD BuildSingleTlv(__in PBYTE buffer, __in BYTE bTlv, __in DWORD dwTlvSize, __inout PDWORD pdwOffset)
243     {
244     DWORD dwSize = 1;
245     buffer[(*pdwOffset)++] = bTlv;
246     // truncate if too long
247     if (dwTlvSize > 0xFFFF) dwTlvSize = 0xFFFF;
248     if (dwTlvSize < 0x7F)
249     {
250     buffer[(*pdwOffset)++] = (BYTE) dwTlvSize;
251     dwSize++;
252     }
253     else if (dwTlvSize < 0xFF)
254     {
255     buffer[(*pdwOffset)++] = 0x81;
256     buffer[(*pdwOffset)++] = (BYTE) dwTlvSize;
257     dwSize+=2;
258     }
259     else
260     {
261     buffer[(*pdwOffset)++] = 0x82;
262     buffer[(*pdwOffset)++] = (BYTE) (dwTlvSize / 0x100);
263     buffer[(*pdwOffset)++] = (BYTE) (dwTlvSize % 0x100);
264     dwSize+=3;
265     }
266     return dwSize;
267     }
268    
269     DWORD BuildPrivateKeyTlv(__in PCARD_DATA pCardData, __in PRSAPUBLICKEYBLOB pbPublicKeyBlob,
270     __in OPENPGP_CONTAINER dwContainer, __in BYTE bFormat,
271 vletoux 1 __out PBYTE * ppbTlv, __out PDWORD pdwTlvSize)
272     {
273 vletoux 2 // structure of the keyblob
274     //BLOBHEADER blobheader;
275     //RSAPUBKEY rsapubkey;
276     //BYTE modulus[rsapubkey.bitlen/8];
277     //BYTE prime1[rsapubkey.bitlen/16];
278     //BYTE prime2[rsapubkey.bitlen/16];
279     //BYTE exponent1[rsapubkey.bitlen/16];
280     //BYTE exponent2[rsapubkey.bitlen/16];
281     //BYTE coefficient[rsapubkey.bitlen/16];
282     //BYTE privateExponent[rsapubkey.bitlen/8];
283     DWORD dwReturn = 0;
284    
285     DWORD bitlen = pbPublicKeyBlob->rsapubkey.bitlen;
286 vletoux 3 PBYTE pbPublicKeyData = (PBYTE) &(pbPublicKeyBlob->modulus);
287 vletoux 2 // 7F48 len is < 7F so its encoded len is 1 bytes
288     // 3 bytes max + length * 7 potential plv
289     BYTE b7F48Header[(3 +1) * 7 + 3] = {0x7F, 0x48};
290     BYTE b5F48Header[3 + 2] = {0x5F, 0x48};
291     BYTE b4DHeader[3 + 1] = {0x4D};
292     DWORD dwOffset = 0;
293     DWORD dw7F48HeaderSize, dw5F48HeaderSize, dw4DHeaderSize;
294     DWORD dwKeyDataSize, dwExtendedHeaderListSize;
295 vletoux 3 DWORD dwI;
296 vletoux 1 __try
297     {
298 vletoux 2 // build the 7F48 header + the data into a buffer
299     dwOffset = 3;
300     dw7F48HeaderSize = 0;
301     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x91, sizeof(DWORD), &dwOffset);
302     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x92, bitlen / 16, &dwOffset);
303     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x93, bitlen / 16, &dwOffset);
304     if (bFormat & 2)
305     {
306     // add crt (chineese reminder theorem) template
307     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x94, bitlen / 16, &dwOffset);
308     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x95, bitlen / 16, &dwOffset);
309     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x96, bitlen / 16, &dwOffset);
310     }
311     if (bFormat & 1)
312     {
313     dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x97, bitlen / 8, &dwOffset);
314     }
315     b7F48Header[2] = (BYTE) dw7F48HeaderSize;
316     dw7F48HeaderSize += 3; // before = only content, after += header size
317     // build 5F48 header in a buffer
318     // size of the data
319     dwKeyDataSize = sizeof(DWORD) // e
320     + bitlen / 16 //prime1
321     + bitlen / 16 //prime2
322     ;
323     if (bFormat & 2)
324     {
325     dwKeyDataSize+= bitlen / 16 //coefficient
326     + bitlen / 16 //exp1
327     + bitlen / 16 //exp2
328     ;
329     }
330     if (bFormat & 1)
331     {
332     dwKeyDataSize+= bitlen / 8 ; //modulus
333     }
334     dwOffset = 1;
335     dw5F48HeaderSize = 1 + BuildSingleTlv(b5F48Header, 0x48, dwKeyDataSize, &dwOffset);
336     // build the extended header list in a buffer
337     dwExtendedHeaderListSize = 2 // for the crt to indicate the private key
338     + dw7F48HeaderSize
339     + dw5F48HeaderSize
340     + dwKeyDataSize;
341     dwOffset = 0;
342     dw4DHeaderSize = BuildSingleTlv(b4DHeader, 0x4D, dwExtendedHeaderListSize, &dwOffset);
343    
344     // allocate the memory
345     *pdwTlvSize = dw4DHeaderSize + dwExtendedHeaderListSize;
346     *ppbTlv = pCardData->pfnCspAlloc(*pdwTlvSize);
347     if (! *ppbTlv)
348     {
349     dwReturn = SCARD_E_NO_MEMORY;
350     __leave;
351     }
352     // 4D header
353     dwOffset = 0;
354     memcpy(*ppbTlv + dwOffset, b4DHeader, dw4DHeaderSize);
355     dwOffset += dw4DHeaderSize;
356     // control reference templace
357 vletoux 3 (*ppbTlv)[dwOffset++] = Containers[dwContainer].bKeyTag;
358 vletoux 2 (*ppbTlv)[dwOffset++] = 0;
359     // cardholder private key template
360     memcpy(*ppbTlv + dwOffset, b7F48Header, dw7F48HeaderSize);
361     dwOffset += dw7F48HeaderSize;
362     // Concatenation of key data header
363     memcpy(*ppbTlv + dwOffset, b5F48Header, dw5F48HeaderSize);
364     dwOffset += dw5F48HeaderSize;
365     // Concatenation of key data
366 vletoux 3 // exponent little => big endian
367 vletoux 2 (*ppbTlv)[dwOffset++] = (BYTE) (pbPublicKeyBlob->rsapubkey.pubexp / 0x1000000);
368     (*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x1000000) / 0x10000);
369     (*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x10000) / 0x100);
370     (*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x100) / 0x1);
371     // prime1
372 vletoux 3 //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2*bitlen)/16, bitlen / 16);
373     for(dwI = 0; dwI < bitlen / 16; dwI++)
374     {
375     (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(3*bitlen)/16 - 1 - dwI];
376     }
377 vletoux 2 dwOffset += bitlen / 16;
378 vletoux 3
379 vletoux 2 // prime2
380 vletoux 3 for(dwI = 0; dwI < bitlen / 16; dwI++)
381     {
382     (*ppbTlv)[dwOffset+dwI] = pbPublicKeyData[(4*bitlen)/16 - 1 - dwI];
383     }
384     //memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (3*bitlen)/16, 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 1 }
420     __finally
421     {
422     }
423 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
424 vletoux 1 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 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
465 vletoux 3 return dwReturn;
466     }
467    
468     DWORD UpdateFingerPrint(__in PCARD_DATA pCardData, __in OPENPGP_CONTAINER dwContainer,
469     __in DWORD dwSecondsSince1970,
470     __in PBYTE pbModulus, __in DWORD dwModulusSizeInBit,
471     __in BOOL fIsModulusInBigEndian,
472     __in DWORD dwExponent)
473     {
474     // modulus in input are in big endian
475     // rfc4880 12.2
476     DWORD dwReturn = 0;
477     PBYTE pbBuffer = NULL;
478     DWORD dwBufferSize;
479     DWORD dwOffset = 0;
480     HCRYPTPROV hProv = 0;
481     HCRYPTHASH hHash = 0;
482     BYTE pbCommand[25] = {0x00, 0xDA, 0x00, 0x00, 0x14};
483     DWORD dwCommandSize = ARRAYSIZE(pbCommand);
484     DWORD dwHashLen = 0x14;
485     __try
486     {
487     dwBufferSize = dwModulusSizeInBit / 8 + sizeof(DWORD) + 10 + 3;
488     pbBuffer = (PBYTE) pCardData->pfnCspAlloc(dwBufferSize);
489     if (!pbBuffer)
490     {
491     dwReturn = SCARD_E_NO_MEMORY;
492     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
493     __leave;
494     }
495     pbBuffer[dwOffset++] = 0x99;
496     // -3 because of the header size
497     pbBuffer[dwOffset++] = (BYTE) ((dwBufferSize-3) / 0x100);
498     pbBuffer[dwOffset++] = (BYTE) ((dwBufferSize-3) % 0x100);
499     // rfc4880 5.5.2
500     // version
501     pbBuffer[dwOffset++] = 4;
502     // timestamp
503     pbBuffer[dwOffset++] = (BYTE) (dwSecondsSince1970 / 0x1000000);
504     pbBuffer[dwOffset++] = (BYTE) ((dwSecondsSince1970 % 0x1000000) / 0x10000);
505     pbBuffer[dwOffset++] = (BYTE) ((dwSecondsSince1970 % 0x10000) / 0x100);
506     pbBuffer[dwOffset++] = (BYTE) ((dwSecondsSince1970 % 0x100) / 0x1);
507     // RSA
508     pbBuffer[dwOffset++] = 1;
509     // size of modulus
510     pbBuffer[dwOffset++] = (BYTE) ((dwModulusSizeInBit % 0x10000) / 0x100);
511     pbBuffer[dwOffset++] = (BYTE) ((dwModulusSizeInBit % 0x100) / 0x1);
512     if (fIsModulusInBigEndian)
513     {
514     memcpy(pbBuffer + dwOffset, pbModulus, dwModulusSizeInBit / 8);
515     }
516     else
517     {
518     DWORD dwI;
519     for(dwI = 0; dwI < dwModulusSizeInBit / 8; dwI++)
520     {
521     pbBuffer[dwOffset + dwI] = pbModulus[dwModulusSizeInBit / 8 - 1 - dwI];
522     }
523     }
524     // size of exponent
525     pbBuffer[dwOffset++] = 0;
526     pbBuffer[dwOffset++] = sizeof(DWORD);
527     // exponent
528     pbBuffer[dwOffset++] = (BYTE) (dwExponent / 0x1000000);
529     pbBuffer[dwOffset++] = (BYTE) ((dwExponent % 0x1000000) / 0x10000);
530     pbBuffer[dwOffset++] = (BYTE) ((dwExponent % 0x10000) / 0x100);
531     pbBuffer[dwOffset++] = (BYTE) ((dwExponent % 0x100) / 0x1);
532    
533     // hash using SHA1
534     if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
535     {
536     dwReturn = GetLastError();
537     Trace(WINEVENT_LEVEL_ERROR, L"CryptAcquireContext 0x%08X", dwReturn);
538     __leave;
539     }
540     if(!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
541     {
542     dwReturn = GetLastError();
543     Trace(WINEVENT_LEVEL_ERROR, L"CryptCreateHash 0x%08X", dwReturn);
544     __leave;
545     }
546     if(!CryptHashData(hHash, pbBuffer, dwBufferSize, 0))
547     {
548     dwReturn = GetLastError();
549     Trace(WINEVENT_LEVEL_ERROR, L"CryptHashData 0x%08X", dwReturn);
550     __leave;
551     }
552     if(!CryptGetHashParam(hHash, HP_HASHVAL, pbCommand + 5, &dwHashLen, 0)) {
553     dwReturn = GetLastError();
554     Trace(WINEVENT_LEVEL_ERROR, L"CryptGetHashParam 0x%08X", dwReturn);
555     __leave;
556     }
557     pbCommand[3] = Containers[dwContainer].bSignatureTag;
558     dwReturn = SCardSendCommand(pCardData, pbCommand, dwCommandSize);
559    
560     }
561     __finally
562     {
563     if (pbBuffer)
564     pCardData->pfnCspFree(pbBuffer);
565     if(hHash)
566     CryptDestroyHash(hHash);
567     if(hProv)
568     CryptReleaseContext(hProv,0);
569    
570     }
571 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
572 vletoux 3 return dwReturn;
573    
574     }
575    
576 vletoux 1 DWORD SCardReadPublicKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, PBYTE *pbPublicKey, PDWORD pdwPublicKeySize)
577     {
578     DWORD dwReturn;
579     PBYTE pbData = NULL;
580     DWORD dwResponseSize = 0;
581     BYTE pbCmd[] = {0x00,
582     0x47,
583     0x81,
584     0x00,
585     0x00,
586     0x00,
587     0x02,
588     0x00,
589     0x00,
590     0x00,
591     0x00
592     };
593     DWORD dwCmdSize;
594     POPENPGP_CONTEXT pContext;
595     PBYTE pbModulus;
596 vletoux 3 DWORD dwModulusSize, dwI;
597 vletoux 1 PBYTE pbExponent;
598     PRSAPUBLICKEYBLOB pbBlob = NULL;
599     __try
600     {
601     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
602     if (dwContainer >= MaxContainer)
603     {
604     dwReturn = SCARD_E_NO_KEY_CONTAINER;
605     Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
606     __leave;
607     }
608     pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
609 vletoux 3 pbCmd[7] = Containers[dwContainer].bKeyTag;
610 vletoux 1 dwCmdSize = 9;
611     if (pContext->fExtentedLeLcFields)
612     {
613     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
614     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
615     }
616     else
617     {
618     pbCmd[dwCmdSize++] = 0xFF;
619     }
620    
621     dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
622     if (dwReturn)
623     {
624     __leave;
625     }
626     if (!find_tlv(pbData,0x81,&pbModulus,&dwModulusSize))
627     {
628     dwReturn = SCARD_E_UNEXPECTED;
629     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
630     __leave;
631     }
632     if (!find_tlv(pbData,0x82,(PBYTE*)&pbExponent,NULL))
633     {
634     dwReturn = SCARD_E_UNEXPECTED;
635     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
636     __leave;
637     }
638 vletoux 3 Trace(WINEVENT_LEVEL_INFO, L"dwModulusSize %d bits", dwModulusSize * 8);
639 vletoux 1 *pdwPublicKeySize = sizeof(RSAPUBLICKEYBLOB) + dwModulusSize - sizeof(DWORD);
640     *pbPublicKey = pCardData->pfnCspAlloc(*pdwPublicKeySize);
641     if (!*pbPublicKey)
642     {
643     dwReturn = SCARD_E_NO_MEMORY;
644 vletoux 3 Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY %d", dwContainer);
645 vletoux 1 __leave;
646     }
647     pbBlob = (PRSAPUBLICKEYBLOB) *pbPublicKey;
648     memset(pbBlob,0,*pdwPublicKeySize);
649     pbBlob->blobheader.bType = PUBLICKEYBLOB;
650     pbBlob->blobheader.bVersion = CUR_BLOB_VERSION;
651     pbBlob->blobheader.reserved = 0;
652     pbBlob->blobheader.aiKeyAlg = Containers[dwContainer].aiKeyAlg;
653     pbBlob->rsapubkey.magic = 0x31415352; //'RSA1';
654     pbBlob->rsapubkey.bitlen = dwModulusSize*8;
655     pbBlob->rsapubkey.pubexp = pbExponent[0] * 0x1000000 + pbExponent[1] * 0x10000 + pbExponent[2] * 0x100 + pbExponent[3];
656 vletoux 3 // convert big endian into little endian
657     //memcpy(pbBlob->modulus, pbModulus, dwModulusSize);
658     for (dwI = 0; dwI < dwModulusSize; dwI++)
659     {
660     pbBlob->modulus[dwI] = pbModulus[dwModulusSize - 1 - dwI];
661     }
662    
663 vletoux 1 dwReturn = 0;
664     }
665     __finally
666     {
667     }
668 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
669 vletoux 1 return dwReturn;
670     }
671    
672     DWORD SCardCreateKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, DWORD dwBitLen)
673     {
674     DWORD dwReturn;
675     PBYTE pbData = NULL;
676     DWORD dwResponseSize = 0, dwCmdSize;
677     OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
678     POPENPGP_CONTEXT pContext;
679 vletoux 3 DWORD dwSecondsSince1970;
680     PBYTE pbModulus, pbExponent;
681     DWORD dwModulusSize, dwExponent;
682 vletoux 1 BYTE pbCmd[] = {0x00,
683     0x47,
684     0x80,
685     0x00,
686     0x00,
687     0x00,
688     0x02,
689     0x00,
690     0x00,
691     0x00,
692     0x00
693     };
694     __try
695     {
696     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
697     if (dwContainer >= MaxContainer)
698     {
699     dwReturn = SCARD_E_NO_KEY_CONTAINER;
700     Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
701     __leave;
702     }
703     // key len
704     dwReturn = GetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
705     if (dwReturn == SCARD_E_FILE_NOT_FOUND)
706     {
707     Attributes.bAlgoId = 0x01;
708     Attributes.bFormat = 0;
709     Attributes.wExponentLength = 0x20;
710     }
711     else if (dwReturn)
712     {
713     __leave;
714     }
715     Attributes.wModulusLength = (WORD) dwBitLen;
716     dwReturn = SetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
717     if (dwReturn)
718     {
719     __leave;
720     }
721    
722     pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
723 vletoux 3 pbCmd[7] = Containers[dwContainer].bKeyTag;
724 vletoux 1 dwCmdSize = 9;
725     if (pContext->fExtentedLeLcFields)
726     {
727     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
728     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
729     }
730     else
731     {
732     pbCmd[dwCmdSize++] = 0xFF;
733     }
734    
735     dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
736     if (dwReturn)
737     {
738     __leave;
739     }
740 vletoux 3 if (!find_tlv(pbData,0x81,&pbModulus,&dwModulusSize))
741     {
742     dwReturn = SCARD_E_UNEXPECTED;
743     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
744     __leave;
745     }
746     if (!find_tlv(pbData,0x82,(PBYTE*)&pbExponent,NULL))
747     {
748     dwReturn = SCARD_E_UNEXPECTED;
749     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
750     __leave;
751     }
752     dwExponent = pbExponent[0] * 0x1000000 + pbExponent[1] * 0x10000 + pbExponent[2] * 0x100 + pbExponent[3];
753     dwReturn = UpdateGenerationDateTime(pCardData, dwContainer, &dwSecondsSince1970);
754     if (dwReturn)
755     {
756     __leave;
757     }
758     dwReturn = UpdateFingerPrint(pCardData, dwContainer, dwSecondsSince1970,
759     pbModulus,
760     dwModulusSize * 8,
761     TRUE,
762     dwExponent
763     );
764 vletoux 1 }
765     __finally
766     {
767     if (pbData)
768     pCardData->pfnCspFree(pbData);
769     }
770 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
771 vletoux 1 return dwReturn;
772     }
773    
774     DWORD SCardImportKey(PCARD_DATA pCardData,
775     OPENPGP_CONTAINER dwContainer,
776     PBYTE pBlob,
777     DWORD dwKeySize)
778     {
779     DWORD dwReturn;
780     PSTR szAlgorithmAttributes = NULL;
781 vletoux 2 PBYTE pbTlv = NULL;
782     DWORD dwTlvSize;
783     PBYTE pbCommand = NULL;
784     DWORD dwCommandSize;
785 vletoux 1 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
786     PRSAPUBLICKEYBLOB pbPublicKeyBlob = (PRSAPUBLICKEYBLOB) pBlob;
787 vletoux 2 BYTE bCommand[] = {0x00,0xDB,0x3F,0xFF};
788 vletoux 3 DWORD dwSecondsSince1970;
789 vletoux 1 __try
790     {
791     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
792     // check blob
793 vletoux 2 if (pbPublicKeyBlob->blobheader.aiKeyAlg != CALG_RSA_SIGN &&
794     pbPublicKeyBlob->blobheader.aiKeyAlg != CALG_RSA_KEYX)
795 vletoux 1 {
796     Trace(WINEVENT_LEVEL_ERROR, L"Wrong aiKeyAlg %d", pbPublicKeyBlob->blobheader.aiKeyAlg);
797     dwReturn = SCARD_E_INVALID_PARAMETER;
798     __leave;
799     }
800 vletoux 2 if (pbPublicKeyBlob->blobheader.bType != PRIVATEKEYBLOB)
801 vletoux 1 {
802     Trace(WINEVENT_LEVEL_ERROR, L"Wrong bType %d", pbPublicKeyBlob->blobheader.bType);
803     dwReturn = SCARD_E_INVALID_PARAMETER;
804     __leave;
805     }
806     if (pbPublicKeyBlob->rsapubkey.magic != 0x32415352)
807     {
808     Trace(WINEVENT_LEVEL_ERROR, L"Wrong magic");
809     dwReturn = SCARD_E_INVALID_PARAMETER;
810     __leave;
811     }
812    
813     dwReturn = GetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
814     if (dwReturn == SCARD_E_FILE_NOT_FOUND)
815     {
816     Attributes.bAlgoId = 0x01;
817     Attributes.bFormat = 0;
818     Attributes.wExponentLength = 0x20;
819     }
820     else if (dwReturn)
821     {
822     __leave;
823     }
824     Attributes.wModulusLength = (WORD) pbPublicKeyBlob->rsapubkey.bitlen;
825     dwReturn = SetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
826     if (dwReturn)
827     {
828     __leave;
829     }
830 vletoux 2 dwReturn = BuildPrivateKeyTlv(pCardData, pbPublicKeyBlob, dwContainer, Attributes.bFormat, &pbTlv, &dwTlvSize);
831     if (dwReturn)
832     {
833     __leave;
834     }
835     if (dwTlvSize > 0xFF)
836     {
837     dwCommandSize = 7 + dwTlvSize;
838    
839     }
840     else
841     {
842     dwCommandSize = 5 + dwTlvSize;
843     }
844     pbCommand = pCardData->pfnCspAlloc(dwCommandSize);
845     if (!pbCommand)
846     {
847     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
848     dwReturn = SCARD_E_NO_MEMORY;
849     __leave;
850     }
851     memcpy(pbCommand, bCommand, 4);
852     if (dwTlvSize > 0xFF)
853     {
854     pbCommand[4] = 0;
855     pbCommand[5] = (BYTE)(dwTlvSize / 0x100);
856     pbCommand[6] = (BYTE)(dwTlvSize % 0x100);
857     memcpy(pbCommand + 7, pbTlv, dwTlvSize);
858     }
859     else
860     {
861     pbCommand[4] = (BYTE) dwTlvSize;
862     memcpy(pbCommand + 5, pbTlv, dwTlvSize);
863     }
864     dwReturn = SCardSendCommand(pCardData, pbCommand, dwCommandSize);
865     if (dwReturn)
866     {
867     __leave;
868     }
869 vletoux 3 dwReturn = UpdateGenerationDateTime(pCardData, dwContainer, &dwSecondsSince1970);
870     if (dwReturn)
871     {
872     __leave;
873     }
874     dwReturn = UpdateFingerPrint(pCardData, dwContainer, dwSecondsSince1970,
875     pbPublicKeyBlob->modulus,
876     pbPublicKeyBlob->rsapubkey.bitlen,
877     FALSE,
878     pbPublicKeyBlob->rsapubkey.pubexp
879     );
880 vletoux 1 }
881     __finally
882     {
883 vletoux 2 if (pbCommand)
884 vletoux 1 {
885 vletoux 2 SecureZeroMemory(pbCommand, dwCommandSize);
886     pCardData->pfnCspFree(pbCommand);
887 vletoux 1 }
888 vletoux 2 if (pbTlv)
889     {
890     SecureZeroMemory(pbTlv, dwTlvSize);
891     pCardData->pfnCspFree(pbTlv);
892     }
893 vletoux 1 }
894 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
895 vletoux 1 return dwReturn;
896     }
897    
898     DWORD SCardSign(PCARD_DATA pCardData,
899     PCARD_SIGNING_INFO pInfo)
900     {
901     DWORD dwReturn;
902     PBYTE pbData = NULL;
903     DWORD dwCmdSize = 0, dwI;
904     POPENPGP_CONTEXT pContext;
905     BYTE pbCmd[6 + 256 + 256] = {0x00,
906     0x2A,
907     0x9E,
908     0x9A,
909     0x00,
910     0x00,
911     };
912     __try
913     {
914     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
915 vletoux 5 if (pInfo->bContainerIndex != Signature)
916 vletoux 1 {
917     dwReturn = SCARD_E_NO_KEY_CONTAINER;
918     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
919     __leave;
920     }
921 vletoux 5 if (CARD_PADDING_PKCS1 & pInfo->dwPaddingType)
922 vletoux 1 {
923 vletoux 5 dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
924     Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PKCS1");
925     __leave;
926     }
927     else if (CARD_PADDING_PSS & pInfo->dwPaddingType)
928     {
929     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
930     Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
931     __leave;
932     }
933     for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
934     {
935     if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
936     {
937     // found
938     break;
939     }
940     }
941     if (dwI >= dwSignatureAlgorithmCount)
942     {
943     Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
944     __leave;
945     }
946     if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
947     {
948     Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
949     __leave;
950     }
951     pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
952    
953     dwCmdSize = 5;
954     if (pContext->fExtentedLeLcFields)
955     {
956     dwCmdSize++;
957     }
958     pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwI].dwEncodedOidSize + pInfo->cbData);
959     memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwI].pbEncodedOid,SignatureAlgorithm[dwI].dwEncodedOidSize);
960     dwCmdSize += SignatureAlgorithm[dwI].dwEncodedOidSize;
961     /*for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
962     {
963     pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
964     }*/
965     memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
966     dwCmdSize += pInfo->cbData;
967    
968    
969     if (pContext->fExtentedLeLcFields)
970     {
971     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
972     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
973     }
974     else
975     {
976     pbCmd[dwCmdSize++] = 0;
977     }
978     dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
979     if (dwReturn == SCARD_W_WRONG_CHV)
980     {
981     dwReturn = SCARD_W_SECURITY_VIOLATION;
982     __leave;
983     }
984     if (dwReturn)
985     {
986     __leave;
987     }
988     // revert the BYTES
989     for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
990     {
991     BYTE bTemp = pInfo->pbSignedData[dwI];
992     pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
993     pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
994     }
995     }
996     __finally
997     {
998     if (dwReturn)
999     {
1000     if (pInfo->pbSignedData)
1001     pCardData->pfnCspFree(pInfo->pbSignedData);
1002     }
1003     }
1004     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1005     return dwReturn;
1006     }
1007    
1008     DWORD SCardAuthenticate(PCARD_DATA pCardData,
1009     PCARD_SIGNING_INFO pInfo)
1010     {
1011     DWORD dwReturn;
1012     PBYTE pbData = NULL;
1013     DWORD dwCmdSize = 0, dwI;
1014     POPENPGP_CONTEXT pContext;
1015     BYTE pbCmd[6 + 256 + 256] = {0x00,
1016     0x88,
1017     0x00,
1018     0x00,
1019     0x00,
1020     0x00,
1021     };
1022     __try
1023     {
1024     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1025     if (pInfo->bContainerIndex != Authentication)
1026     {
1027 vletoux 1 dwReturn = SCARD_E_NO_KEY_CONTAINER;
1028     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1029     __leave;
1030     }
1031     if (CARD_PADDING_PKCS1 & pInfo->dwPaddingType)
1032     {
1033     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1034     Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PKCS1");
1035     __leave;
1036     }
1037     else if (CARD_PADDING_PSS & pInfo->dwPaddingType)
1038     {
1039     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1040     Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
1041     __leave;
1042     }
1043     for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
1044     {
1045     if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
1046     {
1047     // found
1048     break;
1049     }
1050     }
1051     if (dwI >= dwSignatureAlgorithmCount)
1052     {
1053     Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
1054     __leave;
1055     }
1056     if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
1057     {
1058     Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
1059     __leave;
1060     }
1061     pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1062    
1063     dwCmdSize = 5;
1064     if (pContext->fExtentedLeLcFields)
1065     {
1066     dwCmdSize++;
1067     }
1068     pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwI].dwEncodedOidSize + pInfo->cbData);
1069     memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwI].pbEncodedOid,SignatureAlgorithm[dwI].dwEncodedOidSize);
1070     dwCmdSize += SignatureAlgorithm[dwI].dwEncodedOidSize;
1071 vletoux 3 /*for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
1072 vletoux 1 {
1073     pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
1074 vletoux 3 }*/
1075     memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
1076 vletoux 1 dwCmdSize += pInfo->cbData;
1077    
1078    
1079     if (pContext->fExtentedLeLcFields)
1080     {
1081     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
1082     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
1083     }
1084     else
1085     {
1086     pbCmd[dwCmdSize++] = 0;
1087     }
1088     dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
1089     if (dwReturn == SCARD_W_WRONG_CHV)
1090     {
1091     dwReturn = SCARD_W_SECURITY_VIOLATION;
1092     __leave;
1093     }
1094     if (dwReturn)
1095     {
1096     __leave;
1097     }
1098     // revert the BYTES
1099     for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
1100     {
1101     BYTE bTemp = pInfo->pbSignedData[dwI];
1102     pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
1103     pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
1104     }
1105     }
1106     __finally
1107     {
1108     if (dwReturn)
1109     {
1110     if (pInfo->pbSignedData)
1111     pCardData->pfnCspFree(pInfo->pbSignedData);
1112     }
1113     }
1114 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1115 vletoux 1 return dwReturn;
1116     }
1117    
1118     DWORD SCardDecrypt(PCARD_DATA pCardData,
1119     PCARD_RSA_DECRYPT_INFO pInfo)
1120     {
1121     DWORD dwReturn;
1122     PBYTE pbData = NULL;
1123     DWORD dwCmdSize = 0, dwResponseSize;
1124     BYTE pbCmd[6 + 256 + 256] = {0x00,
1125     0x2A,
1126     0x80,
1127     0x86,
1128     0x00,
1129     };
1130     POPENPGP_CONTEXT pContext;
1131 vletoux 3 DWORD dwI;
1132 vletoux 1 __try
1133     {
1134     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1135     if (pInfo->bContainerIndex >= MaxContainer)
1136     {
1137     dwReturn = SCARD_E_NO_KEY_CONTAINER;
1138     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1139     __leave;
1140     }
1141     if (pInfo->bContainerIndex != Confidentiality)
1142     {
1143     dwReturn = SCARD_E_NO_KEY_CONTAINER;
1144     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1145     __leave;
1146     }
1147     pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1148     dwCmdSize = 5;
1149     if (pContext->fExtentedLeLcFields)
1150     {
1151     pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) / 0x100);
1152     pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
1153     }
1154     else
1155     {
1156     pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
1157     }
1158     pbCmd[dwCmdSize++] = 0;
1159 vletoux 4 //little endian => big endian
1160 vletoux 3 for(dwI = 0; dwI < pInfo->cbData; dwI++)
1161     {
1162     pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData -1 -dwI];
1163     }
1164 vletoux 1 dwCmdSize += pInfo->cbData;
1165     if (pContext->fExtentedLeLcFields)
1166     {
1167     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
1168     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
1169     }
1170     else
1171     {
1172     pbCmd[dwCmdSize++] = 0;
1173     }
1174     dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
1175     if (dwReturn)
1176     {
1177     __leave;
1178     }
1179 vletoux 4
1180     // CryptDecrypt expects the data decrypted using rsa (only the mathematical computation)
1181     // this means the data with the padding (removed by the card)
1182     // and in little endian (while the card return the data in big endian)
1183     // so we rebuilt the padding in reverse order
1184    
1185     if ( pInfo->cbData < dwResponseSize + 3 + 11)
1186 vletoux 1 {
1187     dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
1188     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d expected = %d", pInfo->cbData, dwResponseSize);
1189     __leave;
1190     }
1191 vletoux 4
1192     pInfo->pbData[pInfo->cbData - 1] = 0; // start byte
1193     pInfo->pbData[pInfo->cbData - 2] = 02; // block type
1194     // padding
1195     memset(pInfo->pbData + dwResponseSize + 1,1,pInfo->cbData - 3 - dwResponseSize);
1196     pInfo->pbData[dwResponseSize] = 0; // separator
1197     // data field in reverse order
1198     for(dwI = 0; dwI < dwResponseSize; dwI++)
1199     {
1200     pInfo->pbData[dwI] = pbData[dwResponseSize - 1 - dwI];
1201     }
1202 vletoux 1 }
1203     __finally
1204     {
1205     if (pbData)
1206 vletoux 3 {
1207     SecureZeroMemory(pbData, dwResponseSize);
1208 vletoux 1 pCardData->pfnCspFree(pbData);
1209 vletoux 3 }
1210 vletoux 1 }
1211 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1212 vletoux 1 return dwReturn;
1213     }
1214    
1215    
1216     DWORD GetPinInfo(DWORD __in dwPinIndex, __inout PPIN_INFO pPinInfo)
1217     {
1218     DWORD dwReturn=0;
1219     __try
1220     {
1221     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwPinIndex=%d",dwPinIndex);
1222     switch(dwPinIndex)
1223     {
1224     case ROLE_SIGNATURE:
1225     pPinInfo->PinType = AlphaNumericPinType;
1226     pPinInfo->PinPurpose = DigitalSignaturePin;
1227     pPinInfo->dwChangePermission = PIN_CHANGE_FLAG_CHANGEPIN;
1228     pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
1229     pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
1230     break;
1231     case ROLE_AUTHENTICATION:
1232     pPinInfo->PinType = AlphaNumericPinType;
1233     pPinInfo->PinPurpose = AuthenticationPin;
1234     pPinInfo->dwChangePermission = PIN_CHANGE_FLAG_CHANGEPIN;
1235     pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
1236     pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
1237     break;
1238     case ROLE_CONFIDENTIALITY:
1239     pPinInfo->PinType = AlphaNumericPinType;
1240     pPinInfo->PinPurpose = EncryptionPin;
1241     pPinInfo->dwChangePermission = PIN_CHANGE_FLAG_CHANGEPIN;
1242     pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
1243     pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
1244     break;
1245     default:
1246     Trace(WINEVENT_LEVEL_ERROR, L"dwPinIndex == %d", dwPinIndex);
1247     dwReturn = SCARD_E_INVALID_PARAMETER ;
1248     __leave;
1249     }
1250     }
1251     __finally
1252     {
1253     }
1254 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1255 vletoux 1 return dwReturn;
1256     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26