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

Annotation of /trunk/OpenPGPminidriver/CryptoOperations.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26