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