dmloader: complete rewrite and full implementation.
[wine] / dlls / advapi32 / crypt.c
1 /*
2  * Copyright 1999 Ian Schmidt
3  * Copyright 2001 Travis Michielsen
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 /***********************************************************************
21  *
22  *  TODO:
23  *  - Reference counting
24  *  - Thread-safing
25  *  - Signature checking
26  */
27
28 #include <time.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "wine/unicode.h"
33 #include "crypt.h"
34 #include "winnls.h"
35 #include "wincrypt.h"
36 #include "windef.h"
37 #include "winerror.h"
38 #include "winreg.h"
39 #include "winbase.h"
40 #include "winuser.h"
41 #include "wine/debug.h"
42 #include "winternl.h"
43 #include "ntstatus.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
46
47 HWND crypt_hWindow = 0;
48
49 #define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
50
51 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
52 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
53
54 static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
55 {
56         PCSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
57         PSTR keyname;
58
59         keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
60         if (keyname)
61         {
62                 strcpy(keyname, KEYSTR);
63                 strcpy(keyname + strlen(KEYSTR), pProvName);
64         } else
65                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
66         return keyname;
67 }
68
69 static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
70 {
71         PCSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
72         PCSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
73         PSTR keyname;
74         PSTR ptr;
75
76         keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
77         if (keyname)
78         {
79                 user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
80                 ptr = keyname + strlen(keyname);
81                 *(--ptr) = (dwType % 10) + '0';
82                 *(--ptr) = (dwType / 10) + '0';
83                 *(--ptr) = (dwType / 100) + '0';
84         } else
85                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
86         return keyname;
87 }
88
89 /* CRYPT_UnicodeTOANSI
90  * wstr - unicode string
91  * str - pointer to ANSI string
92  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
93  *
94  * returns TRUE if unsuccessfull, FALSE otherwise.
95  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
96  */
97 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
98 {
99         int count;
100
101         if (!wstr)
102         {
103                 *str = NULL;
104                 return TRUE;
105         }
106         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
107         count = count < strsize ? count : strsize;
108         if (strsize == -1)
109                 *str = CRYPT_Alloc(count * sizeof(CHAR));
110         if (*str)
111         {
112                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
113                 return TRUE;
114         }
115         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
116         return FALSE;
117 }
118
119 /* CRYPT_ANSITOUnicode
120  * str - ANSI string
121  * wstr - pointer to unicode string
122  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
123  */
124 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
125 {
126         int wcount;
127
128         if (!str)
129         {
130                 *wstr = NULL;
131                 return TRUE;
132         }
133         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
134         wcount = wcount < wstrsize/sizeof(WCHAR) ? wcount : wstrsize/sizeof(WCHAR);
135         if (wstrsize == -1)
136                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
137         if (*wstr)
138         {
139                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
140                 return TRUE;
141         }
142         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
143         return FALSE;
144 }
145
146 /* These next 2 functions are used by the VTableProvStruc structure */
147 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
148 {
149         if (!lpszImage || !pData)
150         {
151                 SetLastError(ERROR_INVALID_PARAMETER);
152                 return FALSE;
153         }
154
155         FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
156
157         return TRUE;
158 }
159
160 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
161 {
162         if (!phWnd)
163                 return FALSE;
164         *phWnd = crypt_hWindow;
165         return TRUE;
166 }
167
168 #define CRYPT_GetProvFunc(name) \
169         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
170 #define CRYPT_GetProvFuncOpt(name) \
171         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
172 PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
173 {
174         PCRYPTPROV provider;
175         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
176
177         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
178         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
179         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
180         if ( !(provider->hModule = LoadLibraryA(pImage)) )
181         {
182                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
183                 FIXME("Failed to load dll %s\n", debugstr_a(pImage));
184                 goto error;
185         }
186
187         errorcode = NTE_PROVIDER_DLL_FAIL;
188         CRYPT_GetProvFunc(CPAcquireContext);
189         CRYPT_GetProvFunc(CPCreateHash);
190         CRYPT_GetProvFunc(CPDecrypt);
191         CRYPT_GetProvFunc(CPDeriveKey);
192         CRYPT_GetProvFunc(CPDestroyHash);
193         CRYPT_GetProvFunc(CPDestroyKey);
194         CRYPT_GetProvFuncOpt(CPDuplicateHash);
195         CRYPT_GetProvFuncOpt(CPDuplicateKey);
196         CRYPT_GetProvFunc(CPEncrypt);
197         CRYPT_GetProvFunc(CPExportKey);
198         CRYPT_GetProvFunc(CPGenKey);
199         CRYPT_GetProvFunc(CPGenRandom);
200         CRYPT_GetProvFunc(CPGetHashParam);
201         CRYPT_GetProvFunc(CPGetKeyParam);
202         CRYPT_GetProvFunc(CPGetProvParam);
203         CRYPT_GetProvFunc(CPGetUserKey);
204         CRYPT_GetProvFunc(CPHashData);
205         CRYPT_GetProvFunc(CPHashSessionKey);
206         CRYPT_GetProvFunc(CPImportKey);
207         CRYPT_GetProvFunc(CPReleaseContext);
208         CRYPT_GetProvFunc(CPSetHashParam);
209         CRYPT_GetProvFunc(CPSetKeyParam);
210         CRYPT_GetProvFunc(CPSetProvParam);
211         CRYPT_GetProvFunc(CPSignHash);
212         CRYPT_GetProvFunc(CPVerifySignature);
213
214         /* FIXME: Not sure what the pbContextInfo field is for.
215          *        Does it need memory allocation?
216          */
217         provider->pVTable->Version = 3;
218         provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
219         provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
220         provider->pVTable->dwProvType = 0;
221         provider->pVTable->pbContextInfo = NULL;
222         provider->pVTable->cbContextInfo = 0;
223         provider->pVTable->pszProvName = NULL;
224         return provider;
225
226 error:
227         SetLastError(errorcode);
228         if (provider)
229         {
230                 if (provider->hModule)
231                         FreeLibrary(provider->hModule);
232                 CRYPT_Free(provider->pVTable);
233                 CRYPT_Free(provider->pFuncs);
234                 CRYPT_Free(provider);
235         }
236         return NULL;
237 }
238 #undef CRYPT_GetProvFunc
239 #undef CRYPT_GetProvFuncOpt
240
241
242 /******************************************************************************
243  * CryptAcquireContextA (ADVAPI32.@)
244  * Acquire a crypto provider context handle.
245  *
246  * PARAMS
247  * phProv: Pointer to HCRYPTPROV for the output.
248  * pszContainer: Key Container Name
249  * pszProvider: Cryptographic Service Provider Name
250  * dwProvType: Crypto provider type to get a handle.
251  * dwFlags: flags for the operation
252  *
253  * RETURNS TRUE on success, FALSE on failure.
254  */
255 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
256                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
257 {
258         PCRYPTPROV pProv = NULL;
259         HKEY key;
260         PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
261         BYTE* signature;
262         DWORD keytype, type, len;
263         ULONG r;
264
265         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
266                 pszProvider, dwProvType, dwFlags);
267
268         if (!phProv || !dwProvType)
269         {
270                 SetLastError(ERROR_INVALID_PARAMETER);
271                 return FALSE;
272         }
273         if (dwProvType > MAXPROVTYPES)
274         {
275                 SetLastError(NTE_BAD_PROV_TYPE);
276                 return FALSE;
277         }
278
279         if (!pszProvider)
280         {
281                 /* No CSP name specified so try the user default CSP first
282                  * then try the machine default CSP
283                  */
284                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
285                         FIXME("No provider registered for crypto provider type %ld.\n", dwProvType);
286                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
287                         return FALSE;
288                 }
289                 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
290                 {
291                         CRYPT_Free(keyname);
292                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
293                                 FIXME("No type registered for crypto provider type %ld.\n", dwProvType);
294                                 RegCloseKey(key);
295                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
296                                 goto error;
297                         }
298                         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
299                                 FIXME("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
300                                 RegCloseKey(key);
301                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
302                                 goto error;
303                         }
304                 }
305                 CRYPT_Free(keyname);
306                 r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
307                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
308                 {
309                         TRACE("error %ld reading size of 'Name' from registry\n", r );
310                         RegCloseKey(key);
311                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
312                         goto error;
313                 }
314                 if(!(provname = CRYPT_Alloc(len)))
315                 {
316                         RegCloseKey(key);
317                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
318                         goto error;
319                 }
320                 r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
321                 if( r != ERROR_SUCCESS )
322                 {
323                         TRACE("error %ld reading 'Name' from registry\n", r );
324                         RegCloseKey(key);
325                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
326                         goto error;
327                 }
328                 RegCloseKey(key);
329         } else {
330                 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
331                 {
332                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
333                         goto error;
334                 }
335                 strcpy(provname, pszProvider);
336         }
337
338         keyname = CRYPT_GetProvKeyName(provname);
339         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) goto error;
340         CRYPT_Free(keyname);
341         len = sizeof(DWORD);
342         r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
343         if (r != ERROR_SUCCESS || type != dwProvType)
344         {
345                 FIXME("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
346                 SetLastError(NTE_BAD_PROV_TYPE);
347                 goto error;
348         }
349
350         r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
351         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
352         {
353                 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
354                 RegCloseKey(key);
355                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
356                 goto error;
357         }
358         if (!(temp = CRYPT_Alloc(len)))
359         {
360                 RegCloseKey(key);
361                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
362                 goto error;
363         }
364         r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
365         if( r != ERROR_SUCCESS )
366         {
367                 TRACE("error %ld reading 'Image Path' from registry\n", r );
368                 RegCloseKey(key);
369                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
370                 goto error;
371         }
372
373         r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len);
374         if ( r != ERROR_SUCCESS || keytype != REG_BINARY)
375         {
376                 TRACE("error %ld reading size of 'Signature'\n", r );
377                 RegCloseKey(key);
378                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
379                 goto error;
380         }
381         if (!(signature = CRYPT_Alloc(len)))
382         {
383                 RegCloseKey(key);
384                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
385                 goto error;
386         }
387         r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len);
388         if ( r != ERROR_SUCCESS )
389         {
390                 TRACE("error %ld reading 'Signature'\n", r );
391                 RegCloseKey(key);
392                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
393                 goto error;
394         }
395         RegCloseKey(key);
396         len = ExpandEnvironmentStringsA(temp, NULL, 0);
397         if ( !(imagepath = CRYPT_Alloc(len)) )
398         {
399                 CRYPT_Free(signature);
400                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
401                 goto error;
402         }
403         if (!ExpandEnvironmentStringsA(temp, imagepath, len))
404         {
405                 CRYPT_Free(signature);
406                 /* ExpandEnvironmentStrings will call SetLastError */
407                 goto error;
408         }
409
410         if (!CRYPT_VerifyImage(imagepath, signature))
411         {
412                 CRYPT_Free(signature);
413                 SetLastError(NTE_SIGNATURE_FILE_BAD);
414                 goto error;
415         }
416         pProv = CRYPT_LoadProvider(imagepath);
417         CRYPT_Free(temp);
418         CRYPT_Free(signature);
419         if (!pProv) {
420                 /* CRYPT_LoadProvider calls SetLastError */
421                 goto error;
422         }
423         pProv->pVTable->dwProvType = dwProvType;
424         pProv->pVTable->pszProvName = provname;
425         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
426         {
427                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
428                  *       and thus, the CryptReleaseContext function need not be called afterwards.
429                  *       Therefore, we must clean up everything now.
430                  */
431                 if (dwFlags & CRYPT_DELETEKEYSET)
432                 {
433                         FreeLibrary(pProv->hModule);
434                         CRYPT_Free(provname);
435                         CRYPT_Free(pProv->pFuncs);
436                         CRYPT_Free(pProv);
437                 } else {
438                         pProv->pVTable->pszProvName = provname;
439                         pProv->pVTable->dwProvType = dwProvType;
440                         *phProv = (HCRYPTPROV)pProv;
441                 }
442                 return TRUE;
443         }
444         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
445 error:
446         if (pProv)
447         {
448                 FreeLibrary(pProv->hModule);
449                 CRYPT_Free(pProv->pVTable);
450                 CRYPT_Free(pProv->pFuncs);
451                 CRYPT_Free(pProv);
452         }
453         CRYPT_Free(provname);
454         CRYPT_Free(temp);
455         CRYPT_Free(imagepath);
456         CRYPT_Free(keyname);
457         return FALSE;
458 }
459
460 /******************************************************************************
461  * CryptAcquireContextW (ADVAPI32.@)
462  */
463 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
464                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
465 {
466         PSTR pProvider = NULL, pContainer = NULL;
467         BOOL ret = FALSE;
468
469         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
470                 debugstr_w(pszProvider), dwProvType, dwFlags);
471
472         if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
473                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
474         if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
475         {
476                 CRYPT_Free(pContainer);
477                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
478         }
479
480         ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
481
482         if (pContainer)
483                 CRYPT_Free(pContainer);
484         if (pProvider)
485                 CRYPT_Free(pProvider);
486
487         return ret;
488 }
489
490 /******************************************************************************
491  * CryptContextAddRef (ADVAPI32.@)
492  */
493 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
494 {
495         FIXME("(0x%lx, %p, %08lx): stub!\n", hProv, pdwReserved, dwFlags);
496         return FALSE;
497         /* InterlockIncrement?? */
498 }
499
500 /******************************************************************************
501  * CryptReleaseContext (ADVAPI32.@)
502  */
503 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
504 {
505         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
506         BOOL ret;
507
508         TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
509
510         if (!pProv)
511         {
512                 SetLastError(NTE_BAD_UID);
513                 return FALSE;
514         }
515         /* FIXME: Decrement the counter here first if possible */
516         ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
517         FreeLibrary(pProv->hModule);
518 #if 0
519         CRYPT_Free(pProv->pVTable->pContextInfo);
520 #endif
521         CRYPT_Free(pProv->pVTable->pszProvName);
522         CRYPT_Free(pProv->pVTable);
523         CRYPT_Free(pProv->pFuncs);
524         CRYPT_Free(pProv);
525         return ret;
526 }
527
528 /******************************************************************************
529  * CryptGenRandom (ADVAPI32.@)
530  */
531 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
532 {
533         PCRYPTPROV prov = (PCRYPTPROV)hProv;
534
535         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
536
537         if (!hProv)
538                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
539
540         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
541 }
542
543 /******************************************************************************
544  * CryptCreateHash (ADVAPI32.@)
545  */
546 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
547                 DWORD dwFlags, HCRYPTHASH *phHash)
548 {
549         PCRYPTPROV prov = (PCRYPTPROV)hProv;
550         PCRYPTKEY key = (PCRYPTKEY)hKey;
551         PCRYPTHASH hash;
552
553         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
554
555         if (!prov)
556                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
557         if (!phHash)
558                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
559         if (dwFlags)
560                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
561         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
562                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
563
564         hash->pProvider = prov;
565
566         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
567                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
568         {
569             *phHash = (HCRYPTHASH)hash;
570             return TRUE;
571         }
572
573         /* CSP error! */
574         CRYPT_Free(hash);
575         return FALSE;
576 }
577
578 /******************************************************************************
579  * CryptDecrypt (ADVAPI32.@)
580  */
581 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
582                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
583 {
584         PCRYPTPROV prov;
585         PCRYPTKEY key = (PCRYPTKEY)hKey;
586         PCRYPTHASH hash = (PCRYPTHASH)hHash;
587
588         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
589
590         if (!key || !pbData || !pdwDataLen)
591                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
592
593         prov = key->pProvider;
594         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
595                         Final, dwFlags, pbData, pdwDataLen);
596 }
597
598 /******************************************************************************
599  * CryptDeriveKey (ADVAPI32.@)
600  */
601 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
602                 DWORD dwFlags, HCRYPTKEY *phKey)
603 {
604         PCRYPTPROV prov = (PCRYPTPROV)hProv;
605         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
606         PCRYPTKEY key;
607
608         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
609
610         if (!prov || !hash)
611                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
612         if (!phKey)
613                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
614         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
615                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
616
617         key->pProvider = prov;
618         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
619         {
620             *phKey = (HCRYPTKEY)key;
621             return TRUE;
622         }
623
624         /* CSP error! */
625         CRYPT_Free(key);
626         return FALSE;
627 }
628
629 /******************************************************************************
630  * CryptDestroyHash (ADVAPI32.@)
631  */
632 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
633 {
634         PCRYPTHASH hash = (PCRYPTHASH)hHash;
635         PCRYPTPROV prov;
636         BOOL ret;
637
638         TRACE("(0x%lx)\n", hHash);
639
640         if (!hash)
641                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
642
643         prov = hash->pProvider;
644         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
645         CRYPT_Free(hash);
646         return ret;
647 }
648
649 /******************************************************************************
650  *  CryptDestroyKey (ADVAPI32.@)
651  */
652 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
653 {
654         PCRYPTKEY key = (PCRYPTKEY)hKey;
655         PCRYPTPROV prov;
656         BOOL ret;
657
658         TRACE("(0x%lx)\n", hKey);
659
660         if (!key)
661                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
662
663         prov = key->pProvider;
664         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
665         CRYPT_Free(key);
666         return ret;
667 }
668
669 /******************************************************************************
670  * CryptDuplicateHash (ADVAPI32.@)
671  */
672 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
673                 DWORD dwFlags, HCRYPTHASH *phHash)
674 {
675         PCRYPTPROV prov;
676         PCRYPTHASH orghash, newhash;
677
678         TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
679
680         orghash = (PCRYPTHASH)hHash;
681         if (!orghash || pdwReserved || !phHash)
682                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
683
684         prov = orghash->pProvider;
685         if (!prov->pFuncs->pCPDuplicateHash)
686                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
687
688         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
689                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
690
691         newhash->pProvider = prov;
692         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
693         {
694                 *phHash = (HCRYPTHASH)newhash;
695                 return TRUE;
696         }
697         CRYPT_Free(newhash);
698         return FALSE;
699 }
700
701 /******************************************************************************
702  * CryptDuplicateKey (ADVAPI32.@)
703  */
704 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
705 {
706         PCRYPTPROV prov;
707         PCRYPTKEY orgkey, newkey;
708
709         TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
710
711         orgkey = (PCRYPTKEY)hKey;
712         if (!orgkey || pdwReserved || !phKey)
713                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
714
715         prov = orgkey->pProvider;
716         if (!prov->pFuncs->pCPDuplicateKey)
717                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
718
719         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
720                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
721
722         newkey->pProvider = prov;
723         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
724         {
725                 *phKey = (HCRYPTKEY)newkey;
726                 return TRUE;
727         }
728         CRYPT_Free(newkey);
729         return FALSE;
730 }
731
732 /******************************************************************************
733  * CryptEncrypt (ADVAPI32.@)
734  */
735 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
736                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
737 {
738         PCRYPTPROV prov;
739         PCRYPTKEY key = (PCRYPTKEY)hKey;
740         PCRYPTHASH hash = (PCRYPTHASH)hHash;
741
742         TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
743
744         if (!key || !pdwDataLen)
745                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
746
747         prov = key->pProvider;
748         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
749                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
750 }
751
752 /******************************************************************************
753  * CryptEnumProvidersA (ADVAPI32.@)
754  */
755 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
756                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
757 {
758         HKEY hKey;
759
760         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
761                         pdwProvType, pszProvName, pcbProvName);
762
763         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
764         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
765
766         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
767                 CRYPT_ReturnLastError(NTE_FAIL);
768
769         if (!pszProvName)
770         {
771                 DWORD numkeys;
772                 RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, pcbProvName, NULL, NULL, NULL, NULL, NULL, NULL);
773                 (*pcbProvName)++;
774                 if (dwIndex >= numkeys)
775                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
776         } else {
777                 DWORD size = sizeof(DWORD);
778                 HKEY subkey;
779                 if (RegEnumKeyA(hKey, dwIndex, pszProvName, *pcbProvName))
780                         return FALSE;
781                 if (RegOpenKeyA(hKey, pszProvName, &subkey))
782                         return FALSE;
783                 if (RegQueryValueExA(subkey, "Type", NULL, NULL, (BYTE*)pdwProvType, &size))
784                         return FALSE;
785                 RegCloseKey(subkey);
786         }
787         RegCloseKey(hKey);
788         return TRUE;
789 }
790
791 /******************************************************************************
792  * CryptEnumProvidersW (ADVAPI32.@)
793  */
794 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
795                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
796 {
797         PSTR str = NULL;
798         DWORD strlen;
799         BOOL ret; /* = FALSE; */
800
801         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
802                         pdwProvType, pszProvName, pcbProvName);
803
804         strlen = *pcbProvName / sizeof(WCHAR);
805         if ( pszProvName && (str = CRYPT_Alloc(strlen)) )
806                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
807         ret = CryptEnumProvidersA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
808         if (str)
809         {
810                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
811                 CRYPT_Free(str);
812         }
813         *pcbProvName = strlen * sizeof(WCHAR);
814         return ret;
815 }
816
817 /******************************************************************************
818  * CryptEnumProviderTypesA (ADVAPI32.@)
819  */
820 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
821                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
822 {
823         HKEY hKey, hSubkey;
824         DWORD keylen, numkeys;
825         PSTR keyname, ch;
826
827         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
828                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
829
830         if (pdwReserved || !pdwProvType || !pcbTypeName)
831                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
832         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
833
834         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
835                 return FALSE;
836
837         RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
838         if (dwIndex >= numkeys)
839                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
840         keylen++;
841         if ( !(keyname = CRYPT_Alloc(keylen)) )
842                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
843         if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
844                 CRYPT_Free(keyname);
845                 return FALSE;
846         }
847         RegOpenKeyA(hKey, keyname, &hSubkey);
848         ch = keyname + strlen(keyname);
849         /* Convert "Type 000" to 0, etc/ */
850         *pdwProvType = *(--ch) - '0';
851         *pdwProvType += (*(--ch) - '0') * 10;
852         *pdwProvType += (*(--ch) - '0') * 100;
853         CRYPT_Free(keyname);
854         RegQueryValueA(hSubkey, "TypeName", pszTypeName, pcbTypeName);
855         RegCloseKey(hSubkey);
856         RegCloseKey(hKey);
857         return TRUE;
858 }
859
860 /******************************************************************************
861  * CryptEnumProviderTypesW (ADVAPI32.@)
862  */
863 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
864                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
865 {
866         PSTR str = NULL;
867         DWORD strlen;
868         BOOL ret;
869
870         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
871                         pdwProvType, pszTypeName, pcbTypeName);
872         strlen = *pcbTypeName / sizeof(WCHAR);
873         if ( pszTypeName && (str = CRYPT_Alloc(strlen)) )
874                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
875         ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
876         if (str)
877         {
878                 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
879                 CRYPT_Free(str);
880         }
881         *pcbTypeName = strlen * sizeof(WCHAR);
882         return ret;
883 }
884
885 /******************************************************************************
886  * CryptExportKey (ADVAPI32.@)
887  */
888 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
889                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
890 {
891         PCRYPTPROV prov;
892         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
893
894         TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
895
896         if (!key || pdwDataLen)
897                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
898
899         prov = key->pProvider;
900         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
901                         dwBlobType, dwFlags, pbData, pdwDataLen);
902 }
903
904 /******************************************************************************
905  * CryptGenKey (ADVAPI32.@)
906  */
907 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
908 {
909         PCRYPTPROV prov = (PCRYPTPROV)hProv;
910         PCRYPTKEY key;
911
912         TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
913
914         if (!prov)
915                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
916         if (!phKey)
917                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
918         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
919                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
920
921         key->pProvider = prov;
922
923         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
924         {
925             *phKey = (HCRYPTKEY)key;
926             return TRUE;
927         }
928
929         /* CSP error! */
930         CRYPT_Free(key);
931         return FALSE;
932 }
933
934 /******************************************************************************
935  * CryptGetDefaultProviderA (ADVAPI32.@)
936  */
937 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
938                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
939 {
940         HKEY hKey;
941         PSTR keyname;
942
943         if (pdwReserved || !pcbProvName)
944                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
945         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
946                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
947         if (dwProvType > 999)
948                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
949         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
950                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
951         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
952         {
953                 CRYPT_Free(keyname);
954                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
955         }
956         CRYPT_Free(keyname);
957         if (RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName))
958         {
959                 if (GetLastError() != ERROR_MORE_DATA)
960                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
961                 return FALSE;
962         }
963         RegCloseKey(hKey);
964         return TRUE;
965 }
966
967 /******************************************************************************
968  * CryptGetDefaultProviderW (ADVAPI32.@)
969  */
970 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
971                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
972 {
973         PSTR str = NULL;
974         DWORD strlen;
975         BOOL ret = FALSE;
976
977         TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
978
979         strlen = *pcbProvName / sizeof(WCHAR);
980         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
981                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
982         ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
983         if (str)
984         {
985                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
986                 CRYPT_Free(str);
987         }
988         *pcbProvName = strlen * sizeof(WCHAR);
989         return ret;
990 }
991
992 /******************************************************************************
993  * CryptGetHashParam (ADVAPI32.@)
994  */
995 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
996                 DWORD *pdwDataLen, DWORD dwFlags)
997 {
998         PCRYPTPROV prov;
999         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1000
1001         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1002
1003         if (!hash || !pdwDataLen)
1004                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1005
1006         prov = hash->pProvider;
1007         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1008                         pbData, pdwDataLen, dwFlags);
1009 }
1010
1011 /******************************************************************************
1012  * CryptGetKeyParam (ADVAPI32.@)
1013  */
1014 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1015                 DWORD *pdwDataLen, DWORD dwFlags)
1016 {
1017         PCRYPTPROV prov;
1018         PCRYPTKEY key = (PCRYPTKEY)hKey;
1019
1020         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1021
1022         if (!key || !pdwDataLen)
1023                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1024
1025         prov = key->pProvider;
1026         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1027                         pbData, pdwDataLen, dwFlags);
1028 }
1029
1030 /******************************************************************************
1031  * CryptGetProvParam (ADVAPI32.@)
1032  */
1033 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1034                 DWORD *pdwDataLen, DWORD dwFlags)
1035 {
1036         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1037
1038         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1039
1040         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1041 }
1042
1043 /******************************************************************************
1044  * CryptGetUserKey (ADVAPI32.@)
1045  */
1046 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1047 {
1048         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1049         PCRYPTKEY key;
1050
1051         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1052
1053         if (!prov)
1054                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1055         if (!phUserKey)
1056                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1057         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1058                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1059
1060         key->pProvider = prov;
1061
1062         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1063         {
1064             *phUserKey = (HCRYPTKEY)key;
1065             return TRUE;
1066         }
1067
1068         /* CSP Error */
1069         CRYPT_Free(key);
1070         return FALSE;
1071 }
1072
1073 /******************************************************************************
1074  * CryptHashData (ADVAPI32.@)
1075  */
1076 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1077 {
1078         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1079         PCRYPTPROV prov;
1080
1081         TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
1082
1083         if (!hash)
1084                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1085         if (!pbData || !dwDataLen)
1086                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1087
1088         prov = hash->pProvider;
1089         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1090 }
1091
1092 /******************************************************************************
1093  * CryptHashSessionKey (ADVAPI32.@)
1094  */
1095 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1096 {
1097         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1098         PCRYPTKEY key = (PCRYPTKEY)hKey;
1099         PCRYPTPROV prov;
1100
1101         TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
1102
1103         if (!hash || !key)
1104                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1105
1106         prov = hash->pProvider;
1107         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1108 }
1109
1110 /******************************************************************************
1111  * CryptImportKey (ADVAPI32.@)
1112  */
1113 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1114                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1115 {
1116         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1117         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1118
1119         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1120
1121         if (!prov || !pbData || !dwDataLen || !phKey)
1122                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1123
1124         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1125                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1126
1127         importkey->pProvider = prov;
1128         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1129                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1130         {
1131                 *phKey = (HCRYPTKEY)importkey;
1132                 return TRUE;
1133         }
1134
1135         CRYPT_Free(importkey);
1136         return FALSE;
1137 }
1138
1139 /******************************************************************************
1140  * CryptSignHashA
1141  *
1142  * Note: Since the sDesciption (string) is supposed to be NULL and
1143  *      is only retained for compatibility no string conversions are required
1144  *      and only one implementation is required for both ANSI and Unicode.
1145  *      We still need to export both:
1146  *
1147  * CryptSignHashA (ADVAPI32.@)
1148  * CryptSignHashW (ADVAPI32.@)
1149  */
1150 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1151                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1152 {
1153         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1154         PCRYPTPROV prov;
1155
1156         TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
1157         if (sDescription)
1158                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1159
1160         if (!hash)
1161                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1162         if (!pdwSigLen)
1163                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1164
1165         prov = hash->pProvider;
1166         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
1167                 dwFlags, pbSignature, pdwSigLen);
1168 }
1169
1170 /******************************************************************************
1171  * CryptSetHashParam (ADVAPI32.@)
1172  */
1173 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1174 {
1175         PCRYPTPROV prov;
1176         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1177
1178         TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1179
1180         if (!hash || !pbData)
1181                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1182
1183         prov = hash->pProvider;
1184         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1185                         dwParam, pbData, dwFlags);
1186 }
1187
1188 /******************************************************************************
1189  * CryptSetKeyParam (ADVAPI32.@)
1190  */
1191 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1192 {
1193         PCRYPTPROV prov;
1194         PCRYPTKEY key = (PCRYPTKEY)hKey;
1195
1196         TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1197
1198         if (!key || !pbData)
1199                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1200
1201         prov = key->pProvider;
1202         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1203                         dwParam, pbData, dwFlags);
1204 }
1205
1206 /******************************************************************************
1207  * CryptSetProviderA (ADVAPI32.@)
1208  */
1209 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1210 {
1211         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1212         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1213 }
1214
1215 /******************************************************************************
1216  * CryptSetProviderW (ADVAPI32.@)
1217  */
1218 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1219 {
1220         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1221         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1222 }
1223
1224 /******************************************************************************
1225  * CryptSetProviderExA (ADVAPI32.@)
1226  */
1227 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1228 {
1229         HKEY hKey;
1230         PSTR keyname;
1231
1232         TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1233
1234         if (!pszProvName || pdwReserved)
1235                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1236         if (dwProvType > MAXPROVTYPES)
1237                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1238         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1239                         || dwFlags == CRYPT_DELETE_DEFAULT)
1240                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1241
1242         if (dwFlags & CRYPT_DELETE_DEFAULT)
1243         {
1244                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1245                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1246                 RegDeleteKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname);
1247                 CRYPT_Free(keyname);
1248                 return TRUE;
1249         }
1250
1251         if ( !(keyname = CRYPT_GetProvKeyName(pszProvName)) )
1252                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1253         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &hKey))
1254         {
1255                 CRYPT_Free(keyname);
1256                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1257         }
1258         CRYPT_Free(keyname);
1259         RegCloseKey(hKey);
1260         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1261                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1262         RegCreateKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname, &hKey);
1263         CRYPT_Free(keyname);
1264         if (RegSetValueExA(hKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) +1))
1265                 return FALSE;
1266         return TRUE;
1267 }
1268
1269 /******************************************************************************
1270  * CryptSetProviderExW (ADVAPI32.@)
1271  */
1272 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1273 {
1274         BOOL ret = FALSE;
1275         PSTR str = NULL;
1276
1277         TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1278
1279         if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1280         {
1281                 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1282                 CRYPT_Free(str);
1283         }
1284         return ret;
1285 }
1286
1287 /******************************************************************************
1288  * CryptSetProvParam (ADVAPI32.@)
1289  */
1290 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1291 {
1292         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1293
1294         TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1295
1296         if (!prov)
1297                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1298         if (dwFlags & PP_USE_HARDWARE_RNG)
1299         {
1300                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1301                 FIXME("\tLetting the CSP decide.\n");
1302         }
1303         if (dwFlags & PP_CLIENT_HWND)
1304         {
1305                 /* FIXME: Should verify the parameter */
1306                 if (pbData /* && IsWindow((HWND)pbData) */)
1307                 {
1308                         crypt_hWindow = (HWND)(pbData);
1309                         return TRUE;
1310                 } else {
1311                         SetLastError(ERROR_INVALID_PARAMETER);
1312                         return FALSE;
1313                 }
1314         }
1315         /* All other flags go to the CSP */
1316         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1317 }
1318
1319 /******************************************************************************
1320  * CryptVerifySignatureA
1321  *
1322  * Note: Since the sDesciption (string) is supposed to be NULL and
1323  *      is only retained for compatibility no string conversions are required
1324  *      and only one implementation is required for both ANSI and Unicode.
1325  *      We still need to export both:
1326  *
1327  * CryptVerifySignatureA (ADVAPI32.@)
1328  * CryptVerifySignatureW (ADVAPI32.@)
1329  */
1330 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1331                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1332 {
1333         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1334         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1335         PCRYPTPROV prov;
1336
1337         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
1338                         dwSigLen, hPubKey, dwFlags);
1339         if (sDescription)
1340                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1341
1342         if (!hash || !key)
1343                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1344         if (!pbSignature || !dwSigLen)
1345                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1346
1347         prov = hash->pProvider;
1348         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1349                 key->hPrivate, NULL, dwFlags);
1350 }
1351
1352
1353 /*
1354    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
1355    in crypt32.dll.
1356  */
1357
1358 /******************************************************************************
1359  * SystemFunction040   (ADVAPI32.@)
1360  *
1361  * PARAMS:
1362  *   memory : pointer to memory to encrypt
1363  *   length : length of region to encrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
1364  *   flags  : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
1365  *            control whether other processes are able to decrypt the memory. The same value must be given
1366  *            when decrypting the memory.
1367  */
1368 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)  /* RtlEncryptMemory */
1369 {
1370         FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
1371         return STATUS_SUCCESS;
1372 }
1373
1374 /******************************************************************************
1375  * SystemFunction041  (ADVAPI32.@)
1376  *
1377  * PARAMS:
1378  *   memory : pointer to memory to decrypt
1379  *   length : length of region to decrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
1380  *   flags  : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
1381  *            control whether other processes are able to decrypt the memory. The same value must be given
1382  *            when encrypting the memory.
1383  */
1384 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)  /* RtlDecryptMemory */
1385 {
1386         FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
1387         return STATUS_SUCCESS;
1388 }