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