~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/rsaenh/rsaenh.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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