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

Annotation of /trunk/OpenPGPminidriver/CryptoOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Mon Mar 15 18:23:17 2010 UTC (15 years, 1 month ago) by vletoux
File MIME type: text/plain
File size: 50469 byte(s)
first beta version
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 10 {ROLE_CONFIDENTIALITY, AT_KEYEXCHANGE},
40     {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 10 Attributes.wModulusLengthInBit = (unsigned short)dwBitLen * 8;
837     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 8 if (pInfo->dwSigningFlags & CARD_PADDING_INFO_PRESENT)
1108 vletoux 1 {
1109 vletoux 8 if ( pInfo->dwPaddingType == CARD_PADDING_PKCS1)
1110     {
1111 vletoux 9 BCRYPT_PKCS1_PADDING_INFO* padding = (BCRYPT_PKCS1_PADDING_INFO*) pInfo->pPaddingInfo;
1112 vletoux 10 if (padding->pszAlgId == NULL)
1113     {
1114     if (fAllowNoOid)
1115     {
1116     *pdwIndex = OPENPGP_NO_OID;
1117     dwReturn = 0;
1118     __leave;
1119     }
1120     else
1121     {
1122     Trace(WINEVENT_LEVEL_ERROR, L"alg not found %s", padding->pszAlgId);
1123     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1124     __leave;
1125     }
1126     }
1127 vletoux 9 for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
1128     {
1129     if (wcscmp(SignatureAlgorithm[dwI].szAlgId,padding->pszAlgId) == 0)
1130     {
1131     // found
1132     break;
1133     }
1134     }
1135     if (dwI >= dwSignatureAlgorithmCount)
1136     {
1137     Trace(WINEVENT_LEVEL_ERROR, L"alg not found %s", padding->pszAlgId);
1138     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1139     __leave;
1140     }
1141 vletoux 8 }
1142     else if (pInfo->dwPaddingType == CARD_PADDING_PSS)
1143     {
1144     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1145     Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
1146     __leave;
1147     }
1148     else
1149     {
1150     dwReturn = SCARD_E_INVALID_PARAMETER;
1151     Trace(WINEVENT_LEVEL_ERROR, L"pInfo->dwPaddingType = %d", pInfo->dwPaddingType);
1152     __leave;
1153     }
1154 vletoux 5 }
1155 vletoux 9 else
1156 vletoux 5 {
1157 vletoux 9 if (!(pInfo->aiHashAlg & ALG_CLASS_HASH))
1158 vletoux 5 {
1159 vletoux 9 dwReturn = SCARD_E_INVALID_PARAMETER;
1160     Trace(WINEVENT_LEVEL_ERROR, L"pInfo->aiHashAlg == %d", pInfo->aiHashAlg);
1161     __leave;
1162 vletoux 5 }
1163 vletoux 9 for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
1164     {
1165     if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
1166     {
1167     // found
1168     break;
1169     }
1170     }
1171     if (dwI >= dwSignatureAlgorithmCount)
1172     {
1173     Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
1174     dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
1175     __leave;
1176     }
1177 vletoux 5 }
1178     if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
1179     {
1180     Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
1181 vletoux 8 dwReturn = SCARD_E_INVALID_PARAMETER;
1182 vletoux 5 __leave;
1183     }
1184 vletoux 9 *pdwIndex = dwI;
1185     dwReturn = 0;
1186     }
1187     __finally
1188     {
1189     }
1190     return dwReturn;
1191     }
1192    
1193     DWORD OCardSign(PCARD_DATA pCardData,
1194     PCARD_SIGNING_INFO pInfo)
1195     {
1196     DWORD dwReturn;
1197     PBYTE pbData = NULL;
1198     DWORD dwCmdSize = 0, dwIndex, dwI;
1199 vletoux 10 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1200 vletoux 9 BYTE pbCmd[6 + 256 + 256] = {0x00,
1201     0x2A,
1202     0x9E,
1203     0x9A,
1204     0x00,
1205     0x00,
1206     };
1207     __try
1208     {
1209     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1210     if (pInfo->bContainerIndex != ContainerSignature)
1211     {
1212 vletoux 8 dwReturn = SCARD_E_NO_KEY_CONTAINER;
1213     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1214     __leave;
1215     }
1216 vletoux 10 dwReturn = OCardCheckSigningInfo(pInfo, FALSE, &dwIndex);
1217     if (dwReturn)
1218     {
1219     __leave;
1220     }
1221 vletoux 8 if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
1222     {
1223     // optimisation :
1224     // return the buffer size only
1225 vletoux 10 dwReturn = OCardGetKeyLengthInBytes(pCardData, pInfo->bContainerIndex, &pInfo->cbSignedData);
1226 vletoux 8 __leave;
1227     }
1228    
1229 vletoux 5 dwCmdSize = 5;
1230     if (pContext->fExtentedLeLcFields)
1231     {
1232     dwCmdSize++;
1233     }
1234 vletoux 9 pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwIndex].dwEncodedOidSize + pInfo->cbData);
1235     memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwIndex].pbEncodedOid,SignatureAlgorithm[dwIndex].dwEncodedOidSize);
1236     dwCmdSize += SignatureAlgorithm[dwIndex].dwEncodedOidSize;
1237 vletoux 5 /*for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
1238     {
1239     pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
1240     }*/
1241     memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
1242     dwCmdSize += pInfo->cbData;
1243    
1244    
1245     if (pContext->fExtentedLeLcFields)
1246     {
1247 vletoux 6 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
1248     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
1249 vletoux 5 }
1250     else
1251     {
1252     pbCmd[dwCmdSize++] = 0;
1253     }
1254 vletoux 8 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
1255 vletoux 5 if (dwReturn == SCARD_W_WRONG_CHV)
1256     {
1257     dwReturn = SCARD_W_SECURITY_VIOLATION;
1258     __leave;
1259     }
1260     if (dwReturn)
1261     {
1262     __leave;
1263     }
1264     // revert the BYTES
1265     for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
1266     {
1267     BYTE bTemp = pInfo->pbSignedData[dwI];
1268     pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
1269     pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
1270     }
1271     }
1272     __finally
1273     {
1274     if (dwReturn)
1275     {
1276     if (pInfo->pbSignedData)
1277     pCardData->pfnCspFree(pInfo->pbSignedData);
1278     }
1279     }
1280     Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1281     return dwReturn;
1282     }
1283 vletoux 10 DWORD OCardIsConfidentialityKeyTheSameThanAuthentication(__in PCARD_DATA pCardData)
1284     {
1285     DWORD dwReturn;
1286     POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1287     __try
1288     {
1289     // see if the confidentiality key is the same than the authentication key
1290     // if yes, confidentiality key can sign
1291     // else ... we don't follow ms guidelines which requiers every container
1292     // to be able to sign data
1293     dwReturn = OCardUpdateCachedPublicKeyIfNeeded(pCardData, ContainerAuthentication);
1294     if (dwReturn)
1295     {
1296     __leave;
1297     }
1298     dwReturn = OCardUpdateCachedPublicKeyIfNeeded(pCardData, ContainerConfidentiality);
1299     if (dwReturn)
1300     {
1301     __leave;
1302     }
1303     if (pContext->dwModulusSizeInBytes[ContainerAuthentication]
1304     != pContext->dwModulusSizeInBytes[ContainerConfidentiality])
1305     {
1306     dwReturn = SCARD_E_NO_KEY_CONTAINER;
1307     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER");
1308     __leave;
1309     }
1310     if (memcmp(pContext->pbModulusInLittleEndian[ContainerAuthentication],
1311     pContext->pbModulusInLittleEndian[ContainerConfidentiality],
1312     pContext->dwModulusSizeInBytes[ContainerConfidentiality]) != 0)
1313     {
1314     dwReturn = SCARD_E_NO_KEY_CONTAINER;
1315     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER");
1316     __leave;
1317     }
1318     // if we are here, then the confidentiality key can sign using the authentication key
1319     dwReturn = 0;
1320     }
1321     __finally
1322     {
1323     }
1324     return dwReturn;
1325     }
1326 vletoux 8 DWORD OCardAuthenticate(PCARD_DATA pCardData,
1327 vletoux 5 PCARD_SIGNING_INFO pInfo)
1328     {
1329     DWORD dwReturn;
1330     PBYTE pbData = NULL;
1331 vletoux 9 DWORD dwCmdSize = 0, dwIndex, dwI;
1332 vletoux 10 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1333 vletoux 5 BYTE pbCmd[6 + 256 + 256] = {0x00,
1334     0x88,
1335     0x00,
1336     0x00,
1337     0x00,
1338     0x00,
1339     };
1340     __try
1341     {
1342     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1343 vletoux 10
1344     if (pInfo->bContainerIndex != ContainerAuthentication && pInfo->bContainerIndex != ContainerConfidentiality)
1345 vletoux 5 {
1346 vletoux 8 dwReturn = SCARD_E_NO_KEY_CONTAINER;
1347     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1348     __leave;
1349     }
1350 vletoux 10 if (pInfo->bContainerIndex == ContainerConfidentiality)
1351 vletoux 8 {
1352 vletoux 10 dwReturn = OCardIsConfidentialityKeyTheSameThanAuthentication(pCardData);
1353 vletoux 8 if (dwReturn)
1354     {
1355     __leave;
1356     }
1357 vletoux 10 }
1358     dwReturn = OCardCheckSigningInfo(pInfo, TRUE, &dwIndex);
1359     if (dwReturn)
1360     {
1361 vletoux 8 __leave;
1362     }
1363 vletoux 10 if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
1364     {
1365     // optimisation :
1366     // return the buffer size only
1367     dwReturn = OCardGetKeyLengthInBytes(pCardData, pInfo->bContainerIndex, &pInfo->cbSignedData);
1368     __leave;
1369     }
1370 vletoux 8
1371 vletoux 1 dwCmdSize = 5;
1372     if (pContext->fExtentedLeLcFields)
1373     {
1374     dwCmdSize++;
1375     }
1376 vletoux 10 if (dwIndex == OPENPGP_NO_OID)
1377 vletoux 1 {
1378 vletoux 10 pbCmd[dwCmdSize++] = (BYTE) (pInfo->cbData);
1379     }
1380     else
1381     {
1382     pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwIndex].dwEncodedOidSize + pInfo->cbData);
1383     memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwIndex].pbEncodedOid,SignatureAlgorithm[dwIndex].dwEncodedOidSize);
1384     dwCmdSize += SignatureAlgorithm[dwIndex].dwEncodedOidSize;
1385     }
1386 vletoux 3 memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
1387 vletoux 1 dwCmdSize += pInfo->cbData;
1388    
1389     if (pContext->fExtentedLeLcFields)
1390     {
1391 vletoux 6 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
1392     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
1393 vletoux 1 }
1394     else
1395     {
1396     pbCmd[dwCmdSize++] = 0;
1397     }
1398 vletoux 8 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
1399 vletoux 1 if (dwReturn == SCARD_W_WRONG_CHV)
1400     {
1401     dwReturn = SCARD_W_SECURITY_VIOLATION;
1402     __leave;
1403     }
1404     if (dwReturn)
1405     {
1406     __leave;
1407     }
1408     // revert the BYTES
1409     for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
1410     {
1411     BYTE bTemp = pInfo->pbSignedData[dwI];
1412     pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
1413     pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
1414     }
1415     }
1416     __finally
1417     {
1418     if (dwReturn)
1419     {
1420     if (pInfo->pbSignedData)
1421     pCardData->pfnCspFree(pInfo->pbSignedData);
1422     }
1423     }
1424 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1425 vletoux 1 return dwReturn;
1426     }
1427    
1428 vletoux 8 DWORD OCardDecrypt(PCARD_DATA pCardData,
1429 vletoux 1 PCARD_RSA_DECRYPT_INFO pInfo)
1430     {
1431     DWORD dwReturn;
1432     PBYTE pbData = NULL;
1433     DWORD dwCmdSize = 0, dwResponseSize;
1434     BYTE pbCmd[6 + 256 + 256] = {0x00,
1435     0x2A,
1436     0x80,
1437     0x86,
1438     0x00,
1439     };
1440 vletoux 10 POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1441 vletoux 3 DWORD dwI;
1442 vletoux 8 OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
1443 vletoux 1 __try
1444     {
1445     Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
1446 vletoux 9 if (pInfo->bContainerIndex >= ContainerMax)
1447 vletoux 1 {
1448     dwReturn = SCARD_E_NO_KEY_CONTAINER;
1449     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1450     __leave;
1451     }
1452 vletoux 9 if (pInfo->bContainerIndex != ContainerConfidentiality)
1453 vletoux 1 {
1454     dwReturn = SCARD_E_NO_KEY_CONTAINER;
1455     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
1456     __leave;
1457     }
1458 vletoux 8 // check the buffer size
1459 vletoux 9 dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeyConfidentiality, &Attributes);
1460 vletoux 8 if (dwReturn)
1461     {
1462     __leave;
1463     }
1464     if (pInfo->cbData < (DWORD)(Attributes.wModulusLengthInBit/8))
1465     {
1466     dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
1467     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d", pInfo->cbData);
1468     __leave;
1469     }
1470 vletoux 1 dwCmdSize = 5;
1471     if (pContext->fExtentedLeLcFields)
1472     {
1473     pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) / 0x100);
1474     pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
1475     }
1476     else
1477     {
1478     pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
1479     }
1480     pbCmd[dwCmdSize++] = 0;
1481 vletoux 4 //little endian => big endian
1482 vletoux 3 for(dwI = 0; dwI < pInfo->cbData; dwI++)
1483     {
1484     pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData -1 -dwI];
1485     }
1486 vletoux 1 dwCmdSize += pInfo->cbData;
1487     if (pContext->fExtentedLeLcFields)
1488     {
1489 vletoux 6 pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength / 0x100);
1490     pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxCommandDataLength % 0x100);
1491 vletoux 1 }
1492     else
1493     {
1494     pbCmd[dwCmdSize++] = 0;
1495     }
1496 vletoux 8 dwReturn = OCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
1497 vletoux 1 if (dwReturn)
1498     {
1499     __leave;
1500     }
1501 vletoux 4
1502     // CryptDecrypt expects the data decrypted using rsa (only the mathematical computation)
1503     // this means the data with the padding (removed by the card)
1504     // and in little endian (while the card return the data in big endian)
1505     // so we rebuilt the padding in reverse order
1506    
1507     if ( pInfo->cbData < dwResponseSize + 3 + 11)
1508 vletoux 1 {
1509     dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
1510     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d expected = %d", pInfo->cbData, dwResponseSize);
1511     __leave;
1512     }
1513 vletoux 4
1514     pInfo->pbData[pInfo->cbData - 1] = 0; // start byte
1515     pInfo->pbData[pInfo->cbData - 2] = 02; // block type
1516     // padding
1517     memset(pInfo->pbData + dwResponseSize + 1,1,pInfo->cbData - 3 - dwResponseSize);
1518     pInfo->pbData[dwResponseSize] = 0; // separator
1519     // data field in reverse order
1520     for(dwI = 0; dwI < dwResponseSize; dwI++)
1521     {
1522     pInfo->pbData[dwI] = pbData[dwResponseSize - 1 - dwI];
1523     }
1524 vletoux 1 }
1525     __finally
1526     {
1527     if (pbData)
1528 vletoux 3 {
1529     SecureZeroMemory(pbData, dwResponseSize);
1530 vletoux 1 pCardData->pfnCspFree(pbData);
1531 vletoux 3 }
1532 vletoux 1 }
1533 vletoux 5 Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
1534 vletoux 1 return dwReturn;
1535     }
1536    
1537    
1538 vletoux 8 DWORD OCardReadContainerMapFile(__in PCARD_DATA pCardData,
1539     __in PBYTE* ppbResponse, __in PDWORD pdwResponseSize)
1540 vletoux 1 {
1541 vletoux 8 DWORD dwReturn = 0;
1542     POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
1543 vletoux 10 DWORD dwSizeInBits;
1544 vletoux 1 __try
1545     {
1546 vletoux 8 PCONTAINER_MAP_RECORD pContainer = NULL;
1547     BOOL fIsDefaultContainerSet = FALSE;
1548 vletoux 9 *pdwResponseSize = sizeof(CONTAINER_MAP_RECORD) * ContainerMax;
1549 vletoux 8 *ppbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
1550     if (! *ppbResponse )
1551 vletoux 1 {
1552 vletoux 8 dwReturn = SCARD_E_NO_MEMORY;
1553     Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
1554 vletoux 1 __leave;
1555     }
1556 vletoux 8 pContainer = (PCONTAINER_MAP_RECORD) *ppbResponse;
1557 vletoux 9 memset(pContainer,0,sizeof(CONTAINER_MAP_RECORD) * ContainerMax);
1558 vletoux 8
1559 vletoux 10 dwReturn = OCardGetKeyLengthInBytes(pCardData, KeyAuthentication, &dwSizeInBits);
1560 vletoux 8 if (dwReturn)
1561     {
1562     __leave;
1563     }
1564 vletoux 10 pContainer[ContainerAuthentication].wSigKeySizeBits = (WORD)dwSizeInBits * 8;
1565 vletoux 9 swprintf_s(pContainer[ContainerAuthentication].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
1566 vletoux 8 L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Authenticate",
1567     pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
1568     pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
1569     pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
1570     pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
1571 vletoux 9 if (pContext->fHasKey[KeyAuthentication])
1572 vletoux 8 {
1573 vletoux 9 pContainer[ContainerAuthentication].bFlags = CONTAINER_MAP_VALID_CONTAINER | CONTAINER_MAP_DEFAULT_CONTAINER;
1574 vletoux 8 fIsDefaultContainerSet = TRUE;
1575     }
1576 vletoux 9
1577 vletoux 10 dwReturn = OCardGetKeyLengthInBytes(pCardData, KeyConfidentiality, &dwSizeInBits);
1578 vletoux 8 if (dwReturn)
1579     {
1580     __leave;
1581     }
1582 vletoux 10 pContainer[ContainerConfidentiality].wKeyExchangeKeySizeBits = (WORD)dwSizeInBits * 8;
1583 vletoux 9 swprintf_s(pContainer[ContainerConfidentiality].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
1584     L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Confidential",
1585 vletoux 8 pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
1586     pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
1587     pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
1588     pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
1589 vletoux 9 if (pContext->fHasKey[KeyConfidentiality])
1590 vletoux 8 {
1591 vletoux 9 pContainer[ContainerConfidentiality].bFlags = CONTAINER_MAP_VALID_CONTAINER;
1592 vletoux 8 if (!fIsDefaultContainerSet)
1593     {
1594 vletoux 9 pContainer[ContainerConfidentiality].bFlags |= CONTAINER_MAP_DEFAULT_CONTAINER;
1595 vletoux 8 fIsDefaultContainerSet = TRUE;
1596     }
1597     }
1598 vletoux 9
1599 vletoux 10 dwReturn = OCardGetKeyLengthInBytes(pCardData, KeySignature, &dwSizeInBits);
1600 vletoux 8 if (dwReturn)
1601     {
1602     __leave;
1603     }
1604 vletoux 10 pContainer[ContainerSignature].wSigKeySizeBits = (WORD)dwSizeInBits * 8;
1605 vletoux 9 swprintf_s(pContainer[ContainerSignature].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
1606     L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Signature",
1607 vletoux 8 pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
1608     pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
1609     pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
1610     pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
1611 vletoux 9 if (pContext->fHasKey[KeySignature])
1612 vletoux 8 {
1613 vletoux 9 pContainer[ContainerSignature].bFlags = CONTAINER_MAP_VALID_CONTAINER;
1614 vletoux 8 if (!fIsDefaultContainerSet)
1615     {
1616 vletoux 9 pContainer[ContainerSignature].bFlags |= CONTAINER_MAP_DEFAULT_CONTAINER;
1617 vletoux 8 fIsDefaultContainerSet = TRUE;
1618     }
1619     }
1620 vletoux 1 }
1621     __finally
1622     {
1623     }
1624     return dwReturn;
1625     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26