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