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