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

Annotation of /trunk/OpenPGPminidriver/CryptoOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26