Branch the LSA functions from security.c to lsa.c.
[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  */
26
27 #include "config.h"
28
29 #include <time.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <sys/types.h>
33 #ifdef HAVE_SYS_STAT_H
34 # include <sys/stat.h>
35 #endif
36 #include <fcntl.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40
41 #include "crypt.h"
42 #include "winnls.h"
43 #include "winreg.h"
44 #include "wine/debug.h"
45 #include "winternl.h"
46 #include "ntstatus.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
49
50 HWND crypt_hWindow = 0;
51
52 #define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
53
54 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
55 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
56
57 static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
58 {
59         PCSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
60         PSTR keyname;
61
62         keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
63         if (keyname)
64         {
65                 strcpy(keyname, KEYSTR);
66                 strcpy(keyname + strlen(KEYSTR), pProvName);
67         } else
68                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
69         return keyname;
70 }
71
72 static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
73 {
74         PCSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
75         PCSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
76         PSTR keyname;
77         PSTR ptr;
78
79         keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
80         if (keyname)
81         {
82                 user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
83                 ptr = keyname + strlen(keyname);
84                 *(--ptr) = (dwType % 10) + '0';
85                 *(--ptr) = ((dwType / 10) % 10) + '0';
86                 *(--ptr) = (dwType / 100) + '0';
87         } else
88                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
89         return keyname;
90 }
91
92 /* CRYPT_UnicodeTOANSI
93  * wstr - unicode string
94  * str - pointer to ANSI string
95  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
96  *
97  * returns TRUE if unsuccessfull, FALSE otherwise.
98  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
99  */
100 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
101 {
102         int count;
103
104         if (!wstr)
105         {
106                 *str = NULL;
107                 return TRUE;
108         }
109         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
110         if (strsize == -1)
111                 *str = CRYPT_Alloc(count * sizeof(CHAR));
112         else
113                 count = min( count, strsize );
114         if (*str)
115         {
116                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
117                 return TRUE;
118         }
119         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
120         return FALSE;
121 }
122
123 /* CRYPT_ANSITOUnicode
124  * str - ANSI string
125  * wstr - pointer to unicode string
126  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
127  */
128 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
129 {
130         int wcount;
131
132         if (!str)
133         {
134                 *wstr = NULL;
135                 return TRUE;
136         }
137         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
138         if (wstrsize == -1)
139                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
140         else
141                 wcount = min( wcount, wstrsize/sizeof(WCHAR) );
142         if (*wstr)
143         {
144                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
145                 return TRUE;
146         }
147         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
148         return FALSE;
149 }
150
151 /* These next 2 functions are used by the VTableProvStruc structure */
152 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
153 {
154         if (!lpszImage || !pData)
155         {
156                 SetLastError(ERROR_INVALID_PARAMETER);
157                 return FALSE;
158         }
159
160         FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
161
162         return TRUE;
163 }
164
165 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
166 {
167         if (!phWnd)
168                 return FALSE;
169         *phWnd = crypt_hWindow;
170         return TRUE;
171 }
172
173 #define CRYPT_GetProvFunc(name) \
174         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
175 #define CRYPT_GetProvFuncOpt(name) \
176         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
177 static PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
178 {
179         PCRYPTPROV provider;
180         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
181
182         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
183         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
184         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
185         if ( !(provider->hModule = LoadLibraryA(pImage)) )
186         {
187                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
188                 FIXME("Failed to load dll %s\n", debugstr_a(pImage));
189                 goto error;
190         }
191         provider->dwMagic = MAGIC_CRYPTPROV;
192         provider->refcount = 1;
193
194         errorcode = NTE_PROVIDER_DLL_FAIL;
195         CRYPT_GetProvFunc(CPAcquireContext);
196         CRYPT_GetProvFunc(CPCreateHash);
197         CRYPT_GetProvFunc(CPDecrypt);
198         CRYPT_GetProvFunc(CPDeriveKey);
199         CRYPT_GetProvFunc(CPDestroyHash);
200         CRYPT_GetProvFunc(CPDestroyKey);
201         CRYPT_GetProvFuncOpt(CPDuplicateHash);
202         CRYPT_GetProvFuncOpt(CPDuplicateKey);
203         CRYPT_GetProvFunc(CPEncrypt);
204         CRYPT_GetProvFunc(CPExportKey);
205         CRYPT_GetProvFunc(CPGenKey);
206         CRYPT_GetProvFunc(CPGenRandom);
207         CRYPT_GetProvFunc(CPGetHashParam);
208         CRYPT_GetProvFunc(CPGetKeyParam);
209         CRYPT_GetProvFunc(CPGetProvParam);
210         CRYPT_GetProvFunc(CPGetUserKey);
211         CRYPT_GetProvFunc(CPHashData);
212         CRYPT_GetProvFunc(CPHashSessionKey);
213         CRYPT_GetProvFunc(CPImportKey);
214         CRYPT_GetProvFunc(CPReleaseContext);
215         CRYPT_GetProvFunc(CPSetHashParam);
216         CRYPT_GetProvFunc(CPSetKeyParam);
217         CRYPT_GetProvFunc(CPSetProvParam);
218         CRYPT_GetProvFunc(CPSignHash);
219         CRYPT_GetProvFunc(CPVerifySignature);
220
221         /* FIXME: Not sure what the pbContextInfo field is for.
222          *        Does it need memory allocation?
223          */
224         provider->pVTable->Version = 3;
225         provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
226         provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
227         provider->pVTable->dwProvType = 0;
228         provider->pVTable->pbContextInfo = NULL;
229         provider->pVTable->cbContextInfo = 0;
230         provider->pVTable->pszProvName = NULL;
231         return provider;
232
233 error:
234         SetLastError(errorcode);
235         if (provider)
236         {
237                 provider->dwMagic = 0;
238                 if (provider->hModule)
239                         FreeLibrary(provider->hModule);
240                 CRYPT_Free(provider->pVTable);
241                 CRYPT_Free(provider->pFuncs);
242                 CRYPT_Free(provider);
243         }
244         return NULL;
245 }
246 #undef CRYPT_GetProvFunc
247 #undef CRYPT_GetProvFuncOpt
248
249
250 /******************************************************************************
251  * CryptAcquireContextA (ADVAPI32.@)
252  * Acquire a crypto provider context handle.
253  *
254  * PARAMS
255  * phProv: Pointer to HCRYPTPROV for the output.
256  * pszContainer: Key Container Name
257  * pszProvider: Cryptographic Service Provider Name
258  * dwProvType: Crypto provider type to get a handle.
259  * dwFlags: flags for the operation
260  *
261  * RETURNS TRUE on success, FALSE on failure.
262  */
263 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
264                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
265 {
266         PCRYPTPROV pProv = NULL;
267         HKEY key;
268         PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
269         DWORD keytype, type, len;
270         ULONG r;
271
272         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
273                 pszProvider, dwProvType, dwFlags);
274
275         if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
276         {
277                 SetLastError(NTE_BAD_PROV_TYPE);
278                 return FALSE;
279         }
280         
281         if (!phProv)
282         {
283                 SetLastError(ERROR_INVALID_PARAMETER);
284                 return FALSE;
285         }
286
287         if (!pszProvider || !*pszProvider)
288         {
289                 /* No CSP name specified so try the user default CSP first
290                  * then try the machine default CSP
291                  */
292                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
293                         TRACE("No provider registered for crypto provider type %ld.\n", dwProvType);
294                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
295                         return FALSE;
296                 }
297                 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
298                 {
299                         CRYPT_Free(keyname);
300                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
301                                 TRACE("No type registered for crypto provider type %ld.\n", dwProvType);
302                                 RegCloseKey(key);
303                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
304                                 goto error;
305                         }
306                         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
307                                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
308                                 CRYPT_Free(keyname);
309                                 RegCloseKey(key);
310                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
311                                 goto error;
312                         }
313                 }
314                 CRYPT_Free(keyname);
315                 r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
316                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
317                 {
318                         TRACE("error %ld reading size of 'Name' from registry\n", r );
319                         RegCloseKey(key);
320                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
321                         goto error;
322                 }
323                 if(!(provname = CRYPT_Alloc(len)))
324                 {
325                         RegCloseKey(key);
326                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
327                         goto error;
328                 }
329                 r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
330                 if( r != ERROR_SUCCESS )
331                 {
332                         TRACE("error %ld reading 'Name' from registry\n", r );
333                         RegCloseKey(key);
334                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
335                         goto error;
336                 }
337                 RegCloseKey(key);
338         } else {
339                 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
340                 {
341                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
342                         goto error;
343                 }
344                 strcpy(provname, pszProvider);
345         }
346
347         keyname = CRYPT_GetProvKeyName(provname);
348         r = RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key);
349         CRYPT_Free(keyname);
350         if (r != ERROR_SUCCESS)
351         {
352                 SetLastError(NTE_KEYSET_NOT_DEF);
353                 goto error;
354         }
355         len = sizeof(DWORD);
356         r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
357         if (r != ERROR_SUCCESS)
358         {
359                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
360                 goto error;
361         }
362         if (type != dwProvType)
363         {
364                 TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
365                 SetLastError(NTE_PROV_TYPE_NO_MATCH);
366                 goto error;
367         }
368
369         r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
370         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
371         {
372                 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
373                 RegCloseKey(key);
374                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
375                 goto error;
376         }
377         if (!(temp = CRYPT_Alloc(len)))
378         {
379                 RegCloseKey(key);
380                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
381                 goto error;
382         }
383         r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
384         if( r != ERROR_SUCCESS )
385         {
386                 TRACE("error %ld reading 'Image Path' from registry\n", r );
387                 RegCloseKey(key);
388                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
389                 goto error;
390         }
391         RegCloseKey(key);
392         len = ExpandEnvironmentStringsA(temp, NULL, 0);
393         if ( !(imagepath = CRYPT_Alloc(len)) )
394         {
395                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
396                 goto error;
397         }
398         if (!ExpandEnvironmentStringsA(temp, imagepath, len))
399         {
400                 /* ExpandEnvironmentStrings will call SetLastError */
401                 goto error;
402         }
403         pProv = CRYPT_LoadProvider(imagepath);
404         if (!pProv) {
405                 /* CRYPT_LoadProvider calls SetLastError */
406                 goto error;
407         }
408         pProv->pVTable->dwProvType = dwProvType;
409         pProv->pVTable->pszProvName = provname;
410         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
411         {
412                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
413                  *       and thus, the CryptReleaseContext function need not be called afterwards.
414                  *       Therefore, we must clean up everything now.
415                  */
416                 if (dwFlags & CRYPT_DELETEKEYSET)
417                 {
418                         pProv->dwMagic = 0;
419                         FreeLibrary(pProv->hModule);
420                         CRYPT_Free(provname);
421                         CRYPT_Free(pProv->pFuncs);
422                         CRYPT_Free(pProv);
423                 } else {
424                         *phProv = (HCRYPTPROV)pProv;
425                 }
426                 CRYPT_Free(temp);
427                 CRYPT_Free(imagepath);
428                 return TRUE;
429         }
430         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
431 error:
432         if (pProv)
433         {
434                 pProv->dwMagic = 0;
435                 if (pProv->hModule)
436                         FreeLibrary(pProv->hModule);
437                 if (pProv->pVTable)
438                         CRYPT_Free(pProv->pVTable);
439                 if (pProv->pFuncs)
440                         CRYPT_Free(pProv->pFuncs);
441                 CRYPT_Free(pProv);
442         }
443         if (provname)
444                 CRYPT_Free(provname);
445         if (temp)
446                 CRYPT_Free(temp);
447         if (imagepath)
448                 CRYPT_Free(imagepath);
449         return FALSE;
450 }
451
452 /******************************************************************************
453  * CryptAcquireContextW (ADVAPI32.@)
454  *
455  * see CryptAcquireContextA
456  */
457 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
458                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
459 {
460         PSTR pProvider = NULL, pContainer = NULL;
461         BOOL ret = FALSE;
462
463         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
464                 debugstr_w(pszProvider), dwProvType, dwFlags);
465
466         if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
467                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
468         if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
469         {
470                 CRYPT_Free(pContainer);
471                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
472         }
473
474         ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
475
476         if (pContainer)
477                 CRYPT_Free(pContainer);
478         if (pProvider)
479                 CRYPT_Free(pProvider);
480
481         return ret;
482 }
483
484 /******************************************************************************
485  * CryptContextAddRef (ADVAPI32.@)
486  *
487  * Increases reference count of a cryptographic service provider handle
488  * by one.
489  *
490  * PARAMS
491  *  hProv       [I] Handle to the CSP whose reference is being incremented.
492  *  pdwReserved [IN] Reserved for future use and must be NULL.
493  *  dwFlags     [I] Reserved for future use and must be NULL.
494  *
495  * RETURNS
496  *  Success: TRUE
497  *  Failure: FALSE
498  */
499 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
500 {
501         PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
502
503         TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
504
505         if (!pProv)
506         {
507                 SetLastError(NTE_BAD_UID);
508                 return FALSE;
509         }
510
511         if (pProv->dwMagic != MAGIC_CRYPTPROV)
512         {
513                 SetLastError(ERROR_INVALID_PARAMETER);
514                 return FALSE;
515         }
516
517         pProv->refcount++;
518         return TRUE;
519 }
520
521 /******************************************************************************
522  * CryptReleaseContext (ADVAPI32.@)
523  *
524  * Releases the handle of a CSP.  Reference count is decreased.
525  *
526  * PARAMS
527  *  hProv   [I] Handle of a CSP.
528  *  dwFlags [I] Reserved for future use and must be NULL.
529  *
530  * RETURNS
531  *  Success: TRUE
532  *  Failure: FALSE
533  */
534 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
535 {
536         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
537         BOOL ret = TRUE;
538
539         TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
540
541         if (!pProv)
542         {
543                 SetLastError(NTE_BAD_UID);
544                 return FALSE;
545         }
546
547         if (pProv->dwMagic != MAGIC_CRYPTPROV)
548         {
549                 SetLastError(ERROR_INVALID_PARAMETER);
550                 return FALSE;
551         }
552
553         pProv->refcount--;
554         if (pProv->refcount <= 0) 
555         {
556                 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
557                 pProv->dwMagic = 0;
558                 FreeLibrary(pProv->hModule);
559 #if 0
560                 CRYPT_Free(pProv->pVTable->pContextInfo);
561 #endif
562                 CRYPT_Free(pProv->pVTable->pszProvName);
563                 CRYPT_Free(pProv->pVTable);
564                 CRYPT_Free(pProv->pFuncs);
565                 CRYPT_Free(pProv);
566         }
567         return ret;
568 }
569
570 /******************************************************************************
571  * CryptGenRandom (ADVAPI32.@)
572  *
573  * Fills a buffer with cryptographically random bytes.
574  *
575  * PARAMS
576  *  hProv    [I] Handle of a CSP.
577  *  dwLen    [I] Number of bytes to generate.
578  *  pbBuffer [I/O] Buffer to contain random bytes.
579  *
580  * RETURNS
581  *  Success: TRUE
582  *  Failure: FALSE
583  *
584  * NOTES
585  *  pdBuffer must be at least dwLen bytes long.
586  */
587 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
588 {
589         PCRYPTPROV prov = (PCRYPTPROV)hProv;
590
591         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
592
593         if (!hProv)
594                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
595
596         if (prov->dwMagic != MAGIC_CRYPTPROV)
597                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
598
599         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
600 }
601
602 /******************************************************************************
603  * CryptCreateHash (ADVAPI32.@)
604  *
605  * Initiates the hashing of a stream of data.
606  *
607  * PARAMS
608  *  hProv   [I] Handle of a CSP.
609  *  Algid   [I] Identifies the hash algorithm to use.
610  *  hKey    [I] Key for the hash (if required).
611  *  dwFlags [I] Reserved for future use and must be NULL.
612  *  phHash  [O] Address of the future handle to the new hash object.
613  *
614  * RETURNS
615  *  Success: TRUE
616  *  Failure: FALSE
617  *
618  * NOTES
619  *  If the algorithm is a keyed hash, hKey is the key.
620  */
621 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
622                 DWORD dwFlags, HCRYPTHASH *phHash)
623 {
624         PCRYPTPROV prov = (PCRYPTPROV)hProv;
625         PCRYPTKEY key = (PCRYPTKEY)hKey;
626         PCRYPTHASH hash;
627
628         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
629
630         if (!prov)
631                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
632         if (!phHash || prov->dwMagic != MAGIC_CRYPTPROV)
633                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
634         if (dwFlags)
635                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
636         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
637                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
638
639         hash->pProvider = prov;
640
641         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
642                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
643         {
644             *phHash = (HCRYPTHASH)hash;
645             return TRUE;
646         }
647
648         /* CSP error! */
649         CRYPT_Free(hash);
650         *phHash = 0;
651         return FALSE;
652 }
653
654 /******************************************************************************
655  * CryptDecrypt (ADVAPI32.@)
656  *
657  * Decrypts data encrypted by CryptEncrypt.
658  *
659  * PARAMS
660  *  hKey       [I] Handle to the decryption key.
661  *  hHash      [I] Handle to a hash object.
662  *  Final      [I] TRUE if this is the last section to be decrypted.
663  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
664  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
665  *                   data on return
666  *  pdwDataLen [I/O] Length of pbData before and after the call.
667  *
668  *  RETURNS
669  *   Success: TRUE
670  *   Failure: FALSE
671  */
672 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
673                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
674 {
675         PCRYPTPROV prov;
676         PCRYPTKEY key = (PCRYPTKEY)hKey;
677         PCRYPTHASH hash = (PCRYPTHASH)hHash;
678
679         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
680
681         if (!key || !pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
682                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
683
684         prov = key->pProvider;
685         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
686                         Final, dwFlags, pbData, pdwDataLen);
687 }
688
689 /******************************************************************************
690  * CryptDeriveKey (ADVAPI32.@)
691  *
692  * Generates session keys derived from a base data value.
693  *
694  * PARAMS
695  *  hProv     [I] Handle to a CSP.
696  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
697  *  hBaseData [I] Handle to a hash object.
698  *  dwFlags   [I] Type of key to generate.
699  *  phKey     [I/O] Address of the newly generated key.
700  *
701  * RETURNS
702  *  Success: TRUE
703  *  Failure: FALSE
704  */
705 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
706                 DWORD dwFlags, HCRYPTKEY *phKey)
707 {
708         PCRYPTPROV prov = (PCRYPTPROV)hProv;
709         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
710         PCRYPTKEY key;
711
712         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
713
714         if (!prov || !hash)
715                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
716         if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV)
717                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
718         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
719                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
720
721         key->pProvider = prov;
722         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
723         {
724             *phKey = (HCRYPTKEY)key;
725             return TRUE;
726         }
727
728         /* CSP error! */
729         CRYPT_Free(key);
730         *phKey = 0;
731         return FALSE;
732 }
733
734 /******************************************************************************
735  * CryptDestroyHash (ADVAPI32.@)
736  *
737  * Destroys the hash object referenced by hHash.
738  *
739  * PARAMS
740  *  hHash [I] Handle of the hash object to be destroyed.
741  *
742  * RETURNS
743  *  Success: TRUE
744  *  Failure: FALSE
745  */
746 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
747 {
748         PCRYPTHASH hash = (PCRYPTHASH)hHash;
749         PCRYPTPROV prov;
750         BOOL ret;
751
752         TRACE("(0x%lx)\n", hHash);
753
754         if (!hash)
755                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
756
757         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
758                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
759         
760         prov = hash->pProvider;
761         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
762         CRYPT_Free(hash);
763         return ret;
764 }
765
766 /******************************************************************************
767  * CryptDestroyKey (ADVAPI32.@)
768  *
769  * Releases the handle referenced by hKey.
770  *
771  * PARAMS
772  *  hKey [I] Handle of the key to be destroyed.
773  *
774  * RETURNS
775  *  Success: TRUE
776  *  Failure: FALSE
777  */
778 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
779 {
780         PCRYPTKEY key = (PCRYPTKEY)hKey;
781         PCRYPTPROV prov;
782         BOOL ret;
783
784         TRACE("(0x%lx)\n", hKey);
785
786         if (!key)
787                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
788
789         if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
790                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
791
792         prov = key->pProvider;
793         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
794         CRYPT_Free(key);
795         return ret;
796 }
797
798 /******************************************************************************
799  * CryptDuplicateHash (ADVAPI32.@)
800  *
801  * Duplicates a hash.
802  *
803  * PARAMS
804  *  hHash       [I] Handle to the hash to be copied.
805  *  pdwReserved [I] Reserved for future use and must be zero.
806  *  dwFlags     [I] Reserved for future use and must be zero.
807  *  phHash      [O] Address of the handle to receive the copy.
808  *
809  * RETURNS
810  *  Success: TRUE
811  *  Failure: FALSE
812  */
813 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
814                 DWORD dwFlags, HCRYPTHASH *phHash)
815 {
816         PCRYPTPROV prov;
817         PCRYPTHASH orghash, newhash;
818
819         TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
820
821         orghash = (PCRYPTHASH)hHash;
822         if (!orghash || pdwReserved || !phHash || !orghash->pProvider || 
823                 orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
824         {
825                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
826         }
827
828         prov = orghash->pProvider;
829         if (!prov->pFuncs->pCPDuplicateHash)
830                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
831
832         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
833                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
834
835         newhash->pProvider = prov;
836         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
837         {
838                 *phHash = (HCRYPTHASH)newhash;
839                 return TRUE;
840         }
841         CRYPT_Free(newhash);
842         return FALSE;
843 }
844
845 /******************************************************************************
846  * CryptDuplicateKey (ADVAPI32.@)
847  *
848  * Duplicate a key and the key's state.
849  *
850  * PARAMS
851  *  hKey        [I] Handle of the key to copy.
852  *  pdwReserved [I] Reserved for future use and must be NULL.
853  *  dwFlags     [I] Reserved for future use and must be zero.
854  *  phKey       [I] Address of the handle to the duplicated key.
855  *
856  * RETURNS
857  *  Success: TRUE
858  *  Failure: FALSE
859  */
860 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
861 {
862         PCRYPTPROV prov;
863         PCRYPTKEY orgkey, newkey;
864
865         TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
866
867         orgkey = (PCRYPTKEY)hKey;
868         if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider || 
869                 orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
870         {
871                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
872         }
873
874         prov = orgkey->pProvider;
875         if (!prov->pFuncs->pCPDuplicateKey)
876                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
877
878         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
879                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
880
881         newkey->pProvider = prov;
882         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
883         {
884                 *phKey = (HCRYPTKEY)newkey;
885                 return TRUE;
886         }
887         CRYPT_Free(newkey);
888         return FALSE;
889 }
890
891 /******************************************************************************
892  * CryptEncrypt (ADVAPI32.@)
893  *
894  * Encrypts data.
895  *
896  * PARAMS
897  *  hKey       [I] Handle to the enryption key.
898  *  hHash      [I] Handle to a hash object.
899  *  Final      [I] TRUE if this is the last section to encrypt.
900  *  dwFlags    [I] Can be CRYPT_OAEP.
901  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
902  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
903  *                   encrypted data after call.
904  *  dwBufLen   [I] Length of the input pbData buffer.
905  *
906  * RETURNS
907  *  Success: TRUE
908  *  Failure: FALSE
909  *
910  *  NOTES
911  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
912  *   required for the returned data in pdwDataLen.
913  */
914 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
915                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
916 {
917         PCRYPTPROV prov;
918         PCRYPTKEY key = (PCRYPTKEY)hKey;
919         PCRYPTHASH hash = (PCRYPTHASH)hHash;
920
921         TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
922
923         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
924                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
925
926         prov = key->pProvider;
927         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
928                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
929 }
930
931 /******************************************************************************
932  * CryptEnumProvidersW (ADVAPI32.@)
933  *
934  * Returns the next availabe CSP.
935  *
936  * PARAMS
937  *  dwIndex     [I] Index of the next provider to be enumerated.
938  *  pdwReserved [I] Reserved for future use and must be NULL.
939  *  dwFlags     [I] Reserved for future use and must be zero.
940  *  pdwProvType [O] DWORD designating the type of the provider.
941  *  pszProvName [O] Buffer that receives data from the provider.
942  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
943  *                    of bytes stored in the buffer on return.
944  *
945  *  RETURNS
946  *   Success: TRUE
947  *   Failure: FALSE
948  *
949  *  NOTES
950  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
951  *   for memory allocation purposes.
952  */
953 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
954                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
955 {
956         HKEY hKey;
957         
958         static const WCHAR providerW[] = {
959                 'S','o','f','t','w','a','r','e','\\',
960                 'M','i','c','r','o','s','o','f','t','\\',
961                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
962                 'D','e','f','a','u','l','t','s','\\',
963                 'P','r','o','v','i','d','e','r',0
964         };
965         
966         static const WCHAR typeW[] = {'T','y','p','e',0};
967
968         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
969                         pdwProvType, pszProvName, pcbProvName);
970
971         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
972         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
973
974         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
975                 CRYPT_ReturnLastError(NTE_FAIL);
976
977         if (!pszProvName)
978         {
979                 DWORD numkeys;
980                 WCHAR *provNameW;
981                 
982                 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
983                                  NULL, NULL, NULL, NULL, NULL, NULL);
984                 
985                 if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
986                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
987                 
988                 RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
989                 (*pcbProvName)++;
990                 *pcbProvName *= sizeof(WCHAR);
991                 
992                 CRYPT_Free(provNameW);
993                 
994                 if (dwIndex >= numkeys)
995                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
996         } else {
997                 DWORD size = sizeof(DWORD);
998                 DWORD result;
999                 HKEY subkey;
1000                 
1001                 result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1002                 if (result)
1003                         CRYPT_ReturnLastError(result);
1004                 if (RegOpenKeyW(hKey, pszProvName, &subkey))
1005                         return FALSE;
1006                 if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1007                         return FALSE;
1008                 RegCloseKey(subkey);
1009         }
1010         RegCloseKey(hKey);
1011         return TRUE;
1012 }
1013
1014 /******************************************************************************
1015  * CryptEnumProvidersA (ADVAPI32.@)
1016  *
1017  * see CryptEnumProvidersW
1018  */
1019 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1020                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1021 {
1022         PWSTR str = NULL;
1023         DWORD strlen;
1024         BOOL ret; /* = FALSE; */
1025
1026         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1027                         pdwProvType, pszProvName, pcbProvName);
1028
1029         strlen = *pcbProvName * sizeof(WCHAR);
1030         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1031                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1032         ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1033         if (str)
1034         {
1035                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1036                 CRYPT_Free(str);
1037         }
1038         *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
1039         return ret;
1040 }
1041
1042 /******************************************************************************
1043  * CryptEnumProviderTypesA (ADVAPI32i.@)
1044  *
1045  * Retrieves the next type of CSP supported.
1046  *
1047  * PARAMS
1048  *  dwIndex     [I] Index of the next provider to be enumerated.
1049  *  pdwReserved [I] Reserved for future use and must be NULL.
1050  *  dwFlags     [I] Reserved for future use and must be zero.
1051  *  pdwProvType [O] DWORD designating the type of the provider.
1052  *  pszTypeName [O] Buffer that receives data from the provider type.
1053  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1054  *                    of bytes stored in the buffer on return.
1055  *
1056  *  RETURNS
1057  *   Success: TRUE
1058  *   Failure: FALSE
1059  *
1060  *  NOTES
1061  *   If pszTypeName is NULL, CryptEnumProviderTypesA sets the size of the name
1062  *   for memory allocation purposes.
1063  */
1064 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1065                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1066 {
1067         HKEY hKey, hSubkey;
1068         DWORD keylen, numkeys, dwType;
1069         PSTR keyname, ch;
1070         DWORD result;
1071
1072         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
1073                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1074
1075         if (pdwReserved || !pdwProvType || !pcbTypeName)
1076                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1077         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1078
1079         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
1080                 return FALSE;
1081
1082         RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1083         if (dwIndex >= numkeys)
1084                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1085         keylen++;
1086         if ( !(keyname = CRYPT_Alloc(keylen)) )
1087                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1088         if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
1089                 CRYPT_Free(keyname);
1090                 return FALSE;
1091         }
1092         RegOpenKeyA(hKey, keyname, &hSubkey);
1093         ch = keyname + strlen(keyname);
1094         /* Convert "Type 000" to 0, etc/ */
1095         *pdwProvType = *(--ch) - '0';
1096         *pdwProvType += (*(--ch) - '0') * 10;
1097         *pdwProvType += (*(--ch) - '0') * 100;
1098         CRYPT_Free(keyname);
1099         
1100         result = RegQueryValueExA(hSubkey, "TypeName", NULL, &dwType, pszTypeName, pcbTypeName);
1101         if (result)
1102                 CRYPT_ReturnLastError(result);
1103
1104         RegCloseKey(hSubkey);
1105         RegCloseKey(hKey);
1106         return TRUE;
1107 }
1108
1109 /******************************************************************************
1110  * CryptEnumProviderTypesW (ADVAPI32.@)
1111  *
1112  * see CryptEnumProviderTypesA
1113  */
1114 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1115                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1116 {
1117         PSTR str = NULL;
1118         DWORD strlen;
1119         BOOL ret;
1120
1121         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1122                         pdwProvType, pszTypeName, pcbTypeName);
1123         strlen = *pcbTypeName / sizeof(WCHAR);
1124         if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
1125                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1126         ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1127         if (str)
1128         {
1129                 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
1130                 CRYPT_Free(str);
1131         }
1132         *pcbTypeName = strlen * sizeof(WCHAR);
1133         return ret;
1134 }
1135
1136 /******************************************************************************
1137  * CryptExportKey (ADVAPI32.@)
1138  * 
1139  * Exports a cryptographic key from a CSP.
1140  *
1141  * PARAMS
1142  *  hKey       [I] Handle to the key to export.
1143  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1144  *  dwBlobType [I] Type of BLOB to be exported.
1145  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1146  *  pbData     [O] Buffer to receive BLOB data.
1147  *  pdwDataLen [I/O] Specifies the size of pbData.
1148  *
1149  * RETURNS
1150  *  Success: TRUE
1151  *  Failure: FALSE
1152  *
1153  * NOTES
1154  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1155  *  buffer needed to hold the BLOB.
1156  */
1157 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1158                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1159 {
1160         PCRYPTPROV prov;
1161         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1162
1163         TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1164
1165         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1166                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1167
1168         prov = key->pProvider;
1169         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1170                         dwBlobType, dwFlags, pbData, pdwDataLen);
1171 }
1172
1173 /******************************************************************************
1174  * CryptGenKey (ADVAPI32.@)
1175  *
1176  * Generates a random cryptographic session key or a pub/priv key pair.
1177  *
1178  * PARAMS
1179  *  hProv   [I] Handle to a CSP.
1180  *  Algid   [I] Algorithm to use to make key.
1181  *  dwFlags [I] Specifies type of key to make.
1182  *  phKey   [I] Address of the handle to which the new key is copied.
1183  *
1184  *  RETURNS
1185  *   Success: TRUE
1186  *   Failure: FALSE
1187  */
1188 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1189 {
1190         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1191         PCRYPTKEY key;
1192
1193         TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
1194
1195         if (!prov)
1196                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1197         if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
1198                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1199         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1200                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1201
1202         key->pProvider = prov;
1203
1204         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1205         {
1206             *phKey = (HCRYPTKEY)key;
1207             return TRUE;
1208         }
1209
1210         /* CSP error! */
1211         CRYPT_Free(key);
1212         return FALSE;
1213 }
1214
1215 /******************************************************************************
1216  * CryptGetDefaultProviderA (ADVAPI32.@)
1217  *
1218  * Finds the default CSP of a certain provider type.
1219  *
1220  * PARAMS
1221  *  dwProvType  [I] Provider type to look for.
1222  *  pdwReserved [I] Reserved for future use and must be NULL.
1223  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1224  *  pszProvName [O] Name of the default CSP.
1225  *  pcbProvName [I/O] Size of pszProvName
1226  *
1227  * RETURNS
1228  *  Success: TRUE
1229  *  Failure: FALSE
1230  *
1231  * NOTES
1232  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1233  *  memory allocation purposes on return.
1234  */
1235 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1236                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1237 {
1238         HKEY hKey;
1239         PSTR keyname;
1240         DWORD result;
1241
1242         if (pdwReserved || !pcbProvName)
1243                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1244         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1245                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1246         if (dwProvType > 999)
1247                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1248         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1249                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1250         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1251         {
1252                 CRYPT_Free(keyname);
1253                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
1254         }
1255         CRYPT_Free(keyname);
1256         
1257         result = RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName); 
1258         if (result)
1259         {
1260                 if (result != ERROR_MORE_DATA)
1261                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1262                 else
1263                         SetLastError(result);
1264                 
1265                 return FALSE;
1266         }
1267         
1268         RegCloseKey(hKey);
1269         return TRUE;
1270 }
1271
1272 /******************************************************************************
1273  * CryptGetDefaultProviderW (ADVAPI32.@)
1274  *
1275  * see CryptGetDefaultProviderA
1276  */
1277 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1278                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1279 {
1280         PSTR str = NULL;
1281         DWORD strlen;
1282         BOOL ret = FALSE;
1283
1284         TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1285
1286         strlen = *pcbProvName / sizeof(WCHAR);
1287         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1288                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1289         ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
1290         if (str)
1291         {
1292                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
1293                 CRYPT_Free(str);
1294         }
1295         *pcbProvName = strlen * sizeof(WCHAR);
1296         return ret;
1297 }
1298
1299 /******************************************************************************
1300  * CryptGetHashParam (ADVAPI32.@)
1301  *
1302  * Retrieves data that controls the operations of a hash object.
1303  *
1304  * PARAMS
1305  *  hHash      [I] Handle of the hash object to question.
1306  *  dwParam    [I] Query type.
1307  *  pbData     [O] Buffer that receives the value data.
1308  *  pdwDataLen [I/O] Size of the pbData buffer.
1309  *  dwFlags    [I] Reserved for future use and must be zero.
1310  *
1311  * RETURNS
1312  *  Success: TRUE
1313  *  Failure: FALSE
1314  *
1315  * NOTES
1316  *  If pbData is NULL, pdwDataLen will contain the length required.
1317  */
1318 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1319                 DWORD *pdwDataLen, DWORD dwFlags)
1320 {
1321         PCRYPTPROV prov;
1322         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1323
1324         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1325
1326         if (!hash || !pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1327                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1328
1329         prov = hash->pProvider;
1330         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1331                         pbData, pdwDataLen, dwFlags);
1332 }
1333
1334 /******************************************************************************
1335  * CryptGetKeyParam (ADVAPI32.@)
1336  *
1337  * Retrieves data that controls the operations of a key.
1338  *
1339  * PARAMS
1340  *  hKey       [I] Handle to they key in question.
1341  *  dwParam    [I] Specifies query type.
1342  *  pbData     [O] Sequence of bytes to receive data.
1343  *  pdwDataLen [I/O] Size of pbData.
1344  *  dwFlags    [I] Reserved for future use and must be zero.
1345  *
1346  * RETURNS
1347  *  Success: TRUE
1348  *  Failure: FALSE
1349  *
1350  * NOTES
1351  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1352  */
1353 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1354                 DWORD *pdwDataLen, DWORD dwFlags)
1355 {
1356         PCRYPTPROV prov;
1357         PCRYPTKEY key = (PCRYPTKEY)hKey;
1358
1359         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1360
1361         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1362                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1363
1364         prov = key->pProvider;
1365         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1366                         pbData, pdwDataLen, dwFlags);
1367 }
1368
1369 /******************************************************************************
1370  * CryptGetProvParam (ADVAPI32.@)
1371  *
1372  * Retrieves parameters that control the operations of a CSP.
1373  *
1374  * PARAMS
1375  *  hProv      [I] Handle of the CSP in question.
1376  *  dwParam    [I] Specifies query type.
1377  *  pbData     [O] Buffer to receive the data.
1378  *  pdwDataLen [I/O] Size of pbData.
1379  *  dwFlags    [I] see MSDN Docs.
1380  *
1381  * RETURNS
1382  *  Success: TRUE
1383  *  Failure: FALSE
1384  *
1385  * NOTES
1386  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1387  */
1388 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1389                 DWORD *pdwDataLen, DWORD dwFlags)
1390 {
1391         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1392
1393         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1394
1395         if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
1396                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1397
1398         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1399 }
1400
1401 /******************************************************************************
1402  * CryptGetUserKey (ADVAPI32.@)
1403  *
1404  * Gets a handle of one of a user's two public/private key pairs.
1405  *
1406  * PARAMS
1407  *  hProv     [I] Handle of a CSP.
1408  *  dwKeySpec [I] Private key to use.
1409  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1410  *
1411  * RETURNS
1412  *  Success: TRUE
1413  *  Failure: FALSE
1414  */
1415 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1416 {
1417         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1418         PCRYPTKEY key;
1419
1420         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1421
1422         if (!prov)
1423                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1424         if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
1425                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1426         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1427                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1428
1429         key->pProvider = prov;
1430
1431         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1432         {
1433             *phUserKey = (HCRYPTKEY)key;
1434             return TRUE;
1435         }
1436
1437         /* CSP Error */
1438         CRYPT_Free(key);
1439         *phUserKey = 0;
1440         return FALSE;
1441 }
1442
1443 /******************************************************************************
1444  * CryptHashData (ADVAPI32.@)
1445  *
1446  * Adds data to a hash object.
1447  *
1448  * PARAMS
1449  *  hHash     [I] Handle of the hash object.
1450  *  pbData    [I] Buffer of data to be hashed.
1451  *  dwDataLen [I] Number of bytes to add.
1452  *  dwFlags   [I] Can be CRYPT_USERDATA
1453  *
1454  * RETURNS
1455  *  Success: TRUE
1456  *  Failure: FALSE
1457  */
1458 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1459 {
1460         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1461         PCRYPTPROV prov;
1462
1463         TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
1464
1465         if (!hash)
1466                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1467         if (!pbData || !dwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1468                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1469
1470         prov = hash->pProvider;
1471         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1472 }
1473
1474 /******************************************************************************
1475  * CryptHashSessionKey (ADVAPI32.@)
1476  *
1477  * PARAMS 
1478  *  hHash   [I] Handle to the hash object.
1479  *  hKey    [I] Handle to the key to be hashed.
1480  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1481  *
1482  * RETURNS
1483  *  Success: TRUE
1484  *  Failure: FALSE
1485  */
1486 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1487 {
1488         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1489         PCRYPTKEY key = (PCRYPTKEY)hKey;
1490         PCRYPTPROV prov;
1491
1492         TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
1493
1494         if (!hash || !key)
1495                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1496
1497         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1498                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1499
1500         prov = hash->pProvider;
1501         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1502 }
1503
1504 /******************************************************************************
1505  * CryptImportKey (ADVAPI32.@)
1506  *
1507  * PARAMS
1508  *  hProv     [I] Handle of a CSP.
1509  *  pbData    [I] Contains the key to be imported.
1510  *  dwDataLen [I] Length of the key.
1511  *  hPubKey   [I] Cryptographic key that decrypts pdData
1512  *  dwFlags   [I] Used only with a public/private key pair.
1513  *  phKey     [O] Imported key.
1514  *
1515  * RETURNS
1516  *  Success: TRUE
1517  *  Failure: FALSE
1518  */
1519 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1520                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1521 {
1522         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1523         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1524
1525         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1526
1527         if (!prov || !pbData || !dwDataLen || !phKey || prov->dwMagic != MAGIC_CRYPTPROV)
1528                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1529
1530         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1531                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1532
1533         importkey->pProvider = prov;
1534         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1535                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1536         {
1537                 *phKey = (HCRYPTKEY)importkey;
1538                 return TRUE;
1539         }
1540
1541         CRYPT_Free(importkey);
1542         return FALSE;
1543 }
1544
1545 /******************************************************************************
1546  * CryptSignHashW (ADVAPI32.@)
1547  *
1548  * Signs data.
1549  *
1550  * PARAMS
1551  *  hHash        [I] Handle of the hash object to be signed.
1552  *  dwKeySpec    [I] Private key to use.
1553  *  sDescription [I] Should be NULL.
1554  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1555  *  pbSignature  [O] Buffer of the signature data.
1556  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1557  *
1558  * RETURNS
1559  *  Success: TRUE
1560  *  Failure: FALSE
1561  *
1562  * NOTES
1563  *  Because of security flaws sDescription should not be used and should thus be
1564  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1565  *  Providers.
1566  */
1567 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1568                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1569 {
1570         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1571         PCRYPTPROV prov;
1572
1573         TRACE("(0x%lx, %ld, %s, %08ld, %p, %p)\n", 
1574                 hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1575
1576         if (!hash)
1577                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1578         if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1579                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1580
1581         prov = hash->pProvider;
1582         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1583                 dwFlags, pbSignature, pdwSigLen);
1584 }
1585
1586 /******************************************************************************
1587  * CryptSignHashA (ADVAPI32.@)
1588  *
1589  * ASCII version of CryptSignHashW
1590  */
1591 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1592                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1593 {
1594         LPWSTR wsDescription;
1595         BOOL result;
1596
1597         TRACE("(0x%lx, %ld, %s, %08ld, %p, %p)\n", 
1598                 hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
1599
1600         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1601         result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1602         if (wsDescription) CRYPT_Free(wsDescription);
1603
1604         return result;
1605 }
1606
1607 /******************************************************************************
1608  * CryptSetHashParam (ADVAPI32.@)
1609  *
1610  * Customizes the operations of a hash object.
1611  *
1612  * PARAMS
1613  *  hHash   [I] Handle of the hash object to set parameters.
1614  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1615  *  pbData  [I] Value data buffer.
1616  *  dwFlags [I] Reserved for future use and must be zero.
1617  *
1618  * RETURNS
1619  *  Success: TRUE
1620  *  Failure: FALSE
1621  */
1622 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1623 {
1624         PCRYPTPROV prov;
1625         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1626
1627         TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1628
1629         if (!hash || !pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1630                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1631
1632         prov = hash->pProvider;
1633         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1634                         dwParam, pbData, dwFlags);
1635 }
1636
1637 /******************************************************************************
1638  * CryptSetKeyParam (ADVAPI32.@)
1639  *
1640  * Customizes a session key's operations.
1641  *
1642  * PARAMS
1643  *  hKey    [I] Handle to the key to set values.
1644  *  dwParam [I] See MSDN Doc.
1645  *  pbData  [I] Buffer of values to set.
1646  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1647  *
1648  * RETURNS
1649  *  Success: TRUE
1650  *  Failure: FALSE
1651  */
1652 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1653 {
1654         PCRYPTPROV prov;
1655         PCRYPTKEY key = (PCRYPTKEY)hKey;
1656
1657         TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1658
1659         if (!key || !pbData || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1660                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1661
1662         prov = key->pProvider;
1663         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1664                         dwParam, pbData, dwFlags);
1665 }
1666
1667 /******************************************************************************
1668  * CryptSetProviderA (ADVAPI32.@)
1669  *
1670  * Specifies the current user's default CSP.
1671  *
1672  * PARAMS
1673  *  pszProvName [I] Name of the new default CSP.
1674  *  dwProvType  [I] Provider type of the CSP.
1675  *
1676  * RETURNS
1677  *  Success: TRUE
1678  *  Failure: FALSE
1679  */
1680 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1681 {
1682         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1683         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1684 }
1685
1686 /******************************************************************************
1687  * CryptSetProviderW (ADVAPI32.@)
1688  *
1689  * See CryptSetProviderA
1690  */
1691 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1692 {
1693         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1694         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1695 }
1696
1697 /******************************************************************************
1698  * CryptSetProviderExA (ADVAPI32.@)
1699  *
1700  * Specifies the default CSP.
1701  *
1702  * PARAMS
1703  *  pszProvName [I] Name of the new default CSP.
1704  *  dwProvType  [I] Provider type of the CSP.
1705  *  pdwReserved [I] Reserved for future use and must be NULL.
1706  *  dwFlags     [I] See MSDN Doc.
1707  *
1708  * RETURNS
1709  *  Success: TRUE
1710  *  Failure: FALSE
1711  */
1712 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1713 {
1714         HKEY hProvKey, hTypeKey;
1715         PSTR keyname;
1716
1717         TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1718
1719         if (!pszProvName || pdwReserved)
1720                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1721         if (dwProvType > MAXPROVTYPES)
1722                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1723         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1724                         || dwFlags == CRYPT_DELETE_DEFAULT)
1725                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1726         
1727         if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
1728                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1729         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1730                 keyname, &hTypeKey))
1731         {
1732                 CRYPT_Free(keyname);
1733                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1734         }
1735         CRYPT_Free(keyname);
1736         
1737         if (dwFlags & CRYPT_DELETE_DEFAULT)
1738         {
1739                 RegDeleteValueA(hTypeKey, "Name");
1740         }
1741         else
1742         {
1743                 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
1744                 {
1745                         RegCloseKey(hTypeKey);
1746                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1747                 }
1748                 if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1749                         keyname, &hProvKey))
1750                 {
1751                         CRYPT_Free(keyname);
1752                         RegCloseKey(hTypeKey);
1753                         CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1754                 }
1755                 CRYPT_Free(keyname);
1756                 
1757                 if (RegSetValueExA(hTypeKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) + 1))
1758                 {
1759                         RegCloseKey(hTypeKey);
1760                         RegCloseKey(hProvKey);
1761                         return FALSE;
1762                 }
1763                 
1764                 RegCloseKey(hProvKey);
1765         }
1766         RegCloseKey(hTypeKey);
1767
1768         return TRUE;
1769 }
1770
1771 /******************************************************************************
1772  * CryptSetProviderExW (ADVAPI32.@)
1773  *
1774  * See CryptSetProviderExA
1775  */
1776 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1777 {
1778         BOOL ret = FALSE;
1779         PSTR str = NULL;
1780
1781         TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1782
1783         if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1784         {
1785                 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1786                 CRYPT_Free(str);
1787         }
1788         return ret;
1789 }
1790
1791 /******************************************************************************
1792  * CryptSetProvParam (ADVAPI32.@)
1793  *
1794  * Customizes the operations of a CSP.
1795  *
1796  * PARAMS
1797  *  hProv   [I] Handle of a CSP.
1798  *  dwParam [I] See MSDN Doc.
1799  *  pbData  [I] Buffer that contains a value to set as a parameter.
1800  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
1801  *
1802  * RETURNS
1803  *  Success: TRUE
1804  *  Failure: FALSE
1805  */
1806 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1807 {
1808         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1809
1810         TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1811
1812         if (!prov)
1813                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1814         if (prov->dwMagic != MAGIC_CRYPTPROV)
1815                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1816         if (dwFlags & PP_USE_HARDWARE_RNG)
1817         {
1818                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1819                 FIXME("\tLetting the CSP decide.\n");
1820         }
1821         if (dwFlags & PP_CLIENT_HWND)
1822         {
1823                 /* FIXME: Should verify the parameter */
1824                 if (pbData /* && IsWindow((HWND)pbData) */)
1825                 {
1826                         crypt_hWindow = (HWND)(pbData);
1827                         return TRUE;
1828                 } else {
1829                         SetLastError(ERROR_INVALID_PARAMETER);
1830                         return FALSE;
1831                 }
1832         }
1833         /* All other flags go to the CSP */
1834         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1835 }
1836
1837 /******************************************************************************
1838  * CryptVerifySignatureW (ADVAPI32.@)
1839  *
1840  * Verifies the signature of a hash object.
1841  *
1842  * PARAMS
1843  *  hHash        [I] Handle of the hash object to verify.
1844  *  pbSignature  [I] Signature data to verify.
1845  *  dwSigLen     [I] Size of pbSignature.
1846  *  hPubKey      [I] Handle to the public key to authenticate signature.
1847  *  sDescription [I] Should be NULL.
1848  *  dwFlags      [I] See MSDN doc.
1849  *
1850  * RETURNS
1851  *  Success: TRUE
1852  *  Failure: FALSE
1853  * 
1854  * NOTES
1855  *  Because of security flaws sDescription should not be used and should thus be
1856  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1857  *  Providers.
1858  */
1859 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1860                 HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
1861 {
1862         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1863         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1864         PCRYPTPROV prov;
1865
1866         TRACE("(0x%lx, %p, %ld, 0x%lx, %s, %08ld)\n", hHash, pbSignature,
1867                         dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
1868
1869         if (!hash || !key)
1870                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1871         if (!pbSignature || !dwSigLen || 
1872             !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
1873             !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1874         {
1875                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1876         }
1877                 
1878         prov = hash->pProvider;
1879         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1880                 key->hPrivate, sDescription, dwFlags);
1881 }
1882
1883 /******************************************************************************
1884  * CryptVerifySignatureA (ADVAPI32.@)
1885  *
1886  * ASCII version of CryptVerifySignatureW
1887  */
1888 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1889                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1890 {
1891         LPWSTR wsDescription;
1892         BOOL result;
1893
1894         TRACE("(0x%lx, %p, %ld, 0x%lx, %s, %08ld)\n", hHash, pbSignature,
1895                         dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
1896
1897         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1898         result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
1899         if (wsDescription) CRYPT_Free(wsDescription);
1900
1901         return result;
1902 }
1903
1904 /******************************************************************************
1905  * SystemFunction036   (ADVAPI32.@)
1906  *
1907  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
1908  *
1909  * PARAMS
1910  *  pbBufer [O] Pointer to memory to receive random bytes.
1911  *  dwLen   [I] Number of random bytes to fetch.
1912  */
1913
1914 BOOL WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
1915 {
1916     int dev_random;
1917
1918     /* FIXME: /dev/urandom does not provide random numbers of a sufficient
1919      * quality for cryptographic applications. /dev/random is much better,  
1920      * but it blocks if the kernel has not yet collected enough entropy for
1921      * the request, which will suspend the calling thread for an indefinite
1922      * amount of time. */
1923     dev_random = open("/dev/urandom", O_RDONLY);
1924     if (dev_random != -1)
1925     {
1926         if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
1927         {
1928             close(dev_random);
1929             return TRUE;
1930         }
1931         close(dev_random);
1932     }
1933     SetLastError(NTE_FAIL);
1934     return FALSE;
1935 }    
1936     
1937 /*
1938    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
1939    in crypt32.dll.
1940  */
1941
1942 /******************************************************************************
1943  * SystemFunction040   (ADVAPI32.@)
1944  *
1945  * MSDN documents this function as RtlEncryptMemory.
1946  *
1947  * PARAMS
1948  *  memory [I/O] Pointer to memory to encrypt.
1949  *  length [I] Length of region to encrypt in bytes.
1950  *  flags  [I] Control whether other processes are able to decrypt the memory.
1951  *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
1952  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
1953  *    RTL_ENCRYPT_OPTION_SAME_LOGON
1954  *    
1955  * NOTES
1956  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
1957  *  If flags are specified when encrypting, the same flag value must be given
1958  *  when decrypting the memory.
1959  */
1960 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
1961 {
1962         FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
1963         return STATUS_SUCCESS;
1964 }
1965
1966 /******************************************************************************
1967  * SystemFunction041  (ADVAPI32.@)
1968  *
1969  * MSDN documents this function as RtlDecryptMemory.
1970  *
1971  * PARAMS
1972  *  memory [I/O] Pointer to memory to decrypt.
1973  *  length [I] Length of region to decrypt in bytes.
1974  *  flags  [I] Control whether other processes are able to decrypt the memory.
1975  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
1976  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
1977  *    RTL_ENCRYPT_OPTION_SAME_LOGON
1978  *
1979  * NOTES
1980  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
1981  *  If flags are specified when encrypting, the same flag value must be given
1982  *  when decrypting the memory.
1983  */
1984 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
1985 {
1986         FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
1987         return STATUS_SUCCESS;
1988 }