wow64: In wow64_NtSetInformationToken forward TokenIntegrityLevel.
[wine.git] / dlls / advapi32 / crypt.c
blob0c94999660a2a9160c52619e54df98b71cf3efd0
1 /*
2 * Copyright 1999 Ian Schmidt
3 * Copyright 2001 Travis Michielsen
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /***********************************************************************
22 * TODO:
23 * - Reference counting
24 * - Thread-safing
27 #include <limits.h>
28 #include <time.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <sys/types.h>
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "crypt.h"
36 #include "winnls.h"
37 #include "winreg.h"
38 #include "rpc.h"
39 #include "wine/debug.h"
40 #include "wine/exception.h"
41 #include "winternl.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
45 typedef struct tagMD4_CTX {
46 unsigned int buf[4];
47 unsigned int i[2];
48 unsigned char in[64];
49 unsigned char digest[16];
50 } MD4_CTX;
52 void WINAPI MD4Init(MD4_CTX *ctx);
53 void WINAPI MD4Update(MD4_CTX *ctx, const unsigned char *buf, unsigned int len);
54 void WINAPI MD4Final(MD4_CTX *ctx);
56 static HWND crypt_hWindow;
58 #define CRYPT_Alloc(size) (LocalAlloc(LMEM_ZEROINIT, size))
59 #define CRYPT_Free(buffer) (LocalFree(buffer))
61 static void *pointer_from_handle(UINT_PTR handle, DWORD magic)
63 void *ret = NULL;
65 __TRY
67 if (handle && *(DWORD *)handle == magic)
68 ret = (void *)handle;
70 __EXCEPT_PAGE_FAULT
73 __ENDTRY
75 if (!ret)
76 SetLastError(ERROR_INVALID_PARAMETER);
78 return ret;
81 static PCRYPTPROV provider_from_handle(HCRYPTPROV handle)
83 return pointer_from_handle(handle, MAGIC_CRYPTPROV);
86 static PCRYPTHASH hash_from_handle(HCRYPTHASH handle)
88 return pointer_from_handle(handle, MAGIC_CRYPTHASH);
91 static PCRYPTKEY key_from_handle(HCRYPTKEY handle)
93 return pointer_from_handle(handle, MAGIC_CRYPTKEY);
96 static inline PWSTR CRYPT_GetProvKeyName(PCWSTR pProvName)
98 static const WCHAR KEYSTR[] = L"Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
99 PWSTR keyname;
101 keyname = CRYPT_Alloc((lstrlenW(KEYSTR) + lstrlenW(pProvName) +1)*sizeof(WCHAR));
102 if (keyname)
104 lstrcpyW(keyname, KEYSTR);
105 lstrcpyW(keyname + lstrlenW(KEYSTR), pProvName);
106 } else
107 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
108 return keyname;
111 static inline PWSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
113 static const WCHAR MACHINESTR[] = L"Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
114 static const WCHAR USERSTR[] = L"Software\\Microsoft\\Cryptography\\Provider Type XXX";
115 PWSTR keyname;
116 PWSTR ptr;
118 keyname = CRYPT_Alloc( ((user ? lstrlenW(USERSTR) : lstrlenW(MACHINESTR)) +1)*sizeof(WCHAR));
119 if (keyname)
121 user ? lstrcpyW(keyname, USERSTR) : lstrcpyW(keyname, MACHINESTR);
122 ptr = keyname + lstrlenW(keyname);
123 *(--ptr) = (dwType % 10) + '0';
124 *(--ptr) = ((dwType / 10) % 10) + '0';
125 *(--ptr) = (dwType / 100) + '0';
126 } else
127 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
128 return keyname;
131 /* CRYPT_UnicodeToANSI
132 * wstr - unicode string
133 * str - pointer to ANSI string or pointer to null pointer if we have to do the allocation
134 * strsize - size of buffer pointed to by str
136 * returns TRUE if unsuccessful, FALSE otherwise.
137 * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
139 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
141 if (!wstr)
143 *str = NULL;
144 return TRUE;
147 if (!*str)
149 strsize = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
150 *str = CRYPT_Alloc(strsize * sizeof(CHAR));
152 else if (strsize < 0)
154 strsize = INT_MAX; /* windows will pretend that the buffer is infinitely long */
157 if (*str)
159 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, strsize, NULL, NULL);
160 return TRUE;
163 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
164 return FALSE;
167 /* CRYPT_ANSITOUnicode
168 * str - ANSI string
169 * wstr - pointer to unicode string
170 * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
172 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
174 unsigned int wcount;
176 if (!str)
178 *wstr = NULL;
179 return TRUE;
181 wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
182 if (wstrsize == -1)
183 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
184 else
185 wcount = min( wcount, wstrsize/sizeof(WCHAR) );
186 if (*wstr)
188 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
189 return TRUE;
191 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
192 return FALSE;
195 /* These next 2 functions are used by the VTableProvStruc structure */
196 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
198 if (!lpszImage || !pData)
200 SetLastError(ERROR_INVALID_PARAMETER);
201 return FALSE;
204 FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
206 return TRUE;
209 static void CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
211 if (phWnd) *phWnd = crypt_hWindow;
214 #define CRYPT_GetProvFunc(name) \
215 if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
216 #define CRYPT_GetProvFuncOpt(name) \
217 provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
218 static PCRYPTPROV CRYPT_LoadProvider(PCWSTR pImage)
220 PCRYPTPROV provider;
221 DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
223 if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
224 if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
225 if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
226 if ( !(provider->hModule = LoadLibraryW(pImage)) )
228 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
229 FIXME("Failed to load dll %s\n", debugstr_w(pImage));
230 goto error;
232 provider->dwMagic = MAGIC_CRYPTPROV;
233 provider->refcount = 1;
235 errorcode = NTE_PROVIDER_DLL_FAIL;
236 CRYPT_GetProvFunc(CPAcquireContext);
237 CRYPT_GetProvFunc(CPCreateHash);
238 CRYPT_GetProvFunc(CPDecrypt);
239 CRYPT_GetProvFunc(CPDeriveKey);
240 CRYPT_GetProvFunc(CPDestroyHash);
241 CRYPT_GetProvFunc(CPDestroyKey);
242 CRYPT_GetProvFuncOpt(CPDuplicateHash);
243 CRYPT_GetProvFuncOpt(CPDuplicateKey);
244 CRYPT_GetProvFunc(CPEncrypt);
245 CRYPT_GetProvFunc(CPExportKey);
246 CRYPT_GetProvFunc(CPGenKey);
247 CRYPT_GetProvFunc(CPGenRandom);
248 CRYPT_GetProvFunc(CPGetHashParam);
249 CRYPT_GetProvFunc(CPGetKeyParam);
250 CRYPT_GetProvFunc(CPGetProvParam);
251 CRYPT_GetProvFunc(CPGetUserKey);
252 CRYPT_GetProvFunc(CPHashData);
253 CRYPT_GetProvFunc(CPHashSessionKey);
254 CRYPT_GetProvFunc(CPImportKey);
255 CRYPT_GetProvFunc(CPReleaseContext);
256 CRYPT_GetProvFunc(CPSetHashParam);
257 CRYPT_GetProvFunc(CPSetKeyParam);
258 CRYPT_GetProvFunc(CPSetProvParam);
259 CRYPT_GetProvFunc(CPSignHash);
260 CRYPT_GetProvFunc(CPVerifySignature);
262 /* FIXME: Not sure what the pbContextInfo field is for.
263 * Does it need memory allocation?
265 provider->pVTable->Version = 3;
266 provider->pVTable->FuncVerifyImage = CRYPT_VerifyImage;
267 provider->pVTable->FuncReturnhWnd = CRYPT_ReturnhWnd;
268 provider->pVTable->dwProvType = 0;
269 provider->pVTable->pbContextInfo = NULL;
270 provider->pVTable->cbContextInfo = 0;
271 provider->pVTable->pszProvName = NULL;
272 return provider;
274 error:
275 SetLastError(errorcode);
276 if (provider)
278 provider->dwMagic = 0;
279 if (provider->hModule)
280 FreeLibrary(provider->hModule);
281 CRYPT_Free(provider->pVTable);
282 CRYPT_Free(provider->pFuncs);
283 CRYPT_Free(provider);
285 return NULL;
287 #undef CRYPT_GetProvFunc
288 #undef CRYPT_GetProvFuncOpt
291 static void CRYPT_CreateMachineGuid(void)
293 LONG r;
294 HKEY key;
296 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Cryptography", 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY,
297 &key);
298 if (!r)
300 DWORD size;
302 r = RegQueryValueExW(key, L"MachineGuid", NULL, NULL, NULL, &size);
303 if (r == ERROR_FILE_NOT_FOUND)
305 UUID uuid;
306 WCHAR buf[37];
308 if (UuidCreate(&uuid) == S_OK)
310 swprintf(buf, ARRAY_SIZE(buf), L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
311 uuid.Data1, uuid.Data2, uuid.Data3,
312 uuid.Data4[0], uuid.Data4[1],
313 uuid.Data4[2], uuid.Data4[3],
314 uuid.Data4[4], uuid.Data4[5],
315 uuid.Data4[6], uuid.Data4[7] );
316 RegSetValueExW(key, L"MachineGuid", 0, REG_SZ,
317 (const BYTE *)buf,
318 (lstrlenW(buf)+1)*sizeof(WCHAR));
321 RegCloseKey(key);
326 /******************************************************************************
327 * CloseEncryptedFileRaw (ADVAPI32.@)
329 * Close encrypted files
331 * PARAMS
332 * context [I] pointer to the context
333 * RETURNS
334 * Success: ERROR_SUCCESS
335 * Failure: NTSTATUS error code
337 void WINAPI CloseEncryptedFileRaw(PVOID context)
339 FIXME("(%p): stub\n", context);
342 /******************************************************************************
343 * CryptAcquireContextW (ADVAPI32.@)
345 * Acquire a crypto provider context handle.
347 * PARAMS
348 * phProv [O] Pointer to HCRYPTPROV for the output.
349 * pszContainer [I] Key Container Name
350 * pszProvider [I] Cryptographic Service Provider Name
351 * dwProvType [I] Crypto provider type to get a handle.
352 * dwFlags [I] flags for the operation
354 * RETURNS
355 * TRUE on success, FALSE on failure.
357 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
358 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
360 PCRYPTPROV pProv = NULL;
361 HKEY key;
362 PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
363 PSTR provnameA = NULL, pszContainerA = NULL;
364 DWORD keytype, type, len;
365 ULONG r;
367 TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
368 debugstr_w(pszProvider), dwProvType, dwFlags);
370 if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
372 SetLastError(NTE_BAD_PROV_TYPE);
373 return FALSE;
376 if (!phProv)
378 SetLastError(ERROR_INVALID_PARAMETER);
379 return FALSE;
382 /* Make sure the MachineGuid value exists */
383 CRYPT_CreateMachineGuid();
385 if (!pszProvider || !*pszProvider)
387 /* No CSP name specified so try the user default CSP first
388 * then try the machine default CSP
390 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
391 TRACE("No provider registered for crypto provider type %ld.\n", dwProvType);
392 SetLastError(NTE_PROV_TYPE_NOT_DEF);
393 return FALSE;
395 if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
397 CRYPT_Free(keyname);
398 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
399 TRACE("No type registered for crypto provider type %ld.\n", dwProvType);
400 RegCloseKey(key);
401 SetLastError(NTE_PROV_TYPE_NOT_DEF);
402 goto error;
404 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
405 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
406 CRYPT_Free(keyname);
407 RegCloseKey(key);
408 SetLastError(NTE_PROV_TYPE_NOT_DEF);
409 goto error;
412 CRYPT_Free(keyname);
413 r = RegQueryValueExW(key, L"Name", NULL, &keytype, NULL, &len);
414 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
416 TRACE("error %ld reading size of 'Name' from registry\n", r );
417 RegCloseKey(key);
418 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
419 goto error;
421 if(!(provname = CRYPT_Alloc(len)))
423 RegCloseKey(key);
424 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
425 goto error;
427 r = RegQueryValueExW(key, L"Name", NULL, NULL, (LPBYTE)provname, &len);
428 if( r != ERROR_SUCCESS )
430 TRACE("error %ld reading 'Name' from registry\n", r );
431 RegCloseKey(key);
432 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
433 goto error;
435 RegCloseKey(key);
436 } else {
437 if ( !(provname = CRYPT_Alloc((lstrlenW(pszProvider) +1)*sizeof(WCHAR))) )
439 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
440 goto error;
442 lstrcpyW(provname, pszProvider);
445 keyname = CRYPT_GetProvKeyName(provname);
446 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
447 CRYPT_Free(keyname);
448 if (r != ERROR_SUCCESS)
450 SetLastError(NTE_KEYSET_NOT_DEF);
451 goto error;
453 len = sizeof(DWORD);
454 r = RegQueryValueExW(key, L"Type", NULL, NULL, (BYTE*)&type, &len);
455 if (r != ERROR_SUCCESS)
457 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
458 goto error;
460 if (type != dwProvType)
462 TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
463 SetLastError(NTE_PROV_TYPE_NO_MATCH);
464 goto error;
467 r = RegQueryValueExW(key, L"Image Path", NULL, &keytype, NULL, &len);
468 if ( r != ERROR_SUCCESS || keytype != REG_SZ)
470 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
471 RegCloseKey(key);
472 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
473 goto error;
475 if (!(temp = CRYPT_Alloc(len)))
477 RegCloseKey(key);
478 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
479 goto error;
481 r = RegQueryValueExW(key, L"Image Path", NULL, NULL, (LPBYTE)temp, &len);
482 if( r != ERROR_SUCCESS )
484 TRACE("error %ld reading 'Image Path' from registry\n", r );
485 RegCloseKey(key);
486 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
487 goto error;
489 RegCloseKey(key);
490 len = ExpandEnvironmentStringsW(temp, NULL, 0);
491 if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
493 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
494 goto error;
496 if (!ExpandEnvironmentStringsW(temp, imagepath, len))
498 /* ExpandEnvironmentStrings will call SetLastError */
499 goto error;
501 pProv = CRYPT_LoadProvider(imagepath);
502 if (!pProv) {
503 /* CRYPT_LoadProvider calls SetLastError */
504 goto error;
506 pProv->pVTable->dwProvType = dwProvType;
507 if(!CRYPT_UnicodeToANSI(provname, &provnameA, 0))
509 /* CRYPT_UnicodeToANSI calls SetLastError */
510 goto error;
512 pProv->pVTable->pszProvName = provnameA;
513 if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, 0))
515 /* CRYPT_UnicodeToANSI calls SetLastError */
516 goto error;
518 if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
520 /* MSDN: When this flag is set, the value returned in phProv is undefined,
521 * and thus, the CryptReleaseContext function need not be called afterwards.
522 * Therefore, we must clean up everything now.
524 if (dwFlags & CRYPT_DELETEKEYSET)
526 *phProv = 0;
527 pProv->dwMagic = 0;
528 FreeLibrary(pProv->hModule);
529 CRYPT_Free(provnameA);
530 CRYPT_Free(pProv->pVTable);
531 CRYPT_Free(pProv->pFuncs);
532 CRYPT_Free(pProv);
533 } else {
534 *phProv = (HCRYPTPROV)pProv;
536 CRYPT_Free(pszContainerA);
537 CRYPT_Free(provname);
538 CRYPT_Free(temp);
539 CRYPT_Free(imagepath);
540 return TRUE;
542 /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
543 error:
544 if (pProv)
546 pProv->dwMagic = 0;
547 if (pProv->hModule)
548 FreeLibrary(pProv->hModule);
549 CRYPT_Free(pProv->pVTable);
550 CRYPT_Free(pProv->pFuncs);
551 CRYPT_Free(pProv);
553 CRYPT_Free(pszContainerA);
554 CRYPT_Free(provnameA);
555 CRYPT_Free(provname);
556 CRYPT_Free(temp);
557 CRYPT_Free(imagepath);
558 return FALSE;
561 /******************************************************************************
562 * CryptAcquireContextA (ADVAPI32.@)
564 * See CryptAcquireContextW.
566 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
567 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
569 PWSTR pProvider = NULL, pContainer = NULL;
570 BOOL ret = FALSE;
572 TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_a(pszContainer),
573 debugstr_a(pszProvider), dwProvType, dwFlags);
575 if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
577 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
578 return FALSE;
580 if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
582 CRYPT_Free(pContainer);
583 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
584 return FALSE;
587 ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
589 CRYPT_Free(pContainer);
590 CRYPT_Free(pProvider);
592 return ret;
595 /******************************************************************************
596 * CryptContextAddRef (ADVAPI32.@)
598 * Increases reference count of a cryptographic service provider handle
599 * by one.
601 * PARAMS
602 * hProv [I] Handle to the CSP whose reference is being incremented.
603 * pdwReserved [IN] Reserved for future use and must be NULL.
604 * dwFlags [I] Reserved for future use and must be 0.
606 * RETURNS
607 * Success: TRUE
608 * Failure: FALSE
610 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
612 PCRYPTPROV pProv = provider_from_handle(hProv);
614 TRACE("(0x%Ix, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
616 if (!pProv)
617 return FALSE;
619 InterlockedIncrement(&pProv->refcount);
620 return TRUE;
623 /******************************************************************************
624 * CryptReleaseContext (ADVAPI32.@)
626 * Releases the handle of a CSP. Reference count is decreased.
628 * PARAMS
629 * hProv [I] Handle of a CSP.
630 * dwFlags [I] Reserved for future use and must be 0.
632 * RETURNS
633 * Success: TRUE
634 * Failure: FALSE
636 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
638 PCRYPTPROV pProv = provider_from_handle(hProv);
639 BOOL ret = TRUE;
641 TRACE("(0x%Ix, %08lx)\n", hProv, dwFlags);
643 if (!pProv)
644 return FALSE;
646 if (InterlockedDecrement(&pProv->refcount) == 0)
648 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
649 pProv->dwMagic = 0;
650 FreeLibrary(pProv->hModule);
651 #if 0
652 CRYPT_Free(pProv->pVTable->pContextInfo);
653 #endif
654 CRYPT_Free(pProv->pVTable->pszProvName);
655 CRYPT_Free(pProv->pVTable);
656 CRYPT_Free(pProv->pFuncs);
657 CRYPT_Free(pProv);
659 return ret;
662 /******************************************************************************
663 * CryptGenRandom (ADVAPI32.@)
665 * Fills a buffer with cryptographically random bytes.
667 * PARAMS
668 * hProv [I] Handle of a CSP.
669 * dwLen [I] Number of bytes to generate.
670 * pbBuffer [I/O] Buffer to contain random bytes.
672 * RETURNS
673 * Success: TRUE
674 * Failure: FALSE
676 * NOTES
677 * pdBuffer must be at least dwLen bytes long.
679 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
681 PCRYPTPROV prov = provider_from_handle(hProv);
683 TRACE("(0x%Ix, %ld, %p)\n", hProv, dwLen, pbBuffer);
685 if (!prov)
686 return FALSE;
688 return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
691 /******************************************************************************
692 * CryptCreateHash (ADVAPI32.@)
694 * Initiates the hashing of a stream of data.
696 * PARAMS
697 * hProv [I] Handle of a CSP.
698 * Algid [I] Identifies the hash algorithm to use.
699 * hKey [I] Key for the hash (if required).
700 * dwFlags [I] Reserved for future use and must be 0.
701 * phHash [O] Address of the future handle to the new hash object.
703 * RETURNS
704 * Success: TRUE
705 * Failure: FALSE
707 * NOTES
708 * If the algorithm is a keyed hash, hKey is the key.
710 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
711 DWORD dwFlags, HCRYPTHASH *phHash)
713 PCRYPTKEY key = NULL;
714 PCRYPTPROV prov;
715 PCRYPTHASH hash;
717 TRACE("(0x%Ix, 0x%x, 0x%Ix, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
719 if (!(prov = provider_from_handle(hProv)))
720 return FALSE;
722 if (hKey && !(key = key_from_handle(hKey)))
723 return FALSE;
725 if (!phHash)
727 SetLastError(ERROR_INVALID_PARAMETER);
728 return FALSE;
730 if (dwFlags)
732 SetLastError(NTE_BAD_FLAGS);
733 return FALSE;
735 if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
737 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
738 return FALSE;
741 hash->pProvider = prov;
742 hash->dwMagic = MAGIC_CRYPTHASH;
743 if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
744 key ? key->hPrivate : 0, 0, &hash->hPrivate))
746 *phHash = (HCRYPTHASH)hash;
747 return TRUE;
750 /* CSP error! */
751 hash->dwMagic = 0;
752 CRYPT_Free(hash);
753 *phHash = 0;
754 return FALSE;
757 /******************************************************************************
758 * CryptDecrypt (ADVAPI32.@)
760 * Decrypts data encrypted by CryptEncrypt.
762 * PARAMS
763 * hKey [I] Handle to the decryption key.
764 * hHash [I] Handle to a hash object.
765 * Final [I] TRUE if this is the last section to be decrypted.
766 * dwFlags [I] Reserved for future use. Can be CRYPT_OAEP.
767 * pbData [I/O] Buffer that holds the encrypted data. Holds decrypted
768 * data on return
769 * pdwDataLen [I/O] Length of pbData before and after the call.
771 * RETURNS
772 * Success: TRUE
773 * Failure: FALSE
775 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
776 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
778 PCRYPTHASH hash = NULL;
779 PCRYPTPROV prov;
780 PCRYPTKEY key;
782 TRACE("(0x%Ix, 0x%Ix, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
784 if (!(key = key_from_handle(hKey)))
785 return FALSE;
787 if (hHash && !(hash = hash_from_handle(hHash)))
788 return FALSE;
790 if (!pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
792 SetLastError(ERROR_INVALID_PARAMETER);
793 return FALSE;
796 prov = key->pProvider;
797 return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
798 Final, dwFlags, pbData, pdwDataLen);
801 /******************************************************************************
802 * CryptDeriveKey (ADVAPI32.@)
804 * Generates session keys derived from a base data value.
806 * PARAMS
807 * hProv [I] Handle to a CSP.
808 * Algid [I] Identifies the symmetric encryption algorithm to use.
809 * hBaseData [I] Handle to a hash object.
810 * dwFlags [I] Type of key to generate.
811 * phKey [I/O] Address of the newly generated key.
813 * RETURNS
814 * Success: TRUE
815 * Failure: FALSE
817 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
818 DWORD dwFlags, HCRYPTKEY *phKey)
820 PCRYPTPROV prov;
821 PCRYPTHASH hash;
822 PCRYPTKEY key;
824 TRACE("(0x%Ix, 0x%08x, 0x%Ix, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
826 if (!(prov = provider_from_handle(hProv)))
827 return FALSE;
829 if (!(hash = hash_from_handle(hBaseData)))
830 return FALSE;
832 if (!phKey)
834 SetLastError(ERROR_INVALID_PARAMETER);
835 return FALSE;
837 if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
839 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
840 return FALSE;
843 key->pProvider = prov;
844 key->dwMagic = MAGIC_CRYPTKEY;
845 if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
847 *phKey = (HCRYPTKEY)key;
848 return TRUE;
851 /* CSP error! */
852 key->dwMagic = 0;
853 CRYPT_Free(key);
854 *phKey = 0;
855 return FALSE;
858 /******************************************************************************
859 * CryptDestroyHash (ADVAPI32.@)
861 * Destroys the hash object referenced by hHash.
863 * PARAMS
864 * hHash [I] Handle of the hash object to be destroyed.
866 * RETURNS
867 * Success: TRUE
868 * Failure: FALSE
870 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
872 PCRYPTHASH hash;
873 PCRYPTPROV prov;
874 BOOL ret;
876 TRACE("(0x%Ix)\n", hHash);
878 if (!(hash = hash_from_handle(hHash)))
879 return FALSE;
881 if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
883 SetLastError(ERROR_INVALID_PARAMETER);
884 return FALSE;
887 prov = hash->pProvider;
888 ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
889 hash->dwMagic = 0;
890 CRYPT_Free(hash);
891 return ret;
894 /******************************************************************************
895 * CryptDestroyKey (ADVAPI32.@)
897 * Releases the handle referenced by hKey.
899 * PARAMS
900 * hKey [I] Handle of the key to be destroyed.
902 * RETURNS
903 * Success: TRUE
904 * Failure: FALSE
906 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
908 PCRYPTPROV prov;
909 PCRYPTKEY key;
910 BOOL ret;
912 TRACE("(0x%Ix)\n", hKey);
914 if (!(key = key_from_handle(hKey)))
915 return FALSE;
917 if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
919 SetLastError(ERROR_INVALID_PARAMETER);
920 return FALSE;
923 prov = key->pProvider;
924 ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
925 key->dwMagic = 0;
926 CRYPT_Free(key);
927 return ret;
930 /******************************************************************************
931 * CryptDuplicateHash (ADVAPI32.@)
933 * Duplicates a hash.
935 * PARAMS
936 * hHash [I] Handle to the hash to be copied.
937 * pdwReserved [I] Reserved for future use and must be NULL.
938 * dwFlags [I] Reserved for future use and must be zero.
939 * phHash [O] Address of the handle to receive the copy.
941 * RETURNS
942 * Success: TRUE
943 * Failure: FALSE
945 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
946 DWORD dwFlags, HCRYPTHASH *phHash)
948 PCRYPTPROV prov;
949 PCRYPTHASH orghash, newhash;
951 TRACE("(0x%Ix, %p, %08lx, %p)\n", hHash, pdwReserved, dwFlags, phHash);
953 if (!(orghash = hash_from_handle(hHash)))
954 return FALSE;
956 if (pdwReserved || !phHash || !orghash->pProvider || orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
958 SetLastError(ERROR_INVALID_PARAMETER);
959 return FALSE;
962 prov = orghash->pProvider;
963 if (!prov->pFuncs->pCPDuplicateHash)
965 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
966 return FALSE;
969 if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
971 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
972 return FALSE;
975 newhash->pProvider = prov;
976 newhash->dwMagic = MAGIC_CRYPTHASH;
977 if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
979 *phHash = (HCRYPTHASH)newhash;
980 return TRUE;
982 newhash->dwMagic = 0;
983 CRYPT_Free(newhash);
984 return FALSE;
987 /******************************************************************************
988 * CryptDuplicateKey (ADVAPI32.@)
990 * Duplicate a key and the key's state.
992 * PARAMS
993 * hKey [I] Handle of the key to copy.
994 * pdwReserved [I] Reserved for future use and must be NULL.
995 * dwFlags [I] Reserved for future use and must be zero.
996 * phKey [I] Address of the handle to the duplicated key.
998 * RETURNS
999 * Success: TRUE
1000 * Failure: FALSE
1002 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
1004 PCRYPTPROV prov;
1005 PCRYPTKEY orgkey, newkey;
1007 TRACE("(0x%Ix, %p, %08lx, %p)\n", hKey, pdwReserved, dwFlags, phKey);
1009 if (!(orgkey = key_from_handle(hKey)))
1010 return FALSE;
1012 if (pdwReserved || !phKey || !orgkey->pProvider || orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
1014 SetLastError(ERROR_INVALID_PARAMETER);
1015 return FALSE;
1018 prov = orgkey->pProvider;
1019 if (!prov->pFuncs->pCPDuplicateKey)
1021 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1022 return FALSE;
1025 if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1027 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1028 return FALSE;
1031 newkey->pProvider = prov;
1032 newkey->dwMagic = MAGIC_CRYPTKEY;
1033 if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
1035 *phKey = (HCRYPTKEY)newkey;
1036 return TRUE;
1038 newkey->dwMagic = 0;
1039 CRYPT_Free(newkey);
1040 return FALSE;
1043 /******************************************************************************
1044 * CryptEncrypt (ADVAPI32.@)
1046 * Encrypts data.
1048 * PARAMS
1049 * hKey [I] Handle to the encryption key.
1050 * hHash [I] Handle to a hash object.
1051 * Final [I] TRUE if this is the last section to encrypt.
1052 * dwFlags [I] Can be CRYPT_OAEP.
1053 * pbData [I/O] Data to be encrypted. Contains encrypted data after call.
1054 * pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
1055 * encrypted data after call.
1056 * dwBufLen [I] Length of the input pbData buffer.
1058 * RETURNS
1059 * Success: TRUE
1060 * Failure: FALSE
1062 * NOTES
1063 * If pbData is NULL, CryptEncrypt determines stores the number of bytes
1064 * required for the returned data in pdwDataLen.
1066 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1067 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1069 PCRYPTHASH hash = NULL;
1070 PCRYPTPROV prov;
1071 PCRYPTKEY key;
1073 TRACE("(0x%Ix, 0x%Ix, %d, %08lx, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1075 if (!(key = key_from_handle(hKey)))
1076 return FALSE;
1078 if (hHash && !(hash = hash_from_handle(hHash)))
1079 return FALSE;
1081 if (!pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1083 SetLastError(ERROR_INVALID_PARAMETER);
1084 return FALSE;
1087 prov = key->pProvider;
1088 return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
1089 Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1092 /******************************************************************************
1093 * CryptEnumProvidersW (ADVAPI32.@)
1095 * Returns the next available CSP.
1097 * PARAMS
1098 * dwIndex [I] Index of the next provider to be enumerated.
1099 * pdwReserved [I] Reserved for future use and must be NULL.
1100 * dwFlags [I] Reserved for future use and must be zero.
1101 * pdwProvType [O] DWORD designating the type of the provider.
1102 * pszProvName [O] Buffer that receives data from the provider.
1103 * pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
1104 * of bytes stored in the buffer on return.
1106 * RETURNS
1107 * Success: TRUE
1108 * Failure: FALSE
1110 * NOTES
1111 * If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
1112 * for memory allocation purposes.
1114 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
1115 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
1117 HKEY hKey;
1118 BOOL ret;
1120 TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1121 pdwProvType, pszProvName, pcbProvName);
1123 if (pdwReserved || !pcbProvName)
1125 SetLastError(ERROR_INVALID_PARAMETER);
1126 return FALSE;
1128 if (dwFlags)
1130 SetLastError(NTE_BAD_FLAGS);
1131 return FALSE;
1134 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
1136 SetLastError(NTE_FAIL);
1137 return FALSE;
1140 ret = TRUE;
1141 if (!pszProvName)
1143 DWORD numkeys;
1144 WCHAR *provNameW;
1146 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
1147 NULL, NULL, NULL, NULL, NULL, NULL);
1149 if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
1151 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1152 RegCloseKey(hKey);
1153 return FALSE;
1156 RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1157 CRYPT_Free(provNameW);
1158 (*pcbProvName)++;
1159 *pcbProvName *= sizeof(WCHAR);
1161 if (dwIndex >= numkeys)
1163 SetLastError(ERROR_NO_MORE_ITEMS);
1164 ret = FALSE;
1166 } else {
1167 DWORD size = sizeof(DWORD);
1168 DWORD result;
1169 HKEY subkey;
1171 result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1172 if (result)
1174 SetLastError(result);
1175 RegCloseKey(hKey);
1176 return FALSE;
1178 if (RegOpenKeyW(hKey, pszProvName, &subkey))
1180 RegCloseKey(hKey);
1181 return FALSE;
1184 if (RegQueryValueExW(subkey, L"Type", NULL, NULL, (BYTE*)pdwProvType, &size))
1185 ret = FALSE;
1187 RegCloseKey(subkey);
1189 RegCloseKey(hKey);
1190 return ret;
1193 /******************************************************************************
1194 * CryptEnumProvidersA (ADVAPI32.@)
1196 * See CryptEnumProvidersW.
1198 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1199 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1201 PWSTR str = NULL;
1202 DWORD bufsize;
1203 BOOL ret;
1205 TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1206 pdwProvType, pszProvName, pcbProvName);
1208 if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
1209 return FALSE;
1210 if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
1212 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1213 return FALSE;
1215 ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
1216 if (str)
1217 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1218 *pcbProvName = bufsize / sizeof(WCHAR); /* FIXME: not correct */
1219 if (str)
1221 CRYPT_Free(str);
1222 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1224 SetLastError(ERROR_MORE_DATA);
1225 return FALSE;
1228 return ret;
1231 /******************************************************************************
1232 * CryptEnumProviderTypesW (ADVAPI32.@)
1234 * Retrieves the next type of CSP supported.
1236 * PARAMS
1237 * dwIndex [I] Index of the next provider to be enumerated.
1238 * pdwReserved [I] Reserved for future use and must be NULL.
1239 * dwFlags [I] Reserved for future use and must be zero.
1240 * pdwProvType [O] DWORD designating the type of the provider.
1241 * pszTypeName [O] Buffer that receives data from the provider type.
1242 * pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1243 * of bytes stored in the buffer on return.
1245 * RETURNS
1246 * Success: TRUE
1247 * Failure: FALSE
1249 * NOTES
1250 * If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
1251 * for memory allocation purposes.
1253 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1254 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1256 HKEY hKey, hSubkey;
1257 DWORD keylen, numkeys, dwType;
1258 PWSTR keyname, ch;
1259 DWORD result;
1261 TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved,
1262 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1264 if (pdwReserved || !pdwProvType || !pcbTypeName)
1266 SetLastError(ERROR_INVALID_PARAMETER);
1267 return FALSE;
1269 if (dwFlags)
1271 SetLastError(NTE_BAD_FLAGS);
1272 return FALSE;
1275 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
1276 return FALSE;
1278 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1279 if (dwIndex >= numkeys)
1281 SetLastError(ERROR_NO_MORE_ITEMS);
1282 RegCloseKey(hKey);
1283 return FALSE;
1285 keylen++;
1286 if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
1288 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1289 RegCloseKey(hKey);
1290 return FALSE;
1292 if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
1293 CRYPT_Free(keyname);
1294 RegCloseKey(hKey);
1295 return FALSE;
1297 RegOpenKeyW(hKey, keyname, &hSubkey);
1298 RegCloseKey(hKey);
1300 ch = keyname + lstrlenW(keyname);
1301 /* Convert "Type 000" to 0, etc/ */
1302 *pdwProvType = *(--ch) - '0';
1303 *pdwProvType += (*(--ch) - '0') * 10;
1304 *pdwProvType += (*(--ch) - '0') * 100;
1305 CRYPT_Free(keyname);
1307 result = RegQueryValueExW(hSubkey, L"TypeName", NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
1308 if (result)
1310 SetLastError(result);
1311 RegCloseKey(hSubkey);
1312 return FALSE;
1315 RegCloseKey(hSubkey);
1316 return TRUE;
1319 /******************************************************************************
1320 * CryptEnumProviderTypesA (ADVAPI32.@)
1322 * See CryptEnumProviderTypesW.
1324 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1325 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1327 PWSTR str = NULL;
1328 DWORD bufsize;
1329 BOOL ret;
1331 TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1332 pdwProvType, pszTypeName, pcbTypeName);
1334 if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
1335 return FALSE;
1336 if ( pszTypeName && !(str = CRYPT_Alloc(bufsize)) )
1338 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1339 return FALSE;
1341 ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
1342 if (str)
1343 CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
1344 *pcbTypeName = bufsize / sizeof(WCHAR);
1345 if (str)
1347 CRYPT_Free(str);
1348 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1350 SetLastError(ERROR_MORE_DATA);
1351 return FALSE;
1354 return ret;
1357 /******************************************************************************
1358 * CryptExportKey (ADVAPI32.@)
1360 * Exports a cryptographic key from a CSP.
1362 * PARAMS
1363 * hKey [I] Handle to the key to export.
1364 * hExpKey [I] Handle to a cryptographic key of the end user.
1365 * dwBlobType [I] Type of BLOB to be exported.
1366 * dwFlags [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1367 * pbData [O] Buffer to receive BLOB data.
1368 * pdwDataLen [I/O] Specifies the size of pbData.
1370 * RETURNS
1371 * Success: TRUE
1372 * Failure: FALSE
1374 * NOTES
1375 * if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1376 * buffer needed to hold the BLOB.
1378 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1379 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1381 PCRYPTPROV prov;
1382 PCRYPTKEY key, expkey = NULL;
1384 TRACE("(0x%Ix, 0x%Ix, %ld, %08lx, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1386 if (!(key = key_from_handle(hKey)))
1387 return FALSE;
1389 if (hExpKey && !(expkey = key_from_handle(hExpKey)))
1390 return FALSE;
1392 if (!pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1394 SetLastError(ERROR_INVALID_PARAMETER);
1395 return FALSE;
1398 prov = key->pProvider;
1399 return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1400 dwBlobType, dwFlags, pbData, pdwDataLen);
1403 /******************************************************************************
1404 * CryptGenKey (ADVAPI32.@)
1406 * Generates a random cryptographic session key or a pub/priv key pair.
1408 * PARAMS
1409 * hProv [I] Handle to a CSP.
1410 * Algid [I] Algorithm to use to make key.
1411 * dwFlags [I] Specifies type of key to make.
1412 * phKey [I] Address of the handle to which the new key is copied.
1414 * RETURNS
1415 * Success: TRUE
1416 * Failure: FALSE
1418 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1420 PCRYPTPROV prov;
1421 PCRYPTKEY key;
1423 TRACE("(0x%Ix, %d, %08lx, %p)\n", hProv, Algid, dwFlags, phKey);
1425 if (!(prov = provider_from_handle(hProv)))
1426 return FALSE;
1428 if (!phKey)
1430 SetLastError(ERROR_INVALID_PARAMETER);
1431 return FALSE;
1433 if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1435 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1436 return FALSE;
1439 key->pProvider = prov;
1440 key->dwMagic = MAGIC_CRYPTKEY;
1441 if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1443 *phKey = (HCRYPTKEY)key;
1444 return TRUE;
1447 /* CSP error! */
1448 key->dwMagic = 0;
1449 CRYPT_Free(key);
1450 return FALSE;
1453 /******************************************************************************
1454 * CryptGetDefaultProviderW (ADVAPI32.@)
1456 * Finds the default CSP of a certain provider type.
1458 * PARAMS
1459 * dwProvType [I] Provider type to look for.
1460 * pdwReserved [I] Reserved for future use and must be NULL.
1461 * dwFlags [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1462 * pszProvName [O] Name of the default CSP.
1463 * pcbProvName [I/O] Size of pszProvName
1465 * RETURNS
1466 * Success: TRUE
1467 * Failure: FALSE
1469 * NOTES
1470 * If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1471 * memory allocation purposes on return.
1473 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1474 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1476 HKEY hKey;
1477 PWSTR keyname;
1478 DWORD result;
1480 if (pdwReserved || !pcbProvName)
1482 SetLastError(ERROR_INVALID_PARAMETER);
1483 return FALSE;
1485 if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1487 SetLastError(NTE_BAD_FLAGS);
1488 return FALSE;
1490 if (dwProvType > 999)
1492 SetLastError(NTE_BAD_PROV_TYPE);
1493 return FALSE;
1495 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1497 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1498 return FALSE;
1500 if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1502 CRYPT_Free(keyname);
1503 SetLastError(NTE_PROV_TYPE_NOT_DEF);
1504 return FALSE;
1506 CRYPT_Free(keyname);
1508 result = RegQueryValueExW(hKey, L"Name", NULL, NULL, (LPBYTE)pszProvName, pcbProvName);
1509 RegCloseKey(hKey);
1511 if (result)
1513 if (result != ERROR_MORE_DATA)
1514 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1515 else
1516 SetLastError(result);
1518 return FALSE;
1521 return TRUE;
1524 /******************************************************************************
1525 * CryptGetDefaultProviderA (ADVAPI32.@)
1527 * See CryptGetDefaultProviderW.
1529 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1530 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1532 PWSTR str = NULL;
1533 DWORD bufsize;
1534 BOOL ret;
1536 TRACE("(%ld, %p, %08lx, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1538 CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &bufsize);
1539 if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
1541 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1542 return FALSE;
1544 ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &bufsize);
1545 if (str)
1546 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1547 *pcbProvName = bufsize / sizeof(WCHAR);
1548 if (str)
1550 CRYPT_Free(str);
1551 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1553 SetLastError(ERROR_MORE_DATA);
1554 return FALSE;
1557 return ret;
1560 /******************************************************************************
1561 * CryptGetHashParam (ADVAPI32.@)
1563 * Retrieves data that controls the operations of a hash object.
1565 * PARAMS
1566 * hHash [I] Handle of the hash object to question.
1567 * dwParam [I] Query type.
1568 * pbData [O] Buffer that receives the value data.
1569 * pdwDataLen [I/O] Size of the pbData buffer.
1570 * dwFlags [I] Reserved for future use and must be zero.
1572 * RETURNS
1573 * Success: TRUE
1574 * Failure: FALSE
1576 * NOTES
1577 * If pbData is NULL, pdwDataLen will contain the length required.
1579 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1580 DWORD *pdwDataLen, DWORD dwFlags)
1582 PCRYPTPROV prov;
1583 PCRYPTHASH hash;
1585 TRACE("(0x%Ix, %ld, %p, %p, %08lx)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1587 if (!(hash = hash_from_handle(hHash)))
1588 return FALSE;
1591 if (!pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1593 SetLastError(ERROR_INVALID_PARAMETER);
1594 return FALSE;
1597 prov = hash->pProvider;
1598 return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1599 pbData, pdwDataLen, dwFlags);
1602 /******************************************************************************
1603 * CryptGetKeyParam (ADVAPI32.@)
1605 * Retrieves data that controls the operations of a key.
1607 * PARAMS
1608 * hKey [I] Handle to they key in question.
1609 * dwParam [I] Specifies query type.
1610 * pbData [O] Sequence of bytes to receive data.
1611 * pdwDataLen [I/O] Size of pbData.
1612 * dwFlags [I] Reserved for future use and must be zero.
1614 * RETURNS
1615 * Success: TRUE
1616 * Failure: FALSE
1618 * NOTES
1619 * If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1621 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1622 DWORD *pdwDataLen, DWORD dwFlags)
1624 PCRYPTPROV prov;
1625 PCRYPTKEY key;
1627 TRACE("(0x%Ix, %ld, %p, %p, %08lx)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1629 if (!(key = key_from_handle(hKey)))
1630 return FALSE;
1632 if (!pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1634 SetLastError(ERROR_INVALID_PARAMETER);
1635 return FALSE;
1638 prov = key->pProvider;
1639 return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1640 pbData, pdwDataLen, dwFlags);
1643 /******************************************************************************
1644 * CryptGetProvParam (ADVAPI32.@)
1646 * Retrieves parameters that control the operations of a CSP.
1648 * PARAMS
1649 * hProv [I] Handle of the CSP in question.
1650 * dwParam [I] Specifies query type.
1651 * pbData [O] Buffer to receive the data.
1652 * pdwDataLen [I/O] Size of pbData.
1653 * dwFlags [I] see MSDN Docs.
1655 * RETURNS
1656 * Success: TRUE
1657 * Failure: FALSE
1659 * NOTES
1660 * If pbData is NULL, pdwDataLen is set to the needed buffer length.
1662 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1663 DWORD *pdwDataLen, DWORD dwFlags)
1665 PCRYPTPROV prov;
1667 TRACE("(0x%Ix, %ld, %p, %p, %08lx)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1669 if (!(prov = provider_from_handle(hProv)))
1670 return FALSE;
1672 return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1675 /******************************************************************************
1676 * CryptGetUserKey (ADVAPI32.@)
1678 * Gets a handle of one of a user's two public/private key pairs.
1680 * PARAMS
1681 * hProv [I] Handle of a CSP.
1682 * dwKeySpec [I] Private key to use.
1683 * phUserKey [O] Pointer to the handle of the retrieved keys.
1685 * RETURNS
1686 * Success: TRUE
1687 * Failure: FALSE
1689 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1691 PCRYPTPROV prov;
1692 PCRYPTKEY key;
1694 TRACE("(0x%Ix, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1696 if (!(prov = provider_from_handle(hProv)))
1697 return FALSE;
1699 if (!phUserKey)
1701 SetLastError(ERROR_INVALID_PARAMETER);
1702 return FALSE;
1704 if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1706 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1707 return FALSE;
1710 key->pProvider = prov;
1711 key->dwMagic = MAGIC_CRYPTKEY;
1712 if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1714 *phUserKey = (HCRYPTKEY)key;
1715 return TRUE;
1718 /* CSP Error */
1719 key->dwMagic = 0;
1720 CRYPT_Free(key);
1721 *phUserKey = 0;
1722 return FALSE;
1725 /******************************************************************************
1726 * CryptHashData (ADVAPI32.@)
1728 * Adds data to a hash object.
1730 * PARAMS
1731 * hHash [I] Handle of the hash object.
1732 * pbData [I] Buffer of data to be hashed.
1733 * dwDataLen [I] Number of bytes to add.
1734 * dwFlags [I] Can be CRYPT_USERDATA
1736 * RETURNS
1737 * Success: TRUE
1738 * Failure: FALSE
1740 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1742 PCRYPTHASH hash;
1743 PCRYPTPROV prov;
1745 TRACE("(0x%Ix, %p, %ld, %08lx)\n", hHash, pbData, dwDataLen, dwFlags);
1747 if (!(hash = hash_from_handle(hHash)))
1748 return FALSE;
1750 if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1752 SetLastError(ERROR_INVALID_PARAMETER);
1753 return FALSE;
1756 prov = hash->pProvider;
1757 return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1760 /******************************************************************************
1761 * CryptHashSessionKey (ADVAPI32.@)
1763 * Compute the cryptographic hash of a session key object.
1765 * PARAMS
1766 * hHash [I] Handle to the hash object.
1767 * hKey [I] Handle to the key to be hashed.
1768 * dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1770 * RETURNS
1771 * Success: TRUE
1772 * Failure: FALSE
1774 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1776 PCRYPTHASH hash;
1777 PCRYPTKEY key;
1778 PCRYPTPROV prov;
1780 TRACE("(0x%Ix, 0x%Ix, %08lx)\n", hHash, hKey, dwFlags);
1782 if (!(hash = hash_from_handle(hHash)))
1783 return FALSE;
1785 if (!(key = key_from_handle(hKey)))
1786 return FALSE;
1788 if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1790 SetLastError(ERROR_INVALID_PARAMETER);
1791 return FALSE;
1794 prov = hash->pProvider;
1795 return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1798 /******************************************************************************
1799 * CryptImportKey (ADVAPI32.@)
1801 * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
1803 * PARAMS
1804 * hProv [I] Handle of a CSP.
1805 * pbData [I] Contains the key to be imported.
1806 * dwDataLen [I] Length of the key.
1807 * hPubKey [I] Cryptographic key that decrypts pdData
1808 * dwFlags [I] Used only with a public/private key pair.
1809 * phKey [O] Imported key.
1811 * RETURNS
1812 * Success: TRUE
1813 * Failure: FALSE
1815 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, const BYTE *pbData, DWORD dwDataLen,
1816 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1818 PCRYPTPROV prov;
1819 PCRYPTKEY pubkey = NULL, importkey;
1821 TRACE("(0x%Ix, %p, %ld, 0x%Ix, %08lx, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1823 if (!(prov = provider_from_handle(hProv)))
1824 return FALSE;
1826 if (hPubKey && !(pubkey = key_from_handle(hPubKey)))
1827 return FALSE;
1829 if (!pbData || !dwDataLen || !phKey)
1831 SetLastError(ERROR_INVALID_PARAMETER);
1832 return FALSE;
1835 if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1837 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1838 return FALSE;
1841 importkey->pProvider = prov;
1842 importkey->dwMagic = MAGIC_CRYPTKEY;
1843 if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1844 pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1846 *phKey = (HCRYPTKEY)importkey;
1847 return TRUE;
1850 importkey->dwMagic = 0;
1851 CRYPT_Free(importkey);
1852 return FALSE;
1855 /******************************************************************************
1856 * CryptSignHashW (ADVAPI32.@)
1858 * Signs data.
1860 * PARAMS
1861 * hHash [I] Handle of the hash object to be signed.
1862 * dwKeySpec [I] Private key to use.
1863 * sDescription [I] Should be NULL.
1864 * dwFlags [I] CRYPT_NOHASHOID/X931_FORMAT.
1865 * pbSignature [O] Buffer of the signature data.
1866 * pdwSigLen [I/O] Size of the pbSignature buffer.
1868 * RETURNS
1869 * Success: TRUE
1870 * Failure: FALSE
1872 * NOTES
1873 * Because of security flaws sDescription should not be used and should thus be
1874 * NULL. It is supported only for compatibility with Microsoft's Cryptographic
1875 * Providers.
1877 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1878 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1880 PCRYPTHASH hash;
1881 PCRYPTPROV prov;
1883 TRACE("(0x%Ix, %ld, %s, %08lx, %p, %p)\n",
1884 hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1886 if (!(hash = hash_from_handle(hHash)))
1887 return FALSE;
1889 if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1891 SetLastError(ERROR_INVALID_PARAMETER);
1892 return FALSE;
1895 prov = hash->pProvider;
1896 return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1897 dwFlags, pbSignature, pdwSigLen);
1900 /******************************************************************************
1901 * CryptSignHashA (ADVAPI32.@)
1903 * See CryptSignHashW.
1905 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1906 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1908 LPWSTR wsDescription;
1909 BOOL result;
1911 TRACE("(0x%Ix, %ld, %s, %08lx, %p, %p)\n",
1912 hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
1914 CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1915 result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1916 CRYPT_Free(wsDescription);
1918 return result;
1921 /******************************************************************************
1922 * CryptSetHashParam (ADVAPI32.@)
1924 * Customizes the operations of a hash object.
1926 * PARAMS
1927 * hHash [I] Handle of the hash object to set parameters.
1928 * dwParam [I] HP_HMAC_INFO/HASHVAL.
1929 * pbData [I] Value data buffer.
1930 * dwFlags [I] Reserved for future use and must be zero.
1932 * RETURNS
1933 * Success: TRUE
1934 * Failure: FALSE
1936 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
1938 PCRYPTPROV prov;
1939 PCRYPTHASH hash;
1941 TRACE("(0x%Ix, %ld, %p, %08lx)\n", hHash, dwParam, pbData, dwFlags);
1943 if (!(hash = hash_from_handle(hHash)))
1944 return FALSE;
1946 if (!pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1948 SetLastError(ERROR_INVALID_PARAMETER);
1949 return FALSE;
1952 prov = hash->pProvider;
1953 return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1954 dwParam, pbData, dwFlags);
1957 /******************************************************************************
1958 * CryptSetKeyParam (ADVAPI32.@)
1960 * Customizes a session key's operations.
1962 * PARAMS
1963 * hKey [I] Handle to the key to set values.
1964 * dwParam [I] See MSDN Doc.
1965 * pbData [I] Buffer of values to set.
1966 * dwFlags [I] Only used when dwParam == KP_ALGID.
1968 * RETURNS
1969 * Success: TRUE
1970 * Failure: FALSE
1972 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
1974 PCRYPTPROV prov;
1975 PCRYPTKEY key;
1977 TRACE("(0x%Ix, %ld, %p, %08lx)\n", hKey, dwParam, pbData, dwFlags);
1979 if (!(key = key_from_handle(hKey)))
1980 return FALSE;
1982 if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1984 SetLastError(ERROR_INVALID_PARAMETER);
1985 return FALSE;
1988 prov = key->pProvider;
1989 return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1990 dwParam, pbData, dwFlags);
1993 /******************************************************************************
1994 * CryptSetProviderA (ADVAPI32.@)
1996 * Specifies the current user's default CSP.
1998 * PARAMS
1999 * pszProvName [I] Name of the new default CSP.
2000 * dwProvType [I] Provider type of the CSP.
2002 * RETURNS
2003 * Success: TRUE
2004 * Failure: FALSE
2006 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
2008 TRACE("(%s, %ld)\n", pszProvName, dwProvType);
2009 return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
2012 /******************************************************************************
2013 * CryptSetProviderW (ADVAPI32.@)
2015 * See CryptSetProviderA.
2017 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
2019 TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
2020 return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
2023 /******************************************************************************
2024 * CryptSetProviderExW (ADVAPI32.@)
2026 * Specifies the default CSP.
2028 * PARAMS
2029 * pszProvName [I] Name of the new default CSP.
2030 * dwProvType [I] Provider type of the CSP.
2031 * pdwReserved [I] Reserved for future use and must be NULL.
2032 * dwFlags [I] See MSDN Doc.
2034 * RETURNS
2035 * Success: TRUE
2036 * Failure: FALSE
2038 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2040 HKEY hProvKey, hTypeKey;
2041 PWSTR keyname;
2043 TRACE("(%s, %ld, %p, %08lx)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
2045 if (!pszProvName || pdwReserved)
2047 SetLastError(ERROR_INVALID_PARAMETER);
2048 return FALSE;
2050 if (dwProvType > MAXPROVTYPES)
2052 SetLastError(NTE_BAD_PROV_TYPE);
2053 return FALSE;
2055 if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
2056 || dwFlags == CRYPT_DELETE_DEFAULT)
2058 SetLastError(NTE_BAD_FLAGS);
2059 return FALSE;
2062 if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
2064 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2065 return FALSE;
2067 if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2068 keyname, &hTypeKey))
2070 CRYPT_Free(keyname);
2071 SetLastError(NTE_BAD_PROVIDER);
2072 return FALSE;
2074 CRYPT_Free(keyname);
2076 if (dwFlags & CRYPT_DELETE_DEFAULT)
2078 RegDeleteValueW(hTypeKey, L"Name");
2080 else
2082 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
2084 RegCloseKey(hTypeKey);
2085 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2086 return FALSE;
2088 if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2089 keyname, &hProvKey))
2091 CRYPT_Free(keyname);
2092 RegCloseKey(hTypeKey);
2093 SetLastError(NTE_BAD_PROVIDER);
2094 return FALSE;
2096 CRYPT_Free(keyname);
2098 if (RegSetValueExW(hTypeKey, L"Name", 0, REG_SZ, (const BYTE *)pszProvName,
2099 (lstrlenW(pszProvName) + 1)*sizeof(WCHAR)))
2101 RegCloseKey(hTypeKey);
2102 RegCloseKey(hProvKey);
2103 return FALSE;
2106 RegCloseKey(hProvKey);
2108 RegCloseKey(hTypeKey);
2110 return TRUE;
2113 /******************************************************************************
2114 * CryptSetProviderExA (ADVAPI32.@)
2116 * See CryptSetProviderExW.
2118 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2120 BOOL ret = FALSE;
2121 PWSTR str = NULL;
2123 TRACE("(%s, %ld, %p, %08lx)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
2125 if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
2127 ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
2128 CRYPT_Free(str);
2130 return ret;
2133 /******************************************************************************
2134 * CryptSetProvParam (ADVAPI32.@)
2136 * Customizes the operations of a CSP.
2138 * PARAMS
2139 * hProv [I] Handle of a CSP.
2140 * dwParam [I] See MSDN Doc.
2141 * pbData [I] Buffer that contains a value to set as a parameter.
2142 * dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
2144 * RETURNS
2145 * Success: TRUE
2146 * Failure: FALSE
2148 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
2150 PCRYPTPROV prov;
2152 TRACE("(0x%Ix, %ld, %p, %08lx)\n", hProv, dwParam, pbData, dwFlags);
2154 if (!(prov = provider_from_handle(hProv)))
2155 return FALSE;
2157 if (dwParam == PP_USE_HARDWARE_RNG)
2159 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
2160 FIXME("\tLetting the CSP decide.\n");
2162 if (dwFlags & PP_CLIENT_HWND)
2164 /* FIXME: Should verify the parameter */
2165 if (pbData /* && IsWindow((HWND)pbData) */)
2167 crypt_hWindow = (HWND)(pbData);
2168 return TRUE;
2169 } else {
2170 SetLastError(ERROR_INVALID_PARAMETER);
2171 return FALSE;
2174 /* All other flags go to the CSP */
2175 return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
2178 /******************************************************************************
2179 * CryptVerifySignatureW (ADVAPI32.@)
2181 * Verifies the signature of a hash object.
2183 * PARAMS
2184 * hHash [I] Handle of the hash object to verify.
2185 * pbSignature [I] Signature data to verify.
2186 * dwSigLen [I] Size of pbSignature.
2187 * hPubKey [I] Handle to the public key to authenticate signature.
2188 * sDescription [I] Should be NULL.
2189 * dwFlags [I] See MSDN doc.
2191 * RETURNS
2192 * Success: TRUE
2193 * Failure: FALSE
2195 * NOTES
2196 * Because of security flaws sDescription should not be used and should thus be
2197 * NULL. It is supported only for compatibility with Microsoft's Cryptographic
2198 * Providers.
2200 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, const BYTE *pbSignature, DWORD dwSigLen,
2201 HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
2203 PCRYPTHASH hash;
2204 PCRYPTKEY key;
2205 PCRYPTPROV prov;
2207 TRACE("(0x%Ix, %p, %ld, 0x%Ix, %s, %08lx)\n", hHash, pbSignature,
2208 dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
2210 if (!(hash = hash_from_handle(hHash)))
2211 return FALSE;
2213 if (!(key = key_from_handle(hPubKey)))
2214 return FALSE;
2216 if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
2217 !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
2219 SetLastError(ERROR_INVALID_PARAMETER);
2220 return FALSE;
2223 prov = hash->pProvider;
2224 return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
2225 key->hPrivate, sDescription, dwFlags);
2228 /******************************************************************************
2229 * CryptVerifySignatureA (ADVAPI32.@)
2231 * See CryptVerifySignatureW.
2233 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, const BYTE *pbSignature, DWORD dwSigLen,
2234 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
2236 LPWSTR wsDescription;
2237 BOOL result;
2239 TRACE("(0x%Ix, %p, %ld, 0x%Ix, %s, %08lx)\n", hHash, pbSignature,
2240 dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
2242 CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
2243 result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
2244 CRYPT_Free(wsDescription);
2246 return result;
2249 /******************************************************************************
2250 * OpenEncryptedFileRawA (ADVAPI32.@)
2252 * See OpenEncryptedFileRawW
2254 DWORD WINAPI OpenEncryptedFileRawA(LPCSTR filename, ULONG flags, PVOID *context)
2256 FIXME("(%s, %lx, %p): stub\n", debugstr_a(filename), flags, context);
2257 return ERROR_CALL_NOT_IMPLEMENTED;
2260 /******************************************************************************
2261 * OpenEncryptedFileRawW (ADVAPI32.@)
2263 * Opens an EFS encrypted file for backup/restore
2265 * PARAMS
2266 * filename [I] Filename to operate on
2267 * flags [I] Operation to perform
2268 * context [I] Handle to the context (out)
2269 * RETURNS
2270 * Success: ERROR_SUCCESS
2271 * Failure: NTSTATUS error code
2273 DWORD WINAPI OpenEncryptedFileRawW(LPCWSTR filename, ULONG flags, PVOID *context)
2275 FIXME("(%s, %lx, %p): stub\n", debugstr_w(filename), flags, context);
2276 return ERROR_CALL_NOT_IMPLEMENTED;
2279 /******************************************************************************
2280 * ReadEncryptedFileRaw (ADVAPI32.@)
2282 * Export encrypted files
2284 * PARAMS
2285 * export [I] pointer to the export callback function
2286 * callback [I] pointer to the application defined context
2287 * context [I] pointer to the system context
2288 * RETURNS
2289 * Success: ERROR_SUCCESS
2290 * Failure: NTSTATUS error code
2292 DWORD WINAPI ReadEncryptedFileRaw(PFE_EXPORT_FUNC export, PVOID callback, PVOID context)
2294 FIXME("(%p, %p, %p): stub\n", export, callback, context);
2295 return ERROR_CALL_NOT_IMPLEMENTED;
2298 /******************************************************************************
2299 * SystemFunction007 [ADVAPI32.@]
2301 * MD4 hash a unicode string
2303 * PARAMS
2304 * string [I] the string to hash
2305 * output [O] the md4 hash of the string (16 bytes)
2307 * RETURNS
2308 * Success: STATUS_SUCCESS
2309 * Failure: STATUS_UNSUCCESSFUL
2312 NTSTATUS WINAPI SystemFunction007(const UNICODE_STRING *string, LPBYTE hash)
2314 MD4_CTX ctx;
2316 MD4Init( &ctx );
2317 MD4Update( &ctx, (const BYTE *)string->Buffer, string->Length );
2318 MD4Final( &ctx );
2319 memcpy( hash, ctx.digest, 0x10 );
2321 return STATUS_SUCCESS;
2324 /******************************************************************************
2325 * SystemFunction010 [ADVAPI32.@]
2326 * SystemFunction011 [ADVAPI32.@]
2328 * MD4 hashes 16 bytes of data
2330 * PARAMS
2331 * unknown [] seems to have no effect on the output
2332 * data [I] pointer to data to hash (16 bytes)
2333 * output [O] the md4 hash of the data (16 bytes)
2335 * RETURNS
2336 * Success: STATUS_SUCCESS
2337 * Failure: STATUS_UNSUCCESSFUL
2340 NTSTATUS WINAPI SystemFunction010(LPVOID unknown, const BYTE *data, LPBYTE hash)
2342 MD4_CTX ctx;
2344 MD4Init( &ctx );
2345 MD4Update( &ctx, data, 0x10 );
2346 MD4Final( &ctx );
2347 memcpy( hash, ctx.digest, 0x10 );
2349 return STATUS_SUCCESS;
2352 /******************************************************************************
2353 * SystemFunction030 (ADVAPI32.@)
2355 * Tests if two blocks of 16 bytes are equal
2357 * PARAMS
2358 * b1,b2 [I] block of 16 bytes
2360 * RETURNS
2361 * TRUE if blocks are the same
2362 * FALSE if blocks are different
2364 BOOL WINAPI SystemFunction030(LPCVOID b1, LPCVOID b2)
2366 return !memcmp(b1, b2, 0x10);
2369 /******************************************************************************
2370 * SystemFunction035 (ADVAPI32.@)
2372 * Described here:
2373 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
2375 * NOTES
2376 * Stub, always return TRUE.
2378 BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
2380 FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
2381 return TRUE;
2384 static CRITICAL_SECTION random_cs;
2385 static CRITICAL_SECTION_DEBUG random_debug =
2387 0, 0, &random_cs,
2388 { &random_debug.ProcessLocksList, &random_debug.ProcessLocksList },
2389 0, 0, { (DWORD_PTR)(__FILE__ ": random_cs") }
2391 static CRITICAL_SECTION random_cs = { &random_debug, -1, 0, 0, 0, 0 };
2393 #define MAX_CPUS 256
2394 static char random_buf[sizeof(SYSTEM_INTERRUPT_INFORMATION) * MAX_CPUS];
2395 static ULONG random_len;
2396 static ULONG random_pos;
2398 /* FIXME: assumes interrupt information provides sufficient randomness */
2399 static BOOL fill_random_buffer(void)
2401 ULONG len = sizeof(SYSTEM_INTERRUPT_INFORMATION) * min( NtCurrentTeb()->Peb->NumberOfProcessors, MAX_CPUS );
2402 NTSTATUS status;
2404 if ((status = NtQuerySystemInformation( SystemInterruptInformation, random_buf, len, NULL )))
2406 WARN( "failed to get random bytes %08lx\n", status );
2407 return FALSE;
2409 random_len = len;
2410 random_pos = 0;
2411 return TRUE;
2414 /******************************************************************************
2415 * SystemFunction036 (ADVAPI32.@)
2417 * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
2419 * PARAMS
2420 * pbBuffer [O] Pointer to memory to receive random bytes.
2421 * dwLen [I] Number of random bytes to fetch.
2423 * RETURNS
2424 * Success: TRUE
2425 * Failure: FALSE
2428 BOOLEAN WINAPI SystemFunction036( void *buffer, ULONG len )
2430 char *ptr = buffer;
2432 EnterCriticalSection( &random_cs );
2433 while (len)
2435 ULONG size;
2436 if (random_pos >= random_len && !fill_random_buffer())
2438 SetLastError( NTE_FAIL );
2439 LeaveCriticalSection( &random_cs );
2440 return FALSE;
2442 size = min( len, random_len - random_pos );
2443 memcpy( ptr, random_buf + random_pos, size );
2444 random_pos += size;
2445 ptr += size;
2446 len -= size;
2448 LeaveCriticalSection( &random_cs );
2449 return TRUE;
2453 These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
2454 in crypt32.dll.
2457 /******************************************************************************
2458 * SystemFunction040 (ADVAPI32.@)
2460 * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
2462 * PARAMS
2463 * memory [I/O] Pointer to memory to encrypt.
2464 * length [I] Length of region to encrypt in bytes.
2465 * flags [I] Control whether other processes are able to decrypt the memory.
2466 * RTL_ENCRYPT_OPTION_SAME_PROCESS
2467 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
2468 * RTL_ENCRYPT_OPTION_SAME_LOGON
2470 * RETURNS
2471 * Success: STATUS_SUCCESS
2472 * Failure: NTSTATUS error code
2474 * NOTES
2475 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2476 * If flags are specified when encrypting, the same flag value must be given
2477 * when decrypting the memory.
2479 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
2481 FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
2482 return STATUS_SUCCESS;
2485 /******************************************************************************
2486 * SystemFunction041 (ADVAPI32.@)
2488 * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
2490 * PARAMS
2491 * memory [I/O] Pointer to memory to decrypt.
2492 * length [I] Length of region to decrypt in bytes.
2493 * flags [I] Control whether other processes are able to decrypt the memory.
2494 * RTL_ENCRYPT_OPTION_SAME_PROCESS
2495 * RTL_ENCRYPT_OPTION_CROSS_PROCESS
2496 * RTL_ENCRYPT_OPTION_SAME_LOGON
2498 * RETURNS
2499 * Success: STATUS_SUCCESS
2500 * Failure: NTSTATUS error code
2502 * NOTES
2503 * length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2504 * If flags are specified when encrypting, the same flag value must be given
2505 * when decrypting the memory.
2507 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
2509 FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
2510 return STATUS_SUCCESS;
2513 /******************************************************************************
2514 * WriteEncryptedFileRaw (ADVAPI32.@)
2516 * Import encrypted files
2518 * PARAMS
2519 * import [I] pointer to the import callback function
2520 * callback [I] pointer to the application defined context
2521 * context [I] pointer to the system context
2522 * RETURNS
2523 * Success: ERROR_SUCCESS
2524 * Failure: NTSTATUS error code
2526 DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC import, PVOID callback, PVOID context)
2528 FIXME("(%p, %p, %p): stub\n", import, callback, context);
2529 return ERROR_CALL_NOT_IMPLEMENTED;