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