shell32: A nicer icon for "open folder".
[wine] / dlls / rsaenh / rsaenh.c
1 /*
2  * dlls/rsaenh/rsaenh.c
3  * RSAENH - RSA encryption for Wine
4  *
5  * Copyright 2002 TransGaming Technologies (David Hammerton)
6  * Copyright 2004 Mike McCormack for CodeWeavers
7  * Copyright 2004, 2005 Michael Jung
8  * Copyright 2007 Vijay Kiran Kamuju
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27 #include "wine/library.h"
28 #include "wine/debug.h"
29
30 #include <stdarg.h>
31 #include <stdio.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winreg.h"
36 #include "wincrypt.h"
37 #include "handle.h"
38 #include "implglue.h"
39 #include "objbase.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
42
43 /******************************************************************************
44  * CRYPTHASH - hash objects
45  */
46 #define RSAENH_MAGIC_HASH           0x85938417u
47 #define RSAENH_MAX_HASH_SIZE        104
48 #define RSAENH_HASHSTATE_HASHING    1
49 #define RSAENH_HASHSTATE_FINISHED   2
50 typedef struct _RSAENH_TLS1PRF_PARAMS
51 {
52     CRYPT_DATA_BLOB blobLabel;
53     CRYPT_DATA_BLOB blobSeed;
54 } RSAENH_TLS1PRF_PARAMS;
55
56 typedef struct tagCRYPTHASH
57 {
58     OBJECTHDR    header;
59     ALG_ID       aiAlgid;
60     HCRYPTKEY    hKey;
61     HCRYPTPROV   hProv;
62     DWORD        dwHashSize;
63     DWORD        dwState;
64     HASH_CONTEXT context;
65     BYTE         abHashValue[RSAENH_MAX_HASH_SIZE];
66     PHMAC_INFO   pHMACInfo;
67     RSAENH_TLS1PRF_PARAMS tpPRFParams;
68 } CRYPTHASH;
69
70 /******************************************************************************
71  * CRYPTKEY - key objects
72  */
73 #define RSAENH_MAGIC_KEY           0x73620457u
74 #define RSAENH_MAX_KEY_SIZE        48
75 #define RSAENH_MAX_BLOCK_SIZE      24
76 #define RSAENH_KEYSTATE_IDLE       0
77 #define RSAENH_KEYSTATE_ENCRYPTING 1
78 #define RSAENH_KEYSTATE_MASTERKEY  2
79 typedef struct _RSAENH_SCHANNEL_INFO 
80 {
81     SCHANNEL_ALG saEncAlg;
82     SCHANNEL_ALG saMACAlg;
83     CRYPT_DATA_BLOB blobClientRandom;
84     CRYPT_DATA_BLOB blobServerRandom;
85 } RSAENH_SCHANNEL_INFO;
86
87 typedef struct tagCRYPTKEY
88 {
89     OBJECTHDR   header;
90     ALG_ID      aiAlgid;
91     HCRYPTPROV  hProv;
92     DWORD       dwMode;
93     DWORD       dwModeBits;
94     DWORD       dwPermissions;
95     DWORD       dwKeyLen;
96     DWORD       dwEffectiveKeyLen;
97     DWORD       dwSaltLen;
98     DWORD       dwBlockLen;
99     DWORD       dwState;
100     KEY_CONTEXT context;    
101     BYTE        abKeyValue[RSAENH_MAX_KEY_SIZE];
102     BYTE        abInitVector[RSAENH_MAX_BLOCK_SIZE];
103     BYTE        abChainVector[RSAENH_MAX_BLOCK_SIZE];
104     RSAENH_SCHANNEL_INFO siSChannelInfo;
105 } CRYPTKEY;
106
107 /******************************************************************************
108  * KEYCONTAINER - key containers
109  */
110 #define RSAENH_PERSONALITY_BASE        0u
111 #define RSAENH_PERSONALITY_STRONG      1u
112 #define RSAENH_PERSONALITY_ENHANCED    2u
113 #define RSAENH_PERSONALITY_SCHANNEL    3u
114 #define RSAENH_PERSONALITY_AES         4u
115
116 #define RSAENH_MAGIC_CONTAINER         0x26384993u
117 typedef struct tagKEYCONTAINER
118 {
119     OBJECTHDR    header;
120     DWORD        dwFlags;
121     DWORD        dwPersonality;
122     DWORD        dwEnumAlgsCtr;
123     DWORD        dwEnumContainersCtr;
124     CHAR         szName[MAX_PATH];
125     CHAR         szProvName[MAX_PATH];
126     HCRYPTKEY    hKeyExchangeKeyPair;
127     HCRYPTKEY    hSignatureKeyPair;
128 } KEYCONTAINER;
129
130 /******************************************************************************
131  * Some magic constants
132  */
133 #define RSAENH_ENCRYPT                    1
134 #define RSAENH_DECRYPT                    0    
135 #define RSAENH_HMAC_DEF_IPAD_CHAR      0x36
136 #define RSAENH_HMAC_DEF_OPAD_CHAR      0x5c
137 #define RSAENH_HMAC_DEF_PAD_LEN          64
138 #define RSAENH_DES_EFFECTIVE_KEYLEN      56
139 #define RSAENH_DES_STORAGE_KEYLEN        64
140 #define RSAENH_3DES112_EFFECTIVE_KEYLEN 112
141 #define RSAENH_3DES112_STORAGE_KEYLEN   128
142 #define RSAENH_3DES_EFFECTIVE_KEYLEN    168
143 #define RSAENH_3DES_STORAGE_KEYLEN      192
144 #define RSAENH_MAGIC_RSA2        0x32415352
145 #define RSAENH_MAGIC_RSA1        0x31415352
146 #define RSAENH_PKC_BLOCKTYPE           0x02
147 #define RSAENH_SSL3_VERSION_MAJOR         3
148 #define RSAENH_SSL3_VERSION_MINOR         0
149 #define RSAENH_TLS1_VERSION_MAJOR         3
150 #define RSAENH_TLS1_VERSION_MINOR         1
151 #define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s"
152
153 #define RSAENH_MIN(a,b) ((a)<(b)?(a):(b))
154 /******************************************************************************
155  * aProvEnumAlgsEx - Defines the capabilities of the CSP personalities.
156  */
157 #define RSAENH_MAX_ENUMALGS 24
158 #define RSAENH_PCT1_SSL2_SSL3_TLS1 (CRYPT_FLAG_PCT1|CRYPT_FLAG_SSL2|CRYPT_FLAG_SSL3|CRYPT_FLAG_TLS1)
159 static const PROV_ENUMALGS_EX aProvEnumAlgsEx[5][RSAENH_MAX_ENUMALGS+1] =
160 {
161  {
162   {CALG_RC2,       40, 40,   56,0,                    4,"RC2",     24,"RSA Data Security's RC2"},
163   {CALG_RC4,       40, 40,   56,0,                    4,"RC4",     24,"RSA Data Security's RC4"},
164   {CALG_DES,       56, 56,   56,0,                    4,"DES",     31,"Data Encryption Standard (DES)"},
165   {CALG_SHA,      160,160,  160,CRYPT_FLAG_SIGNING,   6,"SHA-1",   30,"Secure Hash Algorithm (SHA-1)"},
166   {CALG_MD2,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD2",     23,"Message Digest 2 (MD2)"},
167   {CALG_MD4,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD4",     23,"Message Digest 4 (MD4)"},
168   {CALG_MD5,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD5",     23,"Message Digest 5 (MD5)"},
169   {CALG_SSL3_SHAMD5,288,288,288,0,                   12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
170   {CALG_MAC,        0,  0,    0,0,                    4,"MAC",     28,"Message Authentication Code"},
171   {CALG_RSA_SIGN, 512,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
172   {CALG_RSA_KEYX, 512,384, 1024,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
173   {CALG_HMAC,       0,  0,    0,0,                    5,"HMAC",    18,"Hugo's MAC (HMAC)"},
174   {0,               0,  0,    0,0,                    1,"",         1,""}
175  },
176  {
177   {CALG_RC2,      128, 40,  128,0,                    4,"RC2",     24,"RSA Data Security's RC2"},
178   {CALG_RC4,      128, 40,  128,0,                    4,"RC4",     24,"RSA Data Security's RC4"},
179   {CALG_DES,       56, 56,   56,0,                    4,"DES",     31,"Data Encryption Standard (DES)"},
180   {CALG_3DES_112, 112,112,  112,0,                   13,"3DES TWO KEY",19,"Two Key Triple DES"},
181   {CALG_3DES,     168,168,  168,0,                    5,"3DES",    21,"Three Key Triple DES"},
182   {CALG_SHA,      160,160,  160,CRYPT_FLAG_SIGNING,   6,"SHA-1",   30,"Secure Hash Algorithm (SHA-1)"},
183   {CALG_MD2,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD2",     23,"Message Digest 2 (MD2)"},
184   {CALG_MD4,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD4",     23,"Message Digest 4 (MD4)"},
185   {CALG_MD5,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD5",     23,"Message Digest 5 (MD5)"},
186   {CALG_SSL3_SHAMD5,288,288,288,0,                   12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
187   {CALG_MAC,        0,  0,    0,0,                    4,"MAC",     28,"Message Authentication Code"},
188   {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
189   {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
190   {CALG_HMAC,       0,  0,    0,0,                    5,"HMAC",    18,"Hugo's MAC (HMAC)"},
191   {0,               0,  0,    0,0,                    1,"",         1,""}
192  },
193  {
194   {CALG_RC2,      128, 40,  128,0,                    4,"RC2",     24,"RSA Data Security's RC2"},
195   {CALG_RC4,      128, 40,  128,0,                    4,"RC4",     24,"RSA Data Security's RC4"},
196   {CALG_DES,       56, 56,   56,0,                    4,"DES",     31,"Data Encryption Standard (DES)"},
197   {CALG_3DES_112, 112,112,  112,0,                   13,"3DES TWO KEY",19,"Two Key Triple DES"},
198   {CALG_3DES,     168,168,  168,0,                    5,"3DES",    21,"Three Key Triple DES"},
199   {CALG_SHA,      160,160,  160,CRYPT_FLAG_SIGNING,   6,"SHA-1",   30,"Secure Hash Algorithm (SHA-1)"},
200   {CALG_MD2,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD2",     23,"Message Digest 2 (MD2)"},
201   {CALG_MD4,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD4",     23,"Message Digest 4 (MD4)"},
202   {CALG_MD5,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD5",     23,"Message Digest 5 (MD5)"},
203   {CALG_SSL3_SHAMD5,288,288,288,0,                   12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
204   {CALG_MAC,        0,  0,    0,0,                    4,"MAC",     28,"Message Authentication Code"},
205   {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
206   {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
207   {CALG_HMAC,       0,  0,    0,0,                    5,"HMAC",    18,"Hugo's MAC (HMAC)"},
208   {0,               0,  0,    0,0,                    1,"",         1,""}
209  },
210  {
211   {CALG_RC2,      128, 40,  128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC2",        24,"RSA Data Security's RC2"},
212   {CALG_RC4,      128, 40,  128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC4",        24,"RSA Data Security's RC4"},
213   {CALG_DES,       56, 56,   56,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"DES",        31,"Data Encryption Standard (DES)"},
214   {CALG_3DES_112, 112,112,  112,RSAENH_PCT1_SSL2_SSL3_TLS1,13,"3DES TWO KEY",19,"Two Key Triple DES"},
215   {CALG_3DES,     168,168,  168,RSAENH_PCT1_SSL2_SSL3_TLS1, 5,"3DES",       21,"Three Key Triple DES"},
216   {CALG_SHA,160,160,160,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,6,"SHA-1",30,"Secure Hash Algorithm (SHA-1)"},
217   {CALG_MD5,128,128,128,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,4,"MD5",23,"Message Digest 5 (MD5)"},
218   {CALG_SSL3_SHAMD5,288,288,288,0,                         12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
219   {CALG_MAC,        0,  0,    0,0,                          4,"MAC",        28,"Message Authentication Code"},
220   {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_SIGN",14,"RSA Signature"},
221   {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_KEYX",17,"RSA Key Exchange"},
222   {CALG_HMAC,       0,  0,    0,0,                          5,"HMAC",       18,"Hugo's MAC (HMAC)"},
223   {CALG_PCT1_MASTER,128,128,128,CRYPT_FLAG_PCT1,           12,"PCT1 MASTER",12,"PCT1 Master"},
224   {CALG_SSL2_MASTER,40,40,  192,CRYPT_FLAG_SSL2,           12,"SSL2 MASTER",12,"SSL2 Master"},
225   {CALG_SSL3_MASTER,384,384,384,CRYPT_FLAG_SSL3,           12,"SSL3 MASTER",12,"SSL3 Master"},
226   {CALG_TLS1_MASTER,384,384,384,CRYPT_FLAG_TLS1,           12,"TLS1 MASTER",12,"TLS1 Master"},
227   {CALG_SCHANNEL_MASTER_HASH,0,0,-1,0,                     16,"SCH MASTER HASH",21,"SChannel Master Hash"},
228   {CALG_SCHANNEL_MAC_KEY,0,0,-1,0,                         12,"SCH MAC KEY",17,"SChannel MAC Key"},
229   {CALG_SCHANNEL_ENC_KEY,0,0,-1,0,                         12,"SCH ENC KEY",24,"SChannel Encryption Key"},
230   {CALG_TLS1PRF,    0,  0,   -1,0,                          9,"TLS1 PRF",   28,"TLS1 Pseudo Random Function"},
231   {0,               0,  0,    0,0,                          1,"",            1,""}
232  },
233  {
234   {CALG_RC2,      128, 40,  128,0,                    4,"RC2",     24,"RSA Data Security's RC2"},
235   {CALG_RC4,      128, 40,  128,0,                    4,"RC4",     24,"RSA Data Security's RC4"},
236   {CALG_DES,       56, 56,   56,0,                    4,"DES",     31,"Data Encryption Standard (DES)"},
237   {CALG_3DES_112, 112,112,  112,0,                   13,"3DES TWO KEY",19,"Two Key Triple DES"},
238   {CALG_3DES,     168,168,  168,0,                    5,"3DES",    21,"Three Key Triple DES"},
239   {CALG_AES,      128,128,  128,0,                    4,"AES",     35,"Advanced Encryption Standard (AES)"},
240   {CALG_AES_128,  128,128,  128,0,                    8,"AES-128", 39,"Advanced Encryption Standard (AES-128)"},
241   {CALG_AES_192,  192,192,  192,0,                    8,"AES-192", 39,"Advanced Encryption Standard (AES-192)"},
242   {CALG_AES_256,  256,256,  256,0,                    8,"AES-256", 39,"Advanced Encryption Standard (AES-256)"},
243   {CALG_SHA,      160,160,  160,CRYPT_FLAG_SIGNING,   6,"SHA-1",   30,"Secure Hash Algorithm (SHA-1)"},
244   {CALG_MD2,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD2",     23,"Message Digest 2 (MD2)"},
245   {CALG_MD4,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD4",     23,"Message Digest 4 (MD4)"},
246   {CALG_MD5,      128,128,  128,CRYPT_FLAG_SIGNING,   4,"MD5",     23,"Message Digest 5 (MD5)"},
247   {CALG_SSL3_SHAMD5,288,288,288,0,                   12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
248   {CALG_MAC,        0,  0,    0,0,                    4,"MAC",     28,"Message Authentication Code"},
249   {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
250   {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
251   {CALG_HMAC,       0,  0,    0,0,                    5,"HMAC",    18,"Hugo's MAC (HMAC)"},
252   {0,               0,  0,    0,0,                    1,"",         1,""}
253  }
254 };
255
256 /******************************************************************************
257  * API forward declarations
258  */
259 BOOL WINAPI 
260 RSAENH_CPGetKeyParam(
261     HCRYPTPROV hProv, 
262     HCRYPTKEY hKey, 
263     DWORD dwParam, 
264     BYTE *pbData, 
265     DWORD *pdwDataLen, 
266     DWORD dwFlags
267 );
268
269 BOOL WINAPI 
270 RSAENH_CPEncrypt(
271     HCRYPTPROV hProv, 
272     HCRYPTKEY hKey, 
273     HCRYPTHASH hHash, 
274     BOOL Final, 
275     DWORD dwFlags, 
276     BYTE *pbData,
277     DWORD *pdwDataLen, 
278     DWORD dwBufLen
279 );
280
281 BOOL WINAPI 
282 RSAENH_CPCreateHash(
283     HCRYPTPROV hProv, 
284     ALG_ID Algid, 
285     HCRYPTKEY hKey, 
286     DWORD dwFlags, 
287     HCRYPTHASH *phHash
288 );
289
290 BOOL WINAPI 
291 RSAENH_CPSetHashParam(
292     HCRYPTPROV hProv, 
293     HCRYPTHASH hHash, 
294     DWORD dwParam, 
295     BYTE *pbData, DWORD dwFlags
296 );
297
298 BOOL WINAPI 
299 RSAENH_CPGetHashParam(
300     HCRYPTPROV hProv, 
301     HCRYPTHASH hHash, 
302     DWORD dwParam, 
303     BYTE *pbData, 
304     DWORD *pdwDataLen, 
305     DWORD dwFlags
306 );
307
308 BOOL WINAPI 
309 RSAENH_CPDestroyHash(
310     HCRYPTPROV hProv, 
311     HCRYPTHASH hHash
312 );
313
314 BOOL WINAPI 
315 RSAENH_CPExportKey(
316     HCRYPTPROV hProv, 
317     HCRYPTKEY hKey, 
318     HCRYPTKEY hPubKey, 
319     DWORD dwBlobType, 
320     DWORD dwFlags, 
321     BYTE *pbData, 
322     DWORD *pdwDataLen
323 );
324
325 BOOL WINAPI 
326 RSAENH_CPImportKey(
327     HCRYPTPROV hProv, 
328     CONST BYTE *pbData, 
329     DWORD dwDataLen, 
330     HCRYPTKEY hPubKey, 
331     DWORD dwFlags, 
332     HCRYPTKEY *phKey
333 );
334
335 BOOL WINAPI 
336 RSAENH_CPHashData(
337     HCRYPTPROV hProv, 
338     HCRYPTHASH hHash, 
339     CONST BYTE *pbData, 
340     DWORD dwDataLen, 
341     DWORD dwFlags
342 );
343
344 /******************************************************************************
345  * CSP's handle table (used by all acquired key containers)
346  */
347 static HANDLETABLE handle_table;
348
349 /******************************************************************************
350  * DllMain (RSAENH.@)
351  *
352  * Initializes and destroys the handle table for the CSP's handles.
353  */
354 int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
355 {
356     switch (fdwReason)
357     {
358         case DLL_PROCESS_ATTACH:
359             DisableThreadLibraryCalls(hInstance);
360             init_handle_table(&handle_table);
361             break;
362
363         case DLL_PROCESS_DETACH:
364             destroy_handle_table(&handle_table);
365             break;
366     }
367     return 1;
368 }
369
370 /******************************************************************************
371  * copy_param [Internal]
372  *
373  * Helper function that supports the standard WINAPI protocol for querying data
374  * of dynamic size.
375  *
376  * PARAMS
377  *  pbBuffer      [O]   Buffer where the queried parameter is copied to, if it is large enough.
378  *                      May be NUL if the required buffer size is to be queried only.
379  *  pdwBufferSize [I/O] In: Size of the buffer at pbBuffer
380  *                      Out: Size of parameter pbParam
381  *  pbParam       [I]   Parameter value.
382  *  dwParamSize   [I]   Size of pbParam
383  *
384  * RETURN
385  *  Success: TRUE (pbParam was copied into pbBuffer or pbBuffer is NULL)
386  *  Failure: FALSE (pbBuffer is not large enough to hold pbParam). Last error: ERROR_MORE_DATA
387  */
388 static inline BOOL copy_param(
389     BYTE *pbBuffer, DWORD *pdwBufferSize, CONST BYTE *pbParam, DWORD dwParamSize) 
390 {
391     if (pbBuffer) 
392     {
393         if (dwParamSize > *pdwBufferSize) 
394         {
395             SetLastError(ERROR_MORE_DATA);
396             *pdwBufferSize = dwParamSize;
397             return FALSE;
398         }
399         memcpy(pbBuffer, pbParam, dwParamSize);
400     }
401     *pdwBufferSize = dwParamSize;
402     return TRUE;
403 }
404
405 /******************************************************************************
406  * get_algid_info [Internal]
407  *
408  * Query CSP capabilities for a given crypto algorithm.
409  * 
410  * PARAMS
411  *  hProv [I] Handle to a key container of the CSP whose capabilities are to be queried.
412  *  algid [I] Identifier of the crypto algorithm about which information is requested.
413  *
414  * RETURNS
415  *  Success: Pointer to a PROV_ENUMALGS_EX struct containing information about the crypto algorithm.
416  *  Failure: NULL (algid not supported)
417  */
418 static inline const PROV_ENUMALGS_EX* get_algid_info(HCRYPTPROV hProv, ALG_ID algid) {
419     const PROV_ENUMALGS_EX *iterator;
420     KEYCONTAINER *pKeyContainer;
421
422     if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, (OBJECTHDR**)&pKeyContainer)) {
423         SetLastError(NTE_BAD_UID);
424         return NULL;
425     }
426
427     for (iterator = aProvEnumAlgsEx[pKeyContainer->dwPersonality]; iterator->aiAlgid; iterator++) {
428         if (iterator->aiAlgid == algid) return iterator;
429     }
430
431     SetLastError(NTE_BAD_ALGID);
432     return NULL;
433 }
434
435 /******************************************************************************
436  * copy_data_blob [Internal] 
437  *
438  * deeply copies a DATA_BLOB
439  *
440  * PARAMS
441  *  dst [O] That's where the blob will be copied to
442  *  src [I] Source blob
443  *
444  * RETURNS
445  *  Success: TRUE
446  *  Failure: FALSE (GetLastError() == NTE_NO_MEMORY
447  *
448  * NOTES
449  *  Use free_data_blob to release resources occupied by copy_data_blob.
450  */
451 static inline BOOL copy_data_blob(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src) {
452     dst->pbData = HeapAlloc(GetProcessHeap(), 0, src->cbData);
453     if (!dst->pbData) {
454         SetLastError(NTE_NO_MEMORY);
455         return FALSE;
456     }    
457     dst->cbData = src->cbData;
458     memcpy(dst->pbData, src->pbData, src->cbData);
459     return TRUE;
460 }
461
462 /******************************************************************************
463  * concat_data_blobs [Internal]
464  *
465  * Concatenates two blobs
466  *
467  * PARAMS
468  *  dst  [O] The new blob will be copied here
469  *  src1 [I] Prefix blob
470  *  src2 [I] Appendix blob
471  *
472  * RETURNS
473  *  Success: TRUE
474  *  Failure: FALSE (GetLastError() == NTE_NO_MEMORY)
475  *
476  * NOTES
477  *  Release resources occupied by concat_data_blobs with free_data_blobs
478  */
479 static inline BOOL concat_data_blobs(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src1, 
480                                      CONST PCRYPT_DATA_BLOB src2) 
481 {
482     dst->cbData = src1->cbData + src2->cbData;
483     dst->pbData = HeapAlloc(GetProcessHeap(), 0, dst->cbData);
484     if (!dst->pbData) {
485         SetLastError(NTE_NO_MEMORY);
486         return FALSE;
487     }
488     memcpy(dst->pbData, src1->pbData, src1->cbData);
489     memcpy(dst->pbData + src1->cbData, src2->pbData, src2->cbData);
490     return TRUE;
491 }
492
493 /******************************************************************************
494  * free_data_blob [Internal]
495  *
496  * releases resource occupied by a dynamically allocated CRYPT_DATA_BLOB
497  * 
498  * PARAMS
499  *  pBlob [I] Heap space occupied by pBlob->pbData is released
500  */
501 static inline void free_data_blob(PCRYPT_DATA_BLOB pBlob) {
502     HeapFree(GetProcessHeap(), 0, pBlob->pbData);
503 }
504
505 /******************************************************************************
506  * init_data_blob [Internal]
507  */
508 static inline void init_data_blob(PCRYPT_DATA_BLOB pBlob) {
509     pBlob->pbData = NULL;
510     pBlob->cbData = 0;
511 }
512
513 /******************************************************************************
514  * free_hmac_info [Internal]
515  *
516  * Deeply free an HMAC_INFO struct.
517  *
518  * PARAMS
519  *  hmac_info [I] Pointer to the HMAC_INFO struct to be freed.
520  *
521  * NOTES
522  *  See Internet RFC 2104 for details on the HMAC algorithm.
523  */
524 static inline void free_hmac_info(PHMAC_INFO hmac_info) {
525     if (!hmac_info) return;
526     HeapFree(GetProcessHeap(), 0, hmac_info->pbInnerString);
527     HeapFree(GetProcessHeap(), 0, hmac_info->pbOuterString);
528     HeapFree(GetProcessHeap(), 0, hmac_info);
529 }
530
531 /******************************************************************************
532  * copy_hmac_info [Internal]
533  *
534  * Deeply copy an HMAC_INFO struct
535  *
536  * PARAMS
537  *  dst [O] Pointer to a location where the pointer to the HMAC_INFO copy will be stored.
538  *  src [I] Pointer to the HMAC_INFO struct to be copied.
539  *
540  * RETURNS
541  *  Success: TRUE
542  *  Failure: FALSE
543  *
544  * NOTES
545  *  See Internet RFC 2104 for details on the HMAC algorithm.
546  */
547 static BOOL copy_hmac_info(PHMAC_INFO *dst, const HMAC_INFO *src) {
548     if (!src) return FALSE;
549     *dst = HeapAlloc(GetProcessHeap(), 0, sizeof(HMAC_INFO));
550     if (!*dst) return FALSE;
551     **dst = *src;
552     (*dst)->pbInnerString = NULL;
553     (*dst)->pbOuterString = NULL;
554     if ((*dst)->cbInnerString == 0) (*dst)->cbInnerString = RSAENH_HMAC_DEF_PAD_LEN;
555     (*dst)->pbInnerString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbInnerString);
556     if (!(*dst)->pbInnerString) {
557         free_hmac_info(*dst);
558         return FALSE;
559     }
560     if (src->cbInnerString) 
561         memcpy((*dst)->pbInnerString, src->pbInnerString, src->cbInnerString);
562     else 
563         memset((*dst)->pbInnerString, RSAENH_HMAC_DEF_IPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
564     if ((*dst)->cbOuterString == 0) (*dst)->cbOuterString = RSAENH_HMAC_DEF_PAD_LEN;
565     (*dst)->pbOuterString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbOuterString);
566     if (!(*dst)->pbOuterString) {
567         free_hmac_info(*dst);
568         return FALSE;
569     }
570     if (src->cbOuterString) 
571         memcpy((*dst)->pbOuterString, src->pbOuterString, src->cbOuterString);
572     else 
573         memset((*dst)->pbOuterString, RSAENH_HMAC_DEF_OPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
574     return TRUE;
575 }
576
577 /******************************************************************************
578  * destroy_hash [Internal]
579  *
580  * Destructor for hash objects
581  *
582  * PARAMS
583  *  pCryptHash [I] Pointer to the hash object to be destroyed. 
584  *                 Will be invalid after function returns!
585  */
586 static void destroy_hash(OBJECTHDR *pObject)
587 {
588     CRYPTHASH *pCryptHash = (CRYPTHASH*)pObject;
589         
590     free_hmac_info(pCryptHash->pHMACInfo);
591     free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
592     free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
593     HeapFree(GetProcessHeap(), 0, pCryptHash);
594 }
595
596 /******************************************************************************
597  * init_hash [Internal]
598  *
599  * Initialize (or reset) a hash object
600  *
601  * PARAMS
602  *  pCryptHash    [I] The hash object to be initialized.
603  */
604 static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
605     DWORD dwLen;
606         
607     switch (pCryptHash->aiAlgid) 
608     {
609         case CALG_HMAC:
610             if (pCryptHash->pHMACInfo) { 
611                 const PROV_ENUMALGS_EX *pAlgInfo;
612                 
613                 pAlgInfo = get_algid_info(pCryptHash->hProv, pCryptHash->pHMACInfo->HashAlgid);
614                 if (!pAlgInfo) return FALSE;
615                 pCryptHash->dwHashSize = pAlgInfo->dwDefaultLen >> 3;
616                 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
617                 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
618                                  pCryptHash->pHMACInfo->pbInnerString, 
619                                  pCryptHash->pHMACInfo->cbInnerString);
620             }
621             return TRUE;
622             
623         case CALG_MAC:
624             dwLen = sizeof(DWORD);
625             RSAENH_CPGetKeyParam(pCryptHash->hProv, pCryptHash->hKey, KP_BLOCKLEN, 
626                                  (BYTE*)&pCryptHash->dwHashSize, &dwLen, 0);
627             pCryptHash->dwHashSize >>= 3;
628             return TRUE;
629
630         default:
631             return init_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context);
632     }
633 }
634
635 /******************************************************************************
636  * update_hash [Internal]
637  *
638  * Hashes the given data and updates the hash object's state accordingly
639  *
640  * PARAMS
641  *  pCryptHash [I] Hash object to be updated.
642  *  pbData     [I] Pointer to data stream to be hashed.
643  *  dwDataLen  [I] Length of data stream.
644  */
645 static inline void update_hash(CRYPTHASH *pCryptHash, CONST BYTE *pbData, DWORD dwDataLen) {
646     BYTE *pbTemp;
647
648     switch (pCryptHash->aiAlgid)
649     {
650         case CALG_HMAC:
651             if (pCryptHash->pHMACInfo) 
652                 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 
653                                  pbData, dwDataLen);
654             break;
655
656         case CALG_MAC:
657             pbTemp = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
658             if (!pbTemp) return;
659             memcpy(pbTemp, pbData, dwDataLen);
660             RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
661                              pbTemp, &dwDataLen, dwDataLen);
662             HeapFree(GetProcessHeap(), 0, pbTemp);
663             break;
664
665         default:
666             update_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pbData, dwDataLen);
667     }
668 }
669
670 /******************************************************************************
671  * finalize_hash [Internal]
672  *
673  * Finalizes the hash, after all data has been hashed with update_hash.
674  * No additional data can be hashed afterwards until the hash gets initialized again.
675  *
676  * PARAMS
677  *  pCryptHash [I] Hash object to be finalized.
678  */
679 static inline void finalize_hash(CRYPTHASH *pCryptHash) {
680     DWORD dwDataLen;
681         
682     switch (pCryptHash->aiAlgid)
683     {
684         case CALG_HMAC:
685             if (pCryptHash->pHMACInfo) {
686                 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
687
688                 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 
689                                    pCryptHash->abHashValue);
690                 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
691                 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
692                 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
693                                  pCryptHash->pHMACInfo->pbOuterString, 
694                                  pCryptHash->pHMACInfo->cbOuterString);
695                 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
696                                  abHashValue, pCryptHash->dwHashSize);
697                 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
698                                    pCryptHash->abHashValue);
699             } 
700             break;
701
702         case CALG_MAC:
703             dwDataLen = 0;
704             RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0,
705                              pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize);
706             break;
707
708         default:
709             finalize_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pCryptHash->abHashValue);
710     }
711 }
712
713 /******************************************************************************
714  * destroy_key [Internal]
715  *
716  * Destructor for key objects
717  *
718  * PARAMS
719  *  pCryptKey [I] Pointer to the key object to be destroyed. 
720  *                Will be invalid after function returns!
721  */
722 static void destroy_key(OBJECTHDR *pObject)
723 {
724     CRYPTKEY *pCryptKey = (CRYPTKEY*)pObject;
725         
726     free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context);
727     free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
728     free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
729     HeapFree(GetProcessHeap(), 0, pCryptKey);
730 }
731
732 /******************************************************************************
733  * setup_key [Internal]
734  *
735  * Initialize (or reset) a key object
736  *
737  * PARAMS
738  *  pCryptKey    [I] The key object to be initialized.
739  */
740 static inline void setup_key(CRYPTKEY *pCryptKey) {
741     pCryptKey->dwState = RSAENH_KEYSTATE_IDLE;
742     memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector));
743     setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen, 
744                    pCryptKey->dwEffectiveKeyLen, pCryptKey->dwSaltLen,
745                    pCryptKey->abKeyValue);
746 }
747
748 /******************************************************************************
749  * new_key [Internal]
750  *
751  * Creates a new key object without assigning the actual binary key value. 
752  * This is done by CPDeriveKey, CPGenKey or CPImportKey, which call this function.
753  *
754  * PARAMS
755  *  hProv      [I] Handle to the provider to which the created key will belong.
756  *  aiAlgid    [I] The new key shall use the crypto algorithm idenfied by aiAlgid.
757  *  dwFlags    [I] Upper 16 bits give the key length.
758  *                 Lower 16 bits: CRYPT_CREATE_SALT, CRYPT_NO_SALT
759  *  ppCryptKey [O] Pointer to the created key
760  *
761  * RETURNS
762  *  Success: Handle to the created key.
763  *  Failure: INVALID_HANDLE_VALUE
764  */
765 static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey)
766 {
767     HCRYPTKEY hCryptKey;
768     CRYPTKEY *pCryptKey;
769     DWORD dwKeyLen = HIWORD(dwFlags);
770     const PROV_ENUMALGS_EX *peaAlgidInfo;
771
772     *ppCryptKey = NULL;
773     
774     /* 
775      * Retrieve the CSP's capabilities for the given ALG_ID value
776      */
777     peaAlgidInfo = get_algid_info(hProv, aiAlgid);
778     if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE;
779
780     /*
781      * Assume the default key length, if none is specified explicitly
782      */
783     if (dwKeyLen == 0) dwKeyLen = peaAlgidInfo->dwDefaultLen;
784     
785     /*
786      * Check if the requested key length is supported by the current CSP.
787      * Adjust key length's for DES algorithms.
788      */
789     switch (aiAlgid) {
790         case CALG_DES:
791             if (dwKeyLen == RSAENH_DES_EFFECTIVE_KEYLEN) {
792                 dwKeyLen = RSAENH_DES_STORAGE_KEYLEN;
793             }
794             if (dwKeyLen != RSAENH_DES_STORAGE_KEYLEN) {
795                 SetLastError(NTE_BAD_FLAGS);
796                 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
797             }
798             break;
799
800         case CALG_3DES_112:
801             if (dwKeyLen == RSAENH_3DES112_EFFECTIVE_KEYLEN) {
802                 dwKeyLen = RSAENH_3DES112_STORAGE_KEYLEN;
803             }
804             if (dwKeyLen != RSAENH_3DES112_STORAGE_KEYLEN) {
805                 SetLastError(NTE_BAD_FLAGS);
806                 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
807             }
808             break;
809
810         case CALG_3DES:
811             if (dwKeyLen == RSAENH_3DES_EFFECTIVE_KEYLEN) {
812                 dwKeyLen = RSAENH_3DES_STORAGE_KEYLEN;
813             }
814             if (dwKeyLen != RSAENH_3DES_STORAGE_KEYLEN) {
815                 SetLastError(NTE_BAD_FLAGS);
816                 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
817             }
818             break;
819         
820         default:
821             if (dwKeyLen % 8 || 
822                 dwKeyLen > peaAlgidInfo->dwMaxLen || 
823                 dwKeyLen < peaAlgidInfo->dwMinLen) 
824             {
825                 SetLastError(NTE_BAD_FLAGS);
826                 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
827             }
828     }
829
830     hCryptKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY,
831                            destroy_key, (OBJECTHDR**)&pCryptKey);
832     if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
833     {
834         pCryptKey->aiAlgid = aiAlgid;
835         pCryptKey->hProv = hProv;
836         pCryptKey->dwModeBits = 0;
837         pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE | 
838                                    CRYPT_MAC;
839         pCryptKey->dwKeyLen = dwKeyLen >> 3;
840         pCryptKey->dwEffectiveKeyLen = 0;
841         if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT))) 
842             pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen;
843         else
844             pCryptKey->dwSaltLen = 0;
845         memset(pCryptKey->abKeyValue, 0, sizeof(pCryptKey->abKeyValue));
846         memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector));
847         init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
848         init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
849             
850         switch(aiAlgid)
851         {
852             case CALG_PCT1_MASTER:
853             case CALG_SSL2_MASTER:
854             case CALG_SSL3_MASTER:
855             case CALG_TLS1_MASTER:
856             case CALG_RC4:
857                 pCryptKey->dwBlockLen = 0;
858                 pCryptKey->dwMode = 0;
859                 break;
860
861             case CALG_RC2:
862             case CALG_DES:
863             case CALG_3DES_112:
864             case CALG_3DES:
865                 pCryptKey->dwBlockLen = 8;
866                 pCryptKey->dwMode = CRYPT_MODE_CBC;
867                 break;
868
869             case CALG_AES:
870             case CALG_AES_128:
871             case CALG_AES_192:
872             case CALG_AES_256:
873                 pCryptKey->dwBlockLen = 16;
874                 pCryptKey->dwMode = CRYPT_MODE_ECB;
875                 break;
876
877             case CALG_RSA_KEYX:
878             case CALG_RSA_SIGN:
879                 pCryptKey->dwBlockLen = dwKeyLen >> 3;
880                 pCryptKey->dwMode = 0;
881                 break;
882         }
883
884         *ppCryptKey = pCryptKey;
885     }
886
887     return hCryptKey;
888 }
889
890 /******************************************************************************
891  * store_key_pair [Internal]
892  *
893  * Stores a key pair to the registry
894  * 
895  * PARAMS
896  *  hCryptKey     [I] Handle to the key to be stored
897  *  hKey          [I] Registry key where the key pair is to be stored
898  *  szValueName   [I] Registry value where key pair's value is to be stored
899  *  dwFlags       [I] Flags for protecting the key
900  */
901 static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, LPCSTR szValueName, DWORD dwFlags)
902 {
903     DATA_BLOB blobIn, blobOut;
904     CRYPTKEY *pKey;
905     DWORD dwLen;
906     BYTE *pbKey;
907
908     if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
909                       (OBJECTHDR**)&pKey))
910     {
911         if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0, PRIVATEKEYBLOB, 0, 0,
912             &dwLen))
913         {
914             pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
915             if (pbKey)
916             {
917                 if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0,
918                                        PRIVATEKEYBLOB, 0, pbKey, &dwLen))
919                 {
920                     blobIn.pbData = pbKey;
921                     blobIn.cbData = dwLen;
922
923                     if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL,
924                         dwFlags, &blobOut))
925                     {
926                         RegSetValueExA(hKey, szValueName, 0, REG_BINARY,
927                                        blobOut.pbData, blobOut.cbData);
928                         LocalFree(blobOut.pbData);
929                     }
930                 }
931                 HeapFree(GetProcessHeap(), 0, pbKey);
932             }
933         }
934         release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
935     }
936 }
937
938 /******************************************************************************
939  * create_container_key [Internal]
940  *
941  * Creates the registry key for a key container's persistent storage.
942  * 
943  * PARAMS
944  *  pKeyContainer [I] Pointer to the key container
945  *  sam           [I] Desired registry access
946  *  phKey         [O] Returned key
947  */
948 static BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam, HKEY *phKey)
949 {
950     CHAR szRSABase[MAX_PATH];
951     HKEY hRootKey;
952
953     sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
954
955     if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
956         hRootKey = HKEY_LOCAL_MACHINE;
957     else
958         hRootKey = HKEY_CURRENT_USER;
959
960     /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
961     /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
962     return RegCreateKeyExA(hRootKey, szRSABase, 0, NULL,
963                            REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL)
964                            == ERROR_SUCCESS;
965 }
966
967 /******************************************************************************
968  * open_container_key [Internal]
969  *
970  * Opens a key container's persistent storage for reading.
971  *
972  * PARAMS
973  *  pszContainerName [I] Name of the container to be opened.  May be the empty
974  *                       string if the parent key of all containers is to be
975  *                       opened.
976  *  dwFlags          [I] Flags indicating which keyset to be opened.
977  *  phKey            [O] Returned key
978  */
979 static BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags, HKEY *phKey)
980 {
981     CHAR szRSABase[MAX_PATH];
982     HKEY hRootKey;
983
984     sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
985
986     if (dwFlags & CRYPT_MACHINE_KEYSET)
987         hRootKey = HKEY_LOCAL_MACHINE;
988     else
989         hRootKey = HKEY_CURRENT_USER;
990
991     /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
992     /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
993     return RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, phKey) ==
994                          ERROR_SUCCESS;
995 }
996
997 /******************************************************************************
998  * delete_container_key [Internal]
999  *
1000  * Deletes a key container's persistent storage.
1001  *
1002  * PARAMS
1003  *  pszContainerName [I] Name of the container to be opened.
1004  *  dwFlags          [I] Flags indicating which keyset to be opened.
1005  */
1006 static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags)
1007 {
1008     CHAR szRegKey[MAX_PATH];
1009
1010     if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainerName) >= MAX_PATH) {
1011         SetLastError(NTE_BAD_KEYSET_PARAM);
1012         return FALSE;
1013     } else {
1014         HKEY hRootKey;
1015         if (dwFlags & CRYPT_MACHINE_KEYSET)
1016             hRootKey = HKEY_LOCAL_MACHINE;
1017         else
1018             hRootKey = HKEY_CURRENT_USER;
1019         if (!RegDeleteKeyA(hRootKey, szRegKey)) {
1020             SetLastError(ERROR_SUCCESS);
1021             return TRUE;
1022         } else {
1023             SetLastError(NTE_BAD_KEYSET);
1024             return FALSE;
1025         }
1026     }
1027 }
1028
1029 /******************************************************************************
1030  * store_key_container_keys [Internal]
1031  *
1032  * Stores key container's keys in a persistent location.
1033  *
1034  * PARAMS
1035  *  pKeyContainer [I] Pointer to the key container whose keys are to be saved
1036  */
1037 static void store_key_container_keys(KEYCONTAINER *pKeyContainer)
1038 {
1039     HKEY hKey;
1040     DWORD dwFlags;
1041
1042     /* On WinXP, persistent keys are stored in a file located at:
1043      * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
1044      */
1045
1046     if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
1047         dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
1048     else
1049         dwFlags = 0;
1050
1051     if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1052     {
1053         store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
1054                        "KeyExchangeKeyPair", dwFlags);
1055         store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
1056                        "SignatureKeyPair", dwFlags);
1057         RegCloseKey(hKey);
1058     }
1059 }
1060
1061 /******************************************************************************
1062  * destroy_key_container [Internal]
1063  *
1064  * Destructor for key containers.
1065  *
1066  * PARAMS
1067  *  pObjectHdr [I] Pointer to the key container to be destroyed.
1068  */
1069 static void destroy_key_container(OBJECTHDR *pObjectHdr)
1070 {
1071     KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
1072
1073     if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
1074         store_key_container_keys(pKeyContainer);
1075     HeapFree( GetProcessHeap(), 0, pKeyContainer );
1076 }
1077
1078 /******************************************************************************
1079  * new_key_container [Internal]
1080  *
1081  * Create a new key container. The personality (RSA Base, Strong or Enhanced CP) 
1082  * of the CSP is determined via the pVTable->pszProvName string.
1083  *
1084  * PARAMS
1085  *  pszContainerName [I] Name of the key container.
1086  *  pVTable          [I] Callback functions and context info provided by the OS
1087  *
1088  * RETURNS
1089  *  Success: Handle to the new key container.
1090  *  Failure: INVALID_HANDLE_VALUE
1091  */
1092 static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1093 {
1094     KEYCONTAINER *pKeyContainer;
1095     HCRYPTPROV hKeyContainer;
1096
1097     hKeyContainer = new_object(&handle_table, sizeof(KEYCONTAINER), RSAENH_MAGIC_CONTAINER,
1098                                destroy_key_container, (OBJECTHDR**)&pKeyContainer);
1099     if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1100     {
1101         lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
1102         pKeyContainer->dwFlags = dwFlags;
1103         pKeyContainer->dwEnumAlgsCtr = 0;
1104         pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1105         pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1106         if (pVTable && pVTable->pszProvName) {
1107             lstrcpynA(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
1108             if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
1109                 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
1110             } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
1111                 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED;
1112             } else if (!strcmp(pVTable->pszProvName, MS_DEF_RSA_SCHANNEL_PROV_A)) { 
1113                 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL;
1114             } else if (!strcmp(pVTable->pszProvName, MS_ENH_RSA_AES_PROV_A)) {
1115                 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_AES;
1116             } else {
1117                 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG;
1118             }
1119         }
1120
1121         /* The new key container has to be inserted into the CSP immediately 
1122          * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */
1123         if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
1124             HKEY hKey;
1125
1126             if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1127                 RegCloseKey(hKey);
1128         }
1129     }
1130
1131     return hKeyContainer;
1132 }
1133
1134 /******************************************************************************
1135  * read_key_value [Internal]
1136  *
1137  * Reads a key pair value from the registry
1138  *
1139  * PARAMS
1140  *  hKeyContainer [I] Crypt provider to use to import the key
1141  *  hKey          [I] Registry key from which to read the key pair
1142  *  szValueName   [I] Registry value from which to read the key pair's value
1143  *  dwFlags       [I] Flags for unprotecting the key
1144  *  phCryptKey    [O] Returned key
1145  */
1146 static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, LPCSTR szValueName, DWORD dwFlags, HCRYPTKEY *phCryptKey)
1147 {
1148     DWORD dwValueType, dwLen;
1149     BYTE *pbKey;
1150     DATA_BLOB blobIn, blobOut;
1151     BOOL ret = FALSE;
1152
1153     if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
1154         ERROR_SUCCESS)
1155     {
1156         pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
1157         if (pbKey)
1158         {
1159             if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, pbKey, &dwLen) ==
1160                 ERROR_SUCCESS)
1161             {
1162                 blobIn.pbData = pbKey;
1163                 blobIn.cbData = dwLen;
1164
1165                 if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
1166                     dwFlags, &blobOut))
1167                 {
1168                     ret = RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
1169                                              phCryptKey);
1170                     LocalFree(blobOut.pbData);
1171                 }
1172             }
1173             HeapFree(GetProcessHeap(), 0, pbKey);
1174         }
1175     }
1176     return ret;
1177 }
1178
1179 /******************************************************************************
1180  * read_key_container [Internal]
1181  *
1182  * Tries to read the persistent state of the key container (mainly the signature
1183  * and key exchange private keys) given by pszContainerName.
1184  *
1185  * PARAMS
1186  *  pszContainerName [I] Name of the key container to read from the registry
1187  *  pVTable          [I] Pointer to context data provided by the operating system
1188  *
1189  * RETURNS
1190  *  Success: Handle to the key container read from the registry
1191  *  Failure: INVALID_HANDLE_VALUE
1192  */
1193 static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1194 {
1195     HKEY hKey;
1196     KEYCONTAINER *pKeyContainer;
1197     HCRYPTPROV hKeyContainer;
1198     HCRYPTKEY hCryptKey;
1199
1200     if (!open_container_key(pszContainerName, dwFlags, &hKey))
1201     {
1202         SetLastError(NTE_BAD_KEYSET);
1203         return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1204     }
1205
1206     hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
1207     if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1208     {
1209         DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ?
1210             CRYPTPROTECT_LOCAL_MACHINE : 0;
1211
1212         if (!lookup_handle(&handle_table, hKeyContainer, RSAENH_MAGIC_CONTAINER, 
1213                            (OBJECTHDR**)&pKeyContainer))
1214             return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1215     
1216         if (read_key_value(hKeyContainer, hKey, "KeyExchangeKeyPair",
1217             dwProtectFlags, &hCryptKey))
1218             pKeyContainer->hKeyExchangeKeyPair = hCryptKey;
1219         if (read_key_value(hKeyContainer, hKey, "SignatureKeyPair",
1220             dwProtectFlags, &hCryptKey))
1221             pKeyContainer->hSignatureKeyPair = hCryptKey;
1222     }
1223
1224     return hKeyContainer;
1225 }
1226
1227 /******************************************************************************
1228  * build_hash_signature [Internal]
1229  *
1230  * Builds a padded version of a hash to match the length of the RSA key modulus.
1231  *
1232  * PARAMS
1233  *  pbSignature [O] The padded hash object is stored here.
1234  *  dwLen       [I] Length of the pbSignature buffer.
1235  *  aiAlgid     [I] Algorithm identifier of the hash to be padded.
1236  *  abHashValue [I] The value of the hash object.
1237  *  dwHashLen   [I] Length of the hash value.
1238  *  dwFlags     [I] Selection of padding algorithm.
1239  *
1240  * RETURNS
1241  *  Success: TRUE
1242  *  Failure: FALSE (NTE_BAD_ALGID)
1243  */
1244 static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid, 
1245                                  CONST BYTE *abHashValue, DWORD dwHashLen, DWORD dwFlags) 
1246 {
1247     /* These prefixes are meant to be concatenated with hash values of the
1248      * respective kind to form a PKCS #7 DigestInfo. */
1249     static const struct tagOIDDescriptor {
1250         ALG_ID aiAlgid;
1251         DWORD dwLen;
1252         CONST BYTE abOID[18];
1253     } aOIDDescriptor[5] = {
1254         { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1255                           0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } },
1256         { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 
1257                           0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 } },
1258         { CALG_MD5, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1259                           0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } },
1260         { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 
1261                           0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } },
1262         { 0,        0,  { 0 } }
1263     };
1264     DWORD dwIdxOID, i, j;
1265
1266     for (dwIdxOID = 0; aOIDDescriptor[dwIdxOID].aiAlgid; dwIdxOID++) {
1267         if (aOIDDescriptor[dwIdxOID].aiAlgid == aiAlgid) break;
1268     }
1269     
1270     if (!aOIDDescriptor[dwIdxOID].aiAlgid) {
1271         SetLastError(NTE_BAD_ALGID);
1272         return FALSE;
1273     }
1274
1275     /* Build the padded signature */
1276     if (dwFlags & CRYPT_X931_FORMAT) {
1277         pbSignature[0] = 0x6b;
1278         for (i=1; i < dwLen - dwHashLen - 3; i++) {
1279             pbSignature[i] = 0xbb;
1280         }
1281         pbSignature[i++] = 0xba;
1282         for (j=0; j < dwHashLen; j++, i++) {
1283             pbSignature[i] = abHashValue[j];
1284         }
1285         pbSignature[i++] = 0x33;
1286         pbSignature[i++] = 0xcc;
1287     } else {
1288         pbSignature[0] = 0x00;
1289         pbSignature[1] = 0x01;
1290         if (dwFlags & CRYPT_NOHASHOID) {
1291             for (i=2; i < dwLen - 1 - dwHashLen; i++) {
1292                 pbSignature[i] = 0xff;
1293             }
1294             pbSignature[i++] = 0x00;
1295         } else {
1296             for (i=2; i < dwLen - 1 - aOIDDescriptor[dwIdxOID].dwLen - dwHashLen; i++) {
1297                 pbSignature[i] = 0xff;
1298             }
1299             pbSignature[i++] = 0x00;
1300             for (j=0; j < aOIDDescriptor[dwIdxOID].dwLen; j++) {
1301                 pbSignature[i++] = aOIDDescriptor[dwIdxOID].abOID[j];
1302             }
1303         }
1304         for (j=0; j < dwHashLen; j++) {
1305             pbSignature[i++] = abHashValue[j];
1306         }
1307     }
1308     
1309     return TRUE;
1310 }
1311
1312 /******************************************************************************
1313  * tls1_p [Internal]
1314  *
1315  * This is an implementation of the 'P_hash' helper function for TLS1's PRF.
1316  * It is used exclusively by tls1_prf. For details see RFC 2246, chapter 5.
1317  * The pseudo random stream generated by this function is exclusive or'ed with
1318  * the data in pbBuffer.
1319  *
1320  * PARAMS
1321  *  hHMAC       [I]   HMAC object, which will be used in pseudo random generation
1322  *  pblobSeed   [I]   Seed value
1323  *  pbBuffer    [I/O] Pseudo random stream will be xor'ed to the provided data
1324  *  dwBufferLen [I]   Number of pseudo random bytes desired
1325  *
1326  * RETURNS
1327  *  Success: TRUE
1328  *  Failure: FALSE
1329  */
1330 static BOOL tls1_p(HCRYPTHASH hHMAC, CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1331 {
1332     CRYPTHASH *pHMAC;
1333     BYTE abAi[RSAENH_MAX_HASH_SIZE];
1334     DWORD i = 0;
1335
1336     if (!lookup_handle(&handle_table, hHMAC, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pHMAC)) {
1337         SetLastError(NTE_BAD_HASH);
1338         return FALSE;
1339     }
1340     
1341     /* compute A_1 = HMAC(seed) */
1342     init_hash(pHMAC);
1343     update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1344     finalize_hash(pHMAC);
1345     memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1346
1347     do {
1348         /* compute HMAC(A_i + seed) */
1349         init_hash(pHMAC);
1350         update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1351         update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1352         finalize_hash(pHMAC);
1353
1354         /* pseudo random stream := CONCAT_{i=1..n} ( HMAC(A_i + seed) ) */
1355         do {
1356             if (i >= dwBufferLen) break;
1357             pbBuffer[i] ^= pHMAC->abHashValue[i % pHMAC->dwHashSize];
1358             i++;
1359         } while (i % pHMAC->dwHashSize);
1360
1361         /* compute A_{i+1} = HMAC(A_i) */
1362         init_hash(pHMAC);
1363         update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1364         finalize_hash(pHMAC);
1365         memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1366     } while (i < dwBufferLen);
1367
1368     return TRUE;
1369 }
1370
1371 /******************************************************************************
1372  * tls1_prf [Internal]
1373  *
1374  * TLS1 pseudo random function as specified in RFC 2246, chapter 5
1375  *
1376  * PARAMS
1377  *  hProv       [I] Key container used to compute the pseudo random stream
1378  *  hSecret     [I] Key that holds the (pre-)master secret
1379  *  pblobLabel  [I] Descriptive label
1380  *  pblobSeed   [I] Seed value
1381  *  pbBuffer    [O] Pseudo random numbers will be stored here
1382  *  dwBufferLen [I] Number of pseudo random bytes desired
1383  *
1384  * RETURNS
1385  *  Success: TRUE
1386  *  Failure: FALSE
1387  */ 
1388 static BOOL tls1_prf(HCRYPTPROV hProv, HCRYPTPROV hSecret, CONST PCRYPT_DATA_BLOB pblobLabel,
1389                      CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1390 {
1391     HMAC_INFO hmacInfo = { 0, NULL, 0, NULL, 0 };
1392     HCRYPTHASH hHMAC = (HCRYPTHASH)INVALID_HANDLE_VALUE;
1393     HCRYPTKEY hHalfSecret = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1394     CRYPTKEY *pHalfSecret, *pSecret;
1395     DWORD dwHalfSecretLen;
1396     BOOL result = FALSE;
1397     CRYPT_DATA_BLOB blobLabelSeed;
1398
1399     TRACE("(hProv=%08lx, hSecret=%08lx, pblobLabel=%p, pblobSeed=%p, pbBuffer=%p, dwBufferLen=%d)\n",
1400           hProv, hSecret, pblobLabel, pblobSeed, pbBuffer, dwBufferLen);
1401
1402     if (!lookup_handle(&handle_table, hSecret, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSecret)) {
1403         SetLastError(NTE_FAIL);
1404         return FALSE;
1405     }
1406
1407     dwHalfSecretLen = (pSecret->dwKeyLen+1)/2;
1408     
1409     /* concatenation of the label and the seed */
1410     if (!concat_data_blobs(&blobLabelSeed, pblobLabel, pblobSeed)) goto exit;
1411    
1412     /* zero out the buffer, since two random streams will be xor'ed into it. */
1413     memset(pbBuffer, 0, dwBufferLen);
1414    
1415     /* build a 'fake' key, to hold the secret. CALG_SSL2_MASTER is used since it provides
1416      * the biggest range of valid key lengths. */
1417     hHalfSecret = new_key(hProv, CALG_SSL2_MASTER, MAKELONG(0,dwHalfSecretLen*8), &pHalfSecret);
1418     if (hHalfSecret == (HCRYPTKEY)INVALID_HANDLE_VALUE) goto exit;
1419
1420     /* Derive an HMAC_MD5 hash and call the helper function. */
1421     memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue, dwHalfSecretLen);
1422     if (!RSAENH_CPCreateHash(hProv, CALG_HMAC, hHalfSecret, 0, &hHMAC)) goto exit;
1423     hmacInfo.HashAlgid = CALG_MD5;
1424     if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1425     if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1426
1427     /* Reconfigure to HMAC_SHA hash and call helper function again. */
1428     memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue + (pSecret->dwKeyLen/2), dwHalfSecretLen);
1429     hmacInfo.HashAlgid = CALG_SHA;
1430     if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1431     if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1432     
1433     result = TRUE;
1434 exit:
1435     release_handle(&handle_table, hHalfSecret, RSAENH_MAGIC_KEY);
1436     if (hHMAC != (HCRYPTHASH)INVALID_HANDLE_VALUE) RSAENH_CPDestroyHash(hProv, hHMAC);
1437     free_data_blob(&blobLabelSeed);
1438     return result;
1439 }
1440
1441 /******************************************************************************
1442  * pad_data [Internal]
1443  *
1444  * Helper function for data padding according to PKCS1 #2
1445  *
1446  * PARAMS
1447  *  abData      [I] The data to be padded
1448  *  dwDataLen   [I] Length of the data 
1449  *  abBuffer    [O] Padded data will be stored here
1450  *  dwBufferLen [I] Length of the buffer (also length of padded data)
1451  *  dwFlags     [I] Padding format (CRYPT_SSL2_FALLBACK)
1452  *
1453  * RETURN
1454  *  Success: TRUE
1455  *  Failure: FALSE (NTE_BAD_LEN, too much data to pad)
1456  */
1457 static BOOL pad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD dwBufferLen, 
1458                      DWORD dwFlags)
1459 {
1460     DWORD i;
1461     
1462     /* Ensure there is enough space for PKCS1 #2 padding */
1463     if (dwDataLen > dwBufferLen-11) {
1464         SetLastError(NTE_BAD_LEN);
1465         return FALSE;
1466     }
1467
1468     memmove(abBuffer + dwBufferLen - dwDataLen, abData, dwDataLen);            
1469     
1470     abBuffer[0] = 0x00;
1471     abBuffer[1] = RSAENH_PKC_BLOCKTYPE; 
1472     for (i=2; i < dwBufferLen - dwDataLen - 1; i++) 
1473         do gen_rand_impl(&abBuffer[i], 1); while (!abBuffer[i]);
1474     if (dwFlags & CRYPT_SSL2_FALLBACK) 
1475         for (i-=8; i < dwBufferLen - dwDataLen - 1; i++) 
1476             abBuffer[i] = 0x03;
1477     abBuffer[i] = 0x00;
1478     
1479     return TRUE; 
1480 }
1481
1482 /******************************************************************************
1483  * unpad_data [Internal]
1484  *
1485  * Remove the PKCS1 padding from RSA decrypted data
1486  *
1487  * PARAMS
1488  *  abData      [I]   The padded data
1489  *  dwDataLen   [I]   Length of the padded data
1490  *  abBuffer    [O]   Data without padding will be stored here
1491  *  dwBufferLen [I/O] I: Length of the buffer, O: Length of unpadded data
1492  *  dwFlags     [I]   Currently none defined
1493  *
1494  * RETURNS
1495  *  Success: TRUE
1496  *  Failure: FALSE, (NTE_BAD_DATA, no valid PKCS1 padding or buffer too small)
1497  */
1498 static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD *dwBufferLen, 
1499                        DWORD dwFlags)
1500 {
1501     DWORD i;
1502     
1503     for (i=2; i<dwDataLen; i++)
1504         if (!abData[i])
1505             break;
1506
1507     if ((i == dwDataLen) || (*dwBufferLen < dwDataLen - i - 1) ||
1508         (abData[0] != 0x00) || (abData[1] != RSAENH_PKC_BLOCKTYPE))
1509     {
1510         SetLastError(NTE_BAD_DATA);
1511         return FALSE;
1512     }
1513
1514     *dwBufferLen = dwDataLen - i - 1;
1515     memmove(abBuffer, abData + i + 1, *dwBufferLen);
1516     return TRUE;
1517 }
1518
1519 /******************************************************************************
1520  * CPAcquireContext (RSAENH.@)
1521  *
1522  * Acquire a handle to the key container specified by pszContainer
1523  *
1524  * PARAMS
1525  *  phProv       [O] Pointer to the location the acquired handle will be written to.
1526  *  pszContainer [I] Name of the desired key container. See Notes
1527  *  dwFlags      [I] Flags. See Notes.
1528  *  pVTable      [I] Pointer to a PVTableProvStruct containing callbacks.
1529  * 
1530  * RETURNS
1531  *  Success: TRUE
1532  *  Failure: FALSE
1533  *
1534  * NOTES
1535  *  If pszContainer is NULL or points to a zero length string the user's login 
1536  *  name will be used as the key container name.
1537  *
1538  *  If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will be created.
1539  *  If a keyset with the given name already exists, the function fails and sets
1540  *  last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified
1541  *  key container does not exist, function fails and sets last error to 
1542  *  NTE_BAD_KEYSET.
1543  */                         
1544 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
1545                    DWORD dwFlags, PVTableProvStruc pVTable)
1546 {
1547     CHAR szKeyContainerName[MAX_PATH];
1548
1549     TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv,
1550           debugstr_a(pszContainer), dwFlags, pVTable);
1551
1552     if (pszContainer && *pszContainer)
1553     {
1554         lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
1555     } 
1556     else
1557     {
1558         DWORD dwLen = sizeof(szKeyContainerName);
1559         if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
1560     }
1561
1562     switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET)) 
1563     {
1564         case 0:
1565             *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1566             break;
1567
1568         case CRYPT_DELETEKEYSET:
1569             return delete_container_key(szKeyContainerName, dwFlags);
1570
1571         case CRYPT_NEWKEYSET:
1572             *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1573             if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) 
1574             {
1575                 release_handle(&handle_table, *phProv, RSAENH_MAGIC_CONTAINER);
1576                 TRACE("Can't create new keyset, already exists\n");
1577                 SetLastError(NTE_EXISTS);
1578                 return FALSE;
1579             }
1580             *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
1581             break;
1582
1583         case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET:
1584         case CRYPT_VERIFYCONTEXT:
1585             if (pszContainer && *pszContainer) {
1586                 TRACE("pszContainer should be empty\n");
1587                 SetLastError(NTE_BAD_FLAGS);
1588                 return FALSE;
1589             }
1590             *phProv = new_key_container("", dwFlags, pVTable);
1591             break;
1592             
1593         default:
1594             *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
1595             SetLastError(NTE_BAD_FLAGS);
1596             return FALSE;
1597     }
1598                 
1599     if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
1600         SetLastError(ERROR_SUCCESS);
1601         return TRUE;
1602     } else {
1603         return FALSE;
1604     }
1605 }
1606
1607 /******************************************************************************
1608  * CPCreateHash (RSAENH.@)
1609  *
1610  * CPCreateHash creates and initalizes a new hash object.
1611  *
1612  * PARAMS
1613  *  hProv   [I] Handle to the key container to which the new hash will belong.
1614  *  Algid   [I] Identifies the hash algorithm, which will be used for the hash.
1615  *  hKey    [I] Handle to a session key applied for keyed hashes.
1616  *  dwFlags [I] Currently no flags defined. Must be zero.
1617  *  phHash  [O] Points to the location where a handle to the new hash will be stored.
1618  *
1619  * RETURNS
1620  *  Success: TRUE
1621  *  Failure: FALSE
1622  *
1623  * NOTES
1624  *  hKey is a handle to a session key applied in keyed hashes like MAC and HMAC.
1625  *  If a normal hash object is to be created (like e.g. MD2 or SHA1) hKey must be zero.
1626  */
1627 BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, 
1628                                 HCRYPTHASH *phHash)
1629 {
1630     CRYPTKEY *pCryptKey;
1631     CRYPTHASH *pCryptHash;
1632     const PROV_ENUMALGS_EX *peaAlgidInfo;
1633         
1634     TRACE("(hProv=%08lx, Algid=%08x, hKey=%08lx, dwFlags=%08x, phHash=%p)\n", hProv, Algid, hKey,
1635           dwFlags, phHash);
1636
1637     peaAlgidInfo = get_algid_info(hProv, Algid);
1638     if (!peaAlgidInfo) return FALSE;
1639
1640     if (dwFlags)
1641     {
1642         SetLastError(NTE_BAD_FLAGS);
1643         return FALSE;
1644     }
1645
1646     if (Algid == CALG_MAC || Algid == CALG_HMAC || Algid == CALG_SCHANNEL_MASTER_HASH || 
1647         Algid == CALG_TLS1PRF) 
1648     {
1649         if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) {
1650             SetLastError(NTE_BAD_KEY);
1651             return FALSE;
1652         }
1653
1654         if ((Algid == CALG_MAC) && (GET_ALG_TYPE(pCryptKey->aiAlgid) != ALG_TYPE_BLOCK)) {
1655             SetLastError(NTE_BAD_KEY);
1656             return FALSE;
1657         }
1658
1659         if ((Algid == CALG_SCHANNEL_MASTER_HASH || Algid == CALG_TLS1PRF) && 
1660             (pCryptKey->aiAlgid != CALG_TLS1_MASTER)) 
1661         {
1662             SetLastError(NTE_BAD_KEY);
1663             return FALSE;
1664         }
1665
1666         if ((Algid == CALG_TLS1PRF) && (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY)) {
1667             SetLastError(NTE_BAD_KEY_STATE);
1668             return FALSE;
1669         }
1670     }
1671
1672     *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1673                          destroy_hash, (OBJECTHDR**)&pCryptHash);
1674     if (!pCryptHash) return FALSE;
1675
1676     pCryptHash->aiAlgid = Algid;
1677     pCryptHash->hKey = hKey;
1678     pCryptHash->hProv = hProv;
1679     pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
1680     pCryptHash->pHMACInfo = NULL;
1681     pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3;
1682     init_data_blob(&pCryptHash->tpPRFParams.blobLabel);
1683     init_data_blob(&pCryptHash->tpPRFParams.blobSeed);
1684
1685     if (Algid == CALG_SCHANNEL_MASTER_HASH) {
1686         static const char keyex[] = "key expansion";
1687         BYTE key_expansion[sizeof keyex];
1688         CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, key_expansion };
1689
1690         memcpy( key_expansion, keyex, sizeof keyex );
1691         
1692         if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) {
1693             static const char msec[] = "master secret";
1694             BYTE master_secret[sizeof msec];
1695             CRYPT_DATA_BLOB blobLabel = { 13, master_secret };
1696             BYTE abKeyValue[48];
1697
1698             memcpy( master_secret, msec, sizeof msec );
1699     
1700             /* See RFC 2246, chapter 8.1 */
1701             if (!concat_data_blobs(&blobRandom, 
1702                                    &pCryptKey->siSChannelInfo.blobClientRandom, 
1703                                    &pCryptKey->siSChannelInfo.blobServerRandom))
1704             {
1705                 return FALSE;
1706             }
1707             tls1_prf(hProv, hKey, &blobLabel, &blobRandom, abKeyValue, 48);
1708             pCryptKey->dwState = RSAENH_KEYSTATE_MASTERKEY; 
1709             memcpy(pCryptKey->abKeyValue, abKeyValue, 48);
1710             free_data_blob(&blobRandom);
1711         }
1712
1713         /* See RFC 2246, chapter 6.3 */
1714         if (!concat_data_blobs(&blobRandom, 
1715                                   &pCryptKey->siSChannelInfo.blobServerRandom, 
1716                                   &pCryptKey->siSChannelInfo.blobClientRandom))
1717         {
1718             return FALSE;
1719         }
1720         tls1_prf(hProv, hKey, &blobKeyExpansion, &blobRandom, pCryptHash->abHashValue, 
1721                  RSAENH_MAX_HASH_SIZE);
1722         free_data_blob(&blobRandom);
1723     }
1724
1725     return init_hash(pCryptHash);
1726 }
1727
1728 /******************************************************************************
1729  * CPDestroyHash (RSAENH.@)
1730  * 
1731  * Releases the handle to a hash object. The object is destroyed if it's reference
1732  * count reaches zero.
1733  *
1734  * PARAMS
1735  *  hProv [I] Handle to the key container to which the hash object belongs.
1736  *  hHash [I] Handle to the hash object to be released.
1737  *
1738  * RETURNS
1739  *  Success: TRUE
1740  *  Failure: FALSE 
1741  */
1742 BOOL WINAPI RSAENH_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash)
1743 {
1744     TRACE("(hProv=%08lx, hHash=%08lx)\n", hProv, hHash);
1745      
1746     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1747     {
1748         SetLastError(NTE_BAD_UID);
1749         return FALSE;
1750     }
1751         
1752     if (!release_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) 
1753     {
1754         SetLastError(NTE_BAD_HASH);
1755         return FALSE;
1756     }
1757     
1758     return TRUE;
1759 }
1760
1761 /******************************************************************************
1762  * CPDestroyKey (RSAENH.@)
1763  *
1764  * Releases the handle to a key object. The object is destroyed if it's reference
1765  * count reaches zero.
1766  *
1767  * PARAMS
1768  *  hProv [I] Handle to the key container to which the key object belongs.
1769  *  hKey  [I] Handle to the key object to be released.
1770  *
1771  * RETURNS
1772  *  Success: TRUE
1773  *  Failure: FALSE
1774  */
1775 BOOL WINAPI RSAENH_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey)
1776 {
1777     TRACE("(hProv=%08lx, hKey=%08lx)\n", hProv, hKey);
1778         
1779     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1780     {
1781         SetLastError(NTE_BAD_UID);
1782         return FALSE;
1783     }
1784         
1785     if (!release_handle(&handle_table, hKey, RSAENH_MAGIC_KEY)) 
1786     {
1787         SetLastError(NTE_BAD_KEY);
1788         return FALSE;
1789     }
1790     
1791     return TRUE;
1792 }
1793
1794 /******************************************************************************
1795  * CPDuplicateHash (RSAENH.@)
1796  *
1797  * Clones a hash object including it's current state.
1798  *
1799  * PARAMS
1800  *  hUID        [I] Handle to the key container the hash belongs to.
1801  *  hHash       [I] Handle to the hash object to be cloned.
1802  *  pdwReserved [I] Reserved. Must be NULL.
1803  *  dwFlags     [I] No flags are currently defined. Must be 0.
1804  *  phHash      [O] Handle to the cloned hash object.
1805  *
1806  * RETURNS
1807  *  Success: TRUE.
1808  *  Failure: FALSE.
1809  */
1810 BOOL WINAPI RSAENH_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved, 
1811                                    DWORD dwFlags, HCRYPTHASH *phHash)
1812 {
1813     CRYPTHASH *pSrcHash, *pDestHash;
1814     
1815     TRACE("(hUID=%08lx, hHash=%08lx, pdwReserved=%p, dwFlags=%08x, phHash=%p)\n", hUID, hHash,
1816            pdwReserved, dwFlags, phHash);
1817
1818     if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1819     {
1820         SetLastError(NTE_BAD_UID);
1821         return FALSE;
1822     }
1823
1824     if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pSrcHash))
1825     {
1826         SetLastError(NTE_BAD_HASH);
1827         return FALSE;
1828     }
1829
1830     if (!phHash || pdwReserved || dwFlags) 
1831     {
1832         SetLastError(ERROR_INVALID_PARAMETER);
1833         return FALSE;
1834     }
1835
1836     *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1837                          destroy_hash, (OBJECTHDR**)&pDestHash);
1838     if (*phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE)
1839     {
1840         *pDestHash = *pSrcHash;
1841         duplicate_hash_impl(pSrcHash->aiAlgid, &pSrcHash->context, &pDestHash->context);
1842         copy_hmac_info(&pDestHash->pHMACInfo, pSrcHash->pHMACInfo);
1843         copy_data_blob(&pDestHash->tpPRFParams.blobLabel, &pSrcHash->tpPRFParams.blobLabel);
1844         copy_data_blob(&pDestHash->tpPRFParams.blobSeed, &pSrcHash->tpPRFParams.blobSeed);
1845     }
1846
1847     return *phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE;
1848 }
1849
1850 /******************************************************************************
1851  * CPDuplicateKey (RSAENH.@)
1852  *
1853  * Clones a key object including it's current state.
1854  *
1855  * PARAMS
1856  *  hUID        [I] Handle to the key container the hash belongs to.
1857  *  hKey        [I] Handle to the key object to be cloned.
1858  *  pdwReserved [I] Reserved. Must be NULL.
1859  *  dwFlags     [I] No flags are currently defined. Must be 0.
1860  *  phHash      [O] Handle to the cloned key object.
1861  *
1862  * RETURNS
1863  *  Success: TRUE.
1864  *  Failure: FALSE.
1865  */
1866 BOOL WINAPI RSAENH_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved, 
1867                                   DWORD dwFlags, HCRYPTKEY *phKey)
1868 {
1869     CRYPTKEY *pSrcKey, *pDestKey;
1870     
1871     TRACE("(hUID=%08lx, hKey=%08lx, pdwReserved=%p, dwFlags=%08x, phKey=%p)\n", hUID, hKey,
1872           pdwReserved, dwFlags, phKey);
1873
1874     if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1875     {
1876         SetLastError(NTE_BAD_UID);
1877         return FALSE;
1878     }
1879
1880     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSrcKey))
1881     {
1882         SetLastError(NTE_BAD_KEY);
1883         return FALSE;
1884     }
1885
1886     if (!phKey || pdwReserved || dwFlags) 
1887     {
1888         SetLastError(ERROR_INVALID_PARAMETER);
1889         return FALSE;
1890     }
1891
1892     *phKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, destroy_key,
1893                         (OBJECTHDR**)&pDestKey);
1894     if (*phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
1895     {
1896         *pDestKey = *pSrcKey;
1897         copy_data_blob(&pDestKey->siSChannelInfo.blobServerRandom,
1898                        &pSrcKey->siSChannelInfo.blobServerRandom);
1899         copy_data_blob(&pDestKey->siSChannelInfo.blobClientRandom, 
1900                        &pSrcKey->siSChannelInfo.blobClientRandom);
1901         duplicate_key_impl(pSrcKey->aiAlgid, &pSrcKey->context, &pDestKey->context);
1902         return TRUE;
1903     }
1904     else
1905     {
1906         return FALSE;
1907     }
1908 }
1909
1910 /******************************************************************************
1911  * CPEncrypt (RSAENH.@)
1912  *
1913  * Encrypt data.
1914  *
1915  * PARAMS
1916  *  hProv      [I]   The key container hKey and hHash belong to.
1917  *  hKey       [I]   The key used to encrypt the data.
1918  *  hHash      [I]   An optional hash object for parallel hashing. See notes.
1919  *  Final      [I]   Indicates if this is the last block of data to encrypt.
1920  *  dwFlags    [I]   Currently no flags defined. Must be zero.
1921  *  pbData     [I/O] Pointer to the data to encrypt. Encrypted data will also be stored there. 
1922  *  pdwDataLen [I/O] I: Length of data to encrypt, O: Length of encrypted data.
1923  *  dwBufLen   [I]   Size of the buffer at pbData.
1924  *
1925  * RETURNS
1926  *  Success: TRUE.
1927  *  Failure: FALSE.
1928  *
1929  * NOTES
1930  *  If a hash object handle is provided in hHash, it will be updated with the plaintext. 
1931  *  This is useful for message signatures.
1932  *
1933  *  This function uses the standard WINAPI protocol for querying data of dynamic length. 
1934  */
1935 BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, 
1936                              DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1937 {
1938     CRYPTKEY *pCryptKey;
1939     BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
1940     DWORD dwEncryptedLen, i, j, k;
1941         
1942     TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
1943           "pdwDataLen=%p, dwBufLen=%d)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen,
1944           dwBufLen);
1945     
1946     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1947     {
1948         SetLastError(NTE_BAD_UID);
1949         return FALSE;
1950     }
1951
1952     if (dwFlags)
1953     {
1954         SetLastError(NTE_BAD_FLAGS);
1955         return FALSE;
1956     }
1957
1958     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
1959     {
1960         SetLastError(NTE_BAD_KEY);
1961         return FALSE;
1962     }
1963
1964     if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) 
1965         pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
1966
1967     if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING) 
1968     {
1969         SetLastError(NTE_BAD_DATA);
1970         return FALSE;
1971     }
1972
1973     if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
1974         if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
1975     }
1976     
1977     if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
1978         if (!Final && (*pdwDataLen % pCryptKey->dwBlockLen)) {
1979             SetLastError(NTE_BAD_DATA);
1980             return FALSE;
1981         }
1982
1983         dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen;
1984
1985         if (pbData == NULL) {
1986             *pdwDataLen = dwEncryptedLen;
1987             return TRUE;
1988         }
1989         else if (dwEncryptedLen > dwBufLen) {
1990             *pdwDataLen = dwEncryptedLen;
1991             SetLastError(ERROR_MORE_DATA);
1992             return FALSE;
1993         }
1994
1995         /* Pad final block with length bytes */
1996         for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
1997         *pdwDataLen = dwEncryptedLen;
1998
1999         for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2000             switch (pCryptKey->dwMode) {
2001                 case CRYPT_MODE_ECB:
2002                     encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
2003                                        RSAENH_ENCRYPT);
2004                     break;
2005                 
2006                 case CRYPT_MODE_CBC:
2007                     for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j];
2008                     encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
2009                                        RSAENH_ENCRYPT);
2010                     memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen);
2011                     break;
2012
2013                 case CRYPT_MODE_CFB:
2014                     for (j=0; j<pCryptKey->dwBlockLen; j++) {
2015                         encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, 
2016                                            pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2017                         out[j] = in[j] ^ o[0];
2018                         for (k=0; k<pCryptKey->dwBlockLen-1; k++) 
2019                             pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2020                         pCryptKey->abChainVector[k] = out[j];
2021                     }
2022                     break;
2023                     
2024                 default:
2025                     SetLastError(NTE_BAD_ALGID);
2026                     return FALSE;
2027             }
2028             memcpy(in, out, pCryptKey->dwBlockLen); 
2029         }
2030     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2031         if (pbData == NULL) {
2032             *pdwDataLen = dwBufLen;
2033             return TRUE;
2034         }
2035         encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2036     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2037         if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2038             SetLastError(NTE_BAD_KEY);
2039             return FALSE;
2040         }
2041         if (!pbData) {
2042             *pdwDataLen = pCryptKey->dwBlockLen;
2043             return TRUE;
2044         }
2045         if (dwBufLen < pCryptKey->dwBlockLen) {
2046             SetLastError(ERROR_MORE_DATA);
2047             return FALSE;
2048         }
2049         if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE;
2050         encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
2051         *pdwDataLen = pCryptKey->dwBlockLen;
2052         Final = TRUE;
2053     } else {
2054         SetLastError(NTE_BAD_TYPE);
2055         return FALSE;
2056     }
2057
2058     if (Final) setup_key(pCryptKey);
2059
2060     return TRUE;
2061 }
2062
2063 /******************************************************************************
2064  * CPDecrypt (RSAENH.@)
2065  *
2066  * Decrypt data.
2067  *
2068  * PARAMS
2069  *  hProv      [I]   The key container hKey and hHash belong to.
2070  *  hKey       [I]   The key used to decrypt the data.
2071  *  hHash      [I]   An optional hash object for parallel hashing. See notes.
2072  *  Final      [I]   Indicates if this is the last block of data to decrypt.
2073  *  dwFlags    [I]   Currently no flags defined. Must be zero.
2074  *  pbData     [I/O] Pointer to the data to decrypt. Plaintext will also be stored there. 
2075  *  pdwDataLen [I/O] I: Length of ciphertext, O: Length of plaintext.
2076  *
2077  * RETURNS
2078  *  Success: TRUE.
2079  *  Failure: FALSE.
2080  *
2081  * NOTES
2082  *  If a hash object handle is provided in hHash, it will be updated with the plaintext. 
2083  *  This is useful for message signatures.
2084  *
2085  *  This function uses the standard WINAPI protocol for querying data of dynamic length. 
2086  */
2087 BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, 
2088                              DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2089 {
2090     CRYPTKEY *pCryptKey;
2091     BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
2092     DWORD i, j, k;
2093     DWORD dwMax;
2094
2095     TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
2096           "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
2097     
2098     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2099     {
2100         SetLastError(NTE_BAD_UID);
2101         return FALSE;
2102     }
2103
2104     if (dwFlags)
2105     {
2106         SetLastError(NTE_BAD_FLAGS);
2107         return FALSE;
2108     }
2109
2110     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2111     {
2112         SetLastError(NTE_BAD_KEY);
2113         return FALSE;
2114     }
2115
2116     if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) 
2117         pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
2118
2119     if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
2120     {
2121         SetLastError(NTE_BAD_DATA);
2122         return FALSE;
2123     }
2124
2125     dwMax=*pdwDataLen;
2126
2127     if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
2128         for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2129             switch (pCryptKey->dwMode) {
2130                 case CRYPT_MODE_ECB:
2131                     encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
2132                                        RSAENH_DECRYPT);
2133                     break;
2134                 
2135                 case CRYPT_MODE_CBC:
2136                     encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
2137                                        RSAENH_DECRYPT);
2138                     for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j];
2139                     memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen);
2140                     break;
2141
2142                 case CRYPT_MODE_CFB:
2143                     for (j=0; j<pCryptKey->dwBlockLen; j++) {
2144                         encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, 
2145                                            pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2146                         out[j] = in[j] ^ o[0];
2147                         for (k=0; k<pCryptKey->dwBlockLen-1; k++) 
2148                             pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2149                         pCryptKey->abChainVector[k] = in[j];
2150                     }
2151                     break;
2152                     
2153                 default:
2154                     SetLastError(NTE_BAD_ALGID);
2155                     return FALSE;
2156             }
2157             memcpy(in, out, pCryptKey->dwBlockLen);
2158         }
2159         if (Final) {
2160             if (pbData[*pdwDataLen-1] &&
2161              pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen &&
2162              pbData[*pdwDataLen-1] < *pdwDataLen) {
2163                 BOOL padOkay = TRUE;
2164
2165                 /* check that every bad byte has the same value */
2166                 for (i = 1; padOkay && i < pbData[*pdwDataLen-1]; i++)
2167                     if (pbData[*pdwDataLen - i - 1] != pbData[*pdwDataLen - 1])
2168                         padOkay = FALSE;
2169                 if (padOkay)
2170                     *pdwDataLen -= pbData[*pdwDataLen-1];
2171                 else {
2172                     SetLastError(NTE_BAD_DATA);
2173                     return FALSE;
2174                 }
2175             }
2176             else {
2177                 SetLastError(NTE_BAD_DATA);
2178                 return FALSE;
2179             }
2180         }
2181
2182     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2183         encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2184     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2185         if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2186             SetLastError(NTE_BAD_KEY);
2187             return FALSE;
2188         }
2189         encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
2190         if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
2191         Final = TRUE;
2192     } else {
2193         SetLastError(NTE_BAD_TYPE);
2194         return FALSE;
2195     } 
2196     
2197     if (Final) setup_key(pCryptKey);
2198
2199     if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
2200         if (*pdwDataLen>dwMax ||
2201             !RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
2202     }
2203     
2204     return TRUE;
2205 }
2206
2207 /******************************************************************************
2208  * CPExportKey (RSAENH.@)
2209  *
2210  * Export a key into a binary large object (BLOB).
2211  *
2212  * PARAMS
2213  *  hProv      [I]   Key container from which a key is to be exported.
2214  *  hKey       [I]   Key to be exported.
2215  *  hPubKey    [I]   Key used to encrypt sensitive BLOB data.
2216  *  dwBlobType [I]   SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
2217  *  dwFlags    [I]   Currently none defined.
2218  *  pbData     [O]   Pointer to a buffer where the BLOB will be written to.
2219  *  pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
2220  *
2221  * RETURNS
2222  *  Success: TRUE.
2223  *  Failure: FALSE.
2224  */
2225 BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey, 
2226                                DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2227 {
2228     CRYPTKEY *pCryptKey, *pPubKey;
2229     BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2230     RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
2231     ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
2232     DWORD dwDataLen;
2233     
2234     TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
2235           "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
2236     
2237     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2238     {
2239         SetLastError(NTE_BAD_UID);
2240         return FALSE;
2241     }
2242
2243     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2244     {
2245         SetLastError(NTE_BAD_KEY);
2246         return FALSE;
2247     }
2248
2249     if (dwFlags & CRYPT_SSL2_FALLBACK) {
2250         if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
2251             SetLastError(NTE_BAD_KEY);
2252             return FALSE;
2253         }
2254     }
2255     
2256     switch ((BYTE)dwBlobType)
2257     {
2258         case SIMPLEBLOB:
2259             if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
2260                 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
2261                 return FALSE;
2262             }
2263
2264             if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
2265                 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2266                 return FALSE;
2267             }
2268
2269             dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
2270             if (pbData) {
2271                 if (*pdwDataLen < dwDataLen) {
2272                     SetLastError(ERROR_MORE_DATA);
2273                     *pdwDataLen = dwDataLen;
2274                     return FALSE;
2275                 }
2276
2277                 pBlobHeader->bType = SIMPLEBLOB;
2278                 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2279                 pBlobHeader->reserved = 0;
2280                 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2281
2282                 *pAlgid = pPubKey->aiAlgid;
2283        
2284                 if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1), 
2285                               pPubKey->dwBlockLen, dwFlags))
2286                 {
2287                     return FALSE;
2288                 }
2289                 
2290                 encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1), 
2291                                    (BYTE*)(pAlgid+1), RSAENH_ENCRYPT); 
2292             }
2293             *pdwDataLen = dwDataLen;
2294             return TRUE;
2295             
2296         case PUBLICKEYBLOB:
2297             if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
2298                 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2299                 return FALSE;
2300             }
2301
2302             if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2303                 SetLastError(NTE_BAD_KEY);
2304                 return FALSE;
2305             }
2306
2307             dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
2308             if (pbData) {
2309                 if (*pdwDataLen < dwDataLen) {
2310                     SetLastError(ERROR_MORE_DATA);
2311                     *pdwDataLen = dwDataLen;
2312                     return FALSE;
2313                 }
2314
2315                 pBlobHeader->bType = PUBLICKEYBLOB;
2316                 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2317                 pBlobHeader->reserved = 0;
2318                 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2319
2320                 pRSAPubKey->magic = RSAENH_MAGIC_RSA1; 
2321                 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2322         
2323                 export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
2324                                        pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2325             }
2326             *pdwDataLen = dwDataLen;
2327             return TRUE;
2328
2329         case PRIVATEKEYBLOB:
2330             if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2331                 SetLastError(NTE_BAD_KEY);
2332                 return FALSE;
2333             }
2334     
2335             dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 
2336                         2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
2337             if (pbData) {
2338                 if (*pdwDataLen < dwDataLen) {
2339                     SetLastError(ERROR_MORE_DATA);
2340                     *pdwDataLen = dwDataLen;
2341                     return FALSE;
2342                 }
2343                 
2344                 pBlobHeader->bType = PRIVATEKEYBLOB;
2345                 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2346                 pBlobHeader->reserved = 0;
2347                 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2348
2349                 pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
2350                 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2351                 
2352                 export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
2353                                         pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2354             }
2355             *pdwDataLen = dwDataLen;
2356             return TRUE;
2357             
2358         default:
2359             SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2360             return FALSE;
2361     }
2362 }
2363
2364 /******************************************************************************
2365  * CPImportKey (RSAENH.@)
2366  *
2367  * Import a BLOB'ed key into a key container.
2368  *
2369  * PARAMS
2370  *  hProv     [I] Key container into which the key is to be imported.
2371  *  pbData    [I] Pointer to a buffer which holds the BLOB.
2372  *  dwDataLen [I] Length of data in buffer at pbData.
2373  *  hPubKey   [I] Key used to decrypt sensitive BLOB data.
2374  *  dwFlags   [I] Currently none defined.
2375  *  phKey     [O] Handle to the imported key.
2376  *
2377  * RETURNS
2378  *  Success: TRUE.
2379  *  Failure: FALSE.
2380  */
2381 BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 
2382                                HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
2383 {
2384     KEYCONTAINER *pKeyContainer;
2385     CRYPTKEY *pCryptKey, *pPubKey;
2386     CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2387     CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
2388     CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
2389     CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
2390     ALG_ID algID;
2391     BYTE *pbDecrypted;
2392     DWORD dwKeyLen;
2393     BOOL ret;
2394
2395     TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
2396         hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
2397     
2398     if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2399                        (OBJECTHDR**)&pKeyContainer)) 
2400     {
2401         SetLastError(NTE_BAD_UID);
2402         return FALSE;
2403     }
2404
2405     if (dwDataLen < sizeof(BLOBHEADER) || 
2406         pBlobHeader->bVersion != CUR_BLOB_VERSION ||
2407         pBlobHeader->reserved != 0) 
2408     {
2409         SetLastError(NTE_BAD_DATA);
2410         return FALSE;
2411     }
2412
2413     switch (pBlobHeader->bType)
2414     {
2415         case PRIVATEKEYBLOB:    
2416             if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) || 
2417                 (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
2418                 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 
2419                     (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4)))) 
2420             {
2421                 SetLastError(NTE_BAD_DATA);
2422                 return FALSE;
2423             }
2424     
2425             *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2426             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2427             setup_key(pCryptKey);
2428             ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
2429                                            pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
2430             if (ret) {
2431                 switch (pBlobHeader->aiKeyAlg)
2432                 {
2433                 case AT_SIGNATURE:
2434                 case CALG_RSA_SIGN:
2435                     TRACE("installing signing key\n");
2436                     RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2437                     copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2438                                 &pKeyContainer->hSignatureKeyPair);
2439                     break;
2440                 case AT_KEYEXCHANGE:
2441                 case CALG_RSA_KEYX:
2442                     TRACE("installing key exchange key\n");
2443                     RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2444                     copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2445                                 &pKeyContainer->hKeyExchangeKeyPair);
2446                     break;
2447                 }
2448             }
2449             return ret;
2450                 
2451         case PUBLICKEYBLOB:
2452             if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) || 
2453                 (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
2454                 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3))) 
2455             {
2456                 SetLastError(NTE_BAD_DATA);
2457                 return FALSE;
2458             }
2459     
2460             /* Since this is a public key blob, only the public key is
2461              * available, so only signature verification is possible.
2462              */
2463             algID = pBlobHeader->aiKeyAlg;
2464             *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey); 
2465             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 
2466             setup_key(pCryptKey);
2467             ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
2468                                           pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
2469             if (ret) {
2470                 switch (pBlobHeader->aiKeyAlg)
2471                 {
2472                 case AT_KEYEXCHANGE:
2473                 case CALG_RSA_KEYX:
2474                     TRACE("installing public key\n");
2475                     RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2476                     copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2477                                 &pKeyContainer->hKeyExchangeKeyPair);
2478                     break;
2479                 }
2480             }
2481             return ret;
2482                 
2483         case SIMPLEBLOB:
2484             if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
2485                 pPubKey->aiAlgid != CALG_RSA_KEYX) 
2486             {
2487                 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
2488                 return FALSE;
2489             }
2490
2491             if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen) 
2492             {
2493                 SetLastError(NTE_BAD_DATA); /* FIXME: error code */
2494                 return FALSE;
2495             }
2496
2497             pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
2498             if (!pbDecrypted) return FALSE;
2499             encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted, 
2500                                RSAENH_DECRYPT);
2501
2502             dwKeyLen = RSAENH_MAX_KEY_SIZE;
2503             if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
2504                 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2505                 return FALSE;
2506             }
2507             
2508             *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
2509             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
2510             {
2511                 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2512                 return FALSE;
2513             }
2514             memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
2515             HeapFree(GetProcessHeap(), 0, pbDecrypted);
2516             setup_key(pCryptKey);
2517             return TRUE;
2518
2519         default:
2520             SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2521             return FALSE;
2522     }
2523 }
2524
2525 /******************************************************************************
2526  * CPGenKey (RSAENH.@)
2527  *
2528  * Generate a key in the key container
2529  *
2530  * PARAMS
2531  *  hProv   [I] Key container for which a key is to be generated.
2532  *  Algid   [I] Crypto algorithm identifier for the key to be generated.
2533  *  dwFlags [I] Upper 16 bits: Binary length of key. Lower 16 bits: Flags. See Notes
2534  *  phKey   [O] Handle to the generated key.
2535  *
2536  * RETURNS
2537  *  Success: TRUE.
2538  *  Failure: FALSE.
2539  *
2540  * FIXME
2541  *  Flags currently not considered.
2542  *
2543  * NOTES
2544  *  Private key-exchange- and signature-keys can be generated with Algid AT_KEYEXCHANGE
2545  *  and AT_SIGNATURE values.
2546  */
2547 BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
2548 {
2549     KEYCONTAINER *pKeyContainer;
2550     CRYPTKEY *pCryptKey;
2551
2552     TRACE("(hProv=%08lx, aiAlgid=%d, dwFlags=%08x, phKey=%p)\n", hProv, Algid, dwFlags, phKey);
2553
2554     if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2555                        (OBJECTHDR**)&pKeyContainer)) 
2556     {
2557         /* MSDN: hProv not containing valid context handle */
2558         SetLastError(NTE_BAD_UID);
2559         return FALSE;
2560     }
2561     
2562     switch (Algid)
2563     {
2564         case AT_SIGNATURE:
2565         case CALG_RSA_SIGN:
2566             *phKey = new_key(hProv, CALG_RSA_SIGN, dwFlags, &pCryptKey);
2567             if (pCryptKey) { 
2568                 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2569                 setup_key(pCryptKey);
2570                 if (Algid == AT_SIGNATURE) {
2571                     RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2572                     copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2573                                 &pKeyContainer->hSignatureKeyPair);
2574                 }
2575             }
2576             break;
2577
2578         case AT_KEYEXCHANGE:
2579         case CALG_RSA_KEYX:
2580             *phKey = new_key(hProv, CALG_RSA_KEYX, dwFlags, &pCryptKey);
2581             if (pCryptKey) { 
2582                 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2583                 setup_key(pCryptKey);
2584                 if (Algid == AT_KEYEXCHANGE) {
2585                     RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2586                     copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2587                                 &pKeyContainer->hKeyExchangeKeyPair);
2588                 }
2589             }
2590             break;
2591             
2592         case CALG_RC2:
2593         case CALG_RC4:
2594         case CALG_DES:
2595         case CALG_3DES_112:
2596         case CALG_3DES:
2597         case CALG_AES:
2598         case CALG_AES_128:
2599         case CALG_AES_192:
2600         case CALG_AES_256:
2601         case CALG_PCT1_MASTER:
2602         case CALG_SSL2_MASTER:
2603         case CALG_SSL3_MASTER:
2604         case CALG_TLS1_MASTER:
2605             *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
2606             if (pCryptKey) {
2607                 gen_rand_impl(pCryptKey->abKeyValue, RSAENH_MAX_KEY_SIZE);
2608                 switch (Algid) {
2609                     case CALG_SSL3_MASTER:
2610                         pCryptKey->abKeyValue[0] = RSAENH_SSL3_VERSION_MAJOR;
2611                         pCryptKey->abKeyValue[1] = RSAENH_SSL3_VERSION_MINOR;
2612                         break;
2613
2614                     case CALG_TLS1_MASTER:
2615                         pCryptKey->abKeyValue[0] = RSAENH_TLS1_VERSION_MAJOR;
2616                         pCryptKey->abKeyValue[1] = RSAENH_TLS1_VERSION_MINOR;
2617                         break;
2618                 }
2619                 setup_key(pCryptKey);
2620             }
2621             break;
2622             
2623         default:
2624             /* MSDN: Algorithm not supported specified by Algid */
2625             SetLastError(NTE_BAD_ALGID);
2626             return FALSE;
2627     }
2628             
2629     return *phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE;
2630 }
2631
2632 /******************************************************************************
2633  * CPGenRandom (RSAENH.@)
2634  *
2635  * Generate a random byte stream.
2636  *
2637  * PARAMS
2638  *  hProv    [I] Key container that is used to generate random bytes.
2639  *  dwLen    [I] Specifies the number of requested random data bytes.
2640  *  pbBuffer [O] Random bytes will be stored here.
2641  *
2642  * RETURNS
2643  *  Success: TRUE
2644  *  Failure: FALSE
2645  */
2646 BOOL WINAPI RSAENH_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
2647 {
2648     TRACE("(hProv=%08lx, dwLen=%d, pbBuffer=%p)\n", hProv, dwLen, pbBuffer);
2649     
2650     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2651     {
2652         /* MSDN: hProv not containing valid context handle */
2653         SetLastError(NTE_BAD_UID);
2654         return FALSE;
2655     }
2656
2657     return gen_rand_impl(pbBuffer, dwLen);
2658 }
2659
2660 /******************************************************************************
2661  * CPGetHashParam (RSAENH.@)
2662  *
2663  * Query parameters of an hash object.
2664  *
2665  * PARAMS
2666  *  hProv      [I]   The kea container, which the hash belongs to.
2667  *  hHash      [I]   The hash object that is to be queried.
2668  *  dwParam    [I]   Specifies the parameter that is to be queried.
2669  *  pbData     [I]   Pointer to the buffer where the parameter value will be stored.
2670  *  pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2671  *  dwFlags    [I]   None currently defined.
2672  *
2673  * RETURNS
2674  *  Success: TRUE
2675  *  Failure: FALSE
2676  *
2677  * NOTES
2678  *  Valid dwParams are: HP_ALGID, HP_HASHSIZE, HP_HASHVALUE. The hash will be 
2679  *  finalized if HP_HASHVALUE is queried.
2680  */
2681 BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, 
2682                                   DWORD *pdwDataLen, DWORD dwFlags) 
2683 {
2684     CRYPTHASH *pCryptHash;
2685         
2686     TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
2687         hProv, hHash, dwParam, pbData, pdwDataLen, dwFlags);
2688     
2689     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2690     {
2691         SetLastError(NTE_BAD_UID);
2692         return FALSE;
2693     }
2694
2695     if (dwFlags)
2696     {
2697         SetLastError(NTE_BAD_FLAGS);
2698         return FALSE;
2699     }
2700     
2701     if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
2702                        (OBJECTHDR**)&pCryptHash))
2703     {
2704         SetLastError(NTE_BAD_HASH);
2705         return FALSE;
2706     }
2707
2708     if (!pdwDataLen)
2709     {
2710         SetLastError(ERROR_INVALID_PARAMETER);
2711         return FALSE;
2712     }
2713     
2714     switch (dwParam)
2715     {
2716         case HP_ALGID:
2717             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->aiAlgid, 
2718                               sizeof(ALG_ID));
2719
2720         case HP_HASHSIZE:
2721             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->dwHashSize, 
2722                               sizeof(DWORD));
2723
2724         case HP_HASHVAL:
2725             if (pCryptHash->aiAlgid == CALG_TLS1PRF) {
2726                 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel,
2727                                 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen);
2728             }
2729
2730             if ( pbData == NULL ) {
2731                 *pdwDataLen = pCryptHash->dwHashSize;
2732                 return TRUE;
2733             }
2734
2735             if (pbData && (pCryptHash->dwState != RSAENH_HASHSTATE_FINISHED))
2736             {
2737                 finalize_hash(pCryptHash);
2738                 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
2739             }
2740             
2741             return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptHash->abHashValue, 
2742                               pCryptHash->dwHashSize);
2743
2744         default:
2745             SetLastError(NTE_BAD_TYPE);
2746             return FALSE;
2747     }
2748 }
2749
2750 /******************************************************************************
2751  * CPSetKeyParam (RSAENH.@)
2752  *
2753  * Set a parameter of a key object
2754  *
2755  * PARAMS
2756  *  hProv   [I] The key container to which the key belongs.
2757  *  hKey    [I] The key for which a parameter is to be set.
2758  *  dwParam [I] Parameter type. See Notes.
2759  *  pbData  [I] Pointer to the parameter value.
2760  *  dwFlags [I] Currently none defined.
2761  *
2762  * RETURNS
2763  *  Success: TRUE.
2764  *  Failure: FALSE.
2765  *
2766  * NOTES:
2767  *  Defined dwParam types are:
2768  *   - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2769  *   - KP_MODE_BITS: Shift width for cipher feedback mode. (Currently ignored by MS CSP's)
2770  *   - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT, 
2771  *                     CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2772  *   - KP_IV: Initialization vector
2773  */
2774 BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, 
2775                                  DWORD dwFlags)
2776 {
2777     CRYPTKEY *pCryptKey;
2778
2779     TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n", hProv, hKey,
2780           dwParam, pbData, dwFlags);
2781
2782     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2783     {
2784         SetLastError(NTE_BAD_UID);
2785         return FALSE;
2786     }
2787
2788     if (dwFlags) {
2789         SetLastError(NTE_BAD_FLAGS);
2790         return FALSE;
2791     }
2792     
2793     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2794     {
2795         SetLastError(NTE_BAD_KEY);
2796         return FALSE;
2797     }
2798     
2799     switch (dwParam) {
2800         case KP_PADDING:
2801             /* The MS providers only support PKCS5_PADDING */
2802             if (*(DWORD *)pbData != PKCS5_PADDING) {
2803                 SetLastError(NTE_BAD_DATA);
2804                 return FALSE;
2805             }
2806             return TRUE;
2807
2808         case KP_MODE:
2809             pCryptKey->dwMode = *(DWORD*)pbData;
2810             return TRUE;
2811
2812         case KP_MODE_BITS:
2813             pCryptKey->dwModeBits = *(DWORD*)pbData;
2814             return TRUE;
2815
2816         case KP_PERMISSIONS:
2817             pCryptKey->dwPermissions = *(DWORD*)pbData;
2818             return TRUE;
2819
2820         case KP_IV:
2821             memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen);
2822             setup_key(pCryptKey);
2823             return TRUE;
2824
2825         case KP_SALT_EX:
2826         {
2827             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData;
2828
2829             /* salt length can't be greater than 184 bits = 24 bytes */
2830             if (blob->cbData > 24)
2831             {
2832                 SetLastError(NTE_BAD_DATA);
2833                 return FALSE;
2834             }
2835             memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, blob->pbData,
2836                    blob->cbData);
2837             pCryptKey->dwSaltLen = blob->cbData;
2838             setup_key(pCryptKey);
2839             return TRUE;
2840         }
2841
2842         case KP_EFFECTIVE_KEYLEN:
2843             switch (pCryptKey->aiAlgid) {
2844                 case CALG_RC2:
2845                     if (!pbData)
2846                     {
2847                         SetLastError(ERROR_INVALID_PARAMETER);
2848                         return FALSE;
2849                     }
2850                     else if (!*(DWORD *)pbData || *(DWORD *)pbData > 1024)
2851                     {
2852                         SetLastError(NTE_BAD_DATA);
2853                         return FALSE;
2854                     }
2855                     else
2856                     {
2857                         pCryptKey->dwEffectiveKeyLen = *(DWORD *)pbData;
2858                         setup_key(pCryptKey);
2859                     }
2860                     break;
2861                 default:
2862                     SetLastError(NTE_BAD_TYPE);
2863                     return FALSE;
2864             }
2865             return TRUE;
2866
2867         case KP_SCHANNEL_ALG:
2868             switch (((PSCHANNEL_ALG)pbData)->dwUse) {
2869                 case SCHANNEL_ENC_KEY:
2870                     memcpy(&pCryptKey->siSChannelInfo.saEncAlg, pbData, sizeof(SCHANNEL_ALG));
2871                     break;
2872
2873                 case SCHANNEL_MAC_KEY:
2874                     memcpy(&pCryptKey->siSChannelInfo.saMACAlg, pbData, sizeof(SCHANNEL_ALG));
2875                     break;
2876
2877                 default:
2878                     SetLastError(NTE_FAIL); /* FIXME: error code */
2879                     return FALSE;
2880             }
2881             return TRUE;
2882
2883         case KP_CLIENT_RANDOM:
2884             return copy_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom, (PCRYPT_DATA_BLOB)pbData);
2885             
2886         case KP_SERVER_RANDOM:
2887             return copy_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom, (PCRYPT_DATA_BLOB)pbData);
2888
2889         default:
2890             SetLastError(NTE_BAD_TYPE);
2891             return FALSE;
2892     }
2893 }
2894
2895 /******************************************************************************
2896  * CPGetKeyParam (RSAENH.@)
2897  *
2898  * Query a key parameter.
2899  *
2900  * PARAMS
2901  *  hProv      [I]   The key container, which the key belongs to.
2902  *  hHash      [I]   The key object that is to be queried.
2903  *  dwParam    [I]   Specifies the parameter that is to be queried.
2904  *  pbData     [I]   Pointer to the buffer where the parameter value will be stored.
2905  *  pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2906  *  dwFlags    [I]   None currently defined.
2907  *
2908  * RETURNS
2909  *  Success: TRUE
2910  *  Failure: FALSE
2911  *
2912  * NOTES
2913  *  Defined dwParam types are:
2914  *   - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2915  *   - KP_MODE_BITS: Shift width for cipher feedback mode. 
2916  *                   (Currently ignored by MS CSP's - always eight)
2917  *   - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT, 
2918  *                     CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2919  *   - KP_IV: Initialization vector.
2920  *   - KP_KEYLEN: Bitwidth of the key.
2921  *   - KP_BLOCKLEN: Size of a block cipher block.
2922  *   - KP_SALT: Salt value.
2923  */
2924 BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, 
2925                                  DWORD *pdwDataLen, DWORD dwFlags)
2926 {
2927     CRYPTKEY *pCryptKey;
2928     DWORD dwValue;
2929         
2930     TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p dwFlags=%08x)\n",
2931           hProv, hKey, dwParam, pbData, pdwDataLen, dwFlags);
2932
2933     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2934     {
2935         SetLastError(NTE_BAD_UID);
2936         return FALSE;
2937     }
2938
2939     if (dwFlags) {
2940         SetLastError(NTE_BAD_FLAGS);
2941         return FALSE;
2942     }
2943
2944     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2945     {
2946         SetLastError(NTE_BAD_KEY);
2947         return FALSE;
2948     }
2949
2950     switch (dwParam) 
2951     {
2952         case KP_IV:
2953             return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptKey->abInitVector, 
2954                               pCryptKey->dwBlockLen);
2955         
2956         case KP_SALT:
2957             return copy_param(pbData, pdwDataLen, 
2958                     (CONST BYTE*)&pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
2959         
2960         case KP_PADDING:
2961             dwValue = PKCS5_PADDING;
2962             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2963
2964         case KP_KEYLEN:
2965             dwValue = pCryptKey->dwKeyLen << 3;
2966             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2967         
2968         case KP_EFFECTIVE_KEYLEN:
2969             if (pCryptKey->dwEffectiveKeyLen)
2970                 dwValue = pCryptKey->dwEffectiveKeyLen;
2971             else
2972                 dwValue = pCryptKey->dwKeyLen << 3;
2973             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2974
2975         case KP_BLOCKLEN:
2976             dwValue = pCryptKey->dwBlockLen << 3;
2977             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2978     
2979         case KP_MODE:
2980             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwMode, sizeof(DWORD));
2981
2982         case KP_MODE_BITS:
2983             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwModeBits, 
2984                               sizeof(DWORD));
2985     
2986         case KP_PERMISSIONS:
2987             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwPermissions, 
2988                               sizeof(DWORD));
2989
2990         case KP_ALGID:
2991             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->aiAlgid, sizeof(DWORD));
2992             
2993         default:
2994             SetLastError(NTE_BAD_TYPE);
2995             return FALSE;
2996     }
2997 }
2998                         
2999 /******************************************************************************
3000  * CPGetProvParam (RSAENH.@)
3001  *
3002  * Query a CSP parameter.
3003  *
3004  * PARAMS
3005  *  hProv      [I]   The key container that is to be queried.
3006  *  dwParam    [I]   Specifies the parameter that is to be queried.
3007  *  pbData     [I]   Pointer to the buffer where the parameter value will be stored.
3008  *  pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
3009  *  dwFlags    [I]   CRYPT_FIRST: Start enumeration (for PP_ENUMALGS{_EX}).
3010  *
3011  * RETURNS
3012  *  Success: TRUE
3013  *  Failure: FALSE
3014  * NOTES:
3015  *  Defined dwParam types:
3016  *   - PP_CONTAINER: Name of the key container.
3017  *   - PP_NAME: Name of the cryptographic service provider.
3018  *   - PP_SIG_KEYSIZE_INC: RSA signature keywidth granularity in bits.
3019  *   - PP_KEYX_KEYSIZE_INC: RSA key-exchange keywidth granularity in bits.
3020  *   - PP_ENUMALGS{_EX}: Query provider capabilities.
3021  */
3022 BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, 
3023                                   DWORD *pdwDataLen, DWORD dwFlags)
3024 {
3025     KEYCONTAINER *pKeyContainer;
3026     PROV_ENUMALGS provEnumalgs;
3027     DWORD dwTemp;
3028     HKEY hKey;
3029    
3030     /* This is for dwParam PP_CRYPT_COUNT_KEY_USE.
3031      * IE6 SP1 asks for it in the 'About' dialog.
3032      * Returning this BLOB seems to satisfy IE. The marked 0x00 seem 
3033      * to be 'don't care's. If you know anything more specific about
3034      * this provider parameter, please report to wine-devel@winehq.org */
3035     static CONST BYTE abWTF[96] = { 
3036         0xb0, 0x25,     0x63,     0x86, 0x9c, 0xab,     0xb6,     0x37, 
3037         0xe8, 0x82, /**/0x00,/**/ 0x72, 0x06, 0xb2, /**/0x00,/**/ 0x3b, 
3038         0x60, 0x35, /**/0x00,/**/ 0x3b, 0x88, 0xce, /**/0x00,/**/ 0x82, 
3039         0xbc, 0x7a, /**/0x00,/**/ 0xb7, 0x4f, 0x7e, /**/0x00,/**/ 0xde, 
3040         0x92, 0xf1, /**/0x00,/**/ 0x83, 0xea, 0x5e, /**/0x00,/**/ 0xc8, 
3041         0x12, 0x1e,     0xd4,     0x06, 0xf7, 0x66, /**/0x00,/**/ 0x01, 
3042         0x29, 0xa4, /**/0x00,/**/ 0xf8, 0x24, 0x0c, /**/0x00,/**/ 0x33, 
3043         0x06, 0x80, /**/0x00,/**/ 0x02, 0x46, 0x0b, /**/0x00,/**/ 0x6d, 
3044         0x5b, 0xca, /**/0x00,/**/ 0x9a, 0x10, 0xf0, /**/0x00,/**/ 0x05, 
3045         0x19, 0xd0, /**/0x00,/**/ 0x2c, 0xf6, 0x27, /**/0x00,/**/ 0xaa, 
3046         0x7c, 0x6f, /**/0x00,/**/ 0xb9, 0xd8, 0x72, /**/0x00,/**/ 0x03, 
3047         0xf3, 0x81, /**/0x00,/**/ 0xfa, 0xe8, 0x26, /**/0x00,/**/ 0xca 
3048     };
3049
3050     TRACE("(hProv=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
3051            hProv, dwParam, pbData, pdwDataLen, dwFlags);
3052
3053     if (!pdwDataLen) {
3054         SetLastError(ERROR_INVALID_PARAMETER);
3055         return FALSE;
3056     }
3057     
3058     if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3059                        (OBJECTHDR**)&pKeyContainer)) 
3060     {
3061         /* MSDN: hProv not containing valid context handle */
3062         SetLastError(NTE_BAD_UID);
3063         return FALSE;
3064     }
3065
3066     switch (dwParam) 
3067     {
3068         case PP_CONTAINER:
3069         case PP_UNIQUE_CONTAINER:/* MSDN says we can return the same value as PP_CONTAINER */
3070             return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName, 
3071                               strlen(pKeyContainer->szName)+1);
3072
3073         case PP_NAME:
3074             return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName, 
3075                               strlen(pKeyContainer->szProvName)+1);
3076
3077         case PP_PROVTYPE:
3078             dwTemp = PROV_RSA_FULL;
3079             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3080
3081         case PP_KEYSPEC:
3082             dwTemp = AT_SIGNATURE | AT_KEYEXCHANGE;
3083             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3084
3085         case PP_KEYSET_TYPE:
3086             dwTemp = pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET;
3087             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3088
3089         case PP_KEYSTORAGE:
3090             dwTemp = CRYPT_SEC_DESCR;
3091             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3092
3093         case PP_SIG_KEYSIZE_INC:
3094         case PP_KEYX_KEYSIZE_INC:
3095             dwTemp = 8;
3096             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3097
3098         case PP_IMPTYPE:
3099             dwTemp = CRYPT_IMPL_SOFTWARE;
3100             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3101
3102         case PP_VERSION:
3103             dwTemp = 0x00000200;
3104             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3105             
3106         case PP_ENUMCONTAINERS:
3107             if ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) pKeyContainer->dwEnumContainersCtr = 0;
3108
3109             if (!pbData) {
3110                 *pdwDataLen = (DWORD)MAX_PATH + 1;
3111                 return TRUE;
3112             }
3113  
3114             if (!open_container_key("", dwFlags, &hKey))
3115             {
3116                 SetLastError(ERROR_NO_MORE_ITEMS);
3117                 return FALSE;
3118             }
3119
3120             dwTemp = *pdwDataLen;
3121             switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, (LPSTR)pbData, &dwTemp,
3122                     NULL, NULL, NULL, NULL))
3123             {
3124                 case ERROR_MORE_DATA:
3125                     *pdwDataLen = (DWORD)MAX_PATH + 1;
3126  
3127                 case ERROR_SUCCESS:
3128                     pKeyContainer->dwEnumContainersCtr++;
3129                     RegCloseKey(hKey);
3130                     return TRUE;
3131
3132                 case ERROR_NO_MORE_ITEMS:
3133                 default:
3134                     SetLastError(ERROR_NO_MORE_ITEMS);
3135                     RegCloseKey(hKey);
3136                     return FALSE;
3137             }
3138  
3139         case PP_ENUMALGS:
3140         case PP_ENUMALGS_EX:
3141             if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) ||
3142                  (!aProvEnumAlgsEx[pKeyContainer->dwPersonality]
3143                    [pKeyContainer->dwEnumAlgsCtr+1].aiAlgid)) && 
3144                 ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST))
3145             {
3146                 SetLastError(ERROR_NO_MORE_ITEMS);
3147                 return FALSE;
3148             }
3149
3150             if (dwParam == PP_ENUMALGS) {    
3151                 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS))) 
3152                     pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ? 
3153                         0 : pKeyContainer->dwEnumAlgsCtr+1;
3154             
3155                 provEnumalgs.aiAlgid = aProvEnumAlgsEx
3156                     [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].aiAlgid;
3157                 provEnumalgs.dwBitLen = aProvEnumAlgsEx
3158                     [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwDefaultLen;
3159                 provEnumalgs.dwNameLen = aProvEnumAlgsEx
3160                     [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwNameLen;
3161                 memcpy(provEnumalgs.szName, aProvEnumAlgsEx
3162                        [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].szName, 
3163                        20*sizeof(CHAR));
3164             
3165                 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&provEnumalgs, 
3166                                   sizeof(PROV_ENUMALGS));
3167             } else {
3168                 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS_EX))) 
3169                     pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ? 
3170                         0 : pKeyContainer->dwEnumAlgsCtr+1;
3171             
3172                 return copy_param(pbData, pdwDataLen, 
3173                                   (CONST BYTE*)&aProvEnumAlgsEx
3174                                       [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr], 
3175                                   sizeof(PROV_ENUMALGS_EX));
3176             }
3177
3178         case PP_CRYPT_COUNT_KEY_USE: /* Asked for by IE About dialog */
3179             return copy_param(pbData, pdwDataLen, abWTF, sizeof(abWTF));
3180
3181         default:
3182             /* MSDN: Unknown parameter number in dwParam */
3183             SetLastError(NTE_BAD_TYPE);
3184             return FALSE;
3185     }
3186 }
3187
3188 /******************************************************************************
3189  * CPDeriveKey (RSAENH.@)
3190  *
3191  * Derives a key from a hash value.
3192  *
3193  * PARAMS
3194  *  hProv     [I] Key container for which a key is to be generated.
3195  *  Algid     [I] Crypto algorithm identifier for the key to be generated.
3196  *  hBaseData [I] Hash from whose value the key will be derived.
3197  *  dwFlags   [I] See Notes.
3198  *  phKey     [O] The generated key.
3199  *
3200  * RETURNS
3201  *  Success: TRUE
3202  *  Failure: FALSE
3203  *
3204  * NOTES
3205  *  Defined flags:
3206  *   - CRYPT_EXPORTABLE: Key can be exported.
3207  *   - CRYPT_NO_SALT: No salt is used for 40 bit keys.
3208  *   - CRYPT_CREATE_SALT: Use remaining bits as salt value.
3209  */
3210 BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, 
3211                                DWORD dwFlags, HCRYPTKEY *phKey)
3212 {
3213     CRYPTKEY *pCryptKey, *pMasterKey;
3214     CRYPTHASH *pCryptHash;
3215     BYTE abHashValue[RSAENH_MAX_HASH_SIZE*2];
3216     DWORD dwLen;
3217     
3218     TRACE("(hProv=%08lx, Algid=%d, hBaseData=%08lx, dwFlags=%08x phKey=%p)\n", hProv, Algid,
3219            hBaseData, dwFlags, phKey);
3220     
3221     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3222     {
3223         SetLastError(NTE_BAD_UID);
3224         return FALSE;
3225     }
3226
3227     if (!lookup_handle(&handle_table, hBaseData, RSAENH_MAGIC_HASH,
3228                        (OBJECTHDR**)&pCryptHash))
3229     {
3230         SetLastError(NTE_BAD_HASH);
3231         return FALSE;
3232     }
3233
3234     if (!phKey)
3235     {
3236         SetLastError(ERROR_INVALID_PARAMETER);
3237         return FALSE;
3238     }
3239
3240     switch (GET_ALG_CLASS(Algid))
3241     {
3242         case ALG_CLASS_DATA_ENCRYPT:
3243             *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
3244             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3245
3246             /* 
3247              * We derive the key material from the hash.
3248              * If the hash value is not large enough for the claimed key, we have to construct
3249              * a larger binary value based on the hash. This is documented in MSDN: CryptDeriveKey.
3250              */
3251             dwLen = RSAENH_MAX_HASH_SIZE;
3252             RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0);
3253     
3254             if (dwLen < pCryptKey->dwKeyLen) {
3255                 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
3256                 BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
3257                 DWORD i;
3258
3259                 memcpy(old_hashval, pCryptHash->abHashValue, RSAENH_MAX_HASH_SIZE);
3260             
3261                 for (i=0; i<RSAENH_HMAC_DEF_PAD_LEN; i++) {
3262                     pad1[i] = RSAENH_HMAC_DEF_IPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3263                     pad2[i] = RSAENH_HMAC_DEF_OPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3264                 }
3265                 
3266                 init_hash(pCryptHash);
3267                 update_hash(pCryptHash, pad1, RSAENH_HMAC_DEF_PAD_LEN);
3268                 finalize_hash(pCryptHash);
3269                 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
3270
3271                 init_hash(pCryptHash);
3272                 update_hash(pCryptHash, pad2, RSAENH_HMAC_DEF_PAD_LEN);
3273                 finalize_hash(pCryptHash);
3274                 memcpy(abHashValue+pCryptHash->dwHashSize, pCryptHash->abHashValue, 
3275                        pCryptHash->dwHashSize);
3276
3277                 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE);
3278             }
3279     
3280             memcpy(pCryptKey->abKeyValue, abHashValue, 
3281                    RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
3282             break;
3283
3284         case ALG_CLASS_MSG_ENCRYPT:
3285             if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3286                                (OBJECTHDR**)&pMasterKey)) 
3287             {
3288                 SetLastError(NTE_FAIL); /* FIXME error code */
3289                 return FALSE;
3290             }
3291                 
3292             switch (Algid) 
3293             {
3294                 /* See RFC 2246, chapter 6.3 Key calculation */
3295                 case CALG_SCHANNEL_ENC_KEY:
3296                     *phKey = new_key(hProv, pMasterKey->siSChannelInfo.saEncAlg.Algid, 
3297                                      MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saEncAlg.cBits),
3298                                      &pCryptKey);
3299                     if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3300                     memcpy(pCryptKey->abKeyValue, 
3301                            pCryptHash->abHashValue + (
3302                                2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3303                                ((dwFlags & CRYPT_SERVER) ? 
3304                                    (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) : 0)),
3305                            pMasterKey->siSChannelInfo.saEncAlg.cBits / 8);
3306                     memcpy(pCryptKey->abInitVector,
3307                            pCryptHash->abHashValue + (
3308                                2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3309                                2 * (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) +
3310                                ((dwFlags & CRYPT_SERVER) ? pCryptKey->dwBlockLen : 0)),
3311                            pCryptKey->dwBlockLen);
3312                     break;
3313                     
3314                 case CALG_SCHANNEL_MAC_KEY:
3315                     *phKey = new_key(hProv, Algid, 
3316                                      MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saMACAlg.cBits),
3317                                      &pCryptKey);
3318                     if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3319                     memcpy(pCryptKey->abKeyValue,
3320                            pCryptHash->abHashValue + ((dwFlags & CRYPT_SERVER) ? 
3321                                pMasterKey->siSChannelInfo.saMACAlg.cBits / 8 : 0),
3322                            pMasterKey->siSChannelInfo.saMACAlg.cBits / 8);
3323                     break;
3324                     
3325                 default:
3326                     SetLastError(NTE_BAD_ALGID);
3327                     return FALSE;
3328             }
3329             break;
3330
3331         default:
3332             SetLastError(NTE_BAD_ALGID);
3333             return FALSE;
3334     }
3335
3336     setup_key(pCryptKey);
3337     return TRUE;    
3338 }
3339
3340 /******************************************************************************
3341  * CPGetUserKey (RSAENH.@)
3342  *
3343  * Returns a handle to the user's private key-exchange- or signature-key.
3344  *
3345  * PARAMS
3346  *  hProv     [I] The key container from which a user key is requested.
3347  *  dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
3348  *  phUserKey [O] Handle to the requested key or INVALID_HANDLE_VALUE in case of failure.
3349  *
3350  * RETURNS
3351  *  Success: TRUE.
3352  *  Failure: FALSE.
3353  *
3354  * NOTE
3355  *  A newly created key container does not contain private user key. Create them with CPGenKey.
3356  */
3357 BOOL WINAPI RSAENH_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
3358 {
3359     KEYCONTAINER *pKeyContainer;
3360
3361     TRACE("(hProv=%08lx, dwKeySpec=%08x, phUserKey=%p)\n", hProv, dwKeySpec, phUserKey);
3362     
3363     if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3364                        (OBJECTHDR**)&pKeyContainer)) 
3365     {
3366         /* MSDN: hProv not containing valid context handle */
3367         SetLastError(NTE_BAD_UID);
3368         return FALSE;
3369     }
3370
3371     switch (dwKeySpec)
3372     {
3373         case AT_KEYEXCHANGE:
3374             copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY, 
3375                         phUserKey);
3376             break;
3377
3378         case AT_SIGNATURE:
3379             copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY, 
3380                         phUserKey);
3381             break;
3382
3383         default:
3384             *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
3385     }
3386
3387     if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
3388     {
3389         /* MSDN: dwKeySpec parameter specifies nonexistent key */
3390         SetLastError(NTE_NO_KEY);
3391         return FALSE;
3392     }
3393
3394     return TRUE;
3395 }
3396
3397 /******************************************************************************
3398  * CPHashData (RSAENH.@)
3399  *
3400  * Updates a hash object with the given data.
3401  *
3402  * PARAMS
3403  *  hProv     [I] Key container to which the hash object belongs.
3404  *  hHash     [I] Hash object which is to be updated.
3405  *  pbData    [I] Pointer to data with which the hash object is to be updated.
3406  *  dwDataLen [I] Length of the data.
3407  *  dwFlags   [I] Currently none defined.
3408  *
3409  * RETURNS
3410  *  Success: TRUE.
3411  *  Failure: FALSE.
3412  *
3413  * NOTES
3414  *  The actual hash value is queried with CPGetHashParam, which will finalize 
3415  *  the hash. Updating a finalized hash will fail with a last error NTE_BAD_HASH_STATE.
3416  */
3417 BOOL WINAPI RSAENH_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData, 
3418                               DWORD dwDataLen, DWORD dwFlags)
3419 {
3420     CRYPTHASH *pCryptHash;
3421         
3422     TRACE("(hProv=%08lx, hHash=%08lx, pbData=%p, dwDataLen=%d, dwFlags=%08x)\n",
3423           hProv, hHash, pbData, dwDataLen, dwFlags);
3424
3425     if (dwFlags)
3426     {
3427         SetLastError(NTE_BAD_FLAGS);
3428         return FALSE;
3429     }
3430
3431     if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3432                        (OBJECTHDR**)&pCryptHash))
3433     {
3434         SetLastError(NTE_BAD_HASH);
3435         return FALSE;
3436     }
3437
3438     if (!get_algid_info(hProv, pCryptHash->aiAlgid) || pCryptHash->aiAlgid == CALG_SSL3_SHAMD5)
3439     {
3440         SetLastError(NTE_BAD_ALGID);
3441         return FALSE;
3442     }
3443     
3444     if (pCryptHash->dwState != RSAENH_HASHSTATE_HASHING)
3445     {
3446         SetLastError(NTE_BAD_HASH_STATE);
3447         return FALSE;
3448     }
3449
3450     update_hash(pCryptHash, pbData, dwDataLen);
3451     return TRUE;
3452 }
3453
3454 /******************************************************************************
3455  * CPHashSessionKey (RSAENH.@)
3456  *
3457  * Updates a hash object with the binary representation of a symmetric key.
3458  *
3459  * PARAMS
3460  *  hProv     [I] Key container to which the hash object belongs.
3461  *  hHash     [I] Hash object which is to be updated.
3462  *  hKey      [I] The symmetric key, whose binary value will be added to the hash.
3463  *  dwFlags   [I] CRYPT_LITTLE_ENDIAN, if the binary key value shall be interpreted as little endian.
3464  *
3465  * RETURNS
3466  *  Success: TRUE.
3467  *  Failure: FALSE.
3468  */
3469 BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, 
3470                                     DWORD dwFlags)
3471 {
3472     BYTE abKeyValue[RSAENH_MAX_KEY_SIZE], bTemp;
3473     CRYPTKEY *pKey;
3474     DWORD i;
3475
3476     TRACE("(hProv=%08lx, hHash=%08lx, hKey=%08lx, dwFlags=%08x)\n", hProv, hHash, hKey, dwFlags);
3477
3478     if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pKey) ||
3479         (GET_ALG_CLASS(pKey->aiAlgid) != ALG_CLASS_DATA_ENCRYPT)) 
3480     {
3481         SetLastError(NTE_BAD_KEY);
3482         return FALSE;
3483     }
3484
3485     if (dwFlags & ~CRYPT_LITTLE_ENDIAN) {
3486         SetLastError(NTE_BAD_FLAGS);
3487         return FALSE;
3488     }
3489
3490     memcpy(abKeyValue, pKey->abKeyValue, pKey->dwKeyLen);
3491     if (!(dwFlags & CRYPT_LITTLE_ENDIAN)) {
3492         for (i=0; i<pKey->dwKeyLen/2; i++) {
3493             bTemp = abKeyValue[i];
3494             abKeyValue[i] = abKeyValue[pKey->dwKeyLen-i-1];
3495             abKeyValue[pKey->dwKeyLen-i-1] = bTemp;
3496         }
3497     }
3498
3499     return RSAENH_CPHashData(hProv, hHash, abKeyValue, pKey->dwKeyLen, 0);
3500 }
3501
3502 /******************************************************************************
3503  * CPReleaseContext (RSAENH.@)
3504  *
3505  * Release a key container.
3506  *
3507  * PARAMS
3508  *  hProv   [I] Key container to be released.
3509  *  dwFlags [I] Currently none defined.
3510  *
3511  * RETURNS
3512  *  Success: TRUE
3513  *  Failure: FALSE
3514  */
3515 BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
3516 {
3517     TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags);
3518
3519     if (!release_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3520     {
3521         /* MSDN: hProv not containing valid context handle */
3522         SetLastError(NTE_BAD_UID);
3523         return FALSE;
3524     }
3525
3526     if (dwFlags) {
3527         SetLastError(NTE_BAD_FLAGS);
3528         return FALSE;
3529     }
3530     
3531     return TRUE;
3532 }
3533
3534 /******************************************************************************
3535  * CPSetHashParam (RSAENH.@)
3536  * 
3537  * Set a parameter of a hash object
3538  *
3539  * PARAMS
3540  *  hProv   [I] The key container to which the key belongs.
3541  *  hHash   [I] The hash object for which a parameter is to be set.
3542  *  dwParam [I] Parameter type. See Notes.
3543  *  pbData  [I] Pointer to the parameter value.
3544  *  dwFlags [I] Currently none defined.
3545  *
3546  * RETURNS
3547  *  Success: TRUE.
3548  *  Failure: FALSE.
3549  *
3550  * NOTES
3551  *  Currently only the HP_HMAC_INFO dwParam type is defined. 
3552  *  The HMAC_INFO struct will be deep copied into the hash object.
3553  *  See Internet RFC 2104 for details on the HMAC algorithm.
3554  */
3555 BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, 
3556                                   BYTE *pbData, DWORD dwFlags)
3557 {
3558     CRYPTHASH *pCryptHash;
3559     CRYPTKEY *pCryptKey;
3560     DWORD i;
3561
3562     TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n",
3563            hProv, hHash, dwParam, pbData, dwFlags);
3564
3565     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3566     {
3567         SetLastError(NTE_BAD_UID);
3568         return FALSE;
3569     }
3570
3571     if (dwFlags) {
3572         SetLastError(NTE_BAD_FLAGS);
3573         return FALSE;
3574     }
3575     
3576     if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3577                        (OBJECTHDR**)&pCryptHash))
3578     {
3579         SetLastError(NTE_BAD_HASH);
3580         return FALSE;
3581     }
3582     
3583     switch (dwParam) {
3584         case HP_HMAC_INFO:
3585             free_hmac_info(pCryptHash->pHMACInfo);
3586             if (!copy_hmac_info(&pCryptHash->pHMACInfo, (PHMAC_INFO)pbData)) return FALSE;
3587
3588             if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY, 
3589                                (OBJECTHDR**)&pCryptKey)) 
3590             {
3591                 SetLastError(NTE_FAIL); /* FIXME: correct error code? */
3592                 return FALSE;
3593             }
3594
3595             for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) {
3596                 pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i];
3597             }
3598             for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbOuterString); i++) {
3599                 pCryptHash->pHMACInfo->pbOuterString[i] ^= pCryptKey->abKeyValue[i];
3600             }
3601             
3602             init_hash(pCryptHash);
3603             return TRUE;
3604
3605         case HP_HASHVAL:
3606             memcpy(pCryptHash->abHashValue, pbData, pCryptHash->dwHashSize);
3607             pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
3608             return TRUE;
3609            
3610         case HP_TLS1PRF_SEED:
3611             return copy_data_blob(&pCryptHash->tpPRFParams.blobSeed, (PCRYPT_DATA_BLOB)pbData);
3612
3613         case HP_TLS1PRF_LABEL:
3614             return copy_data_blob(&pCryptHash->tpPRFParams.blobLabel, (PCRYPT_DATA_BLOB)pbData);
3615             
3616         default:
3617             SetLastError(NTE_BAD_TYPE);
3618             return FALSE;
3619     }
3620 }
3621
3622 /******************************************************************************
3623  * CPSetProvParam (RSAENH.@)
3624  */
3625 BOOL WINAPI RSAENH_CPSetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
3626 {
3627     FIXME("(stub)\n");
3628     return FALSE;
3629 }
3630
3631 /******************************************************************************
3632  * CPSignHash (RSAENH.@)
3633  *
3634  * Sign a hash object
3635  *
3636  * PARAMS
3637  *  hProv        [I]   The key container, to which the hash object belongs.
3638  *  hHash        [I]   The hash object to be signed.
3639  *  dwKeySpec    [I]   AT_SIGNATURE or AT_KEYEXCHANGE: Key used to generate the signature.
3640  *  sDescription [I]   Should be NULL for security reasons. 
3641  *  dwFlags      [I]   0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3642  *  pbSignature  [O]   Buffer, to which the signature will be stored. May be NULL to query SigLen.
3643  *  pdwSigLen    [I/O] Size of the buffer (in), Length of the signature (out)
3644  *
3645  * RETURNS
3646  *  Success: TRUE
3647  *  Failure: FALSE
3648  */
3649 BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec, 
3650                               LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature, 
3651                               DWORD *pdwSigLen)
3652 {
3653     HCRYPTKEY hCryptKey;
3654     CRYPTKEY *pCryptKey;
3655     DWORD dwHashLen;
3656     BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3657     ALG_ID aiAlgid;
3658
3659     TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08x, sDescription=%s, dwFlags=%08x, "
3660         "pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription),
3661         dwFlags, pbSignature, pdwSigLen);
3662
3663     if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3664         SetLastError(NTE_BAD_FLAGS);
3665         return FALSE;
3666     }
3667     
3668     if (!RSAENH_CPGetUserKey(hProv, dwKeySpec, &hCryptKey)) return FALSE;
3669             
3670     if (!lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
3671                        (OBJECTHDR**)&pCryptKey))
3672     {
3673         SetLastError(NTE_NO_KEY);
3674         return FALSE;
3675     }
3676
3677     if (!pbSignature) {
3678         *pdwSigLen = pCryptKey->dwKeyLen;
3679         return TRUE;
3680     }
3681     if (pCryptKey->dwKeyLen > *pdwSigLen)
3682     {
3683         SetLastError(ERROR_MORE_DATA);
3684         *pdwSigLen = pCryptKey->dwKeyLen;
3685         return FALSE;
3686     }
3687     *pdwSigLen = pCryptKey->dwKeyLen;
3688
3689     if (sDescription) {
3690         if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription, 
3691                                 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3692         {
3693             return FALSE;
3694         }
3695     }
3696     
3697     dwHashLen = sizeof(DWORD);
3698     if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3699     
3700     dwHashLen = RSAENH_MAX_HASH_SIZE;
3701     if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3702  
3703
3704     if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3705         return FALSE;
3706     }
3707
3708     return encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
3709 }
3710
3711 /******************************************************************************
3712  * CPVerifySignature (RSAENH.@)
3713  *
3714  * Verify the signature of a hash object.
3715  * 
3716  * PARAMS
3717  *  hProv        [I] The key container, to which the hash belongs.
3718  *  hHash        [I] The hash for which the signature is verified.
3719  *  pbSignature  [I] The binary signature.
3720  *  dwSigLen     [I] Length of the signature BLOB.
3721  *  hPubKey      [I] Public key used to verify the signature.
3722  *  sDescription [I] Should be NULL for security reasons.
3723  *  dwFlags      [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3724  *
3725  * RETURNS
3726  *  Success: TRUE  (Signature is valid)
3727  *  Failure: FALSE (GetLastError() == NTE_BAD_SIGNATURE, if signature is invalid)
3728  */
3729 BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature, 
3730                                      DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, 
3731                                      DWORD dwFlags)
3732 {
3733     BYTE *pbConstructed = NULL, *pbDecrypted = NULL;
3734     CRYPTKEY *pCryptKey;
3735     DWORD dwHashLen;
3736     ALG_ID aiAlgid;
3737     BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3738     BOOL res = FALSE;
3739
3740     TRACE("(hProv=%08lx, hHash=%08lx, pbSignature=%p, dwSigLen=%d, hPubKey=%08lx, sDescription=%s, "
3741           "dwFlags=%08x)\n", hProv, hHash, pbSignature, dwSigLen, hPubKey, debugstr_w(sDescription),
3742           dwFlags);
3743         
3744     if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3745         SetLastError(NTE_BAD_FLAGS);
3746         return FALSE;
3747     }
3748     
3749     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3750     {
3751         SetLastError(NTE_BAD_UID);
3752         return FALSE;
3753     }
3754  
3755     if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY,
3756                        (OBJECTHDR**)&pCryptKey))
3757     {
3758         SetLastError(NTE_BAD_KEY);
3759         return FALSE;
3760     }
3761
3762     /* in Microsoft implementation, the signature length is checked before
3763      * the signature pointer.
3764      */
3765     if (dwSigLen != pCryptKey->dwKeyLen)
3766     {
3767         SetLastError(NTE_BAD_SIGNATURE);
3768         return FALSE;
3769     }
3770
3771     if (!hHash || !pbSignature)
3772     {
3773         SetLastError(ERROR_INVALID_PARAMETER);
3774         return FALSE;
3775     }
3776
3777     if (sDescription) {
3778         if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription, 
3779                                 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3780         {
3781             return FALSE;
3782         }
3783     }
3784     
3785     dwHashLen = sizeof(DWORD);
3786     if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3787     
3788     dwHashLen = RSAENH_MAX_HASH_SIZE;
3789     if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3790
3791     pbConstructed = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3792     if (!pbConstructed) {
3793         SetLastError(NTE_NO_MEMORY);
3794         goto cleanup;
3795     }
3796
3797     pbDecrypted = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3798     if (!pbDecrypted) {
3799         SetLastError(NTE_NO_MEMORY);
3800         goto cleanup;
3801     }
3802
3803     if (!encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbSignature, pbDecrypted, 
3804                             RSAENH_DECRYPT)) 
3805     {
3806         goto cleanup;
3807     }
3808
3809     if (!build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3810         goto cleanup;
3811     }
3812
3813     if (memcmp(pbDecrypted, pbConstructed, dwSigLen)) {
3814         SetLastError(NTE_BAD_SIGNATURE);
3815         goto cleanup;
3816     }
3817     
3818     res = TRUE;
3819 cleanup:
3820     HeapFree(GetProcessHeap(), 0, pbConstructed);
3821     HeapFree(GetProcessHeap(), 0, pbDecrypted);
3822     return res;
3823 }
3824
3825 static const WCHAR szProviderKeys[6][116] = {
3826     {   'S','o','f','t','w','a','r','e','\\',
3827         'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3828         'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3829         'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','B','a','s',
3830         'e',' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3831         'o','v','i','d','e','r',' ','v','1','.','0',0 },
3832     {   'S','o','f','t','w','a','r','e','\\',
3833         'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3834         'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3835         'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3836         'E','n','h','a','n','c','e','d',
3837         ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3838         'o','v','i','d','e','r',' ','v','1','.','0',0 },
3839     {   'S','o','f','t','w','a','r','e','\\',
3840         'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3841         'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3842         'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','S','t','r','o','n','g',
3843         ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3844         'o','v','i','d','e','r',0 },
3845     {   'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3846         'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3847         'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3848         'R','S','A',' ','S','C','h','a','n','n','e','l',' ',
3849         'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
3850     {   'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3851         'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3852         'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3853         'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
3854         'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
3855     {   'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3856         'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3857         'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3858         'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
3859         'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',
3860         ' ','(','P','r','o','t','o','t','y','p','e',')',0 }
3861 };
3862 static const WCHAR szDefaultKeys[3][65] = {
3863     {   'S','o','f','t','w','a','r','e','\\',
3864         'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3865         'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3866         'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','0','1',0 },
3867     {   'S','o','f','t','w','a','r','e','\\',
3868         'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3869         'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3870         'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','1','2',0 },
3871     {   'S','o','f','t','w','a','r','e','\\',
3872         'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3873         'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3874         'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','2','4',0 }
3875 };
3876
3877
3878 /******************************************************************************
3879  * DllRegisterServer (RSAENH.@)
3880  *
3881  * Dll self registration. 
3882  *
3883  * PARAMS
3884  *
3885  * RETURNS
3886  *  Success: S_OK.
3887  *    Failure: != S_OK
3888  * 
3889  * NOTES
3890  *  Registers the following keys:
3891  *   - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3892  *       Microsoft Base Cryptographic Provider v1.0
3893  *   - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3894  *       Microsoft Enhanced Cryptographic Provider
3895  *   - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3896  *       Microsoft Strong Cryptographpic Provider
3897  *   - HKLM\Software\Microsoft\Cryptography\Defaults\Provider Types\Type 001
3898  */
3899 HRESULT WINAPI DllRegisterServer(void)
3900 {
3901     HKEY key;
3902     DWORD dp;
3903     long apiRet;
3904     int i;
3905
3906     for (i=0; i<6; i++) {
3907         apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szProviderKeys[i], 0, NULL,
3908             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3909
3910         if (apiRet == ERROR_SUCCESS)
3911         {
3912             if (dp == REG_CREATED_NEW_KEY)
3913             {
3914                 static const WCHAR szImagePath[] = { 'I','m','a','g','e',' ','P','a','t','h',0 };
3915                 static const WCHAR szRSABase[] = { 'r','s','a','e','n','h','.','d','l','l',0 };
3916                 static const WCHAR szType[] = { 'T','y','p','e',0 };
3917                 static const WCHAR szSignature[] = { 'S','i','g','n','a','t','u','r','e',0 };
3918                 DWORD type, sign;
3919
3920                 switch(i)
3921                 {
3922                     case 3:
3923                         type=PROV_RSA_SCHANNEL;
3924                         break;
3925                     case 4:
3926                     case 5:
3927                         type=PROV_RSA_AES;
3928                         break;
3929                     default:
3930                         type=PROV_RSA_FULL;
3931                         break;
3932                 }
3933                 sign = 0xdeadbeef;
3934                 RegSetValueExW(key, szImagePath, 0, REG_SZ, (const BYTE *)szRSABase,
3935                                (lstrlenW(szRSABase) + 1) * sizeof(WCHAR));
3936                 RegSetValueExW(key, szType, 0, REG_DWORD, (LPBYTE)&type, sizeof(type));
3937                 RegSetValueExW(key, szSignature, 0, REG_BINARY, (LPBYTE)&sign, sizeof(sign));
3938             }
3939             RegCloseKey(key);
3940         }
3941     }
3942     
3943     for (i=0; i<3; i++) {
3944         apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szDefaultKeys[i], 0, NULL,
3945                                  REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3946         if (apiRet == ERROR_SUCCESS)
3947         {
3948             if (dp == REG_CREATED_NEW_KEY)
3949             {
3950                 static const WCHAR szName[] = { 'N','a','m','e',0 };
3951                 static const WCHAR szRSAName[3][54] = {
3952                   { 'M','i','c','r','o','s','o','f','t',' ', 'B','a','s','e',' ',
3953                     'C','r','y','p','t','o','g','r','a','p','h','i','c',' ', 
3954                     'P','r','o','v','i','d','e','r',' ','v','1','.','0',0 },
3955                   { 'M','i','c','r','o','s','o','f','t',' ','R','S','A',' ',
3956                     'S','C','h','a','n','n','e','l',' ',
3957                     'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3958                     'P','r','o','v','i','d','e','r',0 },
3959                   { 'M','i','c','r','o','s','o','f','t',' ','E','n','h','a','n','c','e','d',' ',
3960                     'R','S','A',' ','a','n','d',' ','A','E','S',' ',
3961                     'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3962                     'P','r','o','v','i','d','e','r',0 } };
3963                 static const WCHAR szTypeName[] = { 'T','y','p','e','N','a','m','e',0 };
3964                 static const WCHAR szRSATypeName[3][38] = {
3965                   { 'R','S','A',' ','F','u','l','l',' ',
3966                        '(','S','i','g','n','a','t','u','r','e',' ','a','n','d',' ',
3967                     'K','e','y',' ','E','x','c','h','a','n','g','e',')',0 },
3968                   { 'R','S','A',' ','S','C','h','a','n','n','e','l',0 },
3969                   { 'R','S','A',' ','F','u','l','l',' ','a','n','d',' ','A','E','S',0 } };
3970
3971                 RegSetValueExW(key, szName, 0, REG_SZ,
3972                                 (const BYTE *)szRSAName[i], lstrlenW(szRSAName[i])*sizeof(WCHAR)+sizeof(WCHAR));
3973                 RegSetValueExW(key, szTypeName, 0, REG_SZ, 
3974                                 (const BYTE *)szRSATypeName[i], lstrlenW(szRSATypeName[i])*sizeof(WCHAR)+sizeof(WCHAR));
3975             }
3976         }
3977         RegCloseKey(key);
3978     }
3979     
3980     return HRESULT_FROM_WIN32(apiRet);
3981 }
3982
3983 /******************************************************************************
3984  * DllUnregisterServer (RSAENH.@)
3985  *
3986  * Dll self unregistration. 
3987  *
3988  * PARAMS
3989  *
3990  * RETURNS
3991  *  Success: S_OK
3992  *
3993  * NOTES
3994  *  For the relevant keys see DllRegisterServer.
3995  */
3996 HRESULT WINAPI DllUnregisterServer(void)
3997 {
3998     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[0]);
3999     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[1]);
4000     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[2]);
4001     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[3]);
4002     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[4]);
4003     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[5]);
4004     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[0]);
4005     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[1]);
4006     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[2]);
4007     return S_OK;
4008 }